rails / rails-controller-testing

Brings back `assigns` and `assert_template` to your Rails tests
https://github.com/rails/rails-controller-testing
MIT License
305 stars 53 forks source link

Support for nested matchers in `assert_template` #77

Open klondikemarlen opened 2 years ago

klondikemarlen commented 2 years ago

I would expect

render(
  partial: 'path/to/partial', 
  locals: {
    arg1: 'value-for-arg1',
    arg2: 'value-for-arg2',
    arg3: 'value-for-arg3',
  },
)

expect(view).to render_template(
  partial: 'path/to/partial',
  locals: {
    arg1: 'value-for-arg1',
    arg2: 'value-for-arg2',
    arg3: anything,
  },
)

to work if arg1, and arg2 are correct. Instead the code only seems to work when I also pass the correct value for arg3.

It seems like assert_template isn't accepting nested matchers?

klondikemarlen commented 2 years ago

Using rspec-rails so this is probably not the correct place to post.

klondikemarlen commented 2 years ago

Apparently the issue is in this repo (sort of). https://github.com/rails/rails-controller-testing/blob/master/lib/rails/controller/testing/template_assertions.rb#L170 uses rendered_views.view_rendered? which uses https://github.com/rails/rails/blob/8015c2c2cf5c8718449677570f372ceb01318a32/actionview/lib/action_view/test_case.rb#L159 which is doing == instead of === so it rejects matchers.

klondikemarlen commented 2 years ago

assert(@_rendered_views.view_rendered?(view, options[:locals]), msg) could probably be something like

result = @_rendered_views.locals_for(view).any? do |actual_locals|
  expected_locals.all? { |key, value| value === actual_locals[key] }
end
assert(result, msg)

and it would take nested matchers. Though I'm not actually sure that nested matchers are MiniTest thing and not just an RSpec thing, so maybe its not a problem in this repo after all.