RSpec's Render Template is Permissive
In a controller test, when you expect a request to render a template, you'd write something like this:
expect(response).to render_template(new_user_path)
If your controller action looked like the following, the expectation would pass:
class UsersController < ActionController::Base
def action
...
render :new
end
end
render_template
delegates to ActionController::TemplateAssertions#assert_template
. What I didn't know, however, is how permissive (magical) it is.
Let's say instead of the action's render :new
you returned a json
object with the template, rendered to a string, as one of its values:
def action
response_body = render_to_string(layout: false, template: "users/new.html.haml")
render json: { page: response_body }
end
expect(response).to render_template(new_user_path)
still passess!!!
Also if you say expect(response).to render_template("new.html.haml")
, it also passes. How does it know you meant the user's new.html.haml
and not some other arbitrary one? Maybe because you're in the UsersControllerSpec
. You can also expect...render_template
for templates unrelated to the controller's scope.
I suspect that this permissiveness is caused by Rails registering the rendering of templates, irrespective of whether they are rendered to strings or directly as a response to a controller action. expect...render_template
maybe then looks through the registered renders 🤷🏾♂️. Either way, it's magical!