super_diff 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/lib/super_diff/active_record/object_inspection/inspection_tree_builders/active_record_model.rb +24 -12
  3. data/lib/super_diff/active_record/object_inspection/inspection_tree_builders/active_record_relation.rb +15 -6
  4. data/lib/super_diff/active_support/object_inspection/inspection_tree_builders/hash_with_indifferent_access.rb +23 -8
  5. data/lib/super_diff/active_support/object_inspection/inspection_tree_builders/ordered_options.rb +46 -0
  6. data/lib/super_diff/active_support/object_inspection/inspection_tree_builders.rb +4 -0
  7. data/lib/super_diff/active_support.rb +2 -1
  8. data/lib/super_diff/differs/date_like.rb +15 -0
  9. data/lib/super_diff/differs/defaults.rb +1 -0
  10. data/lib/super_diff/differs.rb +1 -0
  11. data/lib/super_diff/errors.rb +0 -4
  12. data/lib/super_diff/object_inspection/inspection_tree.rb +25 -20
  13. data/lib/super_diff/object_inspection/inspection_tree_builders/array.rb +31 -12
  14. data/lib/super_diff/object_inspection/inspection_tree_builders/custom_object.rb +19 -9
  15. data/lib/super_diff/object_inspection/inspection_tree_builders/date_like.rb +51 -0
  16. data/lib/super_diff/object_inspection/inspection_tree_builders/default_object.rb +46 -21
  17. data/lib/super_diff/object_inspection/inspection_tree_builders/defaults.rb +1 -0
  18. data/lib/super_diff/object_inspection/inspection_tree_builders/hash.rb +39 -14
  19. data/lib/super_diff/object_inspection/inspection_tree_builders/primitive.rb +3 -5
  20. data/lib/super_diff/object_inspection/inspection_tree_builders/time_like.rb +31 -20
  21. data/lib/super_diff/object_inspection/inspection_tree_builders.rb +4 -0
  22. data/lib/super_diff/object_inspection/nodes/as_lines_when_rendering_to_lines.rb +3 -2
  23. data/lib/super_diff/operation_tree_builders/date_like.rb +15 -0
  24. data/lib/super_diff/operation_tree_builders/defaults.rb +1 -1
  25. data/lib/super_diff/operation_tree_builders.rb +1 -0
  26. data/lib/super_diff/rspec/matcher_text_builders/raise_error.rb +3 -7
  27. data/lib/super_diff/rspec/monkey_patches.rb +59 -8
  28. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/collection_containing_exactly.rb +14 -7
  29. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/collection_including.rb +19 -13
  30. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/double.rb +30 -26
  31. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/generic_describable_matcher.rb +19 -0
  32. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/hash_including.rb +19 -14
  33. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/instance_of.rb +9 -10
  34. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/kind_of.rb +9 -10
  35. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/object_having_attributes.rb +14 -7
  36. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders/value_within.rb +10 -11
  37. data/lib/super_diff/rspec/object_inspection/inspection_tree_builders.rb +4 -0
  38. data/lib/super_diff/rspec.rb +10 -9
  39. data/lib/super_diff/version.rb +1 -1
  40. data/lib/super_diff.rb +9 -0
  41. data/spec/examples.txt +543 -493
  42. data/spec/integration/rails/engines_spec.rb +8 -3
  43. data/spec/integration/rspec/contain_exactly_matcher_spec.rb +19 -19
  44. data/spec/integration/rspec/eq_matcher_spec.rb +111 -39
  45. data/spec/integration/rspec/generic_describable_matchers_spec.rb +177 -0
  46. data/spec/integration/rspec/have_attributes_matcher_spec.rb +25 -25
  47. data/spec/integration/rspec/include_matcher_spec.rb +23 -23
  48. data/spec/integration/rspec/magic_metadata_spec.rb +51 -0
  49. data/spec/integration/rspec/match_array_matcher_spec.rb +30 -30
  50. data/spec/integration/rspec/match_matcher_spec.rb +93 -93
  51. data/spec/integration/rspec/raise_error_matcher_spec.rb +813 -69
  52. data/spec/internal/log/test.log +0 -0
  53. data/spec/spec_helper.rb +3 -0
  54. data/spec/support/integration/helpers.rb +15 -10
  55. data/spec/support/integration/matchers.rb +34 -0
  56. data/spec/support/integration/test_programs/base.rb +6 -6
  57. data/spec/support/integration/test_programs/rspec_rails_engine.rb +3 -13
  58. data/spec/support/shared_examples/active_record.rb +33 -33
  59. data/spec/support/shared_examples/active_support.rb +125 -4
  60. data/spec/support/shared_examples/elided_diffs.rb +48 -48
  61. data/spec/support/shared_examples/hash_with_indifferent_access.rb +88 -88
  62. data/spec/support/shared_examples/key.rb +10 -10
  63. data/spec/unit/active_support/object_inspection_spec.rb +170 -0
  64. data/spec/unit/rspec/matchers/raise_error_spec.rb +43 -11
  65. data/spec/unit/rspec/object_inspection/rspec_matcher_spec.rb +91 -0
  66. data/spec/unit/rspec/object_inspection_spec.rb +2 -2
  67. data/spec/unit/super_diff_spec.rb +64 -0
  68. metadata +17 -4
  69. data/lib/super_diff/errors/no_diff_formatter_available_error.rb +0 -21
  70. data/lib/super_diff/errors/no_operational_sequencer_available_error.rb +0 -22
File without changes
data/spec/spec_helper.rb CHANGED
@@ -65,6 +65,9 @@ RSpec.configure do |config|
65
65
  config.default_formatter = "documentation" if !%w[true 1].include?(ENV["CI"])
66
66
 
67
67
  config.filter_run_excluding active_record: true unless active_record_available
68
+ unless defined?(ActiveSupport)
69
+ config.filter_run_excluding active_support: true
70
+ end
68
71
 
69
72
  config.order = :random
70
73
  Kernel.srand config.seed
@@ -9,13 +9,13 @@ module SuperDiff
9
9
  def make_plain_test_program(
10
10
  test,
11
11
  color_enabled:,
12
- configuration: {},
12
+ super_diff_configuration: {},
13
13
  preserve_as_whole_file: false
14
14
  )
15
15
  TestPrograms::Plain.new(
16
16
  test,
17
17
  color_enabled: color_enabled,
18
- configuration: configuration,
18
+ super_diff_configuration: super_diff_configuration,
19
19
  preserve_as_whole_file: preserve_as_whole_file
20
20
  )
21
21
  end
@@ -32,15 +32,13 @@ module SuperDiff
32
32
  TestPrograms::RSpecRails.new(test, color_enabled: color_enabled)
33
33
  end
34
34
 
35
- def make_rspec_rails_engine_program(
35
+ def make_rspec_rails_engine_with_action_controller_program(
36
36
  test,
37
- color_enabled:,
38
- combustion_initialize:
37
+ color_enabled:
39
38
  )
40
- TestPrograms::RspecRailsEngine.new(
39
+ TestPrograms::RspecRailsEngineWithActionController.new(
41
40
  test,
42
- color_enabled: color_enabled,
43
- combustion_initialize: combustion_initialize
41
+ color_enabled: color_enabled
44
42
  )
45
43
  end
46
44
 
@@ -48,15 +46,17 @@ module SuperDiff
48
46
  color_enabled:,
49
47
  snippet:,
50
48
  expectation:,
49
+ test_name: "test passes",
51
50
  key_enabled: true,
52
51
  newline_before_expectation: false,
53
52
  indentation: 7,
54
- diff: nil
53
+ diff: nil,
54
+ extra_failure_lines: nil
55
55
  )
56
56
  colored(color_enabled: color_enabled) do
57
57
  line "Failures:\n"
58
58
 
59
- line "1) test passes", indent_by: 2
59
+ line "1) #{test_name}", indent_by: 2
60
60
 
61
61
  line indent_by: 5 do
62
62
  bold "Failure/Error: "
@@ -106,6 +106,11 @@ module SuperDiff
106
106
  newline
107
107
  end
108
108
  end
109
+
110
+ if extra_failure_lines
111
+ newline
112
+ evaluate_block(&extra_failure_lines)
113
+ end
109
114
  end
110
115
  end
111
116
 
@@ -32,6 +32,40 @@ module SuperDiff
32
32
  PassWithSinglelineFailureMessageMatcher.new
33
33
  end
34
34
 
35
+ RSpec::Matchers.define :failing_custom_matcher_from_dsl do |value|
36
+ match { false }
37
+
38
+ description do
39
+ "custom matcher defined via the DSL with value #{value.inspect}"
40
+ end
41
+ end
42
+
43
+ def failing_custom_matcher_from_scratch(value)
44
+ FailingCustomMatcherFromScratch.new(value)
45
+ end
46
+
47
+ class FailingCustomMatcherFromScratch
48
+ def initialize(value)
49
+ @value = value
50
+ end
51
+
52
+ def matches?(_)
53
+ false
54
+ end
55
+
56
+ def description
57
+ "custom matcher defined from scratch with value #{value.inspect}"
58
+ end
59
+
60
+ def failure_message
61
+ "Expected custom matcher not to fail, but did"
62
+ end
63
+
64
+ private
65
+
66
+ attr_reader :value
67
+ end
68
+
35
69
  class FailWithIndentedMultilineFailureMessageMatcher
36
70
  def matches?(_)
37
71
  false
@@ -13,12 +13,12 @@ module SuperDiff
13
13
  def initialize(
14
14
  code,
15
15
  color_enabled:,
16
- configuration: {},
16
+ super_diff_configuration: {},
17
17
  preserve_as_whole_file: false
18
18
  )
19
19
  @code = code.strip
20
20
  @color_enabled = color_enabled
21
- @configuration = configuration
21
+ @super_diff_configuration = super_diff_configuration
22
22
  @preserve_as_whole_file = preserve_as_whole_file
23
23
  end
24
24
 
@@ -38,7 +38,7 @@ module SuperDiff
38
38
 
39
39
  private
40
40
 
41
- attr_reader :code, :configuration
41
+ attr_reader :code, :super_diff_configuration
42
42
 
43
43
  def color_enabled?
44
44
  @color_enabled
@@ -74,8 +74,8 @@ module SuperDiff
74
74
  color_option,
75
75
  "--no-pry",
76
76
  tempfile.to_s,
77
- "--configuration",
78
- JSON.generate(configuration)
77
+ "--super-diff-configuration",
78
+ JSON.generate(super_diff_configuration)
79
79
  ]
80
80
  else
81
81
  ["rspec", "--options", "/tmp/dummy-rspec-config", tempfile.to_s]
@@ -110,7 +110,7 @@ module SuperDiff
110
110
  test_plan = TestPlan.new(
111
111
  using_outside_of_zeus: true,
112
112
  color_enabled: #{color_enabled?.inspect},
113
- configuration: #{configuration.inspect}
113
+ super_diff_configuration: #{super_diff_configuration.inspect}
114
114
  )
115
115
  #{test_plan_prelude}
116
116
  test_plan.#{test_plan_command}
@@ -1,29 +1,19 @@
1
1
  module SuperDiff
2
2
  module IntegrationTests
3
3
  module TestPrograms
4
- class RspecRailsEngine < Base
5
- def initialize(*args, combustion_initialize:, **options)
6
- super(*args, **options)
7
- @combustion_initialize = combustion_initialize
8
- end
9
-
4
+ class RspecRailsEngineWithActionController < Base
10
5
  protected
11
6
 
12
7
  def test_plan_prelude
13
8
  <<~PRELUDE.strip
14
- test_plan.boot_rails_engine(
15
- combustion_initialize: #{combustion_initialize.inspect}
16
- )
9
+ test_plan.boot
10
+ test_plan.boot_rails_engine_with_action_controller
17
11
  PRELUDE
18
12
  end
19
13
 
20
14
  def test_plan_command
21
15
  "run_rspec_rails_test"
22
16
  end
23
-
24
- private
25
-
26
- attr_reader :combustion_initialize
27
17
  end
28
18
  end
29
19
  end
@@ -4,18 +4,18 @@ shared_examples_for "integration with ActiveRecord" do
4
4
  it "produces the correct output" do
5
5
  as_both_colored_and_uncolored do |color_enabled|
6
6
  snippet = <<~TEST.strip
7
- expected = SuperDiff::Test::Models::ActiveRecord::ShippingAddress.new(
8
- line_1: "123 Main St.",
9
- city: "Hill Valley",
10
- state: "CA",
11
- zip: "90382",
12
- )
13
7
  actual = SuperDiff::Test::Models::ActiveRecord::ShippingAddress.new(
14
8
  line_1: "456 Ponderosa Ct.",
15
9
  city: "Oakland",
16
10
  state: "CA",
17
11
  zip: "91234",
18
12
  )
13
+ expected = SuperDiff::Test::Models::ActiveRecord::ShippingAddress.new(
14
+ line_1: "123 Main St.",
15
+ city: "Hill Valley",
16
+ state: "CA",
17
+ zip: "90382",
18
+ )
19
19
  expect(actual).to eq(expected)
20
20
  TEST
21
21
  program = make_program(snippet, color_enabled: color_enabled)
@@ -63,16 +63,16 @@ shared_examples_for "integration with ActiveRecord" do
63
63
  it "produces the correct output" do
64
64
  as_both_colored_and_uncolored do |color_enabled|
65
65
  snippet = <<~TEST.strip
66
+ actual = SuperDiff::Test::Models::ActiveRecord::Person.new(
67
+ name: "Elliot",
68
+ age: 31,
69
+ )
66
70
  expected = SuperDiff::Test::Models::ActiveRecord::ShippingAddress.new(
67
71
  line_1: "123 Main St.",
68
72
  city: "Hill Valley",
69
73
  state: "CA",
70
74
  zip: "90382",
71
75
  )
72
- actual = SuperDiff::Test::Models::ActiveRecord::Person.new(
73
- name: "Elliot",
74
- age: 31,
75
- )
76
76
  expect(actual).to eq(expected)
77
77
  TEST
78
78
  program = make_program(snippet, color_enabled: color_enabled)
@@ -107,13 +107,13 @@ shared_examples_for "integration with ActiveRecord" do
107
107
  it "produces the correct output" do
108
108
  as_both_colored_and_uncolored do |color_enabled|
109
109
  snippet = <<~TEST.strip
110
+ actual = nil
110
111
  expected = SuperDiff::Test::Models::ActiveRecord::ShippingAddress.new(
111
112
  line_1: "123 Main St.",
112
113
  city: "Hill Valley",
113
114
  state: "CA",
114
115
  zip: "90382"
115
116
  )
116
- actual = nil
117
117
  expect(actual).to eq(expected)
118
118
  TEST
119
119
  program = make_program(snippet, color_enabled: color_enabled)
@@ -148,22 +148,22 @@ shared_examples_for "integration with ActiveRecord" do
148
148
  it "produces the correct output" do
149
149
  as_both_colored_and_uncolored do |color_enabled|
150
150
  snippet = <<~TEST.strip
151
- expected = {
151
+ actual = {
152
152
  name: "Marty McFly",
153
153
  shipping_address: SuperDiff::Test::Models::ActiveRecord::ShippingAddress.new(
154
- line_1: "123 Main St.",
155
- city: "Hill Valley",
154
+ line_1: "456 Ponderosa Ct.",
155
+ city: "Oakland",
156
156
  state: "CA",
157
- zip: "90382",
157
+ zip: "91234",
158
158
  )
159
159
  }
160
- actual = {
160
+ expected = {
161
161
  name: "Marty McFly",
162
162
  shipping_address: SuperDiff::Test::Models::ActiveRecord::ShippingAddress.new(
163
- line_1: "456 Ponderosa Ct.",
164
- city: "Oakland",
163
+ line_1: "123 Main St.",
164
+ city: "Hill Valley",
165
165
  state: "CA",
166
- zip: "91234",
166
+ zip: "90382",
167
167
  )
168
168
  }
169
169
  expect(actual).to eq(expected)
@@ -216,6 +216,13 @@ shared_examples_for "integration with ActiveRecord" do
216
216
  it "produces the correct output" do
217
217
  as_both_colored_and_uncolored do |color_enabled|
218
218
  snippet = <<~TEST.strip
219
+ actual = {
220
+ name: "Marty McFly",
221
+ shipping_address: SuperDiff::Test::Models::ActiveRecord::Person.new(
222
+ name: "Elliot",
223
+ age: 31,
224
+ )
225
+ }
219
226
  expected = {
220
227
  name: "Marty McFly",
221
228
  shipping_address: SuperDiff::Test::Models::ActiveRecord::ShippingAddress.new(
@@ -225,13 +232,6 @@ shared_examples_for "integration with ActiveRecord" do
225
232
  zip: "90382",
226
233
  )
227
234
  }
228
- actual = {
229
- name: "Marty McFly",
230
- shipping_address: SuperDiff::Test::Models::ActiveRecord::Person.new(
231
- name: "Elliot",
232
- age: 31,
233
- )
234
- }
235
235
  expect(actual).to eq(expected)
236
236
  TEST
237
237
  program = make_program(snippet, color_enabled: color_enabled)
@@ -299,8 +299,8 @@ shared_examples_for "integration with ActiveRecord" do
299
299
  zip: "91234",
300
300
  )
301
301
  ]
302
- expected = [shipping_addresses.first]
303
302
  actual = SuperDiff::Test::Models::ActiveRecord::ShippingAddress.all
303
+ expected = [shipping_addresses.first]
304
304
  expect(actual).to eq(expected)
305
305
  TEST
306
306
  program = make_program(snippet, color_enabled: color_enabled)
@@ -362,6 +362,12 @@ shared_examples_for "integration with ActiveRecord" do
362
362
  age: 20
363
363
  )
364
364
 
365
+ actual = [
366
+ SuperDiff::Test::Models::ActiveRecord::Query.new(
367
+ results: SuperDiff::Test::Models::ActiveRecord::Person.all
368
+ )
369
+ ]
370
+
365
371
  expected = [
366
372
  an_object_having_attributes(
367
373
  results: [
@@ -370,12 +376,6 @@ shared_examples_for "integration with ActiveRecord" do
370
376
  )
371
377
  ]
372
378
 
373
- actual = [
374
- SuperDiff::Test::Models::ActiveRecord::Query.new(
375
- results: SuperDiff::Test::Models::ActiveRecord::Person.all
376
- )
377
- ]
378
-
379
379
  expect(actual).to match(expected)
380
380
  TEST
381
381
 
@@ -4,9 +4,9 @@ shared_examples_for "integration with ActiveSupport" do
4
4
  it "produces the correct failure message when used in the positive" do
5
5
  as_both_colored_and_uncolored do |color_enabled|
6
6
  snippet = <<~RUBY
7
- expected = Time.utc(2011, 12, 13, 14, 15, 16)
8
- actual = Time.utc(2011, 12, 13, 15, 15, 16).in_time_zone("Europe/Stockholm")
9
- expect(expected).to eq(actual)
7
+ actual = Time.utc(2011, 12, 13, 14, 15, 16)
8
+ expected = Time.utc(2011, 12, 13, 15, 15, 16).in_time_zone("Europe/Stockholm")
9
+ expect(actual).to eq(expected)
10
10
  RUBY
11
11
  program =
12
12
  make_rspec_rails_test_program(snippet, color_enabled: color_enabled)
@@ -14,7 +14,7 @@ shared_examples_for "integration with ActiveSupport" do
14
14
  expected_output =
15
15
  build_expected_output(
16
16
  color_enabled: color_enabled,
17
- snippet: "expect(expected).to eq(actual)",
17
+ snippet: "expect(actual).to eq(expected)",
18
18
  expectation:
19
19
  proc do
20
20
  line do
@@ -64,4 +64,125 @@ shared_examples_for "integration with ActiveSupport" do
64
64
  end
65
65
  end
66
66
  end
67
+
68
+ context "when comparing OrderedOptions and Hash instances",
69
+ active_record: true do
70
+ it "produces the correct failure message when used in the positive" do
71
+ as_both_colored_and_uncolored do |color_enabled|
72
+ snippet = <<~RUBY
73
+ actual = {beep: :bip}
74
+ expected = ::ActiveSupport::OrderedOptions[beep: :boop]
75
+ expect(actual).to eq(expected)
76
+ RUBY
77
+ program =
78
+ make_rspec_rails_test_program(snippet, color_enabled: color_enabled)
79
+
80
+ expected_output =
81
+ build_expected_output(
82
+ color_enabled: color_enabled,
83
+ snippet: "expect(actual).to eq(expected)",
84
+ expectation:
85
+ proc do
86
+ line do
87
+ plain "Expected "
88
+ actual "{ beep: :bip }"
89
+ plain " to eq "
90
+ expected "#<OrderedOptions { beep: :boop }>"
91
+ plain "."
92
+ end
93
+ end,
94
+ diff:
95
+ proc do
96
+ plain_line " {"
97
+ expected_line "- beep: :boop"
98
+ actual_line "+ beep: :bip"
99
+ plain_line " }"
100
+ end
101
+ )
102
+
103
+ expect(program).to produce_output_when_run(expected_output).in_color(
104
+ color_enabled
105
+ )
106
+ end
107
+ end
108
+ end
109
+
110
+ context "when comparing Date instance and date-like DateTime instance for same day",
111
+ active_record: true do
112
+ it "produces the correct failure message when used in the positive" do
113
+ as_both_colored_and_uncolored do |color_enabled|
114
+ snippet = <<~RUBY
115
+ actual = Date.new(2023, 10, 14)
116
+ expected = DateTime.new(2023, 10, 14, 18, 22, 26)
117
+ expect(actual).to eq(expected)
118
+ RUBY
119
+ program =
120
+ make_rspec_rails_test_program(snippet, color_enabled: color_enabled)
121
+
122
+ expected_output =
123
+ build_expected_output(
124
+ color_enabled: color_enabled,
125
+ snippet: "expect(actual).to eq(expected)",
126
+ expectation:
127
+ proc do
128
+ line do
129
+ plain "Expected "
130
+ actual "#<Date 2023-10-14>"
131
+ plain " to eq "
132
+ expected "#<DateTime 2023-10-14 18:22:26 +00:00 (+00:00)>"
133
+ plain "."
134
+ end
135
+ end
136
+ )
137
+
138
+ expect(program).to produce_output_when_run(expected_output).in_color(
139
+ color_enabled
140
+ )
141
+ end
142
+ end
143
+ end
144
+
145
+ context "when comparing Date instance and date-like DateTime instance for another day",
146
+ active_record: true do
147
+ it "produces the diff for date like objects comparison" do
148
+ as_both_colored_and_uncolored do |color_enabled|
149
+ snippet = <<~RUBY
150
+ actual = Date.new(2023, 10, 14)
151
+ expected = DateTime.new(2023, 10, 31, 18, 22, 26)
152
+ expect(actual).to eq(expected)
153
+ RUBY
154
+ program =
155
+ make_rspec_rails_test_program(snippet, color_enabled: color_enabled)
156
+
157
+ expected_output =
158
+ build_expected_output(
159
+ color_enabled: color_enabled,
160
+ snippet: "expect(actual).to eq(expected)",
161
+ expectation:
162
+ proc do
163
+ line do
164
+ plain "Expected "
165
+ actual "#<Date 2023-10-14>"
166
+ plain " to eq "
167
+ expected "#<DateTime 2023-10-31 18:22:26 +00:00 (+00:00)>"
168
+ plain "."
169
+ end
170
+ end,
171
+ diff:
172
+ proc do
173
+ plain_line " #<Date {"
174
+ plain_line " year: 2023,"
175
+ plain_line " month: 10,"
176
+ expected_line "- day: 31"
177
+ actual_line "+ day: 14"
178
+ plain_line " }>"
179
+ end
180
+ )
181
+
182
+ expect(program).to produce_output_when_run(expected_output).in_color(
183
+ color_enabled
184
+ )
185
+ end
186
+ end
187
+ end
67
188
  end