rspec-enriched_json 0.4.0 → 0.6.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2959f4b47b6018d5293f62a8876036162f6428317796507fed22436312b7609c
4
- data.tar.gz: f27604ef443190fead00765e178a381e29871cdbfd5aea49486e7fd1336abbb6
3
+ metadata.gz: 02a818ba249d1c7880a696e4488a45d827261458a569624263c3983d86eb4f7d
4
+ data.tar.gz: bca3f6099bc1779a07bafd486a4da1734d102fa4d1a3ea97ac18dfe2e059d2ed
5
5
  SHA512:
6
- metadata.gz: 146df6d9cfd90245d34bf1ae4d913834e7ab45de3da22208fd5f5e46c49a6e39335acfa0d9db1e4f0b2270f34dfaa9d87abdc6babc3e24ab423f7fbf4ad0e546
7
- data.tar.gz: 31d802d2c5842ddee236f6e2b530dac5130fa7e8b3ed18c9d3b5269779e4bba0df00f425660e44e929cf87be76535a0ea8f334fd75132e9f593d6e11e9b2c549
6
+ metadata.gz: e5b929b27773dbe3423097855d06ce700d377f5fad568218d22a329fbae70714ddf38cb15300e458d3e55e61350b062f0bb32c165017205e334a674020f1ceba
7
+ data.tar.gz: afa583debdd99a3e93ce77f5764a6b57d22dfb32752565fb9c6f1ebc92b41b9f6801ac191ae7846b685f0c7ac52d8994530d4471ad34008c13b9e6279570da5d
data/README.md CHANGED
@@ -10,7 +10,7 @@ To see the difference between RSpec's built-in JSON formatter and this enriched
10
10
  ruby demo.rb
11
11
  ```
12
12
 
13
- This interactive demo script runs the same failing tests with both formatters and shows you the difference side-by-side. No external dependencies, no file cleanup needed!
13
+ This interactive demo script runs the same failing tests with both formatters and shows you the difference side-by-side.
14
14
 
15
15
  **What you'll see:**
16
16
  - **Built-in formatter**: Failure information embedded in string messages
@@ -88,9 +88,7 @@ With this gem, you get structured data alongside the original message:
88
88
  "actual": "Hello, World!",
89
89
  "matcher_name": "RSpec::Matchers::BuiltIn::Eq",
90
90
  "original_message": null,
91
- "diff_info": {
92
- "diffable": true
93
- }
91
+ "diffable": true
94
92
  }
95
93
  }
96
94
  ```
@@ -104,7 +102,7 @@ With this gem, you get structured data alongside the original message:
104
102
  - **Graceful degradation**: Regular exceptions (non-expectation failures) work normally
105
103
  - **Enhanced metadata capture**: Test location, tags, hierarchy, and custom metadata
106
104
  - **Robust error recovery**: Handles objects that fail to serialize without crashing
107
- - **Diff information**: Includes `diff_info.diffable` to help tools determine if values can be meaningfully diffed
105
+ - **Diff information**: Includes `diffable` to help tools determine if values can be meaningfully diffed
108
106
 
109
107
  ## Examples
110
108
 
@@ -111,11 +111,13 @@ module RSpec
111
111
  actual: Serializer.serialize_value(actual_raw),
112
112
  original_message: original_message, # Only populated when custom message overrides it
113
113
  matcher_name: matcher.class.name,
114
- diff_info: {
115
- diffable: values_diffable?(expected_raw, actual_raw, matcher)
116
- }
114
+ diffable: values_diffable?(expected_raw, actual_raw, matcher)
117
115
  }
118
116
 
117
+ # Capture matcher-specific instance variables
118
+ matcher_data = extract_matcher_specific_data(matcher)
119
+ details.merge!(matcher_data) unless matcher_data.empty?
120
+
119
121
  # Raise new exception with data attached
120
122
  raise EnrichedExpectationNotMetError.new(e.message, details)
121
123
  end
@@ -133,6 +135,71 @@ module RSpec
133
135
  nil
134
136
  end
135
137
 
138
+ def extract_matcher_specific_data(matcher)
139
+ # Skip common instance variables that are already captured
140
+ skip_vars = [
141
+ :@expected, :@actual, :@args, :@name,
142
+ # Skip internal implementation details
143
+ :@matcher, :@matchers, :@target,
144
+ :@delegator, :@base_matcher,
145
+ :@block, :@event_proc,
146
+ # Skip verbose internal state
147
+ :@pairings_maximizer, :@best_solution,
148
+ :@expected_captures, :@match_captures,
149
+ :@failures, :@errors,
150
+ # Skip RSpec internals
151
+ :@matcher_execution_context,
152
+ :@chained_method_with_args_combos
153
+ ]
154
+
155
+ # Define meaningful variables we want to keep
156
+ useful_vars = [
157
+ :@missing_items, :@extra_items, # ContainExactly
158
+ :@expecteds, :@actuals, # Include
159
+ :@operator, :@delta, :@tolerance, # Comparison matchers
160
+ :@expected_before, :@expected_after, :@actual_before, :@actual_after, # Change matcher
161
+ :@from, :@to, :@minimum, :@maximum, :@count, # Various matchers
162
+ :@failure_message, :@failure_message_when_negated,
163
+ :@description
164
+ ]
165
+
166
+ # Get all instance variables
167
+ ivars = matcher.instance_variables - skip_vars
168
+ return {} if ivars.empty?
169
+
170
+ # Build a hash of matcher-specific data
171
+ matcher_data = {}
172
+
173
+ ivars.each do |ivar|
174
+ # Only include if it's in our useful list or looks like user data
175
+ unless useful_vars.include?(ivar) || ivar.to_s.match?(/^@(missing|extra|failed|unmatched|matched)_/)
176
+ next
177
+ end
178
+
179
+ value = matcher.instance_variable_get(ivar)
180
+
181
+ # Skip if value is nil or the matcher itself
182
+ next if value.nil? || value == matcher
183
+
184
+ # Skip procs and complex objects unless they're simple collections
185
+ if value.is_a?(Proc) || (value.is_a?(Object) && !value.is_a?(Enumerable) && !value.is_a?(Numeric) && !value.is_a?(String) && !value.is_a?(Symbol))
186
+ next
187
+ end
188
+
189
+ # Convert instance variable name to a more readable format
190
+ # @missing_items -> missing_items
191
+ key = ivar.to_s.delete_prefix("@").to_sym
192
+
193
+ # Serialize the value
194
+ matcher_data[key] = Serializer.serialize_value(value)
195
+ rescue
196
+ # Skip this instance variable if we can't serialize it
197
+ next
198
+ end
199
+
200
+ matcher_data
201
+ end
202
+
136
203
  def values_diffable?(expected, actual, matcher)
137
204
  # First check if the matcher itself declares diffability
138
205
  if matcher.respond_to?(:diffable?)
@@ -85,13 +85,22 @@ module RSpec
85
85
  end
86
86
 
87
87
  def safe_structured_data(details)
88
- {
88
+ # Start with core fields
89
+ result = {
89
90
  expected: safe_serialize(details[:expected]),
90
91
  actual: safe_serialize(details[:actual]),
91
92
  matcher_name: details[:matcher_name],
92
93
  original_message: details[:original_message],
93
- diff_info: details[:diff_info]
94
- }.compact
94
+ diffable: details[:diffable]
95
+ }
96
+
97
+ # Add any additional matcher-specific fields
98
+ details.each do |key, value|
99
+ next if [:expected, :actual, :matcher_name, :original_message, :diffable].include?(key)
100
+ result[key] = safe_serialize(value)
101
+ end
102
+
103
+ result.compact
95
104
  end
96
105
 
97
106
  def safe_serialize(value)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RSpec
4
4
  module EnrichedJson
5
- VERSION = "0.4.0"
5
+ VERSION = "0.6.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-enriched_json
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Raghu Betina