cucumber-rest-bdd 0.4.4.pre.124 → 0.4.4.pre.136
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Dockerfile +1 -0
- data/Makefile +1 -1
- data/README.md +25 -0
- data/STEPS.md +32 -1
- data/docker-compose.yml +2 -1
- data/features/errors.feature +22 -0
- data/lib/cucumber-rest-bdd/steps/response.rb +21 -11
- data/lib/cucumber-rest-bdd/types.rb +7 -3
- data/server/error.js +14 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f9bb4e19befe54674236ada928775cc8f6a4d6a1
|
4
|
+
data.tar.gz: 0cfc7671388549be92b15f8e7e927600c00ad06a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1de33c7788797ee55173764bf15997c43d965e292006582c0d5b4fdcda13c92babd02be5f692c6b6de597ad1d7de2f2dbd456beb0ba8744bc802e653756c53b1
|
7
|
+
data.tar.gz: b6c62f44e4bd80219a74a8f5f6ea9ff40075c4e2acbd7e70ebe429f5e7432d2066af37186cacaa327043394115477ce946f236c812e4cb388bf96ea6510b95a3
|
data/Dockerfile
CHANGED
data/Makefile
CHANGED
@@ -5,7 +5,7 @@ build:
|
|
5
5
|
docker-compose build runner
|
6
6
|
|
7
7
|
test: start-test-server
|
8
|
-
docker-compose run --rm runner cucumber --order random
|
8
|
+
docker-compose run --rm runner cucumber --order random --format progress
|
9
9
|
make stop-test-server > /dev/null 2>&1 &
|
10
10
|
|
11
11
|
start-test-server: stop-test-server
|
data/README.md
CHANGED
@@ -154,6 +154,31 @@ Then more than 10 posts have five comments
|
|
154
154
|
Then less than 200 posts have five comments
|
155
155
|
```
|
156
156
|
|
157
|
+
#### Errors
|
158
|
+
|
159
|
+
If the `error_key` environment variable is set, if that key is used as the initial step it will ignore any `data_key`
|
160
|
+
setting.
|
161
|
+
|
162
|
+
Example: `error_key=error`, `data_key=data`
|
163
|
+
|
164
|
+
```gherkin
|
165
|
+
Then the response has a list of posts | {"data":[{"id": 12}]}
|
166
|
+
|
167
|
+
Then the response has one error | {"errors":[{"message": "Error"}]}
|
168
|
+
|
169
|
+
Then the response has an error | {"error": {"message": "Error}}
|
170
|
+
```
|
171
|
+
|
172
|
+
Example: `error_key=`, `data_key=data`
|
173
|
+
|
174
|
+
```gherkin
|
175
|
+
Then the response has a list of posts | {"data":[{"id": 12}]}
|
176
|
+
|
177
|
+
Then the response has one error | {"data": {"errors":[{"message": "Error"}]}}
|
178
|
+
|
179
|
+
Then the response has an error | {"data": {"error": {"message": "Error}}}
|
180
|
+
```
|
181
|
+
|
157
182
|
### Creation
|
158
183
|
|
159
184
|
```gherkin
|
data/STEPS.md
CHANGED
@@ -139,6 +139,37 @@ Then more than two items have have the following <N/A>
|
|
139
139
|
"application/json"
|
140
140
|
```
|
141
141
|
|
142
|
+
### Error Handling
|
143
|
+
|
144
|
+
Using the environment variable: `error_key` to represent the error resource
|
145
|
+
|
146
|
+
```
|
147
|
+
Behavioural Functional
|
148
|
+
--------------------------------------------------- --------------------------------------------------------------
|
149
|
+
Then the response has one error: Then the JSON response should have "errors[0].code" of type
|
150
|
+
| attribute | type | value | string with value "ERR-BLA"
|
151
|
+
| code | string | ERR-BLA |
|
152
|
+
|
153
|
+
Then the response has one error with attributes: Then the JSON response should have "errors[0].code" of type
|
154
|
+
| attribute | type | value | string with value "ERR-BLA"
|
155
|
+
| code | string | ERR-BLA |
|
156
|
+
|
157
|
+
Then the response has at least one error Then the JSON response should have "errors" of type array
|
158
|
+
with at least 1 entry
|
159
|
+
|
160
|
+
Then the response has an error Then the JSON response should have required key "error" of
|
161
|
+
Then the response contains an error type object
|
162
|
+
|
163
|
+
Then the response has two errors with:
|
164
|
+
| attribute | type | value |
|
165
|
+
| message | string | super error |
|
166
|
+
|
167
|
+
Then the response has three errors with two links <N/A>
|
168
|
+
with:
|
169
|
+
| attribute | type | value |
|
170
|
+
| href | string | http://oops |
|
171
|
+
```
|
172
|
+
|
142
173
|
### Attribute saving and re-use
|
143
174
|
|
144
175
|
```
|
@@ -155,7 +186,7 @@ Behavioural Functional
|
|
155
186
|
--------------------------------------------------- --------------------------------------------------------------
|
156
187
|
When I request a list of comments for post "1" When I send a GET request to "http://url/posts/1/comments"
|
157
188
|
|
158
|
-
When I request the comment "2" for post "3" When I send a GET request to "http://url/posts/
|
189
|
+
When I request the comment "2" for post "3" When I send a GET request to "http://url/posts/3/comments/2"
|
159
190
|
|
160
191
|
When I request the photo "3" in album "4" for user When I send a GET request to
|
161
192
|
"5" "http://url/users/5/albums/4/photos/3"
|
data/docker-compose.yml
CHANGED
@@ -2,7 +2,7 @@ version: '2'
|
|
2
2
|
services:
|
3
3
|
test-server:
|
4
4
|
image: clue/json-server
|
5
|
-
command: --routes /data/routes.json
|
5
|
+
command: --routes /data/routes.json --middlewares /data/error.js
|
6
6
|
volumes:
|
7
7
|
- ./server:/data:ro
|
8
8
|
|
@@ -19,4 +19,5 @@ services:
|
|
19
19
|
- field_camel=true
|
20
20
|
- resource_single=false
|
21
21
|
- data_key=
|
22
|
+
- error_key=error
|
22
23
|
- set_parent_id=true
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Feature: Handling error responses
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given I am a client
|
5
|
+
|
6
|
+
Scenario: Handle errors as a list
|
7
|
+
When I request the error "list"
|
8
|
+
Then the request fails because the post was not found
|
9
|
+
And the response contains at least one errors
|
10
|
+
And the response has one error
|
11
|
+
And the response has one error with the attributes:
|
12
|
+
| attribute | type | value |
|
13
|
+
| Message | string | Not Found |
|
14
|
+
|
15
|
+
Scenario: Handle error as a single item
|
16
|
+
When I request the error "single"
|
17
|
+
Then the request fails because it was invalid
|
18
|
+
And the response contains an error
|
19
|
+
And the response has an error
|
20
|
+
And the response has an error with the attributes:
|
21
|
+
| attribute | type | value |
|
22
|
+
| Message | string | Bad Request |
|
@@ -4,11 +4,11 @@ require 'cucumber-rest-bdd/types'
|
|
4
4
|
# response interrogation
|
5
5
|
|
6
6
|
Then(/^the response is a list (?:of|containing) (#{FEWER_MORE_THAN})?\s*(#{CAPTURE_INT}|\d+) .*?$/) do |count_mod, count|
|
7
|
-
list = @response.get_as_type
|
8
|
-
raise %/Expected at least #{count} items in array for path '#{
|
7
|
+
list = @response.get_as_type get_root_data_key(), 'array'
|
8
|
+
raise %/Expected at least #{count} items in array for path '#{get_root_data_key()}', found: #{list.count}\n#{@response.to_json_s}/ if !num_compare(count_mod, list.count, count.to_i)
|
9
9
|
end
|
10
10
|
|
11
|
-
Then(/^the response ((?:#{HAVE_SYNONYM} (?:a|an|(?:(?:#{FEWER_MORE_THAN})?\s*#{CAPTURE_INT}|\d+)) (?:\w+) )*)#{HAVE_SYNONYM} (?:the )?(?:following )?(?:data )?attributes:$/) do |nesting, attributes|
|
11
|
+
Then(/^the response ((?:#{HAVE_SYNONYM} (?:a|an|(?:(?:#{FEWER_MORE_THAN})?\s*#{CAPTURE_INT}|\d+)) (?:\w+) )*)#{HAVE_SYNONYM} (?:the )?(?:following )?(?:data|error )?attributes:$/) do |nesting, attributes|
|
12
12
|
expected = get_attributes(attributes.hashes)
|
13
13
|
groups = nesting
|
14
14
|
grouping = get_grouping(groups)
|
@@ -16,8 +16,8 @@ Then(/^the response ((?:#{HAVE_SYNONYM} (?:a|an|(?:(?:#{FEWER_MORE_THAN})?\s*#{C
|
|
16
16
|
root: true,
|
17
17
|
type: 'single'
|
18
18
|
})
|
19
|
-
data = @response.get
|
20
|
-
raise %/Could not find a match for: #{nesting}\n#{expected.inspect}\n#{@response.to_json_s}/ if !nest_match(data, grouping, expected)
|
19
|
+
data = @response.get get_key(grouping)
|
20
|
+
raise %/Could not find a match for: #{nesting}\n#{expected.inspect}\n#{@response.to_json_s}/ if data.empty? || !nest_match(data, grouping, expected)
|
21
21
|
end
|
22
22
|
|
23
23
|
Then(/^the response ((?:#{HAVE_SYNONYM} (?:a|an|(?:(?:#{FEWER_MORE_THAN})?\s*#{CAPTURE_INT}|\d+)) (?:\w+)\s?)+)$/) do |nesting|
|
@@ -27,8 +27,8 @@ Then(/^the response ((?:#{HAVE_SYNONYM} (?:a|an|(?:(?:#{FEWER_MORE_THAN})?\s*#{C
|
|
27
27
|
root: true,
|
28
28
|
type: 'single'
|
29
29
|
})
|
30
|
-
data = @response.get
|
31
|
-
raise %/Could not find a match for: #{nesting}\n#{@response.to_json_s}/ if !nest_match(data, grouping, {})
|
30
|
+
data = @response.get get_key(grouping)
|
31
|
+
raise %/Could not find a match for: #{nesting}\n#{@response.to_json_s}/ if data.empty? || !nest_match(data, grouping, {})
|
32
32
|
end
|
33
33
|
|
34
34
|
Then(/^(#{FEWER_MORE_THAN})?\s*(#{CAPTURE_INT}|\d+) (?:.*?) ((?:#{HAVE_SYNONYM} (?:a|an|(?:(?:#{FEWER_MORE_THAN})?\s*#{CAPTURE_INT}|\d+)) (?:\w+) )*)#{HAVE_SYNONYM} (?:the )?(?:following )?(?:data )?attributes:$/) do |count_mod, count, nesting, attributes|
|
@@ -41,7 +41,7 @@ Then(/^(#{FEWER_MORE_THAN})?\s*(#{CAPTURE_INT}|\d+) (?:.*?) ((?:#{HAVE_SYNONYM}
|
|
41
41
|
count: count.to_i,
|
42
42
|
count_mod: count_mod
|
43
43
|
})
|
44
|
-
data = @response.get
|
44
|
+
data = @response.get get_key(grouping)
|
45
45
|
raise %/Expected #{compare_to_string(count_mod)}#{count} items in array with attributes for: #{nesting}\n#{expected.inspect}\n#{@response.to_json_s}/ if !nest_match(data, grouping, expected)
|
46
46
|
end
|
47
47
|
|
@@ -54,7 +54,7 @@ Then(/^(#{FEWER_MORE_THAN})?\s*(#{CAPTURE_INT}|\d+) (?:.*?) ((?:#{HAVE_SYNONYM}
|
|
54
54
|
count: count.to_i,
|
55
55
|
count_mod: count_mod
|
56
56
|
})
|
57
|
-
data = @response.get
|
57
|
+
data = @response.get get_key(grouping)
|
58
58
|
raise %/Expected #{compare_to_string(count_mod)}#{count} items in array with: #{nesting}\n#{@response.to_json_s}/ if !nest_match(data, grouping, {})
|
59
59
|
end
|
60
60
|
|
@@ -74,7 +74,7 @@ Then(/^the response ((?:#{HAVE_SYNONYM} (?:a|an|(?:(?:#{FEWER_MORE_THAN})?\s*#{C
|
|
74
74
|
root: true,
|
75
75
|
type: 'single'
|
76
76
|
})
|
77
|
-
data = @response.get
|
77
|
+
data = @response.get get_key(grouping)
|
78
78
|
raise %/Could not find a match for #{nesting}#{compare_to_string(num_mod)}#{num} #{item}\n#{@response.to_json_s}/ if !nest_match(data, grouping, {})
|
79
79
|
end
|
80
80
|
|
@@ -96,10 +96,19 @@ Then(/^(#{FEWER_MORE_THAN})?\s*(#{CAPTURE_INT}|\d+) (?:.*?) ((?:#{HAVE_SYNONYM}
|
|
96
96
|
count: count.to_i,
|
97
97
|
count_mod: count_mod
|
98
98
|
})
|
99
|
-
data = @response.get
|
99
|
+
data = @response.get get_key(grouping)
|
100
100
|
raise %/Expected #{compare_to_string(count_mod)}#{count} items with #{nesting}#{compare_to_string(num_mod)}#{num}#{item}\n#{@response.to_json_s}/ if !nest_match(data, grouping, {})
|
101
101
|
end
|
102
102
|
|
103
|
+
# gets the relevant key for the response based on the first key element
|
104
|
+
def get_key(grouping)
|
105
|
+
if ENV['error_key'] && !ENV['error_key'].empty? && grouping.count > 1 && grouping[-2][:key] == ENV['error_key'] then
|
106
|
+
get_root_error_key()
|
107
|
+
else
|
108
|
+
get_root_data_key()
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
103
112
|
# gets an array in the nesting format that nest_match understands to interrogate nested object and array data
|
104
113
|
def get_grouping(nesting)
|
105
114
|
grouping = []
|
@@ -131,6 +140,7 @@ end
|
|
131
140
|
#
|
132
141
|
# returns true if the expected data is contained within the data based on the nesting information
|
133
142
|
def nest_match(data, nesting, expected)
|
143
|
+
return false if !data
|
134
144
|
return data.deep_include?(expected) if nesting.size == 0
|
135
145
|
|
136
146
|
local_nesting = nesting.dup
|
@@ -102,12 +102,16 @@ def get_resource(name)
|
|
102
102
|
resource = (ENV.has_key?('resource_single') && ENV['resource_single'] == 'true') ? resource.singularize : resource.pluralize
|
103
103
|
end
|
104
104
|
|
105
|
-
def
|
105
|
+
def get_root_data_key()
|
106
106
|
return ENV.has_key?('data_key') && !ENV['data_key'].empty? ? "$.#{ENV['data_key']}." : "$."
|
107
107
|
end
|
108
108
|
|
109
|
+
def get_root_error_key()
|
110
|
+
return "$."
|
111
|
+
end
|
112
|
+
|
109
113
|
def get_json_path(names)
|
110
|
-
return "#{
|
114
|
+
return "#{get_root_data_key()}#{get_parameters(names).join('.')}"
|
111
115
|
end
|
112
116
|
|
113
117
|
def get_parameters(names)
|
@@ -119,7 +123,7 @@ def get_parameter(name)
|
|
119
123
|
name = name[1..-2]
|
120
124
|
else
|
121
125
|
separator = ENV.has_key?('field_separator') ? ENV['field_separator'] : '_'
|
122
|
-
name = name.parameterize(separator: separator)
|
126
|
+
name = name.singularize.parameterize(separator: separator)
|
123
127
|
name = name.camelize(:lower) if (ENV.has_key?('field_camel') && ENV['field_camel'] == 'true')
|
124
128
|
end
|
125
129
|
name
|
data/server/error.js
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module.exports = (req, res, next) => {
|
2
|
+
if (req.path == '/errors/list') {
|
3
|
+
res.status(404)
|
4
|
+
res.locals.data = {
|
5
|
+
errors: [{ message: 'Not Found' }]
|
6
|
+
}
|
7
|
+
} else if (req.path == '/errors/single') {
|
8
|
+
res.status(400)
|
9
|
+
res.locals.data = {
|
10
|
+
error: { message: 'Bad Request' }
|
11
|
+
}
|
12
|
+
}
|
13
|
+
next()
|
14
|
+
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cucumber-rest-bdd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.4.pre.
|
4
|
+
version: 0.4.4.pre.136
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Harry Bragg
|
@@ -68,6 +68,7 @@ files:
|
|
68
68
|
- STEPS.md
|
69
69
|
- cucumber-rest-bdd.gemspec
|
70
70
|
- docker-compose.yml
|
71
|
+
- features/errors.feature
|
71
72
|
- features/functional.feature
|
72
73
|
- features/grabs.feature
|
73
74
|
- features/headers.feature
|
@@ -88,6 +89,7 @@ files:
|
|
88
89
|
- lib/cucumber-rest-bdd/types.rb
|
89
90
|
- lib/cucumber-rest-bdd/url.rb
|
90
91
|
- server/db.json
|
92
|
+
- server/error.js
|
91
93
|
- server/routes.json
|
92
94
|
homepage: http://github.com/graze/cucumber-rest-bdd
|
93
95
|
licenses:
|
@@ -109,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
109
111
|
version: 1.3.1
|
110
112
|
requirements: []
|
111
113
|
rubyforge_project:
|
112
|
-
rubygems_version: 2.
|
114
|
+
rubygems_version: 2.6.8
|
113
115
|
signing_key:
|
114
116
|
specification_version: 4
|
115
117
|
summary: BDD Rest API specifics for cucumber
|