Skip to content
This repository has been archived by the owner on Nov 30, 2024. It is now read-only.

Commit

Permalink
Merge pull request #1199 from rspec/fix-differ-support
Browse files Browse the repository at this point in the history
Fix differ support
  • Loading branch information
JonRowe authored Jun 29, 2020
2 parents c87ab72 + 2c77014 commit a7342d0
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 19 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ matrix:
include:
- rvm: jruby-1.7
env: JRUBY_OPTS='--dev --1.8'
- rvm: 2.7.1
env: DIFF_LCS_VERSION="~> 1.3.0"
allow_failures:
- rvm: jruby-head
- rvm: ruby-head
Expand Down
6 changes: 6 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ else
gem 'rake', '> 12.3.2'
end

if ENV['DIFF_LCS_VERSION']
gem 'diff-lcs', ENV['DIFF_LCS_VERSION']
else
gem 'diff-lcs', '~> 1.4', '>= 1.4.3'
end

gem 'coderay' # for syntax highlighting
gem 'yard', '~> 0.9.24', :require => false

Expand Down
71 changes: 70 additions & 1 deletion features/custom_matchers/define_diffable_matcher.feature
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,33 @@ Feature: define diffable matcher

When a matcher is defined as diffable, the output will include a diff of the submitted objects when the objects are more than simple primitives.

Scenario: define a diffable matcher
@skip-when-diff-lcs-1.3
Scenario: define a diffable matcher (with diff-lcs 1.4)
Given a file named "diffable_matcher_spec.rb" with:
"""ruby
RSpec::Matchers.define :be_just_like do |expected|
match do |actual|
actual == expected
end
diffable
end
RSpec.describe "two\nlines" do
it { is_expected.to be_just_like("three\nlines") }
end
"""
When I run `rspec ./diffable_matcher_spec.rb`
Then it should fail with:
"""
Diff:
@@ -1 +1 @@
-three
+two
"""

@skip-when-diff-lcs-1.4
Scenario: define a diffable matcher (with diff-lcs 1.3)
Given a file named "diffable_matcher_spec.rb" with:
"""ruby
RSpec::Matchers.define :be_just_like do |expected|
Expand All @@ -27,10 +53,53 @@ Feature: define diffable matcher
lines
"""

@skip-when-diff-lcs-1.3
Scenario: Redefine actual

Sometimes is neccessary to overwrite actual to make diffing work, e.g. if `actual` is a name of a file you want to read from. For this to work you need to overwrite `@actual` in your matcher.

Given a file named "redefine_actual_matcher_spec.rb" with:
"""ruby
RSpec::Matchers.define :have_content do |expected|
match do |actual|
@actual = File.read(actual).chomp
values_match? expected, @actual
end
diffable
end
RSpec.describe 'Compare files' do
context 'when content is equal' do
it { expect('data.txt').to have_content 'Data' }
end
context 'when files are different' do
it { expect('data.txt').to have_content "No\nData\nhere" }
end
end
"""
And a file named "data.txt" with:
"""
Data
"""
When I run `rspec ./redefine_actual_matcher_spec.rb --format documentation`
Then the exit status should not be 0
And the output should contain:
"""
2 examples, 1 failure
"""
And the output should contain:
"""
@@ -1,4 +1,6 @@
-No
Data
-here
"""

@skip-when-diff-lcs-1.4
Scenario: Redefine actual (with diff-lcs 1.3)
Given a file named "redefine_actual_matcher_spec.rb" with:
"""ruby
RSpec::Matchers.define :have_content do |expected|
Expand Down
30 changes: 29 additions & 1 deletion features/diffing.feature
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,35 @@ Feature: diffing
string
"""

Scenario: diff for a multiline string and a regexp
@skip-when-diff-lcs-1.3
Scenario: diff for a multiline string and a regexp on diff-lcs 1.4
Given a file named "example_spec.rb" with:
"""ruby
RSpec.describe "a multiline string" do
it "is like another string" do
expected = /expected/m
actual = <<-ACTUAL
this is the
actual
string
ACTUAL
expect(actual).to match expected
end
end
"""
When I run `rspec example_spec.rb`
Then the output should contain:
"""
Diff:
@@ -1,3 +1,5 @@
-/expected/m
+this is the
+ actual
+ string
"""

@skip-when-diff-lcs-1.4
Scenario: diff for a multiline string and a regexp on diff-lcs 1.3
Given a file named "example_spec.rb" with:
"""ruby
RSpec.describe "a multiline string" do
Expand Down
15 changes: 15 additions & 0 deletions features/support/diff_lcs_versions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Around "@skip-when-diff-lcs-1.4" do |scenario, block|
if Diff::LCS::VERSION.to_f >= 1.4
warn "Skipping scenario #{scenario.title} on #{Diff::LCS::VERSION.to_f}"
else
block.call
end
end

Around "@skip-when-diff-lcs-1.3" do |scenario, block|
if Diff::LCS::VERSION.to_f < 1.4
warn "Skipping scenario #{scenario.title} on #{Diff::LCS::VERSION.to_f}"
else
block.call
end
end
8 changes: 6 additions & 2 deletions spec/rspec/expectations/fail_with_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
end

RSpec.describe RSpec::Expectations, "#fail_with with matchers" do
include RSpec::Support::Spec::DiffHelpers

before do
allow(RSpec::Matchers.configuration).to receive_messages(:color? => false)
end
Expand All @@ -42,7 +44,7 @@

expected_diff = dedent(<<-EOS)
|
|@@ -1,2 +1,2 @@
|@@ #{one_line_header} @@
|-["poo", "car"]
|+[(a string matching /foo/), (a string matching /bar/)]
|
Expand All @@ -55,14 +57,16 @@
end

RSpec.describe RSpec::Expectations, "#fail_with with --color" do
include RSpec::Support::Spec::DiffHelpers

before do
allow(RSpec::Matchers.configuration).to receive_messages(:color? => true)
end

it "tells the differ to use color" do
expected = "foo bar baz\n"
actual = "foo bang baz\n"
expected_diff = "\e[0m\n\e[0m\e[34m@@ -1,2 +1,2 @@\n\e[0m\e[31m-foo bang baz\n\e[0m\e[32m+foo bar baz\n\e[0m"
expected_diff = "\e[0m\n\e[0m\e[34m@@ #{one_line_header} @@\n\e[0m\e[31m-foo bang baz\n\e[0m\e[32m+foo bar baz\n\e[0m"

expect {
RSpec::Expectations.fail_with "message", actual, expected
Expand Down
13 changes: 4 additions & 9 deletions spec/rspec/matchers/built_in/have_attributes_spec.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
RSpec.describe "#have_attributes matcher" do
include RSpec::Support::Spec::DiffHelpers

Person = Struct.new(:name, :age)

Expand Down Expand Up @@ -36,7 +37,6 @@ def respond_to?(method_name)
end

describe "expect(...).to have_attributes(with_one_attribute)" do

it_behaves_like "an RSpec matcher", :valid_value => Person.new("Correct name", 33), :invalid_value => Person.new("Wrong Name", 11) do
let(:matcher) { have_attributes(:name => "Correct name") }
end
Expand Down Expand Up @@ -71,7 +71,7 @@ def count
allow(RSpec::Matchers.configuration).to receive_messages(:color? => false)

expected_diff = dedent(<<-EOS)
|@@ -1,2 +1,2 @@
|@@ #{one_line_header} @@
|-:name => "Wrong Name",
|+:name => "Correct name",
EOS
Expand Down Expand Up @@ -100,7 +100,6 @@ def count
end

describe "expect(...).to have_attributes(key => matcher)" do

it "passes when the matchers match" do
expect(person).to have_attributes(:age => (a_value > 30))
end
Expand All @@ -119,7 +118,6 @@ def count
end

describe "expect(...).to_not have_attributes(with_one_attribute)" do

it "passes if target does not have any of the expected attributes" do
expect(person).to_not have_attributes(:age => wrong_age)
end
Expand Down Expand Up @@ -150,7 +148,6 @@ def count
end

describe "expect(...).to have_attributes(with_multiple_attributes)" do

it_behaves_like "an RSpec matcher", :valid_value => Person.new("Correct name", 33), :invalid_value => Person.new("Wrong Name", 11) do
let(:matcher) { have_attributes(:name => "Correct name", :age => 33) }
end
Expand All @@ -169,11 +166,11 @@ def count
allow(RSpec::Matchers.configuration).to receive_messages(:color? => false)

expected_diff = dedent(<<-EOS)
|@@ -1,3 +1,3 @@
|@@ #{one_line_header(3)} @@
|-:age => 11,
|+:age => 33,
| :name => "Correct name",
EOS
expected_diff << "\n :name => \"Correct name\",\n" if Diff::LCS::VERSION.to_f < 1.4

expect {
expect(person).to have_attributes(:name => correct_name, :age => wrong_age)
Expand All @@ -194,7 +191,6 @@ def count
end

describe "expect(...).to_not have_attributes(with_multiple_attributes)" do

it "passes if target has none of the expected attributes" do
expect(person).to_not have_attributes(:name => wrong_name, :age => wrong_age)
end
Expand Down Expand Up @@ -229,5 +225,4 @@ def count
def object_inspect(object)
surface_descriptions_in object.inspect
end

end
11 changes: 7 additions & 4 deletions spec/rspec/matchers/built_in/include_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ def to_hash
end

RSpec.describe "#include matcher" do
include RSpec::Support::Spec::DiffHelpers

it "is diffable" do
expect(include("a")).to be_diffable
end
Expand Down Expand Up @@ -87,13 +89,14 @@ def hash.send; :sent; end
|+"foo" => 1,
END
else
dedent(<<-END)
diff = dedent(<<-END)
|Diff:
|@@ -1,3 +1,3 @@
|@@ #{one_line_header(3)} @@
|-:bar => 3,
|+:bar => 2,
| :foo => 1,
END
diff << "\n :foo => 1,\n" if Diff::LCS::VERSION.to_f < 1.4
diff
end

expect {
Expand Down Expand Up @@ -297,7 +300,7 @@ class PseudoHash < SimpleDelegator
)
}.to fail_including(dedent(<<-END))
|Diff:
|@@ -1,2 +1,2 @@
|@@ #{one_line_header} @@
|-[{:number=>1}, {:number=>0}, {:number=>3}]
|+[{:number=>1}, {:number=>2}, {:number=>3}]
END
Expand Down
4 changes: 3 additions & 1 deletion spec/rspec/matchers/built_in/match_spec.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
RSpec.describe "expect(...).to match(expected)" do
include RSpec::Support::Spec::DiffHelpers

it_behaves_like "an RSpec matcher", :valid_value => 'ab', :invalid_value => 'bc' do
let(:matcher) { match(/a/) }
end
Expand Down Expand Up @@ -68,7 +70,7 @@

failure_message_that_includes_diff = %r|
\s*Diff:
\s*@@ -1,2 \+1,2 @@
\s*@@ #{Regexp.escape one_line_header} @@
\s*-/bar/
\s*\+"foo"|

Expand Down
8 changes: 7 additions & 1 deletion spec/rspec/matchers/dsl_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,13 @@ def foo
diff = e.message.sub(/\A.*Diff:/m, "Diff:").gsub(/^\s*/, '')
end

expect(diff).to eq "Diff:\n@@ -1,3 +1,3 @@\n-line1\n+LINE1\nline2\n"
if Diff::LCS::VERSION.to_f < 1.4
expected_diff = "Diff:\n@@ -1,3 +1,3 @@\n-line1\n+LINE1\nline2\n"
else
expected_diff = "Diff:\n@@ -1 +1 @@\n-line1\n+LINE1\n"
end

expect(diff).to eq expected_diff
end

it 'does not confuse the diffability of different matchers' do
Expand Down

0 comments on commit a7342d0

Please sign in to comment.