Skip to content

Commit 05d46b6

Browse files
authored
Merge pull request #197 from dry-rb/super_diff-extension
Add super_diff extension
2 parents fd68fd9 + 5d7e013 commit 05d46b6

File tree

5 files changed

+130
-1
lines changed

5 files changed

+130
-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

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
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+
uncolored = output.gsub(/\e\[([;\d]+)?m/, "")
35+
# cut out significant lines
36+
lines = extract_diff(uncolored, path)
37+
prefix = lines.filter_map { |line|
38+
line.match(/^\A(\s+)/).to_s unless line.strip.empty?
39+
}.min
40+
processed_lines = lines.map { |line| line.gsub(prefix, "") }
41+
remove_banner(processed_lines).join.gsub("\n\n\n", "\n\n").gsub(/\n\n\z/, "\n")
42+
end
43+
44+
# remove this part from the output:
45+
#
46+
# Diff:
47+
#
48+
# ┌ (Key) ──────────────────────────┐
49+
# │ ‹-› in expected, not in actual │
50+
# │ ‹+› in actual, not in expected │
51+
# │ ‹ › in both expected and actual │
52+
# └─────────────────────────────────┘
53+
#
54+
def remove_banner(lines)
55+
before_banner = lines.take_while { |line| !line.start_with?("Diff:") }
56+
after_banner = lines.drop_while { |line|
57+
!line.include?("└")
58+
}.drop(1)
59+
before_banner + after_banner
60+
end
61+
62+
def extract_diff(output, path)
63+
output.lines.drop_while { |line|
64+
!line[output_start_marker]
65+
}.take_while.with_index { |line, idx|
66+
idx.zero? || !(line.include?(path) || line[output_start_marker])
67+
}
68+
end
69+
70+
it "produces a nice diff" do
71+
output = run_spec(<<~RUBY)
72+
let(:user_type) do
73+
module Test
74+
class User < Dry::Struct
75+
attribute :name, 'string'
76+
attribute :age, 'integer'
77+
end
78+
end
79+
80+
Test::User
81+
end
82+
83+
let(:user) do
84+
user_type[name: "Jane", age: 21]
85+
end
86+
87+
let(:other_user) do
88+
user_type[name: "Jane", age: 22]
89+
end
90+
91+
example "failing" do
92+
expect(user).to eql(other_user)
93+
end
94+
RUBY
95+
96+
expect(output).to eql(<<~DIFF)
97+
expected: #<Test::User name: "Jane", age: 22>
98+
got: #<Test::User name: "Jane", age: 21>
99+
100+
(compared using eql?)
101+
102+
#<Test::User {
103+
name: "Jane",
104+
- age: 22
105+
+ age: 21
106+
}>
107+
DIFF
108+
end
109+
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)