cucumber-rest-bdd 0.6.0 → 0.6.1
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/lib/cucumber-rest-bdd/data.rb +66 -40
- data/lib/cucumber-rest-bdd/hash.rb +6 -5
- data/lib/cucumber-rest-bdd/level.rb +37 -36
- data/lib/cucumber-rest-bdd/list.rb +124 -112
- data/lib/cucumber-rest-bdd/steps/functional.rb +39 -14
- data/lib/cucumber-rest-bdd/steps/resource.rb +102 -80
- data/lib/cucumber-rest-bdd/steps/response.rb +131 -88
- data/lib/cucumber-rest-bdd/steps/status.rb +57 -51
- data/lib/cucumber-rest-bdd/types.rb +150 -141
- data/lib/cucumber-rest-bdd/url.rb +6 -5
- metadata +17 -15
@@ -3,25 +3,50 @@ require 'cucumber-api/steps'
|
|
3
3
|
require 'cucumber-rest-bdd/types'
|
4
4
|
require 'cucumber-rest-bdd/list'
|
5
5
|
|
6
|
-
Then(
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
Then(
|
7
|
+
'the response (should )have/has (a/the )header {string} '\
|
8
|
+
"#{HAVE_ALTERNATION} (a/the )value {string}"
|
9
|
+
) do |header, value|
|
10
|
+
p_value = resolve(value)
|
11
|
+
p_header = header.parameterize
|
12
|
+
unless @response.raw_headers.key?(p_header)
|
13
|
+
raise %(Required header: #{header} not found
|
14
|
+
#{@response.raw_headers.inspect})
|
15
|
+
end
|
16
|
+
unless @response.raw_headers[p_header].include? p_value
|
17
|
+
raise %/Expect #{p_value} in #{header} (#{p_header})
|
18
|
+
#{@response.raw_headers.inspect}/
|
19
|
+
end
|
12
20
|
end
|
13
21
|
|
14
|
-
Then(
|
22
|
+
Then(
|
23
|
+
'the JSON response should have {string} of type array '\
|
24
|
+
"#{HAVE_ALTERNATION} {list_has_count} entry/entries"
|
25
|
+
) do |json_path, list_comparison|
|
15
26
|
list = @response.get_as_type json_path, 'array'
|
16
|
-
|
27
|
+
unless list_comparison.compare(list.count)
|
28
|
+
raise %(Expected #{list_comparison.to_string} entries in array for path
|
29
|
+
'#{json_path}', found: #{list.count}
|
30
|
+
#{@response.to_json_s})
|
31
|
+
end
|
17
32
|
end
|
18
33
|
|
19
|
-
Then(
|
20
|
-
|
21
|
-
|
34
|
+
Then(
|
35
|
+
'the JSON response should have {string} of type {word} that matches {string}'
|
36
|
+
) do |json_path, type, regex|
|
37
|
+
value = @response.get_as_type json_path, type
|
38
|
+
if (Regexp.new(regex) =~ value).nil?
|
39
|
+
raise %(Expected #{json_path} value '#{value}' to match regex: #{regex}
|
40
|
+
#{@response.to_json_s})
|
41
|
+
end
|
22
42
|
end
|
23
43
|
|
24
|
-
Then(
|
25
|
-
|
26
|
-
|
44
|
+
Then(
|
45
|
+
'the JSON response should have {string} of type nill/null/nil'
|
46
|
+
) do |json_path|
|
47
|
+
value = @response.get_as_type_or_null json_path, 'string'
|
48
|
+
unless value.nil?
|
49
|
+
raise %(Expected #{json_path} to be nil, was: #{value.class}
|
50
|
+
#{@response.to_json_s})
|
51
|
+
end
|
27
52
|
end
|
@@ -7,139 +7,161 @@ require 'cucumber-rest-bdd/level'
|
|
7
7
|
require 'cucumber-rest-bdd/hash'
|
8
8
|
require 'easy_diff'
|
9
9
|
|
10
|
-
GET_TYPES =
|
11
|
-
WITH_ID =
|
10
|
+
GET_TYPES = '(?:an?(?! list)|the)'.freeze
|
11
|
+
WITH_ID = '(?: with (?:key|id))? "([^"]*)"'.freeze
|
12
12
|
|
13
|
-
Given(
|
14
|
-
|
15
|
-
Given I send "application/json" and accept JSON
|
16
|
-
}
|
13
|
+
Given('I am a client') do
|
14
|
+
steps %(Given I send "application/json" and accept JSON)
|
17
15
|
end
|
18
16
|
|
19
|
-
Given(
|
20
|
-
|
17
|
+
Given('I am issuing requests for {resource_name}') do |resource|
|
18
|
+
@urlbasepath = resource
|
21
19
|
end
|
22
20
|
|
23
21
|
# GET
|
24
22
|
|
25
|
-
When(
|
26
|
-
|
27
|
-
|
23
|
+
When(
|
24
|
+
'I request the {resource_name} (with key/id ){string}{levels}'
|
25
|
+
) do |resource, id, levels|
|
26
|
+
url = get_url("#{levels.url}#{resource}/#{id}")
|
27
|
+
steps %(When I send a GET request to "#{url}")
|
28
28
|
end
|
29
29
|
|
30
|
-
When(
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
30
|
+
When(
|
31
|
+
'I request the {resource_name} (with key/id ){string}{levels} with:'
|
32
|
+
) do |resource, id, levels, params|
|
33
|
+
url = get_url("#{levels.url}#{resource}/#{id}")
|
34
|
+
unless params.raw.empty?
|
35
|
+
query = params.raw.map { |k, v| %(#{parse_field(k)}=#{resolve(v)}) }
|
36
|
+
.join('&')
|
37
|
+
url = "#{url}?#{query}"
|
38
|
+
end
|
39
|
+
steps %(When I send a GET request to "#{url}")
|
37
40
|
end
|
38
41
|
|
39
|
-
When(
|
40
|
-
|
41
|
-
|
42
|
+
When('I request a list of {resource_name}{levels}') do |resource, levels|
|
43
|
+
url = get_url("#{levels.url}#{resource}")
|
44
|
+
steps %(When I send a GET request to "#{url}")
|
42
45
|
end
|
43
46
|
|
44
|
-
When(
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
47
|
+
When(
|
48
|
+
'I request a list of {resource_name}{levels} with:'
|
49
|
+
) do |resource, levels, params|
|
50
|
+
url = get_url("#{levels.url}#{resource}")
|
51
|
+
unless params.raw.empty?
|
52
|
+
query = params.raw.map { |k, v| %(#{parse_field(k)}=#{resolve(v)}) }
|
53
|
+
.join('&')
|
54
|
+
url = "#{url}?#{query}"
|
55
|
+
end
|
56
|
+
steps %(When I send a GET request to "#{url}")
|
51
57
|
end
|
52
58
|
|
53
59
|
# DELETE
|
54
60
|
|
55
|
-
When(
|
56
|
-
|
57
|
-
|
61
|
+
When(
|
62
|
+
'I request to delete/remove a/an/the {resource_name} '\
|
63
|
+
'(with key/id ){string}{levels}'
|
64
|
+
) do |resource, id, levels|
|
65
|
+
url = get_url("#{levels.url}#{resource}/#{id}")
|
66
|
+
steps %(When I send a DELETE request to "#{url}")
|
58
67
|
end
|
59
68
|
|
60
69
|
# POST
|
61
70
|
|
62
|
-
When(
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
71
|
+
When(
|
72
|
+
'I request to create a/an/the {resource_name}{levels}'
|
73
|
+
) do |resource, levels|
|
74
|
+
if ENV['set_parent_id'] == 'true'
|
75
|
+
json = MultiJson.dump(levels.last_hash)
|
76
|
+
steps %(
|
77
|
+
When I set JSON request body to:
|
78
|
+
"""
|
79
|
+
#{json}
|
80
|
+
"""
|
81
|
+
)
|
82
|
+
end
|
83
|
+
url = get_url("#{levels.url}#{resource}")
|
84
|
+
steps %(When I send a POST request to "#{url}")
|
74
85
|
end
|
75
86
|
|
76
|
-
When(
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
87
|
+
When(
|
88
|
+
'I request to create a/an/the {resource_name}{levels} with:'
|
89
|
+
) do |resource, levels, params|
|
90
|
+
request_hash = parse_attributes(params.hashes)
|
91
|
+
request_hash = request_hash.merge(levels.last_hash) if ENV['set_parent_id'] == 'true'
|
92
|
+
json = MultiJson.dump(request_hash)
|
93
|
+
url = get_url("#{levels.url}#{resource}")
|
94
|
+
steps %(
|
82
95
|
When I set JSON request body to:
|
83
96
|
"""
|
84
97
|
#{json}
|
85
98
|
"""
|
86
99
|
And I send a POST request to "#{url}"
|
87
|
-
|
100
|
+
)
|
88
101
|
end
|
89
102
|
|
90
103
|
# PUT
|
91
104
|
|
92
|
-
When(
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
105
|
+
When(
|
106
|
+
'I request to replace/set a/an/the {resource_name} '\
|
107
|
+
'(with key/id ){string}{levels}'
|
108
|
+
) do |resource, id, levels|
|
109
|
+
if ENV['set_parent_id'] == 'true'
|
110
|
+
json = MultiJson.dump(levels.last_hash)
|
111
|
+
steps %(
|
112
|
+
When I set JSON request body to:
|
113
|
+
"""
|
114
|
+
#{json}
|
115
|
+
"""
|
116
|
+
)
|
117
|
+
end
|
118
|
+
url = get_url("#{levels.url}#{resource}/#{id}")
|
119
|
+
steps %(
|
104
120
|
When I send a PUT request to "#{url}"
|
105
|
-
|
121
|
+
)
|
106
122
|
end
|
107
123
|
|
108
|
-
When(
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
124
|
+
When(
|
125
|
+
'I request to replace/set a/an/the {resource_name} '\
|
126
|
+
'(with key/id ){string}{levels} with:'
|
127
|
+
) do |resource, id, levels, params|
|
128
|
+
request_hash = parse_attributes(params.hashes)
|
129
|
+
request_hash = request_hash.merge(levels.last_hash) if ENV['set_parent_id'] == 'true'
|
130
|
+
json = MultiJson.dump(request_hash)
|
131
|
+
url = get_url("#{levels.url}#{resource}/#{id}")
|
132
|
+
steps %(
|
114
133
|
When I set JSON request body to:
|
115
134
|
"""
|
116
135
|
#{json}
|
117
136
|
"""
|
118
137
|
And I send a PUT request to "#{url}"
|
119
|
-
|
138
|
+
)
|
120
139
|
end
|
121
140
|
|
122
141
|
# PATCH
|
123
142
|
|
124
|
-
When(
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
143
|
+
When(
|
144
|
+
'I request to modify/update a/an/the {resource_name} '\
|
145
|
+
'(with key/id ){string}{levels} with:'
|
146
|
+
) do |resource, id, levels, params|
|
147
|
+
request_hash = parse_attributes(params.hashes)
|
148
|
+
json = MultiJson.dump(request_hash)
|
149
|
+
url = get_url("#{levels.url}#{resource}/#{id}")
|
150
|
+
steps %(
|
129
151
|
When I set JSON request body to:
|
130
152
|
"""
|
131
153
|
#{json}
|
132
154
|
"""
|
133
155
|
And I send a PATCH request to "#{url}"
|
134
|
-
|
156
|
+
)
|
135
157
|
end
|
136
158
|
|
137
159
|
# value capture
|
138
160
|
|
139
|
-
When(
|
140
|
-
|
161
|
+
When('I save (attribute ){string}') do |attribute|
|
162
|
+
steps %(When I grab "#{json_path(attribute)}" as "#{attribute}")
|
141
163
|
end
|
142
164
|
|
143
|
-
When(
|
144
|
-
|
165
|
+
When('I save (attribute ){string} to {string}') do |attribute, ref|
|
166
|
+
steps %(When I grab "#{json_path(attribute)}" as "#{ref}")
|
145
167
|
end
|
@@ -4,142 +4,185 @@ require 'cucumber-rest-bdd/list'
|
|
4
4
|
require 'cucumber-rest-bdd/data'
|
5
5
|
|
6
6
|
ParameterType(
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
name: 'item_name',
|
8
|
+
regexp: /([\w\s]+?)/,
|
9
|
+
transformer: ->(s) { s },
|
10
|
+
use_for_snippets: false
|
11
11
|
)
|
12
12
|
|
13
|
-
Then(
|
14
|
-
|
13
|
+
Then('print the response') do
|
14
|
+
puts %(The response:\n#{@response.to_json_s})
|
15
15
|
end
|
16
16
|
|
17
17
|
# SIMPLE VALUE RESPONSE
|
18
18
|
|
19
19
|
# response is a string with the specified value
|
20
|
-
Then(
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
Then(
|
21
|
+
"the response #{HAVE_ALTERNATION} (the )(following )value {string}"
|
22
|
+
) do |value|
|
23
|
+
expected = value
|
24
|
+
data = @response.get root_data_key
|
25
|
+
raise %(Response did not match: #{expected}\n#{data}) if data.empty? || !data.include?(expected)
|
24
26
|
end
|
25
27
|
|
26
28
|
# OBJECT RESPONSE
|
27
29
|
|
28
30
|
# response is an object with a field that is validated by a pre-defined regex
|
29
|
-
Then(
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
31
|
+
Then(
|
32
|
+
"the response #{HAVE_ALTERNATION} {field_name} of type {word}"
|
33
|
+
) do |field, type|
|
34
|
+
regex = case type
|
35
|
+
when 'datetime' then /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:[+|-]\d{2}:\d{2})?$/i
|
36
|
+
when 'guid' then /^[{(]?[0-9A-F]{8}[-]?([0-9A-F]{4}[-]?){3}[0-9A-F]{12}[)}]?$/i
|
37
|
+
end
|
38
|
+
type = 'string' if regex.nil?
|
39
|
+
value = field.get_value(@response, type)
|
40
|
+
field.validate_value(@response, value.to_s, Regexp.new(regex))
|
39
41
|
end
|
40
42
|
|
41
43
|
# response is an object with a field that is validated by a custom regex
|
42
44
|
Then("the response #{HAVE_ALTERNATION} {field_name} of type {word} that matches {string}") do |field, type, regex|
|
43
|
-
|
44
|
-
|
45
|
+
value = field.get_value(@response, type)
|
46
|
+
field.validate_value(@response, value.to_s, Regexp.new(regex))
|
45
47
|
end
|
46
48
|
|
47
49
|
# response is an object with specific attributes having defined values
|
48
50
|
Then("the response #{HAVE_ALTERNATION} (the )(following )attributes:") do |attributes|
|
49
|
-
|
50
|
-
|
51
|
-
|
51
|
+
expected = parse_attributes(attributes.hashes)
|
52
|
+
data = @response.get root_data_key
|
53
|
+
raise %(Response did not match:\n#{expected.inspect}\n#{data}) if data.empty? || !data.deep_include?(expected)
|
52
54
|
end
|
53
55
|
|
54
56
|
# ARRAY RESPONSE
|
55
57
|
|
56
58
|
# response is an array of objects
|
57
|
-
Then(
|
58
|
-
|
59
|
-
|
59
|
+
Then('the response is a list of/containing {list_has_count} {field_name}') do |list_comparison, _item|
|
60
|
+
list = @response.get_as_type root_data_key, 'array'
|
61
|
+
unless list_comparison.compare(list.count)
|
62
|
+
raise %(Expected #{list_comparison.to_string} items in array for path '#{root_data_key}', found: #{list.count}
|
63
|
+
#{@response.to_json_s})
|
64
|
+
end
|
60
65
|
end
|
61
66
|
|
62
67
|
# response is an array of objects where the specified number of entries match the defined data attributes
|
63
|
-
Then(
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
+
Then(
|
69
|
+
'(the response is a list with/of/containing ){list_has_count} {word} '\
|
70
|
+
"#{HAVE_ALTERNATION} (the )(following )(data )attributes:"
|
71
|
+
) do |list_comparison, _item_name, attributes|
|
72
|
+
expected = parse_attributes(attributes.hashes)
|
73
|
+
data = @response.get_as_type root_data_key, 'array'
|
74
|
+
matched = data.select { |item| !item.empty? && item.deep_include?(expected) }
|
75
|
+
unless list_comparison.compare(matched.count)
|
76
|
+
raise %(Expected #{list_comparison.to_string} items in array that matched:\n#{expected.inspect}\n#{data})
|
77
|
+
end
|
68
78
|
end
|
69
79
|
|
70
80
|
# response is an array of objects where the specified number of entries match the defined data attributes
|
71
|
-
Then(
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
81
|
+
Then(
|
82
|
+
'(the response is a list with/of/containing ){list_has_count} {item_name} {list_nesting}'
|
83
|
+
) do |list_comparison, _item_name, nesting|
|
84
|
+
nesting.push(
|
85
|
+
root: true,
|
86
|
+
type: 'multiple',
|
87
|
+
comparison: list_comparison
|
88
|
+
)
|
89
|
+
data = @response.get get_key(nesting.grouping)
|
90
|
+
if data.empty? || !nest_match_attributes(data, nesting.grouping, {}, false)
|
91
|
+
raise %(Could not find a match for: #{nesting.match}\n#{@response.to_json_s})
|
92
|
+
end
|
79
93
|
end
|
80
94
|
|
81
95
|
# response is an array of objects where the specified number of entries match the defined data attributes
|
82
|
-
Then(
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
96
|
+
Then(
|
97
|
+
'(the response is a list with/of/containing ){list_has_count} {item_name} {list_nesting} '\
|
98
|
+
"#{HAVE_ALTERNATION} (the )(following )(data )attributes:"
|
99
|
+
) do |list_comparison, _item_name, nesting, attributes|
|
100
|
+
expected = parse_attributes(attributes.hashes)
|
101
|
+
nesting.push(
|
102
|
+
root: true,
|
103
|
+
type: 'multiple',
|
104
|
+
comparison: list_comparison
|
105
|
+
)
|
106
|
+
data = @response.get get_key(nesting.grouping)
|
107
|
+
if data.empty? || !nest_match_attributes(data, nesting.grouping, expected, false)
|
108
|
+
raise %(Could not find a match for: #{nesting.match}\n#{expected.inspect}\n#{@response.to_json_s})
|
109
|
+
end
|
91
110
|
end
|
92
111
|
|
93
112
|
# response is an array of objects where the specified number of entries match the defined string value
|
94
|
-
Then(
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
113
|
+
Then(
|
114
|
+
'(the response is a list with/of/containing ){list_has_count} {item_name} '\
|
115
|
+
'having/containing/with (the )(following )value {string}'
|
116
|
+
) do |list_comparison, _item_name, value|
|
117
|
+
expected = value
|
118
|
+
data = @response.get_as_type root_data_key, 'array'
|
119
|
+
matched = data.select { |item| !item.empty? && item.include?(expected) }
|
120
|
+
unless list_comparison.compare(matched.count)
|
121
|
+
raise %(Expected #{list_comparison.to_string} items in array that matched:\n#{expected}\n#{data})
|
122
|
+
end
|
99
123
|
end
|
100
124
|
|
101
125
|
# response is an array of objects where the specified number of entries match the defined string value
|
102
|
-
Then(
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
126
|
+
Then(
|
127
|
+
'(the response is a list with/of/containing ){list_has_count} {item_name} {list_nesting} '\
|
128
|
+
"#{HAVE_ALTERNATION} (the )(following )value {string}"
|
129
|
+
) do |list_comparison, _item_name, nesting, value|
|
130
|
+
expected = value
|
131
|
+
nesting.push(
|
132
|
+
root: true,
|
133
|
+
type: 'multiple',
|
134
|
+
comparison: list_comparison
|
135
|
+
)
|
136
|
+
data = @response.get get_key(nesting.grouping)
|
137
|
+
if data.empty? || !nest_match_attributes(data, nesting.grouping, expected, true)
|
138
|
+
raise %(Could not find a match for: #{nesting.match}\n#{expected}\n#{@response.to_json_s})
|
139
|
+
end
|
111
140
|
end
|
112
141
|
|
113
142
|
# HIERARCHICAL RESPONSE
|
114
143
|
|
115
|
-
# response has the specified hierarchy of objects / lists where the
|
144
|
+
# response has the specified hierarchy of objects / lists where the
|
145
|
+
# specified number of leaf items match the defined data attributes
|
116
146
|
Then("the response {list_nesting} #{HAVE_ALTERNATION} (the )(following )attributes:") do |nesting, attributes|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
147
|
+
expected = parse_attributes(attributes.hashes)
|
148
|
+
nesting.push(
|
149
|
+
root: true,
|
150
|
+
type: 'single'
|
151
|
+
)
|
152
|
+
data = @response.get get_key(nesting.grouping)
|
153
|
+
if data.empty? || !nest_match_attributes(data, nesting.grouping, expected, false)
|
154
|
+
raise %(
|
155
|
+
Could not find a match for: #{nesting.match}
|
156
|
+
with: #{expected.inspect}
|
157
|
+
in: #{data}
|
158
|
+
#{@response.to_json_s}
|
159
|
+
)
|
160
|
+
end
|
124
161
|
end
|
125
162
|
|
126
|
-
# response has the specified hierarchy of objects / lists where the
|
163
|
+
# response has the specified hierarchy of objects / lists where the
|
164
|
+
# specified number of leaf items match the defined string value
|
127
165
|
Then("the response {list_nesting} #{HAVE_ALTERNATION} (the )(following )value {string}") do |nesting, value|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
166
|
+
expected = value
|
167
|
+
nesting.push(
|
168
|
+
root: true,
|
169
|
+
type: 'single'
|
170
|
+
)
|
171
|
+
data = @response.get get_key(nesting.grouping)
|
172
|
+
if data.empty? || !nest_match_attributes(data, nesting.grouping, expected, true)
|
173
|
+
raise %(Could not find a match for: #{nesting.match}\n#{expected}\n#{@response.to_json_s})
|
174
|
+
end
|
135
175
|
end
|
136
176
|
|
137
|
-
# response has the specified hierarchy of objects / lists where the
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
177
|
+
# response has the specified hierarchy of objects / lists where the
|
178
|
+
# specified number of leaf items is as expected only (no data checked)
|
179
|
+
Then('the response {list_nesting}') do |nesting|
|
180
|
+
nesting.push(
|
181
|
+
root: true,
|
182
|
+
type: 'single'
|
183
|
+
)
|
184
|
+
data = @response.get get_key(nesting.grouping)
|
185
|
+
if data.empty? || !nest_match_attributes(data, nesting.grouping, {}, false)
|
186
|
+
raise %(Could not find a match for: #{nesting.match}\n#{@response.to_json_s})
|
187
|
+
end
|
145
188
|
end
|