Skip to content

Commit 303a5f0

Browse files
committed
Implement RSpec 3.13.0+ compatibility (#258)
A private RSpec API (specifically `::RSpec::Matchers::{ExpectedsForMultipleDiffs -> MultiMatcherDiff}`) changed in 3.13.0; see rspec/rspec-expectations@81d3a58.
1 parent 63f70ca commit 303a5f0

9 files changed

+271
-58
lines changed

.github/workflows/super_diff.yml

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ jobs:
6565
rspec_appraisal:
6666
- rspec_lt_3_10
6767
- rspec_gte_3_10
68+
- rspec_gte_3_13
6869
env:
6970
BUNDLE_GEMFILE: gemfiles/${{ matrix.rails_appraisal }}_${{ matrix.rspec_appraisal }}.gemfile
7071
steps:

Appraisals

+14-1
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,25 @@ appraisals = {
4949
gem 'rspec-mocks', '3.12.0'
5050
gem 'rspec-support', '3.12.0'
5151

52+
gem 'rspec-rails' if with_rails
53+
end,
54+
rspec_gte_3_13:
55+
proc do |with_rails|
56+
# version = ['>= 3.13', '< 4']
57+
# gem "rspec", *version
58+
59+
gem 'rspec', '3.13.0'
60+
gem 'rspec-core', '3.13.0'
61+
gem 'rspec-expectations', '3.13.0'
62+
gem 'rspec-mocks', '3.13.0'
63+
gem 'rspec-support', '3.13.0'
64+
5265
gem 'rspec-rails' if with_rails
5366
end
5467
}
5568

5669
rails_appraisals = %i[no_rails rails_6_0 rails_6_1 rails_7_0]
57-
rspec_appraisals = %i[rspec_lt_3_10 rspec_gte_3_10]
70+
rspec_appraisals = %i[rspec_lt_3_10 rspec_gte_3_10 rspec_gte_3_13]
5871

5972
rails_appraisals.each do |rails_appraisal|
6073
rspec_appraisals.each do |rspec_appraisal|

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## [Unreleased]
44

5+
### Features
6+
7+
- Implement RSpec 3.13.0+ compatibility. [#258](https://github.com./splitwise/super_diff/pull/258)
8+
59
## 0.14.0 - 2024-11-15
610

711
### Features
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# This file was generated by Appraisal
2+
3+
source "https://rubygems.org"
4+
5+
gem "appraisal", git: "https://github.com./thoughtbot/appraisal"
6+
gem "bundler-audit"
7+
gem "childprocess"
8+
gem "climate_control"
9+
gem "prettier_print"
10+
gem "pry-byebug", platform: :mri
11+
gem "pry-nav", platform: :jruby
12+
gem "rake"
13+
gem "rubocop"
14+
gem "syntax_tree"
15+
gem "syntax_tree-haml"
16+
gem "syntax_tree-rbs"
17+
gem "rspec", "3.13.0"
18+
gem "rspec-core", "3.13.0"
19+
gem "rspec-expectations", "3.13.0"
20+
gem "rspec-mocks", "3.13.0"
21+
gem "rspec-support", "3.13.0"
22+
23+
gemspec path: "../"
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# This file was generated by Appraisal
2+
3+
source "https://rubygems.org"
4+
5+
gem "appraisal", git: "https://github.com./thoughtbot/appraisal"
6+
gem "bundler-audit"
7+
gem "childprocess"
8+
gem "climate_control"
9+
gem "prettier_print"
10+
gem "pry-byebug", platform: :mri
11+
gem "pry-nav", platform: :jruby
12+
gem "rake"
13+
gem "rubocop"
14+
gem "syntax_tree"
15+
gem "syntax_tree-haml"
16+
gem "syntax_tree-rbs"
17+
gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
18+
gem "jdbc-sqlite3", platform: :jruby
19+
gem "net-ftp"
20+
gem "combustion"
21+
gem "rails", "~> 6.0.0"
22+
gem "sqlite3", "~> 1.4.0", platform: [:ruby, :mswin, :mingw]
23+
gem "rspec", "3.13.0"
24+
gem "rspec-core", "3.13.0"
25+
gem "rspec-expectations", "3.13.0"
26+
gem "rspec-mocks", "3.13.0"
27+
gem "rspec-support", "3.13.0"
28+
gem "rspec-rails"
29+
30+
gemspec path: "../"
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# This file was generated by Appraisal
2+
3+
source "https://rubygems.org"
4+
5+
gem "appraisal", git: "https://github.com./thoughtbot/appraisal"
6+
gem "bundler-audit"
7+
gem "childprocess"
8+
gem "climate_control"
9+
gem "prettier_print"
10+
gem "pry-byebug", platform: :mri
11+
gem "pry-nav", platform: :jruby
12+
gem "rake"
13+
gem "rubocop"
14+
gem "syntax_tree"
15+
gem "syntax_tree-haml"
16+
gem "syntax_tree-rbs"
17+
gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
18+
gem "jdbc-sqlite3", platform: :jruby
19+
gem "net-ftp"
20+
gem "combustion"
21+
gem "rails", "~> 6.1.0"
22+
gem "sqlite3", "~> 1.4.0", platform: [:ruby, :mswin, :mingw]
23+
gem "rspec", "3.13.0"
24+
gem "rspec-core", "3.13.0"
25+
gem "rspec-expectations", "3.13.0"
26+
gem "rspec-mocks", "3.13.0"
27+
gem "rspec-support", "3.13.0"
28+
gem "rspec-rails"
29+
30+
gemspec path: "../"
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# This file was generated by Appraisal
2+
3+
source "https://rubygems.org"
4+
5+
gem "appraisal", git: "https://github.com./thoughtbot/appraisal"
6+
gem "bundler-audit"
7+
gem "childprocess"
8+
gem "climate_control"
9+
gem "prettier_print"
10+
gem "pry-byebug", platform: :mri
11+
gem "pry-nav", platform: :jruby
12+
gem "rake"
13+
gem "rubocop"
14+
gem "syntax_tree"
15+
gem "syntax_tree-haml"
16+
gem "syntax_tree-rbs"
17+
gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
18+
gem "jdbc-sqlite3", platform: :jruby
19+
gem "net-ftp"
20+
gem "combustion"
21+
gem "rails", "~> 7.0.0"
22+
gem "sqlite3", "~> 1.4.0", platform: [:ruby, :mswin, :mingw]
23+
gem "rspec", "3.13.0"
24+
gem "rspec-core", "3.13.0"
25+
gem "rspec-expectations", "3.13.0"
26+
gem "rspec-mocks", "3.13.0"
27+
gem "rspec-support", "3.13.0"
28+
gem "rspec-rails"
29+
30+
gemspec path: "../"

lib/super_diff/rspec.rb

+10-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,16 @@ def self.a_value_within_something?(value)
8181
end
8282

8383
def self.aliased_matcher?(value)
84-
value.is_a?(::RSpec::Matchers::AliasedMatcher)
84+
if SuperDiff::RSpec.rspec_version < '3.13.0'
85+
value.is_a?(::RSpec::Matchers::AliasedMatcher)
86+
else # See Github issue #250.
87+
!ordered_options?(value) && value.respond_to?(:base_matcher)
88+
end
89+
end
90+
91+
def self.ordered_options?(value)
92+
defined?(::ActiveSupport::OrderedOptions) &&
93+
value.is_a?(::ActiveSupport::OrderedOptions)
8594
end
8695

8796
def self.rspec_version

lib/super_diff/rspec/monkey_patches.rb

+129-56
Original file line numberDiff line numberDiff line change
@@ -309,73 +309,146 @@ def format(value)
309309
end
310310

311311
module Matchers
312-
class ExpectedsForMultipleDiffs
313-
SuperDiff.insert_singleton_overrides(self) do
314-
# Add a key for different sides
315-
def from(expected)
316-
return expected if self === expected
317-
318-
text = colorizer.wrap("Diff:", SuperDiff.configuration.header_color)
319-
320-
if SuperDiff.configuration.key_enabled?
321-
text +=
322-
"\n\n" +
323-
colorizer.wrap(
324-
"┌ (Key) ──────────────────────────┐",
325-
SuperDiff.configuration.border_color
326-
) + "\n" +
327-
colorizer.wrap("│ ", SuperDiff.configuration.border_color) +
328-
colorizer.wrap(
329-
"‹-› in expected, not in actual",
330-
SuperDiff.configuration.expected_color
331-
) +
332-
colorizer.wrap(" │", SuperDiff.configuration.border_color) +
333-
"\n" +
334-
colorizer.wrap("│ ", SuperDiff.configuration.border_color) +
335-
colorizer.wrap(
336-
"‹+› in actual, not in expected",
337-
SuperDiff.configuration.actual_color
338-
) +
339-
colorizer.wrap(" │", SuperDiff.configuration.border_color) +
340-
"\n" +
341-
colorizer.wrap("│ ", SuperDiff.configuration.border_color) +
342-
"‹ › in both expected and actual" +
343-
colorizer.wrap(" │", SuperDiff.configuration.border_color) +
344-
"\n" +
345-
colorizer.wrap(
346-
"└─────────────────────────────────┘",
347-
SuperDiff.configuration.border_color
348-
)
312+
if SuperDiff::RSpec.rspec_version < "3.13.0"
313+
class ExpectedsForMultipleDiffs
314+
SuperDiff.insert_singleton_overrides(self) do
315+
# Add a key for different sides
316+
def from(expected)
317+
return expected if self === expected
318+
319+
text = colorizer.wrap("Diff:", SuperDiff.configuration.header_color)
320+
321+
if SuperDiff.configuration.key_enabled?
322+
text +=
323+
"\n\n" +
324+
colorizer.wrap(
325+
"┌ (Key) ──────────────────────────┐",
326+
SuperDiff.configuration.border_color
327+
) + "\n" +
328+
colorizer.wrap("│ ", SuperDiff.configuration.border_color) +
329+
colorizer.wrap(
330+
"‹-› in expected, not in actual",
331+
SuperDiff.configuration.expected_color
332+
) +
333+
colorizer.wrap(" │", SuperDiff.configuration.border_color) +
334+
"\n" +
335+
colorizer.wrap("│ ", SuperDiff.configuration.border_color) +
336+
colorizer.wrap(
337+
"‹+› in actual, not in expected",
338+
SuperDiff.configuration.actual_color
339+
) +
340+
colorizer.wrap(" │", SuperDiff.configuration.border_color) +
341+
"\n" +
342+
colorizer.wrap("│ ", SuperDiff.configuration.border_color) +
343+
"‹ › in both expected and actual" +
344+
colorizer.wrap(" │", SuperDiff.configuration.border_color) +
345+
"\n" +
346+
colorizer.wrap(
347+
"└─────────────────────────────────┘",
348+
SuperDiff.configuration.border_color
349+
)
350+
end
351+
352+
new([[expected, text]])
349353
end
350354

351-
new([[expected, text]])
355+
def colorizer
356+
RSpec::Core::Formatters::ConsoleCodes
357+
end
352358
end
353359

354-
def colorizer
355-
RSpec::Core::Formatters::ConsoleCodes
360+
SuperDiff.insert_overrides(self) do
361+
# Add an extra line break
362+
def message_with_diff(message, differ, actual)
363+
diff = diffs(differ, actual)
364+
365+
diff.empty? ? message : "#{message.rstrip}\n\n#{diff}"
366+
end
367+
368+
private
369+
370+
# Add extra line breaks in between diffs, and colorize the word "Diff"
371+
def diffs(differ, actual)
372+
@expected_list
373+
.map do |(expected, diff_label)|
374+
diff = differ.diff(actual, expected)
375+
next if diff.strip.empty?
376+
diff_label + diff
377+
end
378+
.compact
379+
.join("\n\n")
380+
end
356381
end
357382
end
383+
else
384+
class MultiMatcherDiff
385+
SuperDiff.insert_singleton_overrides(self) do
386+
# Add a key for different sides
387+
def from(expected, actual)
388+
return expected if self === expected
389+
390+
text = colorizer.wrap("Diff:", SuperDiff.configuration.header_color)
391+
392+
if SuperDiff.configuration.key_enabled?
393+
text +=
394+
"\n\n" +
395+
colorizer.wrap(
396+
"┌ (Key) ──────────────────────────┐",
397+
SuperDiff.configuration.border_color
398+
) + "\n" +
399+
colorizer.wrap("│ ", SuperDiff.configuration.border_color) +
400+
colorizer.wrap(
401+
"‹-› in expected, not in actual",
402+
SuperDiff.configuration.expected_color
403+
) +
404+
colorizer.wrap(" │", SuperDiff.configuration.border_color) +
405+
"\n" +
406+
colorizer.wrap("│ ", SuperDiff.configuration.border_color) +
407+
colorizer.wrap(
408+
"‹+› in actual, not in expected",
409+
SuperDiff.configuration.actual_color
410+
) +
411+
colorizer.wrap(" │", SuperDiff.configuration.border_color) +
412+
"\n" +
413+
colorizer.wrap("│ ", SuperDiff.configuration.border_color) +
414+
"‹ › in both expected and actual" +
415+
colorizer.wrap(" │", SuperDiff.configuration.border_color) +
416+
"\n" +
417+
colorizer.wrap(
418+
"└─────────────────────────────────┘",
419+
SuperDiff.configuration.border_color
420+
)
421+
end
358422

359-
SuperDiff.insert_overrides(self) do
360-
# Add an extra line break
361-
def message_with_diff(message, differ, actual)
362-
diff = diffs(differ, actual)
423+
new([[expected, text, actual]])
424+
end
363425

364-
diff.empty? ? message : "#{message.rstrip}\n\n#{diff}"
426+
def colorizer
427+
RSpec::Core::Formatters::ConsoleCodes
428+
end
365429
end
366430

367-
private
431+
SuperDiff.insert_overrides(self) do
432+
# Add an extra line break
433+
def message_with_diff(message, differ)
434+
diff = diffs(differ)
435+
436+
diff.empty? ? message : "#{message.rstrip}\n\n#{diff}"
437+
end
368438

369-
# Add extra line breaks in between diffs, and colorize the word "Diff"
370-
def diffs(differ, actual)
371-
@expected_list
372-
.map do |(expected, diff_label)|
373-
diff = differ.diff(actual, expected)
374-
next if diff.strip.empty?
375-
diff_label + diff
376-
end
377-
.compact
378-
.join("\n\n")
439+
private
440+
441+
# Add extra line breaks in between diffs, and colorize the word "Diff"
442+
def diffs(differ)
443+
@expected_list
444+
.map do |(expected, diff_label, actual)|
445+
diff = differ.diff(actual, expected)
446+
next if diff.strip.empty?
447+
diff_label + diff
448+
end
449+
.compact
450+
.join("\n\n")
451+
end
379452
end
380453
end
381454
end

0 commit comments

Comments
 (0)