This doesn't work, but not for the reason you think. Calling have_http_status(200) never raises an exception. It creates a matcher object that the `to` method uses. The ruby || operator (one of few things that can't be overridden) evaluates to the first non falsy thing, so your code is the same as
expect(response).to (have_http_status(200) || have_http_status(302))
so expect(response).to have_http_status(200) | have_http_status(302)
should work, as would things like
expect(3).to eq(2) | eq(3)
This works because | and & are overridable methods and have been defined on matchers to mean "create me a new matcher which matches if either argument matches" (or both match in the & case)
Fred