rspec-json_expectations 1.2.2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ba444e9c321897ecfaef00955d78b897f2132701
4
- data.tar.gz: 381bfa291924bf00bf35993995df35eb7717cd97
3
+ metadata.gz: 635c0cad90f8b318d89952ee50c859dc7bc4110b
4
+ data.tar.gz: 430f157ca89a149f6f0c99e655ae6ebe40180ae1
5
5
  SHA512:
6
- metadata.gz: 032cf41af9b2d4e74c966bcccf82a88d5389c517bc2b2d9180667224a3bae38105781acb608eb6d6539e32b8870dbb7751f830e56bf325194666db3487d5bf14
7
- data.tar.gz: 8f295dce2669d24d8bf6bdaa33ca78644e49d27829c6bd56058fa70c9915dacad15be31a26bba2f67f462dccd95f631951cb20bd8df144826825921605f80cba
6
+ metadata.gz: 07b925d6f73e3478dae9b094e7bcf8a624c3b814e9d22b6c2b877bc628c9676d05bc628e5a0a344b48d16746184f93a2f578c1555502c9a39be4d79dc39048e1
7
+ data.tar.gz: 20ea442c480d27d1af256ea657d206e86f527b38171709aafa3710135565ff0f664a87c8ac981b924ad64d95287f33d2d83c937f9d63ef5d1cf7772c1789dd8e
@@ -0,0 +1,200 @@
1
+ Feature: Unordered array matching support for include_json matcher
2
+
3
+ As a developer extensively testing my APIs
4
+ I want to be able to match json parts with array
5
+ And I don't want to be explicit about the order of the elements
6
+
7
+ Background:
8
+ Given a file "spec/spec_helper.rb" with:
9
+ """ruby
10
+ require "rspec/json_expectations"
11
+
12
+ RSpec.configure do |c|
13
+ c.include RSpec::JsonExpectations::Matchers
14
+ end
15
+ """
16
+ And a local "JSON_WITH_ARRAY" with:
17
+ """json
18
+ {
19
+ "per_page": 3,
20
+ "count": 17,
21
+ "page": 2,
22
+ "page_count": 6,
23
+ "results": [
24
+ {
25
+ "id": 25,
26
+ "email": "john.smith@example.com",
27
+ "badges": ["first flight", "day & night"],
28
+ "name": "John"
29
+ },
30
+ {
31
+ "id": 26,
32
+ "email": "john.smith@example.com",
33
+ "badges": ["first flight"],
34
+ "name": "John"
35
+ },
36
+ {
37
+ "id": 27,
38
+ "email": "john.smith@example.com",
39
+ "badges": ["day & night"],
40
+ "name": "John"
41
+ }
42
+ ]
43
+ }
44
+ """
45
+ And a local "JSON_WITH_ROOT_ARRAY" with:
46
+ """json
47
+ [
48
+ "first flight",
49
+ "day & night"
50
+ ]
51
+ """
52
+
53
+ Scenario: Expecting json string to fully include json with arrays
54
+ Given a file "spec/nested_example_spec.rb" with:
55
+ """ruby
56
+ require "spec_helper"
57
+
58
+ RSpec.describe "A json response" do
59
+ subject { '%{JSON_WITH_ARRAY}' }
60
+
61
+ it "has basic info about user" do
62
+ expect(subject).to include_json(
63
+ results: UnorderedArray(
64
+ { id: 25, badges: ["first flight", "day & night"] },
65
+ { id: 26, badges: ["first flight"] },
66
+ { id: 27, badges: ["day & night"] }
67
+ )
68
+ )
69
+ end
70
+ end
71
+ """
72
+ When I run "rspec spec/nested_example_spec.rb"
73
+ Then I see:
74
+ """
75
+ 1 example, 0 failures
76
+ """
77
+
78
+ Scenario: Expecting json string to fully include json with arrays with different order
79
+ Given a file "spec/nested_example_spec.rb" with:
80
+ """ruby
81
+ require "spec_helper"
82
+
83
+ RSpec.describe "A json response" do
84
+ subject { '%{JSON_WITH_ARRAY}' }
85
+
86
+ it "has basic info about user" do
87
+ expect(subject).to include_json(
88
+ results: UnorderedArray(
89
+ { id: 26, badges: ["first flight"] },
90
+ { id: 27, badges: ["day & night"] },
91
+ { id: 25, badges: ["first flight", "day & night"] }
92
+ )
93
+ )
94
+ end
95
+ end
96
+ """
97
+ When I run "rspec spec/nested_example_spec.rb"
98
+ Then I see:
99
+ """
100
+ 1 example, 0 failures
101
+ """
102
+
103
+ Scenario: Expecting json string to fully include json with wrong values
104
+ Given a file "spec/nested_example_spec.rb" with:
105
+ """ruby
106
+ require "spec_helper"
107
+
108
+ RSpec.describe "A json response" do
109
+ subject { '%{JSON_WITH_ARRAY}' }
110
+
111
+ it "has basic info about user" do
112
+ expect(subject).to include_json(
113
+ results: UnorderedArray(
114
+ { id: 26, badges: ["first flight"] },
115
+ { id: 35, badges: ["unknown", "badge"] },
116
+ { id: 27, badges: ["day & night"] },
117
+ { id: 25, badges: ["first flight", "day & night"] }
118
+ )
119
+ )
120
+ end
121
+ end
122
+ """
123
+ When I run "rspec spec/nested_example_spec.rb"
124
+ Then I see:
125
+ """
126
+ json atom at path "results/1" is missing
127
+ """
128
+ And I see:
129
+ """
130
+ expected: {:id=>35, :badges=>["unknown", "badge"]}
131
+ got: nil
132
+ """
133
+
134
+ Scenario: Expecting json string with array at root to fully include json with arrays
135
+ Given a file "spec/nested_example_spec.rb" with:
136
+ """ruby
137
+ require "spec_helper"
138
+
139
+ RSpec.describe "A json response" do
140
+ subject { '%{JSON_WITH_ROOT_ARRAY}' }
141
+
142
+ it "has basic info about user" do
143
+ expect(subject).to include_json(
144
+ UnorderedArray( "first flight", "day & night" )
145
+ )
146
+ end
147
+ end
148
+ """
149
+ When I run "rspec spec/nested_example_spec.rb"
150
+ Then I see:
151
+ """
152
+ 1 example, 0 failures
153
+ """
154
+
155
+ Scenario: Expecting json string with array at root to fully include json with arrays with different order
156
+ Given a file "spec/nested_example_spec.rb" with:
157
+ """ruby
158
+ require "spec_helper"
159
+
160
+ RSpec.describe "A json response" do
161
+ subject { '%{JSON_WITH_ROOT_ARRAY}' }
162
+
163
+ it "has basic info about user" do
164
+ expect(subject).to include_json(
165
+ UnorderedArray( "day & night", "first flight" )
166
+ )
167
+ end
168
+ end
169
+ """
170
+ When I run "rspec spec/nested_example_spec.rb"
171
+ Then I see:
172
+ """
173
+ 1 example, 0 failures
174
+ """
175
+
176
+ Scenario: Expecting json string with array at root to fully include json with wrong values
177
+ Given a file "spec/nested_example_spec.rb" with:
178
+ """ruby
179
+ require "spec_helper"
180
+
181
+ RSpec.describe "A json response" do
182
+ subject { '%{JSON_WITH_ROOT_ARRAY}' }
183
+
184
+ it "has basic info about user" do
185
+ expect(subject).to include_json(
186
+ UnorderedArray( "day & night", "unknown", "first flight" )
187
+ )
188
+ end
189
+ end
190
+ """
191
+ When I run "rspec spec/nested_example_spec.rb"
192
+ Then I see:
193
+ """
194
+ json atom at path "1" is missing
195
+ """
196
+ And I see:
197
+ """
198
+ expected: "unknown"
199
+ got: nil
200
+ """
@@ -14,7 +14,8 @@ module RSpec
14
14
  [
15
15
  render_no_key(path, error, negate),
16
16
  render_not_eq(path, error, negate),
17
- render_not_match(path, error, negate)
17
+ render_not_match(path, error, negate),
18
+ render_missing(path, error, negate)
18
19
  ].select { |e| e }.first
19
20
  end
20
21
 
@@ -42,6 +43,21 @@ module RSpec
42
43
  } if error_is_not_match?(error)
43
44
  end
44
45
 
46
+ def render_missing(path, error, negate=false)
47
+ return unless error_is_missing?(error)
48
+
49
+ prefix = "#{path}/" if path && !path.empty?
50
+
51
+ items = error[:missing].map do |item|
52
+ %{
53
+ json atom at path "#{prefix}#{item[:index]}" is missing
54
+
55
+ expected: #{item[:item].inspect}
56
+ got: nil
57
+ }
58
+ end.join("\n")
59
+ end
60
+
45
61
  def error_is_not_eq?(error)
46
62
  error.is_a?(Hash) && error.has_key?(:expected) && !error[:expected].is_a?(Regexp)
47
63
  end
@@ -49,6 +65,10 @@ module RSpec
49
65
  def error_is_not_match?(error)
50
66
  error.is_a?(Hash) && error.has_key?(:expected) && error[:expected].is_a?(Regexp)
51
67
  end
68
+
69
+ def error_is_missing?(error)
70
+ error.is_a?(Hash) && error.has_key?(:missing)
71
+ end
52
72
  end
53
73
  end
54
74
  end
@@ -1,4 +1,5 @@
1
1
  require "json"
2
+ require "rspec/json_expectations/matchers"
2
3
 
3
4
  module RSpec
4
5
  module JsonExpectations
@@ -9,13 +10,15 @@ module RSpec
9
10
  class JsonTraverser
10
11
  HANDLED_BY_SIMPLE_VALUE_HANDLER = [String, Numeric, FalseClass, TrueClass, NilClass]
11
12
  RSPECMATCHERS = defined?(RSpec::Matchers) ? [RSpec::Matchers::BuiltIn::BaseMatcher] : []
12
- SUPPORTED_VALUES = [Hash, Regexp, Array] + HANDLED_BY_SIMPLE_VALUE_HANDLER + RSPECMATCHERS
13
+ SUPPORTED_VALUES = [Hash, Regexp, Array, Matchers::UnorderedArrayMatcher] +
14
+ HANDLED_BY_SIMPLE_VALUE_HANDLER + RSPECMATCHERS
13
15
 
14
16
  class << self
15
17
  def traverse(errors, expected, actual, negate=false, prefix=[])
16
18
  [
17
19
  handle_hash(errors, expected, actual, negate, prefix),
18
20
  handle_array(errors, expected, actual, negate, prefix),
21
+ handle_unordered(errors, expected, actual, negate, prefix),
19
22
  handle_value(errors, expected, actual, negate, prefix),
20
23
  handle_regex(errors, expected, actual, negate, prefix),
21
24
  handle_rspec_matcher(errors, expected, actual, negate, prefix),
@@ -50,6 +53,15 @@ module RSpec
50
53
  handle_keyvalue(errors, transformed_expected, actual, negate, prefix)
51
54
  end
52
55
 
56
+ def handle_unordered(errors, expected, actual, negate=false, prefix=[])
57
+ return nil unless expected.is_a?(Matchers::UnorderedArrayMatcher)
58
+
59
+ conditionally_negate(
60
+ expected.match(errors, actual, prefix),
61
+ negate
62
+ )
63
+ end
64
+
53
65
  def handle_value(errors, expected, actual, negate=false, prefix=[])
54
66
  return nil unless handled_by_simple_value?(expected)
55
67
 
@@ -36,7 +36,9 @@ RSpec::Matchers.define :include_json do |expected|
36
36
  end
37
37
 
38
38
  def traverse(expected, actual, negate=false)
39
- unless expected.is_a?(Hash) || expected.is_a?(Array)
39
+ unless expected.is_a?(Hash) ||
40
+ expected.is_a?(Array) ||
41
+ expected.is_a?(::RSpec::JsonExpectations::Matchers::UnorderedArrayMatcher)
40
42
  raise ArgumentError,
41
43
  "Expected value must be a json for include_json matcher"
42
44
  end
@@ -52,3 +54,46 @@ RSpec::Matchers.define :include_json do |expected|
52
54
  )
53
55
  end
54
56
  end
57
+
58
+ module RSpec
59
+ module JsonExpectations
60
+ module Matchers
61
+ class UnorderedArrayMatcher
62
+ attr_reader :array
63
+ def initialize(array)
64
+ @array = array
65
+ end
66
+
67
+ def match(errors, actual, prefix)
68
+ missing_items = []
69
+ errors[prefix.join("/")] = { missing: missing_items }
70
+
71
+ all? do |expected_item, index|
72
+ match_one(missing_items, expected_item, index, actual)
73
+ end
74
+ end
75
+
76
+ def match_one(missing, item, index, actual)
77
+ check_for_missing(missing, item, index,
78
+ actual.any? do |actual_item|
79
+ JsonTraverser.traverse({}, item, actual_item, false)
80
+ end
81
+ )
82
+ end
83
+
84
+ def check_for_missing(missing, item, index, ok)
85
+ missing << { item: item, index: index } unless ok
86
+ ok
87
+ end
88
+
89
+ def all?(&blk)
90
+ array.each_with_index.all?(&blk)
91
+ end
92
+ end
93
+
94
+ def UnorderedArray(*array)
95
+ UnorderedArrayMatcher.new(array)
96
+ end
97
+ end
98
+ end
99
+ end
@@ -1,5 +1,5 @@
1
1
  module RSpec
2
2
  module JsonExpectations
3
- VERSION = "1.2.2"
3
+ VERSION = "1.3.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-json_expectations
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oleksii Fedorov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-17 00:00:00.000000000 Z
11
+ date: 2016-03-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -64,6 +64,7 @@ files:
64
64
  - features/rspec/json_expectations/regular_expressions_support.feature
65
65
  - features/rspec/json_expectations/rspec_matchers_support.feature
66
66
  - features/rspec/json_expectations/simple_hash_match.feature
67
+ - features/rspec/json_expectations/unordered_array_support.feature
67
68
  - features/step_definitions/steps.rb
68
69
  - features/support/env.rb
69
70
  - gemfiles/rspec-2
@@ -108,6 +109,7 @@ test_files:
108
109
  - features/rspec/json_expectations/regular_expressions_support.feature
109
110
  - features/rspec/json_expectations/rspec_matchers_support.feature
110
111
  - features/rspec/json_expectations/simple_hash_match.feature
112
+ - features/rspec/json_expectations/unordered_array_support.feature
111
113
  - features/step_definitions/steps.rb
112
114
  - features/support/env.rb
113
115
  has_rdoc: