From 2b969646bc2586fdcc71ecaa3264c91e7332454d Mon Sep 17 00:00:00 2001 From: evazion Date: Tue, 23 Jun 2020 23:32:14 -0500 Subject: [PATCH] tests: add `respond_to_search` test helper. Add a `respond_to_search` test helper for concisely testing that a controller's index action correctly responds to a search. Usage: # Tests that `/tags.json?search[name]=touhou` returns the `touhou` tag. setup { @touhou = create(:tag, name: "touhou") } should respond_to_search(name: "touhou").with { @touhou } --- test/test_helper.rb | 2 ++ test/test_helpers/controller_helper.rb | 47 ++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 test/test_helpers/controller_helper.rb diff --git a/test/test_helper.rb b/test/test_helper.rb index 1d81bdb12..892046f7e 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -61,6 +61,8 @@ class ActiveSupport::TestCase end class ActionDispatch::IntegrationTest + extend ControllerHelper + register_encoder :xml, response_parser: ->(body) { Nokogiri.XML(body) } def method_authenticated(method_name, url, user, **options) diff --git a/test/test_helpers/controller_helper.rb b/test/test_helpers/controller_helper.rb new file mode 100644 index 000000000..716bfaa97 --- /dev/null +++ b/test/test_helpers/controller_helper.rb @@ -0,0 +1,47 @@ +module ControllerHelper + # A custom Shoulda matcher that tests that a controller's index endpoint + # responds to a search correctly. See https://thoughtbot.com/blog/shoulda-matchers. + # + # Usage: + # + # # Tests that `/tags.json?search[name]=touhou` returns the `touhou` tag. + # subject { TagsController } + # setup { @touhou = create(:tag, name: "touhou") } + # should respond_to_search(name: "touhou").with { @touhou } + # + def respond_to_search(search_params) + RespondToSearchMatcher.new(search_params) + end + + class RespondToSearchMatcher < Struct.new(:params) + def description + "should respond to a search for #{params}" + end + + def matches?(subject, &block) + search_params = { search: params } + expected_items = @test_case.instance_eval(&@expected) + + @test_case.instance_eval do + # calls e.g. "wiki_pages_path" if we're in WikiPagesControllerTest. + index_url = send("#{subject.controller_path}_path") + get index_url, as: :json, params: search_params + + expected_ids = Array(expected_items).map(&:id) + responded_ids = response.parsed_body.map { |item| item["id"] } + + assert_response :success + assert_equal(expected_ids, responded_ids) + end + end + + def with(&block) + @expected = block + self + end + + def in_context(test_case) + @test_case = test_case + end + end +end