Skip to content

Commit 277d0bd

Browse files
committed
Add super_diff extension
1 parent fd68fd9 commit 277d0bd

File tree

5 files changed

+129
-1
lines changed

5 files changed

+129
-1
lines changed

Gemfile

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ eval_gemfile "Gemfile.devtools"
77
gemspec
88

99
group :test do
10-
gem "dry-monads"
10+
gem "dry-monads", github: "dry-rb/dry-monads"
11+
gem "super_diff"
1112
end
1213

1314
group :benchmarks do

lib/dry/struct/extensions.rb

+4
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,7 @@
33
Dry::Struct.register_extension(:pretty_print) do
44
require "dry/struct/extensions/pretty_print"
55
end
6+
7+
Dry::Struct.register_extension(:super_diff) do
8+
require "dry/struct/extensions/super_diff"
9+
end
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# frozen_string_literal: true
2+
3+
require "super_diff"
4+
require "super_diff/rspec"
5+
6+
module Dry
7+
class Struct
8+
def attributes_for_super_diff = attributes
9+
end
10+
end

spec/extensions/super_diff_spec.rb

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# frozen_string_literal: true
2+
3+
require "tempfile"
4+
require "spec_helper"
5+
6+
RSpec.describe Dry::Struct do
7+
let(:output_start_marker) do
8+
/(expected:)|(Expected )/
9+
end
10+
11+
let(:output_end_marker) do
12+
/#{output_start_marker.source}|Finished/
13+
end
14+
15+
def run_spec(code)
16+
temp_spec = Tempfile.new(["failing_spec", ".rb"])
17+
temp_spec.write(<<~RUBY)
18+
require "dry/struct"
19+
20+
RSpec.describe "A failing example" do
21+
before(:all) do
22+
Dry::Struct.load_extensions(:super_diff)
23+
end
24+
25+
#{code}
26+
end
27+
RUBY
28+
temp_spec.close
29+
30+
process_output(`rspec #{temp_spec.path}`, temp_spec.path)
31+
end
32+
33+
def process_output(output, path)
34+
# cut out significant lines
35+
lines = extract_diff(output, path)
36+
prefix = lines.filter_map { |line|
37+
line.match(/^\A(\s+)/).to_s unless line.strip.empty?
38+
}.min
39+
processed_lines = lines.map { |line| line.gsub(prefix, "") }
40+
remove_banner(processed_lines).join.gsub("\n\n\n", "\n\n").gsub(/\n\n\z/, "\n")
41+
end
42+
43+
# remove this part from the output:
44+
#
45+
# Diff:
46+
#
47+
# ┌ (Key) ──────────────────────────┐
48+
# │ ‹-› in expected, not in actual │
49+
# │ ‹+› in actual, not in expected │
50+
# │ ‹ › in both expected and actual │
51+
# └─────────────────────────────────┘
52+
#
53+
def remove_banner(lines)
54+
before_banner = lines.take_while { |line| !line.start_with?("Diff:") }
55+
after_banner = lines.drop_while { |line|
56+
!line.include?("└")
57+
}.drop(1)
58+
before_banner + after_banner
59+
end
60+
61+
def extract_diff(output, path)
62+
output.lines.drop_while { |line|
63+
!line[output_start_marker]
64+
}.take_while.with_index { |line, idx|
65+
idx.zero? || !(line.include?(path) || line[output_start_marker])
66+
}
67+
end
68+
69+
it "produces a nice diff" do
70+
output = run_spec(<<~RUBY)
71+
let(:user_type) do
72+
module Test
73+
class User < Dry::Struct
74+
attribute :name, 'string'
75+
attribute :age, 'integer'
76+
end
77+
end
78+
79+
Test::User
80+
end
81+
82+
let(:user) do
83+
user_type[name: "Jane", age: 21]
84+
end
85+
86+
let(:other_user) do
87+
user_type[name: "Jane", age: 22]
88+
end
89+
90+
example "failing" do
91+
expect(user).to eql(other_user)
92+
end
93+
RUBY
94+
95+
expect(output).to eql(<<~DIFF)
96+
expected: #<Test::User name: "Jane", age: 22>
97+
got: #<Test::User name: "Jane", age: 21>
98+
99+
(compared using eql?)
100+
101+
#<Test::User {
102+
name: "Jane",
103+
- age: 22
104+
+ age: 21
105+
}>
106+
DIFF
107+
end
108+
end

spec/spec_helper.rb

+5
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ module DryStructSpec
2727
end
2828

2929
Dir[Pathname(__dir__).join("shared/*.rb")].each(&method(:require))
30+
31+
Warning.ignore(/rspec-expectations/)
32+
Warning.ignore(/super_diff/)
33+
Warning.process { raise _1 }
34+
3035
require "dry/types/spec/types"
3136

3237
RSpec.configure do |config|

0 commit comments

Comments
 (0)