Skip to content

Commit e8ef5f7

Browse files
committed
Fixes for Ruby 3.4 new Hash#inspect syntax
This fix keeps the new Ruby 3.4 formatting. To adjust the tests, it 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: #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
1 parent 609bb83 commit e8ef5f7

File tree

5 files changed

+44
-15
lines changed

5 files changed

+44
-15
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ jobs:
4545
RAILS_VERSION: 'main'
4646

4747
# Rails 8.0 builds >= 3.2
48+
- ruby: 3.4.0-rc1
49+
env:
50+
RAILS_VERSION: '~> 8.0.0'
4851
- ruby: 3.3
4952
env:
5053
RAILS_VERSION: '~> 8.0.0'

spec/rspec/rails/matchers/action_cable/have_broadcasted_to_spec.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,12 +248,16 @@ def broadcast(stream, msg)
248248
end
249249

250250
it "has an appropriate description including the matcher's description when qualified with `#with` and a composable matcher" do
251-
expect(
252-
have_broadcasted_to("my_stream")
251+
description = have_broadcasted_to("my_stream")
253252
.from_channel(channel)
254253
.with(a_hash_including(a: :b))
255254
.description
256-
).to eq("have broadcasted exactly 1 messages to my_stream with a hash including {:a => :b}")
255+
256+
if RUBY_VERSION >= '3.4'
257+
expect(description).to eq("have broadcasted exactly 1 messages to my_stream with a hash including {a: :b}")
258+
else
259+
expect(description).to eq("have broadcasted exactly 1 messages to my_stream with a hash including {:a => :b}")
260+
end
257261
end
258262
end
259263
end

spec/rspec/rails/matchers/be_a_new_spec.rb

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,13 @@ def new_record?; true; end
7474
expect {
7575
expect(record).to be_a_new(record.class).with(
7676
foo: a_string_matching("bar"))
77-
}.to raise_error("attribute {\"foo\"=>(a string matching \"bar\")} was not set on #{record.inspect}")
77+
}.to raise_error { |e|
78+
if RUBY_VERSION >= '3.4'
79+
"attribute {\"foo\" => (a string matching \"bar\")} was not set on #{record.inspect}"
80+
else
81+
"attribute {\"foo\"=>(a string matching \"bar\")} was not set on #{record.inspect}"
82+
end
83+
}
7884
end
7985

8086
context "matcher is wrong type" do
@@ -106,7 +112,13 @@ def new_record?; true; end
106112
foo: a_string_matching("foo"),
107113
bar: a_string_matching("barn")
108114
)
109-
}.to raise_error("attribute {\"bar\"=>(a string matching \"barn\")} was not set on #{record.inspect}")
115+
}.to raise_error { |e|
116+
if RUBY_VERSION >= '3.4'
117+
"attribute {\"bar\" => (a string matching \"barn\")} was not set on #{record.inspect}"
118+
else
119+
"attribute {\"bar\"=>(a string matching \"barn\")} was not set on #{record.inspect}"
120+
end
121+
}
110122
end
111123
end
112124
end
@@ -118,8 +130,13 @@ def new_record?; true; end
118130
expect(record).to be_a_new(record.class).with(zoo: 'zoo', car: 'car')
119131
}.to raise_error { |e|
120132
expect(e.message).to match(/attributes \{.*\} were not set on #{Regexp.escape record.inspect}/)
121-
expect(e.message).to match(/"zoo"=>"zoo"/)
122-
expect(e.message).to match(/"car"=>"car"/)
133+
if RUBY_VERSION >= '3.4'
134+
expect(e.message).to match(/"zoo" => "zoo"/)
135+
expect(e.message).to match(/"car" => "car"/)
136+
else
137+
expect(e.message).to match(/"zoo"=>"zoo"/)
138+
expect(e.message).to match(/"car"=>"car"/)
139+
end
123140
}
124141
end
125142
end
@@ -129,7 +146,7 @@ def new_record?; true; end
129146
expect {
130147
expect(record).to be_a_new(record.class).with(foo: 'bar')
131148
}.to raise_error(
132-
%(attribute {"foo"=>"bar"} was not set on #{record.inspect})
149+
%(attribute #{{"foo"=>"bar"}} was not set on #{record.inspect})
133150
)
134151
end
135152
end
@@ -166,8 +183,13 @@ def new_record?; false; end
166183
expect(record).to be_a_new(String).with(zoo: 'zoo', car: 'car')
167184
}.to raise_error { |e|
168185
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}/)
169-
expect(e.message).to match(/"zoo"=>"zoo"/)
170-
expect(e.message).to match(/"car"=>"car"/)
186+
if RUBY_VERSION >= '3.4'
187+
expect(e.message).to match(/"zoo" => "zoo"/)
188+
expect(e.message).to match(/"car" => "car"/)
189+
else
190+
expect(e.message).to match(/"zoo"=>"zoo"/)
191+
expect(e.message).to match(/"car"=>"car"/)
192+
end
171193
}
172194
end
173195
end
@@ -178,7 +200,7 @@ def new_record?; false; end
178200
expect(record).to be_a_new(String).with(foo: 'bar')
179201
}.to raise_error(
180202
"expected #{record.inspect} to be a new String and " +
181-
%(attribute {"foo"=>"bar"} was not set on #{record.inspect})
203+
%(attribute #{{"foo"=>"bar"}} was not set on #{record.inspect})
182204
)
183205
end
184206
end

spec/rspec/rails/matchers/be_routable_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
allow(routes).to receive(:recognize_path) { raise ActionController::RoutingError, 'ignore' }
2121
expect do
2222
expect({ get: "/a/path" }).to be_routable
23-
end.to raise_error(/expected \{:get=>"\/a\/path"\} to be routable/)
23+
end.to raise_error(/expected #{{:get=>"\/a\/path"}} to be routable/)
2424
end
2525
end
2626

@@ -37,7 +37,7 @@
3737
allow(routes).to receive(:recognize_path) { { controller: "foo" } }
3838
expect do
3939
expect({ get: "/a/path" }).not_to be_routable
40-
end.to raise_error(/expected \{:get=>"\/a\/path"\} not to be routable, but it routes to \{:controller=>"foo"\}/)
40+
end.to raise_error(/expected #{{:get=>"\/a\/path"}} not to be routable, but it routes to #{{:controller=>"foo"}}/)
4141
end
4242
end
4343
end

spec/rspec/rails/matchers/route_to_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ def assert_recognizes(*)
99
it "provides a description" do
1010
matcher = route_to("these" => "options")
1111
matcher.matches?(get: "path")
12-
expect(matcher.description).to eq("route {:get=>\"path\"} to {\"these\"=>\"options\"}")
12+
expect(matcher.description).to eq("route #{{:get=>"path"}} to #{{"these"=>"options"}}")
1313
end
1414

1515
it "delegates to assert_recognizes" do
@@ -109,7 +109,7 @@ def assert_recognizes(*)
109109
it "fails with custom message" do
110110
expect {
111111
expect({ get: "path" }).not_to route_to("these" => "options")
112-
}.to raise_error(/expected \{:get=>"path"\} not to route to \{"these"=>"options"\}/)
112+
}.to raise_error(/expected #{{:get=>"path"}} not to route to #{{"these"=>"options"}}/)
113113
end
114114
end
115115

0 commit comments

Comments
 (0)