diff --git a/NEWS.md b/NEWS.md index f546ae648..e92a230c9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -256,6 +256,9 @@ * Fix `permit` + `on` as it did not work correctly. ([#771], [0d43835]) +* Fix `shoulda/matchers/independent` so that it can be required + independently, without having to require all of the gem. ([#746]) + ### Features * Add `on` qualifier to `permit`. This allows you to make an assertion that @@ -301,6 +304,7 @@ [#699]: https://github.com/thoughtbot/shoulda-matchers/pull/699 [#771]: https://github.com/thoughtbot/shoulda-matchers/pull/771 [0d43835]: https://github.com/thoughtbot/shoulda-matchers/commit/0d43835b615f379f069c7d2c2264a80332510778 +[#746]: https://github.com/thoughtbot/shoulda-matchers/pull/746 # 2.8.0 diff --git a/lib/shoulda/matchers/independent/delegate_method_matcher.rb b/lib/shoulda/matchers/independent/delegate_method_matcher.rb index f4a89fe9b..a79cfc187 100644 --- a/lib/shoulda/matchers/independent/delegate_method_matcher.rb +++ b/lib/shoulda/matchers/independent/delegate_method_matcher.rb @@ -1,3 +1,6 @@ +require 'shoulda/matchers/doublespeak' +require 'shoulda/matchers/matcher_context' + module Shoulda module Matchers module Independent diff --git a/spec/acceptance/independent_matchers_spec.rb b/spec/acceptance/independent_matchers_spec.rb index 5cddfbdf1..0db4aee7f 100644 --- a/spec/acceptance/independent_matchers_spec.rb +++ b/spec/acceptance/independent_matchers_spec.rb @@ -1,64 +1,125 @@ require 'acceptance_spec_helper' -describe 'shoulda-matchers has independent matchers' do - context 'specifically delegate_method' do - specify 'and integrates with a Ruby application that uses the default test framework' do - create_generic_bundler_project - - updating_bundle do - add_minitest_to_project - add_shoulda_context_to_project(manually: true) - add_shoulda_matchers_to_project( - test_frameworks: [default_test_framework], - manually: true - ) +describe 'shoulda-matchers has independent matchers, specifically delegate_method' do + specify 'and integrates with a Ruby application that uses the default test framework' do + create_generic_bundler_project + + updating_bundle do + add_minitest_to_project + add_shoulda_context_to_project(manually: true) + add_shoulda_matchers_to_project( + test_frameworks: [default_test_framework], + manually: true + ) + end + + write_file 'lib/post_office.rb', <<-FILE + class PostOffice end + FILE + + write_file 'lib/courier.rb', <<-FILE + require 'forwardable' - write_file 'lib/post_office.rb', <<-FILE - class PostOffice + class Courier + extend Forwardable + + def_delegators :post_office, :deliver + + attr_reader :post_office + + def initialize(post_office) + @post_office = post_office + end + end + FILE + + write_n_unit_test 'test/courier_test.rb' do |test_case_superclass| + <<-FILE + require 'test_helper' + require 'courier' + require 'post_office' + + class CourierTest < #{test_case_superclass} + subject { Courier.new(post_office) } + + should delegate_method(:deliver).to(:post_office) + + def post_office + PostOffice.new + end end FILE + end - write_file 'lib/courier.rb', <<-FILE - require 'forwardable' + result = run_n_unit_tests('test/courier_test.rb') - class Courier - extend Forwardable + expect(result).to indicate_number_of_tests_was_run(1) + expect(result).to have_output( + 'Courier should delegate #deliver to #post_office object' + ) + end - def_delegators :post_office, :deliver + specify 'and integrates with a Ruby application that uses RSpec' do + create_generic_bundler_project - attr_reader :post_office + updating_bundle do + add_rspec_to_project + add_shoulda_matchers_to_project( + manually: true, + with_configuration: false + ) + write_file 'spec/spec_helper.rb', <<-FILE + require 'shoulda/matchers/independent' - def initialize(post_office) - @post_office = post_office - end + RSpec.configure do |config| + config.include(Shoulda::Matchers::Independent) end FILE + end + + write_file 'lib/post_office.rb', <<-FILE + class PostOffice + end + FILE - write_n_unit_test 'test/courier_test.rb' do |test_case_superclass| - <<-FILE - require 'test_helper' - require 'courier' - require 'post_office' + write_file 'lib/courier.rb', <<-FILE + require 'forwardable' - class CourierTest < #{test_case_superclass} - subject { Courier.new(post_office) } + class Courier + extend Forwardable - should delegate_method(:deliver).to(:post_office) + def_delegators :post_office, :deliver - def post_office - PostOffice.new - end - end - FILE + attr_reader :post_office + + def initialize(post_office) + @post_office = post_office + end end + FILE - result = run_n_unit_tests('test/courier_test.rb') + write_file 'spec/courier_spec.rb', <<-FILE + require 'spec_helper' + require 'courier' + require 'post_office' - expect(result).to indicate_number_of_tests_was_run(1) - expect(result).to have_output( - 'Courier should delegate #deliver to #post_office object' - ) - end + describe Courier do + subject { Courier.new(post_office) } + + it { should delegate_method(:deliver).to(:post_office) } + + def post_office + PostOffice.new + end + end + FILE + + result = run_rspec_tests('spec/courier_spec.rb') + + expect(result).to indicate_number_of_tests_was_run(1) + expect(result).to have_output( + /Courier\s+should delegate #deliver to #post_office object/ + ) end end diff --git a/spec/support/acceptance/adds_shoulda_matchers_to_project.rb b/spec/support/acceptance/adds_shoulda_matchers_to_project.rb index 6a1663f85..c684e1962 100644 --- a/spec/support/acceptance/adds_shoulda_matchers_to_project.rb +++ b/spec/support/acceptance/adds_shoulda_matchers_to_project.rb @@ -16,7 +16,10 @@ def initialize(options) def call add_gem 'shoulda-matchers', gem_options - configure_test_helper_files + + unless options[:with_configuration] === false + configure_test_helper_files + end end protected @@ -48,8 +51,10 @@ def configure_test_helper_files def each_test_helper_file options[:test_frameworks].each do |test_framework| libraries = options.fetch(:libraries, []) - test_helper_file = test_helper_file_for(test_framework, libraries) - yield test_helper_file, test_framework, libraries + + test_helper_files_for(test_framework, libraries).each do |test_helper_file| + yield test_helper_file, test_framework, libraries + end end end @@ -85,16 +90,26 @@ def library_config_for(libraries) libraries.map { |library| "with.library :#{library}" }.join("\n") end - def test_helper_file_for(test_framework, libraries) - if integrates_with_rails?(test_framework, libraries) || - integrates_with_nunit?(test_framework) - 'test/test_helper.rb' - elsif integrates_with_rspec?(test_framework) - spec_helper_file_path + def test_helper_files_for(test_framework, libraries) + files = [] + + if integrates_with_nunit_and_rails?(test_framework, libraries) || + integrates_with_nunit_only?(test_framework) + files << 'test/test_helper.rb' end + + if integrates_with_rspec?(test_framework) + if bundle.includes?('rspec-rails') + files << 'spec/rails_helper.rb' + else + files << 'spec/spec_helper.rb' + end + end + + files end - def integrates_with_nunit?(test_framework) + def integrates_with_nunit_only?(test_framework) nunit_frameworks = [:test_unit, :minitest, :minitest_4, :minitest_5] nunit_frameworks.include?(test_framework) end @@ -103,8 +118,16 @@ def integrates_with_rspec?(test_framework) test_framework == :rspec end - def integrates_with_rails?(test_framework, libraries) + def integrates_with_rspec_rails_3_x?(test_framework, libraries) + integrates_with_rails?(libraries) && rspec_rails_version >= 3 + end + + def integrates_with_nunit_and_rails?(test_framework, libraries) test_framework.nil? && libraries.include?(:rails) end + + def integrates_with_rails?(libraries) + libraries.include?(:rails) + end end end diff --git a/spec/support/acceptance/helpers/rspec_helpers.rb b/spec/support/acceptance/helpers/rspec_helpers.rb index 6a0fdc8d9..875a91152 100644 --- a/spec/support/acceptance/helpers/rspec_helpers.rb +++ b/spec/support/acceptance/helpers/rspec_helpers.rb @@ -4,25 +4,21 @@ module AcceptanceTests module RspecHelpers include GemHelpers - def rspec_rails_version - bundle_version_of('rspec-rails') + def rspec_core_version + bundle_version_of('rspec-core') end - def add_rspec_file(path, content) - content = "require '#{spec_helper_require_path}'\n#{content}" - write_file path, content + def rspec_expectations_version + bundle_version_of('rspec-expectations') end - def spec_helper_require_path - if rspec_rails_version >= 3 - 'rails_helper' - else - 'spec_helper' - end + def rspec_rails_version + bundle_version_of('rspec-rails') end - def spec_helper_file_path - "spec/#{spec_helper_require_path}.rb" + def add_rspec_file(path, content) + content = "require 'rails_helper'\n#{content}" + write_file path, content end end end diff --git a/spec/support/acceptance/helpers/step_helpers.rb b/spec/support/acceptance/helpers/step_helpers.rb index 7fc3fb613..b0cd60da5 100644 --- a/spec/support/acceptance/helpers/step_helpers.rb +++ b/spec/support/acceptance/helpers/step_helpers.rb @@ -90,12 +90,25 @@ def configure_routes_with_single_wildcard_route FILE end + def add_rspec_to_project + add_gem 'rspec-core', rspec_core_version + add_gem 'rspec-expectations', rspec_expectations_version + append_to_file 'spec/spec_helper.rb', <<-FILE + require 'rspec/core' + require 'rspec/expectations' + FILE + end + def add_rspec_rails_to_project! add_gem 'rspec-rails', rspec_rails_version run_command_within_bundle!('rails g rspec:install') remove_from_file '.rspec', '--warnings' end + def run_rspec_tests(*paths) + run_command_within_bundle 'rspec --format documentation --backtrace', *paths + end + def run_rspec_suite run_rake_tasks('spec', env: { SPEC_OPTS: '-fd' }) end diff --git a/spec/support/acceptance/matchers/have_output.rb b/spec/support/acceptance/matchers/have_output.rb index ec0ec4bb2..4f8e60e00 100644 --- a/spec/support/acceptance/matchers/have_output.rb +++ b/spec/support/acceptance/matchers/have_output.rb @@ -18,7 +18,7 @@ def failure_message "Expected command to have output, but did not.\n\n" + "Command: #{runner.formatted_command}\n\n" + "Expected output:\n" + - output + "\n\n" + + output.inspect + "\n\n" + "Actual output:\n" + runner.output end diff --git a/spec/support/acceptance/matchers/indicate_number_of_tests_was_run_matcher.rb b/spec/support/acceptance/matchers/indicate_number_of_tests_was_run_matcher.rb index bb47e07e4..7ca88c8ff 100644 --- a/spec/support/acceptance/matchers/indicate_number_of_tests_was_run_matcher.rb +++ b/spec/support/acceptance/matchers/indicate_number_of_tests_was_run_matcher.rb @@ -40,7 +40,7 @@ def failure_message private def expected_output - /#{number} (tests|runs), #{number} assertions, 0 failures, 0 errors(, 0 skips)?/ + /#{number} (?:tests?|runs?|examples?)(?:, #{number} assertions)?, 0 failures(?:, 0 errors(?:, 0 skips)?)?/ end def actual_output diff --git a/spec/support/tests/command_runner.rb b/spec/support/tests/command_runner.rb index 29e58a7f0..45798d4ab 100644 --- a/spec/support/tests/command_runner.rb +++ b/spec/support/tests/command_runner.rb @@ -117,7 +117,11 @@ def fail! end def has_output?(expected_output) - output.include?(expected_output) + if expected_output.is_a?(Regexp) + output =~ expected_output + else + output.include?(expected_output) + end end protected