Skip to content

Commit

Permalink
Fixes for Ruby 3.4 new Hash#inspect syntax
Browse files Browse the repository at this point in the history
The fixes generally tries to leverage the native `Hash#inspect` behavior
to remove the difference between Ruby 3.4 and older Rubies output.
However, some of the case are peculiar due to `DescribableItem#inspect`
\[[2]\] formatting. These needs special casing by `RUBY_VERSION`

Fixes: rspec#2820

[1]: https://bugs.ruby-lang.org/issues/20433
[2]: https://github.com/rspec/rspec/blob/60a7a65e195953196fb8d1836257909c56d2da85/rspec-expectations/lib/rspec/matchers/composable.rb#L162
  • Loading branch information
voxik committed Dec 17, 2024
1 parent 609bb83 commit f6e5c3b
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 15 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ jobs:
RAILS_VERSION: 'main'

# Rails 8.0 builds >= 3.2
- ruby: 3.4.0-rc1
env:
RAILS_VERSION: '~> 8.0.0'
- ruby: 3.3
env:
RAILS_VERSION: '~> 8.0.0'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,12 +248,16 @@ def broadcast(stream, msg)
end

it "has an appropriate description including the matcher's description when qualified with `#with` and a composable matcher" do
expect(
have_broadcasted_to("my_stream")
description = have_broadcasted_to("my_stream")
.from_channel(channel)
.with(a_hash_including(a: :b))
.description
).to eq("have broadcasted exactly 1 messages to my_stream with a hash including {:a => :b}")

if RUBY_VERSION >= '3.4'
expect(description).to eq("have broadcasted exactly 1 messages to my_stream with a hash including {a: :b}")
else
expect(description).to eq("have broadcasted exactly 1 messages to my_stream with a hash including {:a => :b}")
end
end
end
end
38 changes: 30 additions & 8 deletions spec/rspec/rails/matchers/be_a_new_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,13 @@ def new_record?; true; end
expect {
expect(record).to be_a_new(record.class).with(
foo: a_string_matching("bar"))
}.to raise_error("attribute {\"foo\"=>(a string matching \"bar\")} was not set on #{record.inspect}")
}.to raise_error { |e|
if RUBY_VERSION >= '3.4'
"attribute {\"foo\" => (a string matching \"bar\")} was not set on #{record.inspect}"
else
"attribute {\"foo\"=>(a string matching \"bar\")} was not set on #{record.inspect}"
end
}
end

context "matcher is wrong type" do
Expand Down Expand Up @@ -106,7 +112,13 @@ def new_record?; true; end
foo: a_string_matching("foo"),
bar: a_string_matching("barn")
)
}.to raise_error("attribute {\"bar\"=>(a string matching \"barn\")} was not set on #{record.inspect}")
}.to raise_error { |e|
if RUBY_VERSION >= '3.4'
"attribute {\"bar\" => (a string matching \"barn\")} was not set on #{record.inspect}"
else
"attribute {\"bar\"=>(a string matching \"barn\")} was not set on #{record.inspect}"
end
}
end
end
end
Expand All @@ -118,8 +130,13 @@ def new_record?; true; end
expect(record).to be_a_new(record.class).with(zoo: 'zoo', car: 'car')
}.to raise_error { |e|
expect(e.message).to match(/attributes \{.*\} were not set on #{Regexp.escape record.inspect}/)
expect(e.message).to match(/"zoo"=>"zoo"/)
expect(e.message).to match(/"car"=>"car"/)
if RUBY_VERSION >= '3.4'
expect(e.message).to match(/"zoo" => "zoo"/)
expect(e.message).to match(/"car" => "car"/)
else
expect(e.message).to match(/"zoo"=>"zoo"/)
expect(e.message).to match(/"car"=>"car"/)
end
}
end
end
Expand All @@ -129,7 +146,7 @@ def new_record?; true; end
expect {
expect(record).to be_a_new(record.class).with(foo: 'bar')
}.to raise_error(
%(attribute {"foo"=>"bar"} was not set on #{record.inspect})
%(attribute #{{"foo"=>"bar"}} was not set on #{record.inspect})
)
end
end
Expand Down Expand Up @@ -166,8 +183,13 @@ def new_record?; false; end
expect(record).to be_a_new(String).with(zoo: 'zoo', car: 'car')
}.to raise_error { |e|
expect(e.message).to match(/expected #{Regexp.escape record.inspect} to be a new String and attributes \{.*\} were not set on #{Regexp.escape record.inspect}/)
expect(e.message).to match(/"zoo"=>"zoo"/)
expect(e.message).to match(/"car"=>"car"/)
if RUBY_VERSION >= '3.4'
expect(e.message).to match(/"zoo" => "zoo"/)
expect(e.message).to match(/"car" => "car"/)
else
expect(e.message).to match(/"zoo"=>"zoo"/)
expect(e.message).to match(/"car"=>"car"/)
end
}
end
end
Expand All @@ -178,7 +200,7 @@ def new_record?; false; end
expect(record).to be_a_new(String).with(foo: 'bar')
}.to raise_error(
"expected #{record.inspect} to be a new String and " +
%(attribute {"foo"=>"bar"} was not set on #{record.inspect})
%(attribute #{{"foo"=>"bar"}} was not set on #{record.inspect})
)
end
end
Expand Down
4 changes: 2 additions & 2 deletions spec/rspec/rails/matchers/be_routable_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
allow(routes).to receive(:recognize_path) { raise ActionController::RoutingError, 'ignore' }
expect do
expect({ get: "/a/path" }).to be_routable
end.to raise_error(/expected \{:get=>"\/a\/path"\} to be routable/)
end.to raise_error(/expected #{{:get=>"\/a\/path"}} to be routable/)
end
end

Expand All @@ -37,7 +37,7 @@
allow(routes).to receive(:recognize_path) { { controller: "foo" } }
expect do
expect({ get: "/a/path" }).not_to be_routable
end.to raise_error(/expected \{:get=>"\/a\/path"\} not to be routable, but it routes to \{:controller=>"foo"\}/)
end.to raise_error(/expected #{{:get=>"\/a\/path"}} not to be routable, but it routes to #{{:controller=>"foo"}}/)
end
end
end
4 changes: 2 additions & 2 deletions spec/rspec/rails/matchers/route_to_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def assert_recognizes(*)
it "provides a description" do
matcher = route_to("these" => "options")
matcher.matches?(get: "path")
expect(matcher.description).to eq("route {:get=>\"path\"} to {\"these\"=>\"options\"}")
expect(matcher.description).to eq("route #{{:get=>"path"}} to #{{"these"=>"options"}}")
end

it "delegates to assert_recognizes" do
Expand Down Expand Up @@ -109,7 +109,7 @@ def assert_recognizes(*)
it "fails with custom message" do
expect {
expect({ get: "path" }).not_to route_to("these" => "options")
}.to raise_error(/expected \{:get=>"path"\} not to route to \{"these"=>"options"\}/)
}.to raise_error(/expected #{{:get=>"path"}} not to route to #{{"these"=>"options"}}/)
end
end

Expand Down

0 comments on commit f6e5c3b

Please sign in to comment.