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
@@ -0,0 +1,13 @@
1
+ module SuperDiff
2
+ module RSpec
3
+ module Differs
4
+ autoload(
5
+ :CollectionContainingExactly,
6
+ "super_diff/rspec/differs/collection_containing_exactly",
7
+ )
8
+ autoload :PartialArray, "super_diff/rspec/differs/partial_array"
9
+ autoload :PartialHash, "super_diff/rspec/differs/partial_hash"
10
+ autoload :PartialObject, "super_diff/rspec/differs/partial_object"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ module SuperDiff
2
+ module RSpec
3
+ module Differs
4
+ class CollectionContainingExactly < SuperDiff::Differs::Array
5
+ def self.applies_to?(expected, actual)
6
+ SuperDiff::RSpec.collection_containing_exactly?(expected) &&
7
+ actual.is_a?(::Array)
8
+ end
9
+
10
+ private
11
+
12
+ def operations
13
+ OperationalSequencers::CollectionContainingExactly.call(
14
+ expected: expected,
15
+ actual: actual,
16
+ extra_operational_sequencer_classes: extra_operational_sequencer_classes,
17
+ extra_diff_formatter_classes: extra_diff_formatter_classes,
18
+ )
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,22 @@
1
+ module SuperDiff
2
+ module RSpec
3
+ module Differs
4
+ class PartialArray < SuperDiff::Differs::Array
5
+ def self.applies_to?(expected, actual)
6
+ SuperDiff::RSpec.partial_array?(expected) && actual.is_a?(::Array)
7
+ end
8
+
9
+ private
10
+
11
+ def operations
12
+ OperationalSequencers::PartialArray.call(
13
+ expected: expected,
14
+ actual: actual,
15
+ extra_operational_sequencer_classes: extra_operational_sequencer_classes,
16
+ extra_diff_formatter_classes: extra_diff_formatter_classes,
17
+ )
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ module SuperDiff
2
+ module RSpec
3
+ module Differs
4
+ class PartialHash < SuperDiff::Differs::Hash
5
+ def self.applies_to?(expected, actual)
6
+ SuperDiff::RSpec.partial_hash?(expected) && actual.is_a?(::Hash)
7
+ end
8
+
9
+ private
10
+
11
+ def operations
12
+ OperationalSequencers::PartialHash.call(
13
+ expected: expected,
14
+ actual: actual,
15
+ extra_operational_sequencer_classes: extra_operational_sequencer_classes,
16
+ extra_diff_formatter_classes: extra_diff_formatter_classes,
17
+ )
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ module SuperDiff
2
+ module RSpec
3
+ module Differs
4
+ class PartialObject < SuperDiff::Differs::DefaultObject
5
+ def self.applies_to?(expected, _actual)
6
+ SuperDiff::RSpec.partial_object?(expected)
7
+ end
8
+
9
+ private
10
+
11
+ def operations
12
+ OperationalSequencers::PartialObject.call(
13
+ expected: expected,
14
+ actual: actual,
15
+ extra_operational_sequencer_classes: extra_operational_sequencer_classes,
16
+ extra_diff_formatter_classes: extra_diff_formatter_classes,
17
+ )
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ module SuperDiff
2
+ module RSpec
3
+ module MatcherTextBuilders
4
+ autoload :Base, "super_diff/rspec/matcher_text_builders/base"
5
+ autoload(
6
+ :BePredicate,
7
+ "super_diff/rspec/matcher_text_builders/be_predicate",
8
+ )
9
+ autoload(
10
+ :ContainExactly,
11
+ "super_diff/rspec/matcher_text_builders/contain_exactly",
12
+ )
13
+ autoload :Match, "super_diff/rspec/matcher_text_builders/match"
14
+ autoload(
15
+ :RaiseError,
16
+ "super_diff/rspec/matcher_text_builders/raise_error",
17
+ )
18
+ autoload(
19
+ :RespondTo,
20
+ "super_diff/rspec/matcher_text_builders/respond_to",
21
+ )
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,155 @@
1
+ module SuperDiff
2
+ module RSpec
3
+ module MatcherTextBuilders
4
+ class Base
5
+ def initialize(
6
+ actual:,
7
+ expected_for_failure_message:,
8
+ expected_for_description:,
9
+ expected_action_for_failure_message:,
10
+ expected_action_for_description:
11
+ )
12
+ @actual = actual
13
+ @expected_for_failure_message = expected_for_failure_message
14
+ @expected_for_description = expected_for_description
15
+ @expected_action_for_failure_message =
16
+ expected_action_for_failure_message
17
+ @expected_action_for_description = expected_action_for_description
18
+
19
+ @negated = nil
20
+ @template = MatcherTextTemplate.new
21
+ end
22
+
23
+ def call(negated:)
24
+ @negated = negated
25
+
26
+ fill_template
27
+ template.to_s
28
+ end
29
+
30
+ def matcher_description
31
+ template = MatcherTextTemplate.new do |t|
32
+ t.add_text expected_action_for_description
33
+ add_expected_value_to_description(t)
34
+ add_extra_after_expected_to(t)
35
+ end
36
+
37
+ Csi.decolorize(template.to_s(as_single_line: true))
38
+ end
39
+
40
+ protected
41
+
42
+ def add_extra_after_expected_to(template)
43
+ end
44
+
45
+ def add_extra_after_error
46
+ end
47
+
48
+ def beta_color
49
+ SuperDiff::COLORS.fetch(:beta)
50
+ end
51
+
52
+ def alpha_color
53
+ SuperDiff::COLORS.fetch(:alpha)
54
+ end
55
+
56
+ private
57
+
58
+ attr_reader(
59
+ :actual,
60
+ :expected_for_failure_message,
61
+ :expected_for_description,
62
+ :expected_action_for_failure_message,
63
+ :expected_action_for_description,
64
+ :template,
65
+ )
66
+
67
+ def negated?
68
+ @negated
69
+ end
70
+
71
+ def fill_template
72
+ add_actual_section
73
+ template.add_break
74
+ template.insert expected_section
75
+ add_extra_after_expected_to(template)
76
+ template.add_text_in_singleline_mode "."
77
+ add_extra_after_error
78
+ end
79
+
80
+ def add_actual_section
81
+ template.add_text_in_singleline_mode actual_phrase
82
+ template.add_text_in_multiline_mode do
83
+ actual_phrase.rjust(phrase_width)
84
+ end
85
+ template.add_text " "
86
+ add_actual_value
87
+ end
88
+
89
+ def actual_phrase
90
+ "Expected"
91
+ end
92
+
93
+ def add_actual_value
94
+ template.add_text_in_color(beta_color) { actual }
95
+ end
96
+
97
+ def expected_section
98
+ MatcherTextTemplate.new do |t|
99
+ t.add_text_in_singleline_mode expected_phrase
100
+ t.add_text_in_multiline_mode do
101
+ expected_phrase.to_s.rjust(phrase_width)
102
+ end
103
+ add_expected_value_to_failure_message(t)
104
+ end
105
+ end
106
+
107
+ def add_expected_value_to_failure_message(template)
108
+ if respond_to?(:add_expected_value_to, true)
109
+ add_expected_value_to(template, expected_for_failure_message)
110
+ else
111
+ template.add_text " "
112
+ template.add_text_in_color(
113
+ alpha_color,
114
+ expected_for_failure_message,
115
+ )
116
+ end
117
+ end
118
+
119
+ def add_expected_value_to_description(template)
120
+ if respond_to?(:add_expected_value_to, true)
121
+ add_expected_value_to(template, expected_for_description)
122
+ else
123
+ template.add_text " "
124
+ template.add_text_in_color(alpha_color, expected_for_description)
125
+ end
126
+ end
127
+
128
+ def expected_phrase
129
+ "#{to_or_not_to} #{expected_action_for_failure_message}"
130
+ end
131
+
132
+ def to_or_not_to
133
+ if negated?
134
+ "not to"
135
+ else
136
+ "to"
137
+ end
138
+ end
139
+
140
+ def phrase_width
141
+ [actual_phrase, expected_phrase].
142
+ map { |text| Csi.decolorize(text.to_s).length }.
143
+ max
144
+ end
145
+
146
+ # TODO: Should this be applied to expected and actual automatically
147
+ # instead of expecting the caller to pass in already formatted versions
148
+ # of those objects?
149
+ def description_of(object)
150
+ ::RSpec::Support::ObjectFormatter.format(object)
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,78 @@
1
+ module SuperDiff
2
+ module RSpec
3
+ module MatcherTextBuilders
4
+ class BePredicate < Base
5
+ def initialize(
6
+ predicate_accessible:,
7
+ private_predicate:,
8
+ expected_predicate_method_name:,
9
+ **rest
10
+ )
11
+ super(**rest)
12
+ @predicate_accessible = predicate_accessible
13
+ @private_predicate = private_predicate
14
+ @expected_predicate_method_name = expected_predicate_method_name
15
+ end
16
+
17
+ protected
18
+
19
+ def expected_action_for_failure_message
20
+ if predicate_accessible?
21
+ "return a truthy result for"
22
+ elsif private_predicate?
23
+ "have a public method"
24
+ else
25
+ "respond to"
26
+ end
27
+ end
28
+
29
+ def beta_color
30
+ :yellow
31
+ end
32
+
33
+ def add_actual_value
34
+ template.add_text_in_color(beta_color) do
35
+ description_of(actual)
36
+ end
37
+ end
38
+
39
+ def add_expected_value_to(template, expected)
40
+ template.add_text " "
41
+ template.add_text_in_color(alpha_color, "`#{expected}?`")
42
+ template.add_text " or "
43
+ template.add_text_in_color(alpha_color, "`#{expected}s?`")
44
+ end
45
+
46
+ def add_extra_after_error
47
+ if expected_predicate_method_name == :true?
48
+ template.add_text "\n\n"
49
+ template.add_text "(Perhaps you want to use "
50
+ template.add_text_in_color(:blue, "`be(true)`")
51
+ template.add_text " or "
52
+ template.add_text_in_color(:blue, "`be_truthy`")
53
+ template.add_text " instead?)"
54
+ elsif expected_predicate_method_name == :false?
55
+ template.add_text "\n\n"
56
+ template.add_text "(Perhaps you want to use "
57
+ template.add_text_in_color(:blue, "`be(false)`")
58
+ template.add_text " or "
59
+ template.add_text_in_color(:blue, "`be_falsey`")
60
+ template.add_text " instead?)"
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ attr_reader :expected_predicate_method_name
67
+
68
+ def predicate_accessible?
69
+ @predicate_accessible
70
+ end
71
+
72
+ def private_predicate?
73
+ @private_predicate
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,14 @@
1
+ module SuperDiff
2
+ module RSpec
3
+ module MatcherTextBuilders
4
+ class ContainExactly < Base
5
+ protected
6
+
7
+ def add_expected_value_to(template, expected)
8
+ template.add_text " "
9
+ template.add_list_in_color(alpha_color, expected)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,23 @@
1
+ module SuperDiff
2
+ module RSpec
3
+ module MatcherTextBuilders
4
+ class Match < Base
5
+ def initialize(expected_captures:, **rest)
6
+ super(rest)
7
+ @expected_captures = expected_captures
8
+ end
9
+
10
+ def add_extra
11
+ if expected_captures
12
+ template.add_text "with captures "
13
+ template.add_text_in_color :blue, description_of(expected_captures)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :expected_captures
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,13 @@
1
+ module SuperDiff
2
+ module RSpec
3
+ module MatcherTextBuilders
4
+ class RaiseError < Base
5
+ protected
6
+
7
+ def actual_phrase
8
+ "Expected raised exception"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,99 @@
1
+ module SuperDiff
2
+ module RSpec
3
+ module MatcherTextBuilders
4
+ class RespondTo < Base
5
+ def initialize(
6
+ expected_arity:,
7
+ arbitrary_keywords:,
8
+ expected_keywords:,
9
+ unlimited_arguments:,
10
+ **rest
11
+ )
12
+ super(rest)
13
+ @expected_arity = expected_arity
14
+ @arbitrary_keywords = arbitrary_keywords
15
+ @expected_keywords = expected_keywords
16
+ @unlimited_arguments = unlimited_arguments
17
+ end
18
+
19
+ protected
20
+
21
+ def add_expected_value_to(template, expected)
22
+ template.add_text " "
23
+ template.add_list_in_color(alpha_color, expected)
24
+ end
25
+
26
+ def add_extra_after_expected_to(template)
27
+ if expected_arity
28
+ add_arity_clause_to(template)
29
+ end
30
+
31
+ if arbitrary_keywords?
32
+ add_arbitrary_keywords_clause_to(template)
33
+ elsif has_expected_keywords?
34
+ add_keywords_clause_to(template)
35
+ end
36
+
37
+ if unlimited_arguments?
38
+ add_unlimited_arguments_clause_to(template)
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ attr_reader :expected_arity, :expected_keywords
45
+
46
+ def arbitrary_keywords?
47
+ @arbitrary_keywords
48
+ end
49
+
50
+ def has_expected_keywords?
51
+ expected_keywords && expected_keywords.count > 0
52
+ end
53
+
54
+ def unlimited_arguments?
55
+ @unlimited_arguments
56
+ end
57
+
58
+ def add_arity_clause_to(template)
59
+ template.add_text " with "
60
+ template.add_text_in_color alpha_color, expected_arity
61
+ template.add_text " "
62
+ template.add_text pluralize("argument", expected_arity)
63
+ end
64
+
65
+ def add_arbitrary_keywords_clause_to(template)
66
+ template.add_text " with "
67
+ template.add_text_in_color alpha_color, "any"
68
+ template.add_text " keywords"
69
+ end
70
+
71
+ def add_keywords_clause_to(template)
72
+ template.add_text " with "
73
+ template.add_text pluralize("keyword", expected_keywords.length)
74
+ template.add_text " "
75
+ template.add_list_in_color alpha_color, expected_keywords
76
+ end
77
+
78
+ def add_unlimited_arguments_clause_to(template)
79
+ if arbitrary_keywords? || has_expected_keywords?
80
+ template.add_text " and "
81
+ else
82
+ template.add_text " with "
83
+ end
84
+
85
+ template.add_text_in_color alpha_color, "unlimited"
86
+ template.add_text " arguments"
87
+ end
88
+
89
+ def pluralize(word, count)
90
+ if count == 1
91
+ word
92
+ else
93
+ "#{word}s"
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end