super_diff 0.1.0 → 0.2.0

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 (206) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +117 -89
  3. data/lib/super_diff.rb +33 -47
  4. data/lib/super_diff/active_record.rb +41 -0
  5. data/lib/super_diff/active_record/diff_formatters.rb +10 -0
  6. data/lib/super_diff/active_record/diff_formatters/active_record_relation.rb +23 -0
  7. data/lib/super_diff/active_record/differs.rb +10 -0
  8. data/lib/super_diff/active_record/differs/active_record_relation.rb +30 -0
  9. data/lib/super_diff/active_record/object_inspection.rb +14 -0
  10. data/lib/super_diff/active_record/object_inspection/inspectors.rb +16 -0
  11. data/lib/super_diff/active_record/object_inspection/inspectors/active_record_model.rb +38 -0
  12. data/lib/super_diff/active_record/object_inspection/inspectors/active_record_relation.rb +18 -0
  13. data/lib/super_diff/active_record/object_inspection/map_extension.rb +18 -0
  14. data/lib/super_diff/active_record/operation_sequences.rb +10 -0
  15. data/lib/super_diff/active_record/operation_sequences/active_record_relation.rb +16 -0
  16. data/lib/super_diff/active_record/operational_sequencers.rb +14 -0
  17. data/lib/super_diff/active_record/operational_sequencers/active_record_model.rb +19 -0
  18. data/lib/super_diff/active_record/operational_sequencers/active_record_relation.rb +24 -0
  19. data/lib/super_diff/active_support.rb +33 -0
  20. data/lib/super_diff/active_support/diff_formatters.rb +10 -0
  21. data/lib/super_diff/active_support/diff_formatters/hash_with_indifferent_access.rb +36 -0
  22. data/lib/super_diff/active_support/differs.rb +10 -0
  23. data/lib/super_diff/active_support/differs/hash_with_indifferent_access.rb +36 -0
  24. data/lib/super_diff/active_support/object_inspection.rb +14 -0
  25. data/lib/super_diff/active_support/object_inspection/inspectors.rb +12 -0
  26. data/lib/super_diff/active_support/object_inspection/inspectors/hash_with_indifferent_access.rb +18 -0
  27. data/lib/super_diff/active_support/object_inspection/map_extension.rb +15 -0
  28. data/lib/super_diff/active_support/operation_sequences.rb +10 -0
  29. data/lib/super_diff/active_support/operation_sequences/hash_with_indifferent_access.rb +16 -0
  30. data/lib/super_diff/active_support/operational_sequencers.rb +10 -0
  31. data/lib/super_diff/active_support/operational_sequencers/hash_with_indifferent_access.rb +21 -0
  32. data/lib/super_diff/colorized_document_extensions.rb +17 -0
  33. data/lib/super_diff/csi.rb +45 -15
  34. data/lib/super_diff/csi/bold_sequence.rb +9 -0
  35. data/lib/super_diff/csi/color.rb +62 -0
  36. data/lib/super_diff/csi/color_sequence_block.rb +28 -0
  37. data/lib/super_diff/csi/colorized_document.rb +72 -0
  38. data/lib/super_diff/csi/document.rb +183 -0
  39. data/lib/super_diff/csi/eight_bit_color.rb +72 -26
  40. data/lib/super_diff/csi/four_bit_color.rb +63 -29
  41. data/lib/super_diff/csi/twenty_four_bit_color.rb +79 -18
  42. data/lib/super_diff/csi/uncolorized_document.rb +29 -0
  43. data/lib/super_diff/diff_formatter.rb +10 -15
  44. data/lib/super_diff/diff_formatters.rb +10 -1
  45. data/lib/super_diff/diff_formatters/base.rb +12 -17
  46. data/lib/super_diff/diff_formatters/collection.rb +81 -50
  47. data/lib/super_diff/diff_formatters/{object.rb → custom_object.rb} +12 -9
  48. data/lib/super_diff/diff_formatters/default_object.rb +48 -0
  49. data/lib/super_diff/diff_formatters/multiline_string.rb +31 -0
  50. data/lib/super_diff/differ.rb +35 -32
  51. data/lib/super_diff/differs.rb +16 -1
  52. data/lib/super_diff/differs/array.rb +2 -2
  53. data/lib/super_diff/differs/base.rb +11 -21
  54. data/lib/super_diff/differs/custom_object.rb +26 -0
  55. data/lib/super_diff/differs/default_object.rb +25 -0
  56. data/lib/super_diff/differs/empty.rb +1 -1
  57. data/lib/super_diff/differs/hash.rb +2 -2
  58. data/lib/super_diff/differs/{multi_line_string.rb → multiline_string.rb} +6 -5
  59. data/lib/super_diff/equality_matcher.rb +9 -22
  60. data/lib/super_diff/equality_matchers.rb +19 -1
  61. data/lib/super_diff/equality_matchers/array.rb +6 -4
  62. data/lib/super_diff/equality_matchers/base.rb +8 -16
  63. data/lib/super_diff/equality_matchers/default.rb +60 -0
  64. data/lib/super_diff/equality_matchers/hash.rb +6 -4
  65. data/lib/super_diff/equality_matchers/{multi_line_string.rb → multiline_string.rb} +9 -6
  66. data/lib/super_diff/equality_matchers/primitive.rb +34 -0
  67. data/lib/super_diff/equality_matchers/{single_line_string.rb → singleline_string.rb} +7 -5
  68. data/lib/super_diff/helpers.rb +17 -81
  69. data/lib/super_diff/no_differ_available_error.rb +22 -0
  70. data/lib/super_diff/{errors.rb → no_operational_sequencer_available_error.rb} +0 -0
  71. data/lib/super_diff/object_inspection.rb +24 -0
  72. data/lib/super_diff/object_inspection/inspection_tree.rb +144 -0
  73. data/lib/super_diff/object_inspection/inspector.rb +27 -0
  74. data/lib/super_diff/object_inspection/inspectors.rb +18 -0
  75. data/lib/super_diff/object_inspection/inspectors/array.rb +22 -0
  76. data/lib/super_diff/object_inspection/inspectors/custom_object.rb +27 -0
  77. data/lib/super_diff/object_inspection/inspectors/default_object.rb +47 -0
  78. data/lib/super_diff/object_inspection/inspectors/hash.rb +22 -0
  79. data/lib/super_diff/object_inspection/inspectors/primitive.rb +13 -0
  80. data/lib/super_diff/object_inspection/inspectors/string.rb +13 -0
  81. data/lib/super_diff/object_inspection/map.rb +28 -0
  82. data/lib/super_diff/object_inspection/nodes.rb +49 -0
  83. data/lib/super_diff/object_inspection/nodes/base.rb +86 -0
  84. data/lib/super_diff/object_inspection/nodes/break.rb +15 -0
  85. data/lib/super_diff/object_inspection/nodes/inspection.rb +15 -0
  86. data/lib/super_diff/object_inspection/nodes/nesting.rb +16 -0
  87. data/lib/super_diff/object_inspection/nodes/text.rb +15 -0
  88. data/lib/super_diff/object_inspection/nodes/when_empty.rb +30 -0
  89. data/lib/super_diff/object_inspection/nodes/when_multiline.rb +22 -0
  90. data/lib/super_diff/object_inspection/nodes/when_non_empty.rb +30 -0
  91. data/lib/super_diff/object_inspection/nodes/when_singleline.rb +24 -0
  92. data/lib/super_diff/operation_sequences.rb +9 -0
  93. data/lib/super_diff/operation_sequences/base.rb +1 -1
  94. data/lib/super_diff/operation_sequences/{object.rb → custom_object.rb} +4 -3
  95. data/lib/super_diff/operation_sequences/default_object.rb +25 -0
  96. data/lib/super_diff/operational_sequencer.rb +23 -18
  97. data/lib/super_diff/operational_sequencers.rb +12 -1
  98. data/lib/super_diff/operational_sequencers/array.rb +65 -62
  99. data/lib/super_diff/operational_sequencers/base.rb +18 -26
  100. data/lib/super_diff/operational_sequencers/custom_object.rb +35 -0
  101. data/lib/super_diff/operational_sequencers/{object.rb → default_object.rb} +21 -11
  102. data/lib/super_diff/operational_sequencers/hash.rb +8 -5
  103. data/lib/super_diff/operational_sequencers/{multi_line_string.rb → multiline_string.rb} +11 -6
  104. data/lib/super_diff/operations.rb +6 -0
  105. data/lib/super_diff/operations/binary_operation.rb +14 -34
  106. data/lib/super_diff/operations/unary_operation.rb +11 -2
  107. data/lib/super_diff/rails.rb +1 -0
  108. data/lib/super_diff/recursion_guard.rb +47 -0
  109. data/lib/super_diff/rspec-rails.rb +2 -0
  110. data/lib/super_diff/rspec.rb +52 -8
  111. data/lib/super_diff/rspec/augmented_matcher.rb +98 -0
  112. data/lib/super_diff/rspec/configuration.rb +31 -0
  113. data/lib/super_diff/rspec/differ.rb +60 -16
  114. data/lib/super_diff/rspec/differs.rb +13 -0
  115. data/lib/super_diff/rspec/differs/collection_containing_exactly.rb +23 -0
  116. data/lib/super_diff/rspec/differs/partial_array.rb +22 -0
  117. data/lib/super_diff/rspec/differs/partial_hash.rb +22 -0
  118. data/lib/super_diff/rspec/differs/partial_object.rb +22 -0
  119. data/lib/super_diff/rspec/matcher_text_builders.rb +24 -0
  120. data/lib/super_diff/rspec/matcher_text_builders/base.rb +155 -0
  121. data/lib/super_diff/rspec/matcher_text_builders/be_predicate.rb +78 -0
  122. data/lib/super_diff/rspec/matcher_text_builders/contain_exactly.rb +14 -0
  123. data/lib/super_diff/rspec/matcher_text_builders/match.rb +23 -0
  124. data/lib/super_diff/rspec/matcher_text_builders/raise_error.rb +13 -0
  125. data/lib/super_diff/rspec/matcher_text_builders/respond_to.rb +99 -0
  126. data/lib/super_diff/rspec/matcher_text_template.rb +240 -0
  127. data/lib/super_diff/rspec/monkey_patches.rb +601 -98
  128. data/lib/super_diff/rspec/object_inspection.rb +8 -0
  129. data/lib/super_diff/rspec/object_inspection/inspectors.rb +24 -0
  130. data/lib/super_diff/rspec/object_inspection/inspectors/collection_containing_exactly.rb +19 -0
  131. data/lib/super_diff/rspec/object_inspection/inspectors/partial_array.rb +22 -0
  132. data/lib/super_diff/rspec/object_inspection/inspectors/partial_hash.rb +21 -0
  133. data/lib/super_diff/rspec/object_inspection/inspectors/partial_object.rb +21 -0
  134. data/lib/super_diff/rspec/object_inspection/map_extension.rb +23 -0
  135. data/lib/super_diff/rspec/operational_sequencers.rb +22 -0
  136. data/lib/super_diff/rspec/operational_sequencers/collection_containing_exactly.rb +97 -0
  137. data/lib/super_diff/rspec/operational_sequencers/partial_array.rb +23 -0
  138. data/lib/super_diff/rspec/operational_sequencers/partial_hash.rb +32 -0
  139. data/lib/super_diff/rspec/operational_sequencers/partial_object.rb +64 -0
  140. data/lib/super_diff/version.rb +1 -1
  141. data/spec/examples.txt +328 -46
  142. data/spec/integration/rails/active_record_spec.rb +19 -0
  143. data/spec/integration/rails/hash_with_indifferent_access_spec.rb +19 -0
  144. data/spec/integration/rspec/be_falsey_matcher_spec.rb +53 -0
  145. data/spec/integration/rspec/be_matcher_spec.rb +565 -0
  146. data/spec/integration/rspec/be_nil_matcher_spec.rb +53 -0
  147. data/spec/integration/rspec/be_predicate_matcher_spec.rb +546 -0
  148. data/spec/integration/rspec/be_truthy_matcher_spec.rb +57 -0
  149. data/spec/integration/rspec/contain_exactly_matcher_spec.rb +368 -0
  150. data/spec/integration/rspec/eq_matcher_spec.rb +874 -0
  151. data/spec/integration/rspec/have_attributes_matcher_spec.rb +299 -0
  152. data/spec/integration/rspec/include_matcher_spec.rb +350 -0
  153. data/spec/integration/rspec/match_matcher_spec.rb +1258 -0
  154. data/spec/integration/rspec/raise_error_matcher_spec.rb +350 -0
  155. data/spec/integration/rspec/respond_to_matcher_spec.rb +994 -0
  156. data/spec/integration/rspec/unhandled_errors_spec.rb +94 -0
  157. data/spec/spec_helper.rb +19 -4
  158. data/spec/support/colorizer.rb +9 -0
  159. data/spec/support/command_runner.rb +4 -0
  160. data/spec/support/integration/helpers.rb +179 -0
  161. data/spec/support/integration/matchers/produce_output_when_run_matcher.rb +79 -41
  162. data/spec/support/models/a.rb +11 -0
  163. data/spec/support/models/active_record/person.rb +26 -0
  164. data/spec/support/models/active_record/shipping_address.rb +29 -0
  165. data/spec/support/models/customer.rb +24 -0
  166. data/spec/support/models/empty_class.rb +6 -0
  167. data/spec/support/models/item.rb +10 -0
  168. data/spec/support/models/order.rb +9 -0
  169. data/spec/support/models/person.rb +20 -0
  170. data/spec/support/models/player.rb +33 -0
  171. data/spec/support/models/shipping_address.rb +34 -0
  172. data/spec/support/ruby_versions.rb +7 -0
  173. data/spec/support/shared_examples/active_record.rb +338 -0
  174. data/spec/support/shared_examples/hash_with_indifferent_access.rb +233 -0
  175. data/spec/unit/equality_matcher_spec.rb +579 -171
  176. data/spec/unit/object_inspection_spec.rb +1092 -0
  177. data/spec/unit/rspec/matchers/be_compared_to_spec.rb +23 -0
  178. data/spec/unit/rspec/matchers/be_falsey_spec.rb +9 -0
  179. data/spec/unit/rspec/matchers/be_nil_spec.rb +9 -0
  180. data/spec/unit/rspec/matchers/be_predicate_spec.rb +31 -0
  181. data/spec/unit/rspec/matchers/be_spec.rb +17 -0
  182. data/spec/unit/rspec/matchers/be_truthy_spec.rb +9 -0
  183. data/spec/unit/rspec/matchers/contain_exactly_spec.rb +11 -0
  184. data/spec/unit/rspec/matchers/eq_spec.rb +9 -0
  185. data/spec/unit/rspec/matchers/have_attributes_spec.rb +11 -0
  186. data/spec/unit/rspec/matchers/include_spec.rb +21 -0
  187. data/spec/unit/rspec/matchers/match_spec.rb +9 -0
  188. data/spec/unit/rspec/matchers/raise_error_spec.rb +29 -0
  189. data/spec/unit/rspec/matchers/respond_to_spec.rb +78 -0
  190. data/super_diff.gemspec +4 -2
  191. metadata +231 -34
  192. data/lib/super_diff/csi/color_helper.rb +0 -52
  193. data/lib/super_diff/csi/eight_bit_sequence.rb +0 -27
  194. data/lib/super_diff/csi/four_bit_sequence.rb +0 -24
  195. data/lib/super_diff/csi/sequence.rb +0 -22
  196. data/lib/super_diff/csi/twenty_four_bit_sequence.rb +0 -27
  197. data/lib/super_diff/diff_formatters/multi_line_string.rb +0 -31
  198. data/lib/super_diff/differs/object.rb +0 -68
  199. data/lib/super_diff/equality_matchers/object.rb +0 -18
  200. data/lib/super_diff/value_inspection.rb +0 -11
  201. data/spec/integration/rspec_spec.rb +0 -261
  202. data/spec/support/color_helper.rb +0 -49
  203. data/spec/support/person.rb +0 -23
  204. data/spec/support/person_diff_formatter.rb +0 -15
  205. data/spec/support/person_operation_sequence.rb +0 -14
  206. data/spec/support/person_operational_sequencer.rb +0 -19
@@ -1,8 +1,9 @@
1
1
  module SuperDiff
2
2
  module OperationalSequencers
3
- class MultiLineString < Base
4
- def self.applies_to?(value)
5
- value.is_a?(::String) && value.include?("\n")
3
+ class MultilineString < Base
4
+ def self.applies_to?(expected, actual)
5
+ expected.is_a?(::String) && actual.is_a?(::String) &&
6
+ (expected.include?("\n") || actual.include?("\n"))
6
7
  end
7
8
 
8
9
  def initialize(*args)
@@ -29,8 +30,8 @@ module SuperDiff
29
30
  end
30
31
  end
31
32
 
32
- def operation_sequence_class
33
- OperationSequences::Array
33
+ def build_operation_sequencer
34
+ OperationSequences::Array.new([])
34
35
  end
35
36
 
36
37
  private
@@ -38,7 +39,11 @@ module SuperDiff
38
39
  attr_reader :sequence_matcher, :original_expected, :original_actual
39
40
 
40
41
  def split_into_lines(str)
41
- str.split(/(\n)/).map { |v| v.tr("\n", "⏎") }.each_slice(2).map(&:join)
42
+ str.
43
+ split(/(\r?\n)/).
44
+ each_slice(2).
45
+ map(&:join).
46
+ map { |line| line.inspect[1..-2] }
42
47
  end
43
48
 
44
49
  def opcodes
@@ -0,0 +1,6 @@
1
+ module SuperDiff
2
+ module Operations
3
+ autoload :BinaryOperation, "super_diff/operations/binary_operation"
4
+ autoload :UnaryOperation, "super_diff/operations/unary_operation"
5
+ end
6
+ end
@@ -1,42 +1,22 @@
1
1
  module SuperDiff
2
2
  module Operations
3
3
  class BinaryOperation
4
- attr_reader(
5
- :name,
6
- :left_collection,
7
- :right_collection,
8
- :left_key,
9
- :right_key,
10
- :left_value,
11
- :right_value,
12
- :left_index,
13
- :right_index,
14
- :child_operations,
15
- )
4
+ extend AttrExtras.mixin
16
5
 
17
- def initialize(
18
- name:,
19
- left_collection:,
20
- right_collection:,
21
- left_index:,
22
- right_index:,
23
- left_key:,
24
- right_key:,
25
- left_value:,
26
- right_value:,
27
- child_operations: []
6
+ rattr_initialize(
7
+ [
8
+ :name!,
9
+ :left_collection!,
10
+ :right_collection!,
11
+ :left_key!,
12
+ :right_key!,
13
+ :left_value!,
14
+ :right_value!,
15
+ :left_index!,
16
+ :right_index!,
17
+ child_operations: [],
18
+ ],
28
19
  )
29
- @name = name
30
- @left_collection = left_collection
31
- @right_collection = right_collection
32
- @left_index = left_index
33
- @right_index = right_index
34
- @left_key = left_key
35
- @right_key = right_key
36
- @left_value = left_value
37
- @right_value = right_value
38
- @child_operations = child_operations
39
- end
40
20
 
41
21
  def should_add_comma_after_displaying?
42
22
  left_index < left_collection.size - 1 ||
@@ -7,18 +7,27 @@ module SuperDiff
7
7
  :key,
8
8
  :value,
9
9
  :index,
10
+ :index_in_collection,
10
11
  )
11
12
 
12
- def initialize(name:, collection:, key:, value:, index:)
13
+ def initialize(
14
+ name:,
15
+ collection:,
16
+ key:,
17
+ value:,
18
+ index:,
19
+ index_in_collection: index
20
+ )
13
21
  @name = name
14
22
  @collection = collection
15
23
  @key = key
16
24
  @value = value
17
25
  @index = index
26
+ @index_in_collection = index_in_collection
18
27
  end
19
28
 
20
29
  def should_add_comma_after_displaying?
21
- index < collection.size - 1
30
+ index_in_collection < collection.size - 1
22
31
  end
23
32
  end
24
33
  end
@@ -0,0 +1 @@
1
+ require "super_diff/active_record"
@@ -0,0 +1,47 @@
1
+ module SuperDiff
2
+ module RecursionGuard
3
+ RECURSION_GUARD_KEY = "super_diff_recursion_guard_key".freeze
4
+ PLACEHOLDER = "∙∙∙".freeze
5
+
6
+ def self.guarding_recursion_of(*objects, &block)
7
+ already_seen_objects, first_seen_objects = objects.partition do |object|
8
+ already_seen_object_ids.include?(object.object_id)
9
+ end
10
+
11
+ first_seen_objects.each do |object|
12
+ already_seen_object_ids.add(object.object_id)
13
+ end
14
+
15
+ result =
16
+ if block.arity > 0
17
+ block.call(already_seen_objects.any?)
18
+ else
19
+ block.call
20
+ end
21
+
22
+ first_seen_objects.each do |object|
23
+ already_seen_object_ids.delete(object.object_id)
24
+ end
25
+
26
+ result
27
+ end
28
+
29
+ def self.substituting_recursion_of(*objects)
30
+ guarding_recursion_of(*objects) do |already_seen|
31
+ if already_seen
32
+ PLACEHOLDER
33
+ else
34
+ yield
35
+ end
36
+ end
37
+ end
38
+
39
+ def self.already_seen_objects
40
+ already_seen_object_ids.map { |object_id| ObjectSpace._id2ref(object_id) }
41
+ end
42
+
43
+ def self.already_seen_object_ids
44
+ Thread.current[RECURSION_GUARD_KEY] ||= Set.new
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,2 @@
1
+ require "super_diff/rspec"
2
+ require "super_diff/rails"
@@ -1,19 +1,63 @@
1
- require_relative "../super_diff"
2
- require_relative "rspec/differ"
3
- require_relative "rspec/monkey_patches"
1
+ require "super_diff"
4
2
 
5
3
  module SuperDiff
6
4
  module RSpec
5
+ autoload :AugmentedMatcher, "super_diff/rspec/augmented_matcher"
6
+ autoload :Configuration, "super_diff/rspec/configuration"
7
+ autoload :Differ, "super_diff/rspec/differ"
8
+ autoload :Differs, "super_diff/rspec/differs"
9
+ autoload :MatcherTextBuilders, "super_diff/rspec/matcher_text_builders"
10
+ autoload :MatcherTextTemplate, "super_diff/rspec/matcher_text_template"
11
+ autoload :ObjectInspection, "super_diff/rspec/object_inspection"
12
+ autoload :OperationalSequencers, "super_diff/rspec/operational_sequencers"
13
+
7
14
  class << self
15
+ attr_accessor :extra_differ_classes
8
16
  attr_accessor :extra_operational_sequencer_classes
9
17
  attr_accessor :extra_diff_formatter_classes
18
+ end
19
+
20
+ def self.configure
21
+ yield configuration
22
+ end
23
+
24
+ def self.configuration
25
+ @_configuration ||= Configuration.new
26
+ end
27
+
28
+ def self.partial_hash?(value)
29
+ partial_placeholder?(value) &&
30
+ value.respond_to?(:expecteds) &&
31
+ value.expecteds.one? &&
32
+ value.expecteds.first.is_a?(::Hash)
33
+ end
10
34
 
11
- def configure
12
- yield self
13
- end
35
+ def self.partial_array?(value)
36
+ partial_placeholder?(value) &&
37
+ value.respond_to?(:expecteds) &&
38
+ !(value.expecteds.one? && value.expecteds.first.is_a?(::Hash))
14
39
  end
15
40
 
16
- self.extra_operational_sequencer_classes = []
17
- self.extra_diff_formatter_classes = []
41
+ def self.partial_object?(value)
42
+ partial_placeholder?(value) &&
43
+ value.base_matcher.is_a?(::RSpec::Matchers::BuiltIn::HaveAttributes)
44
+ end
45
+
46
+ def self.collection_containing_exactly?(value)
47
+ partial_placeholder?(value) &&
48
+ value.base_matcher.is_a?(::RSpec::Matchers::BuiltIn::ContainExactly)
49
+ end
50
+
51
+ def self.partial_placeholder?(value)
52
+ value.is_a?(::RSpec::Matchers::AliasedMatcher)
53
+ end
18
54
  end
19
55
  end
56
+
57
+ require_relative "rspec/monkey_patches"
58
+
59
+ SuperDiff::ObjectInspection.map.prepend(
60
+ SuperDiff::RSpec::ObjectInspection::MapExtension,
61
+ )
62
+
63
+ SuperDiff::Csi.color_enabled = RSpec.configuration.color_enabled?
@@ -0,0 +1,98 @@
1
+ module SuperDiff
2
+ module RSpec
3
+ module AugmentedMatcher
4
+ # Update to use expected_for_description instead of @expected
5
+ # TODO: Test
6
+ def description
7
+ matcher_text_builder.matcher_description
8
+ end
9
+
10
+ # Colorize the 'actual' value
11
+ def failure_message
12
+ build_failure_message(negated: false)
13
+ end
14
+
15
+ # Colorize the 'actual' value
16
+ def failure_message_when_negated
17
+ build_failure_message(negated: true)
18
+ end
19
+
20
+ # Always be diffable (we have the logic of whether to show a diff or not
21
+ # in SuperDiff::RSpec::Differ)
22
+ def diffable?
23
+ true
24
+ end
25
+
26
+ protected
27
+
28
+ def build_failure_message(negated:)
29
+ matcher_text_builder.call(negated: negated)
30
+ end
31
+
32
+ def matcher_text_builder
33
+ @_matcher_text_builder ||=
34
+ matcher_text_builder_class.new(matcher_text_builder_args)
35
+ end
36
+
37
+ def matcher_text_builder_class
38
+ RSpec::MatcherTextBuilders::Base
39
+ end
40
+
41
+ def matcher_text_builder_args
42
+ {
43
+ actual: actual_for_matcher_text,
44
+ expected_for_failure_message: expected_for_failure_message,
45
+ expected_for_description: expected_for_description,
46
+ expected_action_for_failure_message: expected_action_for_failure_message,
47
+ expected_action_for_description: expected_action_for_description,
48
+ }
49
+ end
50
+
51
+ def actual_for_matcher_text
52
+ description_of(actual)
53
+ end
54
+
55
+ def expected_for_matcher_text
56
+ description_of(expected)
57
+ end
58
+
59
+ def expected_for_failure_message
60
+ expected_for_matcher_text
61
+ end
62
+
63
+ def expected_for_description
64
+ expected_for_matcher_text
65
+ end
66
+
67
+ private
68
+
69
+ def expected_action_for_matcher_text
70
+ ::RSpec::Matchers::EnglishPhrasing.split_words(self.class.matcher_name)
71
+ end
72
+
73
+ def expected_action_for_failure_message
74
+ expected_action_for_matcher_text
75
+ end
76
+
77
+ def expected_action_for_description
78
+ expected_action_for_matcher_text
79
+ end
80
+
81
+ def readable_list_of(things)
82
+ ::RSpec::Matchers::EnglishPhrasing.list(things)
83
+ end
84
+
85
+ def matchers
86
+ Object.new.tap do |object|
87
+ object.singleton_class.class_eval do
88
+ include ::RSpec::Matchers
89
+ end
90
+ end
91
+ end
92
+
93
+ def colorizer
94
+ ::RSpec::Core::Formatters::ConsoleCodes
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,31 @@
1
+ module SuperDiff
2
+ module RSpec
3
+ class Configuration
4
+ attr_reader(
5
+ :extra_differ_classes,
6
+ :extra_operational_sequencer_classes,
7
+ :extra_diff_formatter_classes,
8
+ )
9
+
10
+ def initialize
11
+ @extra_differ_classes = [].freeze
12
+ @extra_operational_sequencer_classes = [].freeze
13
+ @extra_diff_formatter_classes = [].freeze
14
+ end
15
+
16
+ def add_extra_differ_class(klass)
17
+ @extra_differ_classes = (@extra_differ_classes + [klass]).freeze
18
+ end
19
+
20
+ def add_extra_operational_sequencer_class(klass)
21
+ @extra_operational_sequencer_classes =
22
+ (@extra_operational_sequencer_classes + [klass]).freeze
23
+ end
24
+
25
+ def add_extra_diff_formatter_class(klass)
26
+ @extra_diff_formatter_classes =
27
+ (@extra_diff_formatter_classes + [klass]).freeze
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,29 +1,73 @@
1
1
  module SuperDiff
2
2
  module RSpec
3
- module Differ
4
- def self.diff(actual, expected)
5
- if (
6
- expected != actual &&
7
- expected.class == actual.class &&
8
- !expected.is_a?(Symbol) &&
9
- !expected.is_a?(Integer) &&
10
- !(
11
- expected.is_a?(String) &&
12
- actual.is_a?(String) &&
13
- !expected.include?("\n") &&
14
- !actual.include?("\n")
15
- )
16
- )
3
+ class Differ
4
+ extend AttrExtras.mixin
5
+
6
+ static_facade :diff, :actual, :expected
7
+
8
+ def diff
9
+ if worth_diffing?
17
10
  diff = SuperDiff::Differ.call(
18
11
  expected,
19
12
  actual,
20
- extra_operational_sequencer_classes: RSpec.extra_operational_sequencer_classes,
21
- extra_diff_formatter_classes: RSpec.extra_diff_formatter_classes,
13
+ omit_empty: true,
14
+ extra_classes: [
15
+ *RSpec.configuration.extra_differ_classes,
16
+ Differs::CollectionContainingExactly,
17
+ Differs::PartialArray,
18
+ Differs::PartialHash,
19
+ Differs::PartialObject,
20
+ ],
21
+ extra_operational_sequencer_classes: [
22
+ *RSpec.configuration.extra_operational_sequencer_classes,
23
+ OperationalSequencers::CollectionContainingExactly,
24
+ OperationalSequencers::PartialArray,
25
+ OperationalSequencers::PartialHash,
26
+ OperationalSequencers::PartialObject,
27
+ ],
28
+ extra_diff_formatter_classes: RSpec.configuration.extra_diff_formatter_classes,
22
29
  )
23
30
  "\n\n" + diff
24
31
  else
25
32
  ""
26
33
  end
34
+ rescue NoDifferAvailableError
35
+ ""
36
+ end
37
+
38
+ private
39
+
40
+ def worth_diffing?
41
+ comparing_inequal_values? &&
42
+ !comparing_primitive_values? &&
43
+ !comparing_singleline_strings?
44
+ end
45
+
46
+ def comparing_inequal_values?
47
+ !helpers.values_match?(expected, actual)
48
+ end
49
+
50
+ def comparing_primitive_values?
51
+ expected.is_a?(Symbol) ||
52
+ expected.is_a?(Integer) ||
53
+ [true, false, nil].include?(expected)
54
+ end
55
+
56
+ def comparing_singleline_strings?
57
+ expected.is_a?(String) &&
58
+ actual.is_a?(String) &&
59
+ !expected.include?("\n") &&
60
+ !actual.include?("\n")
61
+ end
62
+
63
+ def helpers
64
+ @_helpers ||= Helpers.new
65
+ end
66
+
67
+ class Helpers
68
+ include ::RSpec::Matchers::Composable
69
+
70
+ public :values_match?
27
71
  end
28
72
  end
29
73
  end