From fb82b23646ab6296d72e7b436b9d741a89734eca Mon Sep 17 00:00:00 2001 From: Jon Rowe Date: Thu, 5 Sep 2024 22:48:07 +0100 Subject: [PATCH] Fix singular regexp include --- features/built_in_matchers/include.feature | 6 +++++- lib/rspec/matchers/built_in/include.rb | 2 ++ spec/rspec/matchers/built_in/include_spec.rb | 12 ++++++++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/features/built_in_matchers/include.feature b/features/built_in_matchers/include.feature index d337b22a9..295d9b60f 100644 --- a/features/built_in_matchers/include.feature +++ b/features/built_in_matchers/include.feature @@ -4,6 +4,7 @@ Feature: `include` matcher ```ruby expect("a string").to include("a") + expect("a string").to include(/str..g/) expect("a string").to include(/a|str/).twice expect("a string").to include("str", "g") expect("a string").not_to include("foo") @@ -80,6 +81,7 @@ Feature: `include` matcher RSpec.describe "a string" do it { is_expected.to include("str") } it { is_expected.to include("a", "str", "ng") } + it { is_expected.to include(/str..g/) } it { is_expected.to include(/a|str/).twice } it { is_expected.not_to include("foo") } it { is_expected.not_to include("foo", "bar") } @@ -87,6 +89,7 @@ Feature: `include` matcher # deliberate failures it { is_expected.to include("foo") } it { is_expected.not_to include("str") } + it { is_expected.not_to include(/str..g/) } it { is_expected.to include("str").at_least(:twice) } it { is_expected.to include("str", "foo") } it { is_expected.not_to include("str", "foo") } @@ -94,8 +97,9 @@ Feature: `include` matcher """ When I run `rspec string_include_matcher_spec.rb` Then the output should contain all of these: - | 10 examples, 5 failures | + | 12 examples, 6 failures | | expected "a string" to include "foo" | + | expected "a string" not to include /str..g/ | | expected "a string" not to include "str" | | expected "a string" to include "str" at least twice but it is included once | | expected "a string" to include "foo" | diff --git a/lib/rspec/matchers/built_in/include.rb b/lib/rspec/matchers/built_in/include.rb index f2f187de3..3fedee3ab 100644 --- a/lib/rspec/matchers/built_in/include.rb +++ b/lib/rspec/matchers/built_in/include.rb @@ -166,6 +166,7 @@ def actual_hash_has_key?(expected_key) end def actual_collection_includes?(expected_item) + return actual.scan(expected_item).size > 0 if Regexp === expected_item && String === actual return true if actual.include?(expected_item) # String lacks an `any?` method... @@ -200,6 +201,7 @@ def count_inclusions def diff_would_wrongly_highlight_matched_item? return false unless actual.is_a?(String) && expected.is_a?(Array) + return false if Regexp === expecteds.first lines = actual.split("\n") expected.any? do |str| diff --git a/spec/rspec/matchers/built_in/include_spec.rb b/spec/rspec/matchers/built_in/include_spec.rb index 500f01b81..e4102adf0 100644 --- a/spec/rspec/matchers/built_in/include_spec.rb +++ b/spec/rspec/matchers/built_in/include_spec.rb @@ -215,6 +215,10 @@ def hash.send; :sent; end expect("abc").to include("a") end + it "passes if target matches a regexp" do + expect("abc").to include(/[cba]{3}/) + end + it "fails if target does not include expected" do expect { expect("abc").to include("d") @@ -240,16 +244,20 @@ def hash.send; :sent; end end context "with exact count" do - it 'fails if the block yields wrong number of times' do + it 'fails if the string contains the wrong number of occurences' do expect { expect('foo bar foo').to include('foo').once }.to fail_with(/expected "foo bar foo" to include "foo" once but it is included twice/) + expect { + expect('foo bar foo').to include(/[of]{3}/).once + }.to fail_with(/expected "foo bar foo" to include \/\[of\]\{3\}\/ once but it is included twice/) end - it 'passes if the block yields the specified number of times' do + it 'passes if the string contains the correct number of occurences' do expect('fooo bar').to include('oo').once expect('fooo bar').to include('o').thrice expect('fooo ooo oo bar foo').to include('oo').exactly(4).times + expect('fooo ooo oo bar foo').to include(/fo{2}/).exactly(2).times end end