specdiff 0.3.0.rc2 → 0.3.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 +4 -4
- data/CHANGELOG.md +6 -0
- data/DEVELOPMENT.md +74 -0
- data/README.md +139 -98
- data/glossary.txt +4 -0
- data/lib/specdiff/differ/hash.rb +5 -0
- data/lib/specdiff/hashprint.rb +36 -29
- data/lib/specdiff/rspec.rb +2 -0
- data/lib/specdiff/version.rb +1 -1
- data/lib/specdiff/webmock.rb +1 -0
- data/lib/specdiff.rb +0 -5
- data/specdiff.gemspec +11 -3
- metadata +17 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 16d43f0ff6248844478dc69d99ebb9e5de1212804fba96b859d947e446e5fae7
|
|
4
|
+
data.tar.gz: 0c9e973795920664617d2c57211e40569a0aee10ee6b6c35b02680a6789edf2f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a21ca995b7418a69deaeb6c024f40b2fc6342200edc33f4179f979ce7555bf346b29012184784b59f0736ac55b089a55836dd21756e14100d7a76260b5c7d69a
|
|
7
|
+
data.tar.gz: e457b0266ddc5f11df693baae9594dd790498e687ce7a4d263b9b291108af2a14f976499dd3b1eee9294a6827e2f15f527c0ae451035c8f73dc2dbaea9245f2d
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.0] - 2024-04-16
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Hashprint now sorts keys (if all the keys are strings or symbols), leading to better text diffs from the hash differ.
|
|
15
|
+
|
|
10
16
|
## [0.3.0.rc2] - 2024-04-05
|
|
11
17
|
|
|
12
18
|
### Changed
|
data/DEVELOPMENT.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Development
|
|
2
|
+
|
|
3
|
+
## Glossary
|
|
4
|
+
|
|
5
|
+
Check out the [glossary](./glossary.txt) to make sure we are using the same
|
|
6
|
+
words for things.
|
|
7
|
+
|
|
8
|
+
## Setup
|
|
9
|
+
|
|
10
|
+
Install the software versions specified in `.tool-versions`.
|
|
11
|
+
|
|
12
|
+
Run `bin/setup` to install dependencies. Then, run `bundle exec rake` to run
|
|
13
|
+
the tests and linter and make sure they're green
|
|
14
|
+
before starting to make your changes.
|
|
15
|
+
|
|
16
|
+
Run `bundle exec rake -AD` for a full list of all the available tasks you may use for development purposes.
|
|
17
|
+
|
|
18
|
+
Run `bundle exec rake` to run the tests and linter.
|
|
19
|
+
|
|
20
|
+
## Examples
|
|
21
|
+
|
|
22
|
+
The `examples/` directory is used as an ad-hoc integration testing method.
|
|
23
|
+
[Read more here](./examples/)
|
|
24
|
+
|
|
25
|
+
## Pull request checklist
|
|
26
|
+
|
|
27
|
+
- [ ] Make sure the tests are passing
|
|
28
|
+
- [ ] Make sure the linter is happy
|
|
29
|
+
- [ ] Make sure the `examples/` look the same or have suffered and improvement
|
|
30
|
+
- [ ] Update the unreleased section of the [changelog](./CHANGELOG.md) with a human readable explanation of your changes
|
|
31
|
+
|
|
32
|
+
## Architecture
|
|
33
|
+
|
|
34
|
+
High level description of the heuristic specdiff implements
|
|
35
|
+
|
|
36
|
+
1. receive 2 pieces of data: `a` and `b`
|
|
37
|
+
2. determine types for `a` and `b`
|
|
38
|
+
1. test against plugin types
|
|
39
|
+
2. test against built in types
|
|
40
|
+
3. fall back to the `:unknown` type
|
|
41
|
+
3. determine which differ is appropriate for the types
|
|
42
|
+
1. test against plugin differs
|
|
43
|
+
2. test against built in differs
|
|
44
|
+
3. fall back to the null differ (`NotFound`)
|
|
45
|
+
7. run the selected differ with a and b
|
|
46
|
+
8. package it into a `::Specdiff::Diff` which records the detected types
|
|
47
|
+
|
|
48
|
+
\<time passes>
|
|
49
|
+
|
|
50
|
+
6. at some point later when `#to_s` is invoked, stringify the diff using the differ's `#stringify`
|
|
51
|
+
|
|
52
|
+
## Maintainer's notes
|
|
53
|
+
|
|
54
|
+
### Release procedure
|
|
55
|
+
|
|
56
|
+
- [ ] unit tests are passing (`$ bundle exec rake test`)
|
|
57
|
+
- [ ] linter is happy (`$ bundle exec rake lint`)
|
|
58
|
+
- [ ] `examples/` look good
|
|
59
|
+
- [ ] check the package size using `$ bundle exec inspect_build`, make sure you haven't added any large files by accident
|
|
60
|
+
- [ ] update the version number in `version.rb`
|
|
61
|
+
- [ ] make sure the `examples/` `Gemfile.lock` files are updated (run bundle install)
|
|
62
|
+
- [ ] make sure `Gemfile.lock` is updated (run bundle install)
|
|
63
|
+
- [ ] move unreleased changes to the next version in the [changelog](./CHANGELOG.md)
|
|
64
|
+
- [ ] commit in the form "vX.X.X" and push
|
|
65
|
+
- [ ] make sure the pipeline is green
|
|
66
|
+
- [ ] `$ bundle exec rake release`
|
|
67
|
+
|
|
68
|
+
### Contemplated improvements (AKA the todo list)
|
|
69
|
+
|
|
70
|
+
- [ ] word diff
|
|
71
|
+
- [ ] yard documentation?
|
|
72
|
+
- [ ] 2.7.0 support
|
|
73
|
+
- [ ] actual integration tests (replacing `examples/`)
|
|
74
|
+
- [ ] real documentation for the plugin interface
|
data/README.md
CHANGED
|
@@ -1,36 +1,40 @@
|
|
|
1
1
|
# Specdiff
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Specdiff is an opinionated gem that provides diffing between arbitrary data. It
|
|
4
|
+
was built in an effort to improve [WebMock](https://rubygems.org/gems/webmock)'s
|
|
5
|
+
and [RSpec](https://rubygems.org/gems/rspec)'s diff output, and
|
|
6
|
+
comes with integrations for both. It produces output that looks very similiar to
|
|
7
|
+
RSpec, but with better support for nested hash/array structures.
|
|
4
8
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
if they happen to both be json (including setting content type). This gem aims
|
|
8
|
-
to bring text diffing (ala rspec) to webmock via monkey-patch, as well as
|
|
9
|
-
dropping the content type requirement.
|
|
9
|
+
By default, specdiff will produce diff output for multiline text by using
|
|
10
|
+
[diff-lcs](https://rubygems.org/gems/diff-lcs):
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
diff between them.
|
|
12
|
+

|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
It also diffs hashes and arrays:
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
diff
|
|
16
|
+
|  |  |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| Hashdiff based hash diff | Text based hash diff |
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
Specdiff will automatically switch between these two types of hash/array diff
|
|
21
|
+
output depending on what it thinks is more readable. The first type of output
|
|
22
|
+
showcased here comes from the
|
|
23
|
+
[hashdiff](https://rubygems.org/gems/hashdiff) gem, one of specdiff's
|
|
24
|
+
dependencies. The other is the *text diff* run on the output of *hashprint*.
|
|
25
|
+
Specdiff switches to using hashprint/text diff when it estimates that a lot of
|
|
26
|
+
the keys changed names, which is a point of weakness for hashdiff's output.
|
|
21
27
|
|
|
22
|
-
|
|
23
|
-
even if the request did not have the content type header:
|
|
24
|
-
|
|
25
|
-

|
|
26
|
-
|
|
27
|
-
(The output of the json diff is experimental, feedback would be great!)
|
|
28
|
+
## Installation
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
### Requirements
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
Specdiff is tested to work with:
|
|
33
|
+
- Ruby `>= 3.0`.
|
|
34
|
+
- RSpec `3.13.0`, `3.12.2`, `3.12.0`.
|
|
35
|
+
- WebMock `3.19.1`, `3.18.1`.
|
|
32
36
|
|
|
33
|
-
|
|
37
|
+
### Use bundler
|
|
34
38
|
|
|
35
39
|
Add this line to your application's Gemfile:
|
|
36
40
|
|
|
@@ -40,122 +44,159 @@ gem "specdiff", require: false
|
|
|
40
44
|
|
|
41
45
|
And then execute:
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
Or install it yourself as:
|
|
47
|
+
`$ bundle install`
|
|
46
48
|
|
|
47
|
-
|
|
49
|
+
### Loading the gem and its integrations
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
Put the following in your `spec_helper.rb`. (Or equivalent initializer
|
|
52
|
-
for test environment) You probably don't want to load/use this gem in a release
|
|
53
|
-
environment.
|
|
51
|
+
Put the following in the initializer for your test environment (`spec_helper.rb`):
|
|
54
52
|
|
|
55
53
|
```rb
|
|
56
|
-
#
|
|
57
|
-
|
|
58
|
-
require "specdiff"
|
|
59
|
-
|
|
54
|
+
require "specdiff" # may be unneccessary if you're using bundler to load your gems
|
|
55
|
+
require "specdiff/rspec" # optional, enables RSpec integration
|
|
56
|
+
require "specdiff/webmock" # optional, enables WebMock integration
|
|
57
|
+
Specdiff.load!(:json) # optional, automatically detects json and uses the hash differ on it
|
|
60
58
|
|
|
61
|
-
# optionally, you can turn off terminal colors
|
|
62
59
|
Specdiff.configure do |config|
|
|
63
|
-
config.colorize = true
|
|
60
|
+
config.colorize = true # toggles color output
|
|
64
61
|
end
|
|
65
62
|
```
|
|
66
63
|
|
|
64
|
+
The monkey-patches should go after the gems they are patching.
|
|
65
|
+
|
|
66
|
+
*This gem is intended for use in test environments, not production or release environments.*
|
|
67
|
+
|
|
68
|
+
## Usage
|
|
69
|
+
|
|
70
|
+
Specdiff has two integrations: [WebMock](https://rubygems.org/gems/webmock) and
|
|
71
|
+
[RSpec](https://rubygems.org/gems/rspec). These are the main way specdiff is
|
|
72
|
+
intended to be used.
|
|
73
|
+
|
|
74
|
+
### RSpec
|
|
75
|
+
|
|
76
|
+
The RSpec integration improves on RSpec's built in diffing functionality by
|
|
77
|
+
diffing nested hash/array structures with
|
|
78
|
+
[hashdiff](https://rubygems.org/gems/hashdiff). This produces clearer
|
|
79
|
+
output when deeply nested structures are involved:
|
|
80
|
+
|
|
81
|
+
|  |  |  |
|
|
82
|
+
| --- | --- | --- |
|
|
83
|
+
| Test source | RSpec's diff | Specdiff's diff |
|
|
84
|
+
|
|
85
|
+
In some cases specdiff may produce a text-based diff of deeply nested hashes or
|
|
86
|
+
arrays instead. This also represents an improvement over RSpec's text-based diff
|
|
87
|
+
of nested hashes/arrays, by virtue of custom pretty-printing code designed for
|
|
88
|
+
the text differ to work on:
|
|
89
|
+
|
|
90
|
+
|  |  |  |
|
|
91
|
+
| --- | --- | --- |
|
|
92
|
+
| Test source | RSpec's diff | Specdiff's diff |
|
|
93
|
+
|
|
94
|
+
The RSpec integration also prevents RSpec from truncating your data before
|
|
95
|
+
printing it (by replacing the inspect implementation), avoiding the necessity
|
|
96
|
+
of a diff in some instances:
|
|
97
|
+
|
|
98
|
+
|  |  |
|
|
99
|
+
| --- | --- |
|
|
100
|
+
| RSpec truncating your data | Specdiff preventing truncation |
|
|
101
|
+
|
|
102
|
+
(Although this is an instance where a "word diff" would be more helpful)
|
|
103
|
+
|
|
67
104
|
### WebMock
|
|
68
105
|
|
|
69
|
-
|
|
70
|
-
|
|
106
|
+
WebMock already ships with a dependency on
|
|
107
|
+
[hashdiff](https://rubygems.org/gems/hashdiff), providing diffs of json request
|
|
108
|
+
stubs. Specdiff prints hashdiff's output differently, and does not require the
|
|
109
|
+
content type to be specified:
|
|
71
110
|
|
|
72
|
-
|
|
111
|
+
(This requires you to enable the json plugin)
|
|
73
112
|
|
|
74
|
-
|
|
113
|
+
|  |  |  |
|
|
114
|
+
| --- | --- | --- |
|
|
115
|
+
| Source | WebMock | Specdiff |
|
|
75
116
|
|
|
76
|
-
|
|
77
|
-
diff = Specdiff.diff(something, and_something_else)
|
|
117
|
+
With specdiff enabled you also get text diffs where previously there were none:
|
|
78
118
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
119
|
+
|  |  |  |
|
|
120
|
+
| --- | --- | --- |
|
|
121
|
+
| Source | WebMock | Specdiff |
|
|
82
122
|
|
|
83
|
-
|
|
123
|
+
The WebMock integration continues to respect the `show_body_diff` setting in
|
|
124
|
+
WebMock:
|
|
84
125
|
|
|
85
126
|
```rb
|
|
86
|
-
#
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
Specdiff.load!(MyCustomType)
|
|
127
|
+
# this will cause diffs to not be produced, regardless of whether specdiff is
|
|
128
|
+
# loaded. body diffs are enabled by default in WebMock so you don't need to
|
|
129
|
+
# touch this.
|
|
130
|
+
WebMock.hide_body_diff!
|
|
91
131
|
```
|
|
92
132
|
|
|
93
|
-
|
|
133
|
+
### Direct usage
|
|
134
|
+
|
|
135
|
+
It is also possible to call into specdiff with arbitrary data.
|
|
136
|
+
This is essentially what the integrations do for you.
|
|
137
|
+
This is suitable if you are developing a library and intend to depend on
|
|
138
|
+
specdiff for diff output.
|
|
94
139
|
|
|
95
|
-
|
|
140
|
+
```rb
|
|
141
|
+
# Generate a diff, using all plugins available.
|
|
142
|
+
diff = Specdiff.diff(something, anything)
|
|
96
143
|
|
|
97
|
-
|
|
98
|
-
|
|
144
|
+
diff.empty? # => true/false, if true you probably don't want to actually show the diff
|
|
145
|
+
diff.to_s # => a String for showing to a developer who may or may not be scratching their head
|
|
99
146
|
|
|
100
|
-
|
|
147
|
+
# Generate an indented, pretty-printed string representation of a ruby hash.
|
|
148
|
+
printed_hash = Specdiff.hashprint(my_big_nested_hash)
|
|
149
|
+
printed_hash # => String
|
|
150
|
+
|
|
151
|
+
# Inspect something, but with prettier output for certain classes
|
|
152
|
+
# (Time/DateTime/BigDecimal). This is not indented. Usually defers to #inspect.
|
|
153
|
+
specdiff_inspected = Specdiff.diff_inspect(something)
|
|
154
|
+
specdiff_inspected # => String
|
|
155
|
+
```
|
|
101
156
|
|
|
102
|
-
|
|
157
|
+
Any methods or properties not documented here are considered private
|
|
158
|
+
implementation details.
|
|
103
159
|
|
|
104
|
-
|
|
160
|
+
## Plugins
|
|
105
161
|
|
|
106
|
-
|
|
162
|
+
It is possible to create and load plugins into specdiff to customize Specdiff's
|
|
163
|
+
behaviour. This was implemented in case you have special needs (e.g. diffing
|
|
164
|
+
things other than text, hashes, arrays and json).
|
|
107
165
|
|
|
108
|
-
|
|
166
|
+
### JSON
|
|
109
167
|
|
|
110
|
-
|
|
168
|
+
The built-in json plugin is optional, and loaded like so:
|
|
111
169
|
|
|
112
|
-
|
|
170
|
+
```rb
|
|
171
|
+
Specdiff.load!(:json)
|
|
172
|
+
```
|
|
113
173
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
2. test against built in types
|
|
118
|
-
3. fall back to the `:unknown` type
|
|
119
|
-
3. determine which differ is appropriate for the types
|
|
120
|
-
1. test against plugin differs
|
|
121
|
-
2. test against built in differs
|
|
122
|
-
3. fall back to the null differ (`NotFound`)
|
|
123
|
-
7. run the selected differ with a and b
|
|
124
|
-
8. package it into a `::Specdiff::Diff` which records the detected types
|
|
174
|
+
The JSON plugin attempts to parse strings into json using `JSON.parse`. If
|
|
175
|
+
successful, it considers that string a json, and will use the parse result as if
|
|
176
|
+
it had been passed directly to specdiff in the first place.
|
|
125
177
|
|
|
126
|
-
|
|
178
|
+
### Defining your own plugins
|
|
127
179
|
|
|
128
|
-
|
|
180
|
+
While other plugins are loaded by simply passing them to `::load!`:
|
|
129
181
|
|
|
130
|
-
|
|
182
|
+
```rb
|
|
183
|
+
class MySpecdiffPlugin
|
|
184
|
+
# Read the source code to figure out how plugins work. Sorry.
|
|
185
|
+
end
|
|
131
186
|
|
|
132
|
-
|
|
187
|
+
Specdiff.load!(MySpecdiffPlugin)
|
|
188
|
+
```
|
|
133
189
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
- [ ] check the package size using `$ bundle exec inspect_build`, make sure you haven't added any large files by accident
|
|
138
|
-
- [ ] update the version number in `version.rb`
|
|
139
|
-
- [ ] make sure the `examples/` `Gemfile.lock` files are updated (run bundle install)
|
|
140
|
-
- [ ] make sure `Gemfile.lock` is updated (run bundle install)
|
|
141
|
-
- [ ] move unreleased changes to the next version in the [changelog](./CHANGELOG.md)
|
|
142
|
-
- [ ] commit in the form "vX.X.X" and push
|
|
143
|
-
- [ ] make sure the pipeline is green
|
|
144
|
-
- [ ] `$ bundle exec rake release`
|
|
190
|
+
This was intended to allow implementing (potentially janky and inefficient)
|
|
191
|
+
plugins to help diff XML, but in practice the text differ was good enough for
|
|
192
|
+
diffing indented XML.
|
|
145
193
|
|
|
146
194
|
## Contributing
|
|
147
195
|
|
|
196
|
+
Read [DEVELOPMENT.md](./DEVELOPMENT.md) for current development practices.
|
|
197
|
+
|
|
148
198
|
Bug reports and pull requests are welcome on GitHub at https://github.com/odinhb/specdiff.
|
|
149
199
|
|
|
150
200
|
## License
|
|
151
201
|
|
|
152
202
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
153
|
-
|
|
154
|
-
## TODO
|
|
155
|
-
|
|
156
|
-
This documents potential improvements/issues I know about or have thought about.
|
|
157
|
-
|
|
158
|
-
- [ ] test the webmock monkey-patch. currently there is an empty webmock_spec.rb (should we do this using rspec?) and the examples/ directory contains a few webmock examples (which are a good idea to run before releasing) but it would be nice to have the pipeline fail if it doesn't work for whatever reason
|
|
159
|
-
- [ ] finalize plugin interface (are the methods named intuitively? should we split type detector definitions and differ definitions?)
|
|
160
|
-
- [ ] document how to define a plugin properly (instead of just linking to the source code)
|
|
161
|
-
- [ ] is the stringification of hashdiff's output really better than pretty print? or just more wordy? (the colors are definitely nice)
|
data/glossary.txt
CHANGED
|
@@ -44,3 +44,7 @@ side
|
|
|
44
44
|
compare
|
|
45
45
|
the procedure that implements the main function of specdiff including
|
|
46
46
|
accounting for any plugin types and differs
|
|
47
|
+
|
|
48
|
+
integration
|
|
49
|
+
refers to the provided monkey-patches and conscious relationship between
|
|
50
|
+
specdiff and another gem or piece of software it was intended to work with.
|
data/lib/specdiff/differ/hash.rb
CHANGED
|
@@ -15,8 +15,13 @@ class Specdiff::Differ::Hash
|
|
|
15
15
|
# array_path: true returns the path as an array, which differentiates
|
|
16
16
|
# between symbol keys and string keys in hashes, while the string
|
|
17
17
|
# representation does not.
|
|
18
|
+
|
|
18
19
|
# hmm it really seems like use_lcs: true gives much less human-readable
|
|
19
20
|
# (human-comprehensible) output when arrays are involved.
|
|
21
|
+
|
|
22
|
+
# use_lcs: true may also cause Hashdiff to use a lot of memory when BIG
|
|
23
|
+
# arrays are involved: https://github.com/liufengyun/hashdiff/issues/49
|
|
24
|
+
# so we might as well avoid that problem altogether.
|
|
20
25
|
hashdiff_diff = ::Hashdiff.diff(
|
|
21
26
|
a.value, b.value,
|
|
22
27
|
array_path: true,
|
data/lib/specdiff/hashprint.rb
CHANGED
|
@@ -17,7 +17,7 @@ class Specdiff::Hashprint
|
|
|
17
17
|
@indentation_level = 0
|
|
18
18
|
@indentation_per_level = SPACE * INDENTATION_SPACES
|
|
19
19
|
@indent = ""
|
|
20
|
-
@
|
|
20
|
+
@next_value_is_hash_value = false
|
|
21
21
|
|
|
22
22
|
@output = StringIO.new
|
|
23
23
|
|
|
@@ -42,15 +42,15 @@ private
|
|
|
42
42
|
recalculate_indent
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
def
|
|
46
|
-
@
|
|
45
|
+
def next_value_is_hash_value
|
|
46
|
+
@next_value_is_hash_value = true
|
|
47
47
|
|
|
48
48
|
nil
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
-
def
|
|
52
|
-
if @
|
|
53
|
-
@
|
|
51
|
+
def outputting_hash_value?
|
|
52
|
+
if @next_value_is_hash_value
|
|
53
|
+
@next_value_is_hash_value = false
|
|
54
54
|
true
|
|
55
55
|
else
|
|
56
56
|
false
|
|
@@ -89,33 +89,34 @@ private
|
|
|
89
89
|
COLON = ":".freeze
|
|
90
90
|
|
|
91
91
|
def output_hash(hash)
|
|
92
|
-
@output << @indent unless
|
|
92
|
+
@output << @indent unless outputting_hash_value?
|
|
93
93
|
|
|
94
94
|
@output << HASH_OPEN
|
|
95
95
|
@output << NEWLINE
|
|
96
96
|
|
|
97
97
|
increase_indentation
|
|
98
98
|
track_recursion(hash) do
|
|
99
|
-
hash
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
99
|
+
try_to_sort(hash)
|
|
100
|
+
.each do |key, value|
|
|
101
|
+
@output << @indent
|
|
102
|
+
|
|
103
|
+
if key.is_a?(Symbol)
|
|
104
|
+
@output << key
|
|
105
|
+
@output << COLON
|
|
106
|
+
@output << SPACE
|
|
107
|
+
else
|
|
108
|
+
@output << ::Specdiff.diff_inspect(key)
|
|
109
|
+
@output << SPACE
|
|
110
|
+
@output << HASHROCKET
|
|
111
|
+
@output << SPACE
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
next_value_is_hash_value
|
|
115
|
+
output(value)
|
|
116
|
+
|
|
117
|
+
@output << COMMA
|
|
118
|
+
@output << NEWLINE
|
|
111
119
|
end
|
|
112
|
-
|
|
113
|
-
skip_next_opening_indent
|
|
114
|
-
output(value)
|
|
115
|
-
|
|
116
|
-
@output << COMMA
|
|
117
|
-
@output << NEWLINE
|
|
118
|
-
end
|
|
119
120
|
end
|
|
120
121
|
decrease_indentation
|
|
121
122
|
|
|
@@ -123,11 +124,17 @@ private
|
|
|
123
124
|
@output << HASH_CLOSE
|
|
124
125
|
end
|
|
125
126
|
|
|
127
|
+
def try_to_sort(hash)
|
|
128
|
+
return hash unless hash.keys.all? { |k| String === k || Symbol === k }
|
|
129
|
+
|
|
130
|
+
hash.sort_by { |k, _v| k.to_s }
|
|
131
|
+
end
|
|
132
|
+
|
|
126
133
|
ARRAY_OPEN = "[".freeze
|
|
127
134
|
ARRAY_CLOSE = "]".freeze
|
|
128
135
|
|
|
129
136
|
def output_array(array)
|
|
130
|
-
@output << @indent unless
|
|
137
|
+
@output << @indent unless outputting_hash_value?
|
|
131
138
|
|
|
132
139
|
@output << ARRAY_OPEN
|
|
133
140
|
@output << NEWLINE
|
|
@@ -147,7 +154,7 @@ private
|
|
|
147
154
|
end
|
|
148
155
|
|
|
149
156
|
def output_unknown(thing)
|
|
150
|
-
@output << @indent unless
|
|
157
|
+
@output << @indent unless outputting_hash_value?
|
|
151
158
|
|
|
152
159
|
@output << ::Specdiff.diff_inspect(thing)
|
|
153
160
|
end
|
|
@@ -157,7 +164,7 @@ private
|
|
|
157
164
|
STANDARD_INSPECT_RECURSIVE_HASH = "{...}".freeze
|
|
158
165
|
|
|
159
166
|
def output_deja_vu(thing)
|
|
160
|
-
@output << @indent unless
|
|
167
|
+
@output << @indent unless outputting_hash_value?
|
|
161
168
|
|
|
162
169
|
case thing
|
|
163
170
|
when Array
|
data/lib/specdiff/rspec.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
raise "rspec must be required before specdiff/rspec!" unless defined?(RSpec)
|
|
2
2
|
raise "RSpec::Support is missing????" unless defined?(RSpec::Support)
|
|
3
3
|
|
|
4
|
+
# https://github.com/rspec/rspec-support/blob/v3.13.1/lib/rspec/support/differ.rb
|
|
4
5
|
class RSpec::Support::Differ
|
|
5
6
|
alias old_diff diff
|
|
6
7
|
|
|
@@ -16,6 +17,7 @@ end
|
|
|
16
17
|
|
|
17
18
|
# This stops rspec from truncating strings w/ ellipsis, as well as making the
|
|
18
19
|
# "inspect" output consistent with specdiff's.
|
|
20
|
+
# https://github.com/rspec/rspec-support/blob/v3.13.1/lib/rspec/support/object_formatter.rb
|
|
19
21
|
class RSpec::Support::ObjectFormatter
|
|
20
22
|
def format(object)
|
|
21
23
|
::Specdiff.diff_inspect(object)
|
data/lib/specdiff/version.rb
CHANGED
data/lib/specdiff/webmock.rb
CHANGED
data/lib/specdiff.rb
CHANGED
|
@@ -6,19 +6,14 @@ require_relative "specdiff/hashprint"
|
|
|
6
6
|
require_relative "specdiff/compare"
|
|
7
7
|
|
|
8
8
|
module Specdiff
|
|
9
|
-
# Compare two things, returns a Specdiff::Diff.
|
|
10
9
|
def self.diff(...)
|
|
11
10
|
::Specdiff::Compare.call(...)
|
|
12
11
|
end
|
|
13
12
|
|
|
14
|
-
# Use Specdiff's implementation for turning a nested hash/array structure
|
|
15
|
-
# into a string. Optimized for diff quality.
|
|
16
13
|
def self.hashprint(...)
|
|
17
14
|
::Specdiff::Hashprint.call(...)
|
|
18
15
|
end
|
|
19
16
|
|
|
20
|
-
# Use Specdiff's inspect, which has some extra logic layered in for
|
|
21
|
-
# dates/time/bigdecimal. For most objects this just delegates to #inspect.
|
|
22
17
|
def self.diff_inspect(...)
|
|
23
18
|
::Specdiff::Inspect.call(...)
|
|
24
19
|
end
|
data/specdiff.gemspec
CHANGED
|
@@ -6,10 +6,18 @@ Gem::Specification.new do |spec|
|
|
|
6
6
|
spec.name = "specdiff"
|
|
7
7
|
spec.version = Specdiff::VERSION
|
|
8
8
|
spec.authors = ["Odin Heggvold Bekkelund"]
|
|
9
|
-
spec.email = ["
|
|
9
|
+
spec.email = ["odin.heggvold.bekkelund@dev.dodo.no"]
|
|
10
10
|
|
|
11
|
-
spec.summary = "Improved
|
|
12
|
-
spec.
|
|
11
|
+
spec.summary = "Improved diffing for WebMock and RSpec"
|
|
12
|
+
spec.description = <<~TXT
|
|
13
|
+
Specdiff aims to improve both RSpec's and WebMock's diffing by applying \
|
|
14
|
+
opinionated heuristics, and comes with integrations (monkey-patches) for \
|
|
15
|
+
both. Particularly noteworthy improvements are made to working with deeply \
|
|
16
|
+
nested hash/array structures in RSpec, and plaintext/xml request bodies in \
|
|
17
|
+
WebMock.
|
|
18
|
+
TXT
|
|
19
|
+
|
|
20
|
+
spec.homepage = "https://github.com/dodoas/specdiff"
|
|
13
21
|
spec.license = "MIT"
|
|
14
22
|
spec.required_ruby_version = ">= 3.0.0"
|
|
15
23
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: specdiff
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.0
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Odin Heggvold Bekkelund
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-04-
|
|
11
|
+
date: 2024-04-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: hashdiff
|
|
@@ -38,15 +38,21 @@ dependencies:
|
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '1.5'
|
|
41
|
-
description:
|
|
41
|
+
description: 'Specdiff aims to improve both RSpec''s and WebMock''s diffing by applying
|
|
42
|
+
opinionated heuristics, and comes with integrations (monkey-patches) for both. Particularly
|
|
43
|
+
noteworthy improvements are made to working with deeply nested hash/array structures
|
|
44
|
+
in RSpec, and plaintext/xml request bodies in WebMock.
|
|
45
|
+
|
|
46
|
+
'
|
|
42
47
|
email:
|
|
43
|
-
-
|
|
48
|
+
- odin.heggvold.bekkelund@dev.dodo.no
|
|
44
49
|
executables: []
|
|
45
50
|
extensions: []
|
|
46
51
|
extra_rdoc_files: []
|
|
47
52
|
files:
|
|
48
53
|
- ".gitignore"
|
|
49
54
|
- CHANGELOG.md
|
|
55
|
+
- DEVELOPMENT.md
|
|
50
56
|
- LICENSE.txt
|
|
51
57
|
- README.md
|
|
52
58
|
- glossary.txt
|
|
@@ -68,13 +74,13 @@ files:
|
|
|
68
74
|
- lib/specdiff/version.rb
|
|
69
75
|
- lib/specdiff/webmock.rb
|
|
70
76
|
- specdiff.gemspec
|
|
71
|
-
homepage: https://github.com/
|
|
77
|
+
homepage: https://github.com/dodoas/specdiff
|
|
72
78
|
licenses:
|
|
73
79
|
- MIT
|
|
74
80
|
metadata:
|
|
75
|
-
homepage_uri: https://github.com/
|
|
76
|
-
source_code_uri: https://github.com/
|
|
77
|
-
changelog_uri: https://github.com/
|
|
81
|
+
homepage_uri: https://github.com/dodoas/specdiff
|
|
82
|
+
source_code_uri: https://github.com/dodoas/specdiff
|
|
83
|
+
changelog_uri: https://github.com/dodoas/specdiff/CHANGELOG.md
|
|
78
84
|
post_install_message:
|
|
79
85
|
rdoc_options: []
|
|
80
86
|
require_paths:
|
|
@@ -86,12 +92,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
86
92
|
version: 3.0.0
|
|
87
93
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
94
|
requirements:
|
|
89
|
-
- - "
|
|
95
|
+
- - ">="
|
|
90
96
|
- !ruby/object:Gem::Version
|
|
91
|
-
version:
|
|
97
|
+
version: '0'
|
|
92
98
|
requirements: []
|
|
93
99
|
rubygems_version: 3.2.22
|
|
94
100
|
signing_key:
|
|
95
101
|
specification_version: 4
|
|
96
|
-
summary: Improved
|
|
102
|
+
summary: Improved diffing for WebMock and RSpec
|
|
97
103
|
test_files: []
|