super_diff 0.4.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +104 -73
  3. data/lib/super_diff.rb +20 -11
  4. data/lib/super_diff/active_record.rb +20 -24
  5. data/lib/super_diff/active_record/diff_formatters/active_record_relation.rb +3 -3
  6. data/lib/super_diff/active_record/differs/active_record_relation.rb +3 -5
  7. data/lib/super_diff/active_record/object_inspection/inspectors/active_record_model.rb +32 -22
  8. data/lib/super_diff/active_record/object_inspection/inspectors/active_record_relation.rb +17 -7
  9. data/lib/super_diff/active_record/operation_tree_builders.rb +14 -0
  10. data/lib/super_diff/active_record/{operational_sequencers → operation_tree_builders}/active_record_model.rb +2 -2
  11. data/lib/super_diff/active_record/{operational_sequencers → operation_tree_builders}/active_record_relation.rb +4 -4
  12. data/lib/super_diff/active_record/{operation_sequences.rb → operation_trees.rb} +2 -2
  13. data/lib/super_diff/active_record/{operation_sequences → operation_trees}/active_record_relation.rb +2 -2
  14. data/lib/super_diff/active_support.rb +16 -19
  15. data/lib/super_diff/active_support/diff_formatters/hash_with_indifferent_access.rb +3 -3
  16. data/lib/super_diff/active_support/differs/hash_with_indifferent_access.rb +3 -5
  17. data/lib/super_diff/active_support/object_inspection/inspectors/hash_with_indifferent_access.rb +17 -7
  18. data/lib/super_diff/active_support/operation_tree_builders.rb +10 -0
  19. data/lib/super_diff/active_support/{operational_sequencers → operation_tree_builders}/hash_with_indifferent_access.rb +2 -2
  20. data/lib/super_diff/active_support/{operation_sequences.rb → operation_trees.rb} +2 -2
  21. data/lib/super_diff/active_support/{operation_sequences → operation_trees}/hash_with_indifferent_access.rb +2 -2
  22. data/lib/super_diff/configuration.rb +60 -0
  23. data/lib/super_diff/diff_formatters.rb +3 -3
  24. data/lib/super_diff/diff_formatters/array.rb +3 -3
  25. data/lib/super_diff/diff_formatters/base.rb +3 -2
  26. data/lib/super_diff/diff_formatters/collection.rb +2 -2
  27. data/lib/super_diff/diff_formatters/custom_object.rb +3 -3
  28. data/lib/super_diff/diff_formatters/default_object.rb +6 -8
  29. data/lib/super_diff/diff_formatters/defaults.rb +10 -0
  30. data/lib/super_diff/diff_formatters/hash.rb +3 -3
  31. data/lib/super_diff/diff_formatters/main.rb +41 -0
  32. data/lib/super_diff/diff_formatters/multiline_string.rb +3 -3
  33. data/lib/super_diff/differs.rb +4 -11
  34. data/lib/super_diff/differs/array.rb +2 -11
  35. data/lib/super_diff/differs/base.rb +20 -3
  36. data/lib/super_diff/differs/custom_object.rb +2 -11
  37. data/lib/super_diff/differs/default_object.rb +2 -8
  38. data/lib/super_diff/differs/defaults.rb +12 -0
  39. data/lib/super_diff/differs/hash.rb +2 -11
  40. data/lib/super_diff/differs/main.rb +48 -0
  41. data/lib/super_diff/differs/multiline_string.rb +2 -14
  42. data/lib/super_diff/differs/time_like.rb +15 -0
  43. data/lib/super_diff/equality_matchers.rb +3 -9
  44. data/lib/super_diff/equality_matchers/array.rb +1 -7
  45. data/lib/super_diff/equality_matchers/base.rb +1 -1
  46. data/lib/super_diff/equality_matchers/default.rb +1 -7
  47. data/lib/super_diff/equality_matchers/defaults.rb +12 -0
  48. data/lib/super_diff/equality_matchers/hash.rb +1 -7
  49. data/lib/super_diff/equality_matchers/main.rb +21 -0
  50. data/lib/super_diff/equality_matchers/multiline_string.rb +1 -7
  51. data/lib/super_diff/errors.rb +16 -0
  52. data/lib/super_diff/errors/no_diff_formatter_available_error.rb +21 -0
  53. data/lib/super_diff/errors/no_differ_available_error.rb +24 -0
  54. data/lib/super_diff/errors/no_operational_sequencer_available_error.rb +22 -0
  55. data/lib/super_diff/implementation_checks.rb +19 -0
  56. data/lib/super_diff/object_inspection.rb +1 -10
  57. data/lib/super_diff/object_inspection/inspection_tree.rb +6 -2
  58. data/lib/super_diff/object_inspection/inspectors.rb +5 -1
  59. data/lib/super_diff/object_inspection/inspectors/array.rb +20 -10
  60. data/lib/super_diff/object_inspection/inspectors/base.rb +36 -0
  61. data/lib/super_diff/object_inspection/inspectors/custom_object.rb +24 -14
  62. data/lib/super_diff/object_inspection/inspectors/default_object.rb +44 -30
  63. data/lib/super_diff/object_inspection/inspectors/defaults.rb +15 -0
  64. data/lib/super_diff/object_inspection/inspectors/hash.rb +20 -10
  65. data/lib/super_diff/object_inspection/inspectors/main.rb +35 -0
  66. data/lib/super_diff/object_inspection/inspectors/primitive.rb +20 -5
  67. data/lib/super_diff/object_inspection/inspectors/string.rb +15 -5
  68. data/lib/super_diff/object_inspection/inspectors/time_like.rb +23 -0
  69. data/lib/super_diff/object_inspection/nodes/inspection.rb +9 -2
  70. data/lib/super_diff/operation_tree_builders.rb +18 -0
  71. data/lib/super_diff/{operational_sequencers → operation_tree_builders}/array.rb +38 -59
  72. data/lib/super_diff/operation_tree_builders/base.rb +98 -0
  73. data/lib/super_diff/{operational_sequencers → operation_tree_builders}/custom_object.rb +3 -3
  74. data/lib/super_diff/{operational_sequencers → operation_tree_builders}/default_object.rb +8 -3
  75. data/lib/super_diff/operation_tree_builders/defaults.rb +5 -0
  76. data/lib/super_diff/operation_tree_builders/hash.rb +226 -0
  77. data/lib/super_diff/operation_tree_builders/main.rb +42 -0
  78. data/lib/super_diff/{operational_sequencers → operation_tree_builders}/multiline_string.rb +3 -3
  79. data/lib/super_diff/operation_tree_builders/time_like.rb +34 -0
  80. data/lib/super_diff/operation_trees.rb +13 -0
  81. data/lib/super_diff/{operation_sequences → operation_trees}/array.rb +5 -1
  82. data/lib/super_diff/{operation_sequences → operation_trees}/base.rb +9 -1
  83. data/lib/super_diff/{operation_sequences → operation_trees}/custom_object.rb +5 -1
  84. data/lib/super_diff/{operation_sequences → operation_trees}/default_object.rb +10 -8
  85. data/lib/super_diff/operation_trees/defaults.rb +5 -0
  86. data/lib/super_diff/{operation_sequences → operation_trees}/hash.rb +5 -1
  87. data/lib/super_diff/operation_trees/main.rb +35 -0
  88. data/lib/super_diff/operation_trees/multiline_string.rb +18 -0
  89. data/lib/super_diff/operations/unary_operation.rb +3 -0
  90. data/lib/super_diff/recursion_guard.rb +2 -0
  91. data/lib/super_diff/rspec.rb +45 -13
  92. data/lib/super_diff/rspec/augmented_matcher.rb +1 -1
  93. data/lib/super_diff/rspec/differ.rb +2 -17
  94. data/lib/super_diff/rspec/differs/collection_containing_exactly.rb +2 -7
  95. data/lib/super_diff/rspec/differs/collection_including.rb +2 -7
  96. data/lib/super_diff/rspec/differs/hash_including.rb +2 -7
  97. data/lib/super_diff/rspec/differs/object_having_attributes.rb +2 -7
  98. data/lib/super_diff/rspec/matcher_text_builders/match.rb +1 -1
  99. data/lib/super_diff/rspec/matcher_text_builders/respond_to.rb +1 -1
  100. data/lib/super_diff/rspec/matcher_text_template.rb +1 -1
  101. data/lib/super_diff/rspec/monkey_patches.rb +9 -5
  102. data/lib/super_diff/rspec/object_inspection.rb +0 -1
  103. data/lib/super_diff/rspec/object_inspection/inspectors.rb +16 -0
  104. data/lib/super_diff/rspec/object_inspection/inspectors/collection_containing_exactly.rb +17 -8
  105. data/lib/super_diff/rspec/object_inspection/inspectors/collection_including.rb +15 -9
  106. data/lib/super_diff/rspec/object_inspection/inspectors/hash_including.rb +20 -10
  107. data/lib/super_diff/rspec/object_inspection/inspectors/instance_of.rb +23 -0
  108. data/lib/super_diff/rspec/object_inspection/inspectors/kind_of.rb +23 -0
  109. data/lib/super_diff/rspec/object_inspection/inspectors/object_having_attributes.rb +20 -11
  110. data/lib/super_diff/rspec/object_inspection/inspectors/primitive.rb +13 -0
  111. data/lib/super_diff/rspec/object_inspection/inspectors/value_within.rb +29 -0
  112. data/lib/super_diff/rspec/operation_tree_builders.rb +22 -0
  113. data/lib/super_diff/rspec/{operational_sequencers → operation_tree_builders}/collection_containing_exactly.rb +5 -5
  114. data/lib/super_diff/rspec/{operational_sequencers → operation_tree_builders}/collection_including.rb +2 -2
  115. data/lib/super_diff/rspec/{operational_sequencers → operation_tree_builders}/hash_including.rb +3 -11
  116. data/lib/super_diff/rspec/{operational_sequencers → operation_tree_builders}/object_having_attributes.rb +4 -8
  117. data/lib/super_diff/version.rb +1 -1
  118. data/spec/examples.txt +5 -0
  119. data/spec/integration/rspec/have_attributes_matcher_spec.rb +354 -227
  120. data/spec/integration/rspec/include_matcher_spec.rb +2 -2
  121. data/spec/integration/rspec/unhandled_errors_spec.rb +81 -4
  122. data/spec/support/command_runner.rb +3 -0
  123. data/spec/support/integration/helpers.rb +12 -96
  124. data/spec/support/integration/matchers/produce_output_when_run_matcher.rb +14 -29
  125. data/spec/support/integration/test_programs/base.rb +120 -0
  126. data/spec/support/integration/test_programs/plain.rb +13 -0
  127. data/spec/support/integration/test_programs/rspec_active_record.rb +17 -0
  128. data/spec/support/integration/test_programs/rspec_rails.rb +17 -0
  129. data/spec/support/models/active_record/person.rb +4 -11
  130. data/spec/support/models/active_record/shipping_address.rb +10 -14
  131. data/spec/support/object_id.rb +6 -5
  132. data/spec/support/shared_examples/hash_with_indifferent_access.rb +724 -208
  133. data/spec/unit/{equality_matcher_spec.rb → equality_matchers/main_spec.rb} +157 -1
  134. data/spec/unit/object_inspection_spec.rb +77 -1
  135. data/spec/unit/rspec/matchers/raise_error_spec.rb +16 -0
  136. data/super_diff.gemspec +4 -5
  137. metadata +77 -56
  138. data/lib/super_diff/active_record/object_inspection/map_extension.rb +0 -18
  139. data/lib/super_diff/active_record/operational_sequencers.rb +0 -14
  140. data/lib/super_diff/active_support/object_inspection/map_extension.rb +0 -15
  141. data/lib/super_diff/active_support/operational_sequencers.rb +0 -10
  142. data/lib/super_diff/diff_formatter.rb +0 -32
  143. data/lib/super_diff/differ.rb +0 -51
  144. data/lib/super_diff/differs/time.rb +0 -24
  145. data/lib/super_diff/equality_matcher.rb +0 -32
  146. data/lib/super_diff/no_differ_available_error.rb +0 -22
  147. data/lib/super_diff/no_operational_sequencer_available_error.rb +0 -20
  148. data/lib/super_diff/object_inspection/inspector.rb +0 -27
  149. data/lib/super_diff/object_inspection/inspectors/time.rb +0 -13
  150. data/lib/super_diff/object_inspection/map.rb +0 -30
  151. data/lib/super_diff/operation_sequences.rb +0 -9
  152. data/lib/super_diff/operational_sequencer.rb +0 -48
  153. data/lib/super_diff/operational_sequencers.rb +0 -17
  154. data/lib/super_diff/operational_sequencers/base.rb +0 -89
  155. data/lib/super_diff/operational_sequencers/hash.rb +0 -85
  156. data/lib/super_diff/operational_sequencers/time_like.rb +0 -30
  157. data/lib/super_diff/rspec/configuration.rb +0 -31
  158. data/lib/super_diff/rspec/object_inspection/map_extension.rb +0 -23
  159. data/lib/super_diff/rspec/operational_sequencers.rb +0 -22
@@ -2,18 +2,28 @@ module SuperDiff
2
2
  module RSpec
3
3
  module ObjectInspection
4
4
  module Inspectors
5
- HashIncluding = SuperDiff::ObjectInspection::InspectionTree.new do
6
- add_text "#<a hash including ("
7
-
8
- nested do |aliased_matcher|
9
- insert_hash_inspection_of(
10
- aliased_matcher.expecteds.first,
11
- initial_break: nil,
12
- )
5
+ class HashIncluding < SuperDiff::ObjectInspection::Inspectors::Base
6
+ def self.applies_to?(value)
7
+ SuperDiff::RSpec.a_hash_including_something?(value)
13
8
  end
14
9
 
15
- add_break
16
- add_text ")>"
10
+ protected
11
+
12
+ def inspection_tree
13
+ SuperDiff::ObjectInspection::InspectionTree.new do
14
+ add_text "#<a hash including ("
15
+
16
+ nested do |aliased_matcher|
17
+ insert_hash_inspection_of(
18
+ aliased_matcher.expecteds.first,
19
+ initial_break: nil,
20
+ )
21
+ end
22
+
23
+ add_break
24
+ add_text ")>"
25
+ end
26
+ end
17
27
  end
18
28
  end
19
29
  end
@@ -0,0 +1,23 @@
1
+ module SuperDiff
2
+ module RSpec
3
+ module ObjectInspection
4
+ module Inspectors
5
+ class InstanceOf < SuperDiff::ObjectInspection::Inspectors::Base
6
+ def self.applies_to?(value)
7
+ SuperDiff::RSpec.an_instance_of_something?(value)
8
+ end
9
+
10
+ protected
11
+
12
+ def inspection_tree
13
+ SuperDiff::ObjectInspection::InspectionTree.new do
14
+ add_text do |aliased_matcher|
15
+ "#<an instance of #{aliased_matcher.expected}>"
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module SuperDiff
2
+ module RSpec
3
+ module ObjectInspection
4
+ module Inspectors
5
+ class KindOf < SuperDiff::ObjectInspection::Inspectors::Base
6
+ def self.applies_to?(value)
7
+ SuperDiff::RSpec.a_kind_of_something?(value)
8
+ end
9
+
10
+ protected
11
+
12
+ def inspection_tree
13
+ SuperDiff::ObjectInspection::InspectionTree.new do
14
+ add_text do |aliased_matcher|
15
+ "#<a kind of #{aliased_matcher.expected}>"
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -2,20 +2,29 @@ module SuperDiff
2
2
  module RSpec
3
3
  module ObjectInspection
4
4
  module Inspectors
5
- ObjectHavingAttributes =
6
- SuperDiff::ObjectInspection::InspectionTree.new do
7
- add_text "#<an object having attributes ("
5
+ class ObjectHavingAttributes < SuperDiff::ObjectInspection::Inspectors::Base
6
+ def self.applies_to?(value)
7
+ SuperDiff::RSpec.an_object_having_some_attributes?(value)
8
+ end
8
9
 
9
- nested do |aliased_matcher|
10
- insert_hash_inspection_of(
11
- aliased_matcher.expected,
12
- initial_break: nil,
13
- )
14
- end
10
+ protected
11
+
12
+ def inspection_tree
13
+ SuperDiff::ObjectInspection::InspectionTree.new do
14
+ add_text "#<an object having attributes ("
15
15
 
16
- add_break
17
- add_text ")>"
16
+ nested do |aliased_matcher|
17
+ insert_hash_inspection_of(
18
+ aliased_matcher.expected,
19
+ initial_break: nil,
20
+ )
21
+ end
22
+
23
+ add_break
24
+ add_text ")>"
25
+ end
18
26
  end
27
+ end
19
28
  end
20
29
  end
21
30
  end
@@ -0,0 +1,13 @@
1
+ module SuperDiff
2
+ module RSpec
3
+ module ObjectInspection
4
+ module Inspectors
5
+ class Primitive < SuperDiff::ObjectInspection::Inspectors::Primitive
6
+ def self.applies_to?(value)
7
+ super || value.is_a?(::RSpec::Mocks::Double)
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+ module SuperDiff
2
+ module RSpec
3
+ module ObjectInspection
4
+ module Inspectors
5
+ class ValueWithin < SuperDiff::ObjectInspection::Inspectors::Base
6
+ def self.applies_to?(value)
7
+ SuperDiff::RSpec.a_value_within_something?(value)
8
+ end
9
+
10
+ protected
11
+
12
+ def inspection_tree
13
+ SuperDiff::ObjectInspection::InspectionTree.new do
14
+ add_text "#<a value within "
15
+
16
+ add_inspection_of do |aliased_matcher|
17
+ aliased_matcher.base_matcher.instance_variable_get("@delta")
18
+ end
19
+
20
+ add_text " of "
21
+ add_inspection_of(&:expected)
22
+ add_text ">"
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,22 @@
1
+ module SuperDiff
2
+ module RSpec
3
+ module OperationTreeBuilders
4
+ autoload(
5
+ :CollectionContainingExactly,
6
+ "super_diff/rspec/operation_tree_builders/collection_containing_exactly",
7
+ )
8
+ autoload(
9
+ :CollectionIncluding,
10
+ "super_diff/rspec/operation_tree_builders/collection_including",
11
+ )
12
+ autoload(
13
+ :HashIncluding,
14
+ "super_diff/rspec/operation_tree_builders/hash_including",
15
+ )
16
+ autoload(
17
+ :ObjectHavingAttributes,
18
+ "super_diff/rspec/operation_tree_builders/object_having_attributes",
19
+ )
20
+ end
21
+ end
22
+ end
@@ -1,13 +1,13 @@
1
1
  module SuperDiff
2
2
  module RSpec
3
- module OperationalSequencers
4
- class CollectionContainingExactly < SuperDiff::OperationalSequencers::Base
3
+ module OperationTreeBuilders
4
+ class CollectionContainingExactly < SuperDiff::OperationTreeBuilders::Base
5
5
  def self.applies_to?(expected, actual)
6
6
  SuperDiff::RSpec.a_collection_containing_exactly_something?(expected) &&
7
7
  actual.is_a?(::Array)
8
8
  end
9
9
 
10
- def initialize(actual:, **rest)
10
+ def initialize(actual:, **)
11
11
  super
12
12
  populate_pairings_maximizer_in_expected_with(actual)
13
13
  end
@@ -28,8 +28,8 @@ module SuperDiff
28
28
  operations
29
29
  end
30
30
 
31
- def build_operation_sequencer
32
- OperationSequences::Array.new([])
31
+ def build_operation_tree
32
+ OperationTrees::Array.new([])
33
33
  end
34
34
 
35
35
  private
@@ -1,7 +1,7 @@
1
1
  module SuperDiff
2
2
  module RSpec
3
- module OperationalSequencers
4
- class CollectionIncluding < SuperDiff::OperationalSequencers::Array
3
+ module OperationTreeBuilders
4
+ class CollectionIncluding < SuperDiff::OperationTreeBuilders::Array
5
5
  def self.applies_to?(expected, actual)
6
6
  SuperDiff::RSpec.a_collection_including_something?(expected) &&
7
7
  actual.is_a?(::Array)
@@ -1,16 +1,14 @@
1
1
  module SuperDiff
2
2
  module RSpec
3
- module OperationalSequencers
4
- class HashIncluding < SuperDiff::OperationalSequencers::Hash
3
+ module OperationTreeBuilders
4
+ class HashIncluding < SuperDiff::OperationTreeBuilders::Hash
5
5
  def self.applies_to?(expected, actual)
6
6
  SuperDiff::RSpec.a_hash_including_something?(expected) &&
7
7
  actual.is_a?(::Hash)
8
8
  end
9
9
 
10
10
  def initialize(expected:, **rest)
11
- super
12
-
13
- @expected = expected.expecteds.first
11
+ super(expected: expected.expecteds.first, **rest)
14
12
  end
15
13
 
16
14
  private
@@ -21,12 +19,6 @@ module SuperDiff
21
19
  expected[key] == actual[key]
22
20
  )
23
21
  end
24
-
25
- def should_add_insert_operation?(key)
26
- expected.include?(key) &&
27
- actual.include?(key) &&
28
- expected[key] != actual[key]
29
- end
30
22
  end
31
23
  end
32
24
  end
@@ -1,19 +1,15 @@
1
1
  module SuperDiff
2
2
  module RSpec
3
- module OperationalSequencers
4
- class ObjectHavingAttributes < SuperDiff::OperationalSequencers::DefaultObject
3
+ module OperationTreeBuilders
4
+ class ObjectHavingAttributes < SuperDiff::OperationTreeBuilders::DefaultObject
5
5
  def self.applies_to?(expected, _actual)
6
6
  SuperDiff::RSpec.an_object_having_some_attributes?(expected)
7
7
  end
8
8
 
9
9
  protected
10
10
 
11
- def build_operation_sequencer
12
- if actual.respond_to?(:attributes_for_super_diff)
13
- OperationSequences::CustomObject.new([], value_class: actual.class)
14
- else
15
- OperationSequences::DefaultObject.new([], value_class: actual.class)
16
- end
11
+ def build_operation_tree
12
+ find_operation_tree_for(actual)
17
13
  end
18
14
 
19
15
  def attribute_names
@@ -1,3 +1,3 @@
1
1
  module SuperDiff
2
- VERSION = "0.4.0".freeze
2
+ VERSION = "0.5.2".freeze
3
3
  end
@@ -0,0 +1,5 @@
1
+ example_id | status | run_time |
2
+ ---------------------------------------------------------- | ------ | -------------- |
3
+ ./spec/integration/rspec/unhandled_errors_spec.rb[1:1:1:1] | passed | 1.28 seconds |
4
+ ./spec/integration/rspec/unhandled_errors_spec.rb[1:1:2:1] | passed | 1.31 seconds |
5
+ ./spec/integration/rspec/unhandled_errors_spec.rb[1:2:1] | failed | 0.7241 seconds |
@@ -1,255 +1,369 @@
1
1
  require "spec_helper"
2
2
 
3
3
  RSpec.describe "Integration with RSpec's #have_attributes matcher", type: :integration do
4
- context "when given a small set of attributes" do
5
- context "when all of the names are methods on the actual object" do
6
- it "produces the correct output when used in the positive" do
7
- as_both_colored_and_uncolored do |color_enabled|
8
- snippet = <<~TEST.strip
9
- expected = { name: "b" }
10
- actual = SuperDiff::Test::Person.new(name: "a", age: 9)
11
- expect(actual).to have_attributes(expected)
12
- TEST
13
- program = make_plain_test_program(
14
- snippet,
15
- color_enabled: color_enabled,
16
- )
4
+ context "when the actual value is an object" do
5
+ context "with a small set of attributes" do
6
+ context "when all of the names are methods on the actual object" do
7
+ it "produces the correct output when used in the positive" do
8
+ as_both_colored_and_uncolored do |color_enabled|
9
+ snippet = <<~TEST.strip
10
+ expected = { name: "b" }
11
+ actual = SuperDiff::Test::Person.new(name: "a", age: 9)
12
+ expect(actual).to have_attributes(expected)
13
+ TEST
14
+ program = make_plain_test_program(
15
+ snippet,
16
+ color_enabled: color_enabled,
17
+ )
17
18
 
18
- expected_output = build_expected_output(
19
- color_enabled: color_enabled,
20
- snippet: %|expect(actual).to have_attributes(expected)|,
21
- expectation: proc {
22
- line do
23
- plain "Expected "
24
- beta %|#<SuperDiff::Test::Person name: "a", age: 9>|
25
- plain " to have attributes "
26
- alpha %|(name: "b")|
27
- plain "."
28
- end
29
- },
30
- diff: proc {
31
- plain_line %| #<SuperDiff::Test::Person {|
32
- # alpha_line %|- name: "b",| # FIXME
33
- alpha_line %|- name: "b"|
34
- beta_line %|+ name: "a",|
35
- plain_line %| age: 9|
36
- plain_line %| }>|
37
- },
38
- )
19
+ expected_output = build_expected_output(
20
+ color_enabled: color_enabled,
21
+ snippet: %|expect(actual).to have_attributes(expected)|,
22
+ expectation: proc {
23
+ line do
24
+ plain "Expected "
25
+ beta %|#<SuperDiff::Test::Person name: "a", age: 9>|
26
+ plain " to have attributes "
27
+ alpha %|(name: "b")|
28
+ plain "."
29
+ end
30
+ },
31
+ diff: proc {
32
+ plain_line %| #<SuperDiff::Test::Person {|
33
+ # alpha_line %|- name: "b",| # FIXME
34
+ alpha_line %|- name: "b"|
35
+ beta_line %|+ name: "a",|
36
+ plain_line %| age: 9|
37
+ plain_line %| }>|
38
+ },
39
+ )
39
40
 
40
- expect(program).
41
- to produce_output_when_run(expected_output).
42
- in_color(color_enabled)
41
+ expect(program).
42
+ to produce_output_when_run(expected_output).
43
+ in_color(color_enabled)
44
+ end
43
45
  end
44
- end
45
46
 
46
- it "produces the correct output when used in the negative" do
47
- as_both_colored_and_uncolored do |color_enabled|
48
- snippet = <<~TEST.strip
49
- expected = { name: "a" }
50
- actual = SuperDiff::Test::Person.new(name: "a", age: 9)
51
- expect(actual).not_to have_attributes(expected)
52
- TEST
53
- program = make_plain_test_program(
54
- snippet,
55
- color_enabled: color_enabled,
56
- )
47
+ it "produces the correct output when used in the negative" do
48
+ as_both_colored_and_uncolored do |color_enabled|
49
+ snippet = <<~TEST.strip
50
+ expected = { name: "a" }
51
+ actual = SuperDiff::Test::Person.new(name: "a", age: 9)
52
+ expect(actual).not_to have_attributes(expected)
53
+ TEST
54
+ program = make_plain_test_program(
55
+ snippet,
56
+ color_enabled: color_enabled,
57
+ )
57
58
 
58
- expected_output = build_expected_output(
59
- color_enabled: color_enabled,
60
- snippet: %|expect(actual).not_to have_attributes(expected)|,
61
- expectation: proc {
62
- line do
63
- plain "Expected "
64
- beta %|#<SuperDiff::Test::Person name: "a", age: 9>|
65
- plain " not to have attributes "
66
- alpha %|(name: "a")|
67
- plain "."
68
- end
69
- },
70
- )
59
+ expected_output = build_expected_output(
60
+ color_enabled: color_enabled,
61
+ snippet: %|expect(actual).not_to have_attributes(expected)|,
62
+ expectation: proc {
63
+ line do
64
+ plain "Expected "
65
+ beta %|#<SuperDiff::Test::Person name: "a", age: 9>|
66
+ plain " not to have attributes "
67
+ alpha %|(name: "a")|
68
+ plain "."
69
+ end
70
+ },
71
+ )
71
72
 
72
- expect(program).
73
- to produce_output_when_run(expected_output).
74
- in_color(color_enabled)
73
+ expect(program).
74
+ to produce_output_when_run(expected_output).
75
+ in_color(color_enabled)
76
+ end
75
77
  end
76
78
  end
77
- end
78
79
 
79
- context "when some of the names are not methods on the actual object" do
80
- it "produces the correct output" do
81
- as_both_colored_and_uncolored do |color_enabled|
82
- snippet = <<~TEST.strip
83
- expected = { name: "b", foo: "bar" }
84
- actual = SuperDiff::Test::Person.new(name: "a", age: 9)
85
- expect(actual).to have_attributes(expected)
86
- TEST
87
- program = make_plain_test_program(
88
- snippet,
89
- color_enabled: color_enabled,
90
- )
80
+ context "when some of the names are not methods on the actual object" do
81
+ it "produces the correct output" do
82
+ as_both_colored_and_uncolored do |color_enabled|
83
+ snippet = <<~TEST.strip
84
+ expected = { name: "b", foo: "bar" }
85
+ actual = SuperDiff::Test::Person.new(name: "a", age: 9)
86
+ expect(actual).to have_attributes(expected)
87
+ TEST
88
+ program = make_plain_test_program(
89
+ snippet,
90
+ color_enabled: color_enabled,
91
+ )
91
92
 
92
- expected_output = build_expected_output(
93
- color_enabled: color_enabled,
94
- snippet: %|expect(actual).to have_attributes(expected)|,
95
- expectation: proc {
96
- line do
97
- plain "Expected "
98
- beta %|#<SuperDiff::Test::Person name: "a", age: 9>|
99
- plain " to respond to "
100
- alpha %|:foo|
101
- plain " with "
102
- alpha %|0|
103
- plain " arguments."
104
- end
105
- },
106
- diff: proc {
107
- plain_line %| #<SuperDiff::Test::Person {|
108
- plain_line %| name: "a",|
109
- # plain_line %| age: 9,| # FIXME
110
- plain_line %| age: 9|
111
- # alpha_line %|- foo: "bar",| # FIXME
112
- alpha_line %|- foo: "bar"|
113
- plain_line %| }>|
114
- },
115
- )
93
+ expected_output = build_expected_output(
94
+ color_enabled: color_enabled,
95
+ snippet: %|expect(actual).to have_attributes(expected)|,
96
+ expectation: proc {
97
+ line do
98
+ plain "Expected "
99
+ beta %|#<SuperDiff::Test::Person name: "a", age: 9>|
100
+ plain " to respond to "
101
+ alpha %|:foo|
102
+ plain " with "
103
+ alpha %|0|
104
+ plain " arguments."
105
+ end
106
+ },
107
+ diff: proc {
108
+ plain_line %| #<SuperDiff::Test::Person {|
109
+ plain_line %| name: "a",|
110
+ # plain_line %| age: 9,| # FIXME
111
+ plain_line %| age: 9|
112
+ # alpha_line %|- foo: "bar",| # FIXME
113
+ alpha_line %|- foo: "bar"|
114
+ plain_line %| }>|
115
+ },
116
+ )
116
117
 
117
- expect(program).
118
- to produce_output_when_run(expected_output).
119
- in_color(color_enabled)
118
+ expect(program).
119
+ to produce_output_when_run(expected_output).
120
+ in_color(color_enabled)
121
+ end
120
122
  end
121
123
  end
122
124
  end
123
- end
124
125
 
125
- context "when given a large set of attributes" do
126
- context "when all of the names are methods on the actual object" do
127
- it "produces the correct output when used in the positive" do
128
- as_both_colored_and_uncolored do |color_enabled|
129
- snippet = <<~TEST.strip
130
- expected = {
131
- line_1: "123 Main St.",
132
- city: "Oakland",
133
- state: "CA",
134
- zip: "91234"
135
- }
136
- actual = SuperDiff::Test::ShippingAddress.new(
137
- line_1: "456 Ponderosa Ct.",
138
- line_2: nil,
139
- city: "Hill Valley",
140
- state: "CA",
141
- zip: "90382"
126
+ context "with a large set of attributes" do
127
+ context "when all of the names are methods on the actual object" do
128
+ it "produces the correct output when used in the positive" do
129
+ as_both_colored_and_uncolored do |color_enabled|
130
+ snippet = <<~TEST.strip
131
+ expected = {
132
+ line_1: "123 Main St.",
133
+ city: "Oakland",
134
+ state: "CA",
135
+ zip: "91234"
136
+ }
137
+ actual = SuperDiff::Test::ShippingAddress.new(
138
+ line_1: "456 Ponderosa Ct.",
139
+ line_2: nil,
140
+ city: "Hill Valley",
141
+ state: "CA",
142
+ zip: "90382"
143
+ )
144
+ expect(actual).to have_attributes(expected)
145
+ TEST
146
+ program = make_plain_test_program(
147
+ snippet,
148
+ color_enabled: color_enabled,
142
149
  )
143
- expect(actual).to have_attributes(expected)
144
- TEST
145
- program = make_plain_test_program(
146
- snippet,
147
- color_enabled: color_enabled,
148
- )
149
150
 
150
- expected_output = build_expected_output(
151
- color_enabled: color_enabled,
152
- snippet: %|expect(actual).to have_attributes(expected)|,
153
- expectation: proc {
154
- line do
155
- plain " Expected "
156
- beta %|#<SuperDiff::Test::ShippingAddress line_1: "456 Ponderosa Ct.", line_2: nil, city: "Hill Valley", state: "CA", zip: "90382">|
157
- end
151
+ expected_output = build_expected_output(
152
+ color_enabled: color_enabled,
153
+ snippet: %|expect(actual).to have_attributes(expected)|,
154
+ expectation: proc {
155
+ line do
156
+ plain " Expected "
157
+ beta %|#<SuperDiff::Test::ShippingAddress line_1: "456 Ponderosa Ct.", line_2: nil, city: "Hill Valley", state: "CA", zip: "90382">|
158
+ end
158
159
 
159
- line do
160
- plain "to have attributes "
161
- alpha %|(line_1: "123 Main St.", city: "Oakland", state: "CA", zip: "91234")|
162
- end
163
- },
164
- diff: proc {
165
- plain_line %| #<SuperDiff::Test::ShippingAddress {|
166
- alpha_line %|- line_1: "123 Main St.",|
167
- beta_line %|+ line_1: "456 Ponderosa Ct.",|
168
- plain_line %| line_2: nil,|
169
- alpha_line %|- city: "Oakland",|
170
- beta_line %|+ city: "Hill Valley",|
171
- plain_line %| state: "CA",|
172
- # alpha_line %|- zip: "91234",| # FIXME
173
- alpha_line %|- zip: "91234"|
174
- beta_line %|+ zip: "90382"|
175
- plain_line %| }>|
176
- },
177
- )
160
+ line do
161
+ plain "to have attributes "
162
+ alpha %|(line_1: "123 Main St.", city: "Oakland", state: "CA", zip: "91234")|
163
+ end
164
+ },
165
+ diff: proc {
166
+ plain_line %| #<SuperDiff::Test::ShippingAddress {|
167
+ alpha_line %|- line_1: "123 Main St.",|
168
+ beta_line %|+ line_1: "456 Ponderosa Ct.",|
169
+ plain_line %| line_2: nil,|
170
+ alpha_line %|- city: "Oakland",|
171
+ beta_line %|+ city: "Hill Valley",|
172
+ plain_line %| state: "CA",|
173
+ # alpha_line %|- zip: "91234",| # FIXME
174
+ alpha_line %|- zip: "91234"|
175
+ beta_line %|+ zip: "90382"|
176
+ plain_line %| }>|
177
+ },
178
+ )
178
179
 
179
- expect(program).
180
- to produce_output_when_run(expected_output).
181
- in_color(color_enabled)
180
+ expect(program).
181
+ to produce_output_when_run(expected_output).
182
+ in_color(color_enabled)
183
+ end
184
+ end
185
+
186
+ it "produces the correct output when used in the negative" do
187
+ as_both_colored_and_uncolored do |color_enabled|
188
+ snippet = <<~TEST.strip
189
+ expected = {
190
+ line_1: "123 Main St.",
191
+ city: "Oakland",
192
+ state: "CA",
193
+ zip: "91234"
194
+ }
195
+ actual = SuperDiff::Test::ShippingAddress.new(
196
+ line_1: "123 Main St.",
197
+ line_2: nil,
198
+ city: "Oakland",
199
+ state: "CA",
200
+ zip: "91234"
201
+ )
202
+ expect(actual).not_to have_attributes(expected)
203
+ TEST
204
+ program = make_plain_test_program(
205
+ snippet,
206
+ color_enabled: color_enabled,
207
+ )
208
+
209
+ expected_output = build_expected_output(
210
+ color_enabled: color_enabled,
211
+ snippet: %|expect(actual).not_to have_attributes(expected)|,
212
+ newline_before_expectation: true,
213
+ expectation: proc {
214
+ line do
215
+ plain " Expected "
216
+ beta %|#<SuperDiff::Test::ShippingAddress line_1: "123 Main St.", line_2: nil, city: "Oakland", state: "CA", zip: "91234">|
217
+ end
218
+
219
+ line do
220
+ plain "not to have attributes "
221
+ alpha %|(line_1: "123 Main St.", city: "Oakland", state: "CA", zip: "91234")|
222
+ end
223
+ },
224
+ )
225
+
226
+ expect(program).
227
+ to produce_output_when_run(expected_output).
228
+ in_color(color_enabled)
229
+ end
182
230
  end
183
231
  end
184
232
 
185
- it "produces the correct output when used in the negative" do
186
- as_both_colored_and_uncolored do |color_enabled|
187
- snippet = <<~TEST.strip
188
- expected = {
189
- line_1: "123 Main St.",
190
- city: "Oakland",
191
- state: "CA",
192
- zip: "91234"
193
- }
194
- actual = SuperDiff::Test::ShippingAddress.new(
195
- line_1: "123 Main St.",
196
- line_2: nil,
197
- city: "Oakland",
198
- state: "CA",
199
- zip: "91234"
233
+ context "when some of the names are not methods on the actual object" do
234
+ it "produces the correct output" do
235
+ as_both_colored_and_uncolored do |color_enabled|
236
+ snippet = <<~TEST.strip
237
+ expected = {
238
+ line_1: "123 Main St.",
239
+ city: "Oakland",
240
+ state: "CA",
241
+ zip: "91234",
242
+ foo: "bar",
243
+ baz: "qux"
244
+ }
245
+ actual = SuperDiff::Test::ShippingAddress.new(
246
+ line_1: "456 Ponderosa Ct.",
247
+ line_2: nil,
248
+ city: "Hill Valley",
249
+ state: "CA",
250
+ zip: "90382"
251
+ )
252
+ expect(actual).to have_attributes(expected)
253
+ TEST
254
+ program = make_plain_test_program(
255
+ snippet,
256
+ color_enabled: color_enabled,
200
257
  )
201
- expect(actual).not_to have_attributes(expected)
202
- TEST
203
- program = make_plain_test_program(
204
- snippet,
205
- color_enabled: color_enabled,
206
- )
207
258
 
208
- expected_output = build_expected_output(
209
- color_enabled: color_enabled,
210
- snippet: %|expect(actual).not_to have_attributes(expected)|,
211
- newline_before_expectation: true,
212
- expectation: proc {
213
- line do
214
- plain " Expected "
215
- beta %|#<SuperDiff::Test::ShippingAddress line_1: "123 Main St.", line_2: nil, city: "Oakland", state: "CA", zip: "91234">|
216
- end
259
+ expected_output = build_expected_output(
260
+ color_enabled: color_enabled,
261
+ snippet: %|expect(actual).to have_attributes(expected)|,
262
+ expectation: proc {
263
+ line do
264
+ plain " Expected "
265
+ beta %|#<SuperDiff::Test::ShippingAddress line_1: "456 Ponderosa Ct.", line_2: nil, city: "Hill Valley", state: "CA", zip: "90382">|
266
+ end
217
267
 
218
- line do
219
- plain "not to have attributes "
220
- alpha %|(line_1: "123 Main St.", city: "Oakland", state: "CA", zip: "91234")|
221
- end
222
- },
223
- )
268
+ line do
269
+ plain "to respond to "
270
+ alpha %|:foo|
271
+ plain " and "
272
+ alpha %|:baz|
273
+ plain " with "
274
+ alpha %|0|
275
+ plain " arguments"
276
+ end
277
+ },
278
+ diff: proc {
279
+ plain_line %| #<SuperDiff::Test::ShippingAddress {|
280
+ plain_line %| line_1: "456 Ponderosa Ct.",|
281
+ plain_line %| line_2: nil,|
282
+ plain_line %| city: "Hill Valley",|
283
+ plain_line %| state: "CA",|
284
+ # plain_line %| zip: "90382",| # FIXME
285
+ plain_line %| zip: "90382"|
286
+ # alpha_line %|- foo: "bar",| # FIXME
287
+ alpha_line %|- foo: "bar"|
288
+ alpha_line %|- baz: "qux"|
289
+ plain_line %| }>|
290
+ },
291
+ )
224
292
 
225
- expect(program).
226
- to produce_output_when_run(expected_output).
227
- in_color(color_enabled)
293
+ expect(program).
294
+ to produce_output_when_run(expected_output).
295
+ in_color(color_enabled)
296
+ end
228
297
  end
229
298
  end
230
299
  end
300
+ end
301
+
302
+ context "when the actual value is actually a hash instead of an object" do
303
+ it "displays the diff as if we were comparing hashes" do
304
+ as_both_colored_and_uncolored do |color_enabled|
305
+ snippet = <<~TEST.strip
306
+ expected = { name: "Elliot", age: 32 }
307
+ actual = {}
308
+ expect(actual).to have_attributes(expected)
309
+ TEST
310
+
311
+ program = make_plain_test_program(snippet, color_enabled: color_enabled)
231
312
 
232
- context "when some of the names are not methods on the actual object" do
233
- it "produces the correct output" do
313
+ expected_output = build_expected_output(
314
+ color_enabled: color_enabled,
315
+ snippet: %|expect(actual).to have_attributes(expected)|,
316
+ expectation: proc {
317
+ line do
318
+ plain "Expected "
319
+ beta %|{}|
320
+ plain " to respond to "
321
+ alpha %|:name|
322
+ plain " and "
323
+ alpha %|:age|
324
+ plain " with "
325
+ alpha %|0|
326
+ plain " arguments."
327
+ end
328
+ },
329
+ diff: proc {
330
+ plain_line %| {|
331
+ alpha_line %|- name: "Elliot",|
332
+ alpha_line %|- age: 32|
333
+ plain_line %| }|
334
+ },
335
+ )
336
+
337
+ expect(program).
338
+ to produce_output_when_run(expected_output).
339
+ in_color(color_enabled)
340
+ end
341
+ end
342
+
343
+ # TODO: Add as many fuzzy matchers as we can here
344
+ context "that contains fuzzy matcher objects instead of an object" do
345
+ it "displays the hash correctly" do
234
346
  as_both_colored_and_uncolored do |color_enabled|
235
347
  snippet = <<~TEST.strip
236
348
  expected = {
237
- line_1: "123 Main St.",
238
- city: "Oakland",
239
- state: "CA",
240
- zip: "91234",
241
- foo: "bar",
242
- baz: "qux"
349
+ name: "Elliot",
350
+ shipping_address: an_object_having_attributes(
351
+ line_1: a_kind_of(String),
352
+ line_2: nil,
353
+ city: an_instance_of(String),
354
+ state: "CA",
355
+ zip: "91234"
356
+ ),
357
+ order_ids: a_collection_including(1, 2),
358
+ data: a_hash_including(active: true),
359
+ created_at: a_value_within(1).of(Time.utc(2020, 4, 9))
243
360
  }
244
- actual = SuperDiff::Test::ShippingAddress.new(
245
- line_1: "456 Ponderosa Ct.",
246
- line_2: nil,
247
- city: "Hill Valley",
248
- state: "CA",
249
- zip: "90382"
250
- )
361
+
362
+ actual = {}
363
+
251
364
  expect(actual).to have_attributes(expected)
252
365
  TEST
366
+
253
367
  program = make_plain_test_program(
254
368
  snippet,
255
369
  color_enabled: color_enabled,
@@ -261,31 +375,44 @@ RSpec.describe "Integration with RSpec's #have_attributes matcher", type: :integ
261
375
  expectation: proc {
262
376
  line do
263
377
  plain " Expected "
264
- beta %|#<SuperDiff::Test::ShippingAddress line_1: "456 Ponderosa Ct.", line_2: nil, city: "Hill Valley", state: "CA", zip: "90382">|
378
+ beta %|{}|
265
379
  end
266
380
 
267
381
  line do
268
382
  plain "to respond to "
269
- alpha %|:foo|
383
+ alpha %|:name|
384
+ plain ", "
385
+ alpha %|:shipping_address|
386
+ plain ", "
387
+ alpha %|:order_ids|
388
+ plain ", "
389
+ alpha %|:data|
270
390
  plain " and "
271
- alpha %|:baz|
391
+ alpha %|:created_at|
272
392
  plain " with "
273
393
  alpha %|0|
274
394
  plain " arguments"
275
395
  end
276
396
  },
277
397
  diff: proc {
278
- plain_line %| #<SuperDiff::Test::ShippingAddress {|
279
- plain_line %| line_1: "456 Ponderosa Ct.",|
280
- plain_line %| line_2: nil,|
281
- plain_line %| city: "Hill Valley",|
282
- plain_line %| state: "CA",|
283
- # plain_line %| zip: "90382",| # FIXME
284
- plain_line %| zip: "90382"|
285
- # alpha_line %|- foo: "bar",| # FIXME
286
- alpha_line %|- foo: "bar"|
287
- alpha_line %|- baz: "qux"|
288
- plain_line %| }>|
398
+ plain_line %| {|
399
+ alpha_line %|- name: "Elliot",|
400
+ alpha_line %|- shipping_address: #<an object having attributes (|
401
+ alpha_line %|- line_1: #<a kind of String>,|
402
+ alpha_line %|- line_2: nil,|
403
+ alpha_line %|- city: #<an instance of String>,|
404
+ alpha_line %|- state: "CA",|
405
+ alpha_line %|- zip: "91234"|
406
+ alpha_line %|- )>,|
407
+ alpha_line %|- order_ids: #<a collection including (|
408
+ alpha_line %|- 1,|
409
+ alpha_line %|- 2|
410
+ alpha_line %|- )>,|
411
+ alpha_line %|- data: #<a hash including (|
412
+ alpha_line %|- active: true|
413
+ alpha_line %|- )>,|
414
+ alpha_line %|- created_at: #<a value within 1 of 2020-04-09 00:00:00.000 UTC +00:00 (Time)>|
415
+ plain_line %| }|
289
416
  },
290
417
  )
291
418