cucumber-rest-bdd 0.4.4 → 0.5.1.pre.140
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/Dockerfile +2 -1
- data/LICENSE +1 -1
- data/Makefile +1 -1
- data/README.md +26 -0
- data/STEPS.md +32 -1
- data/cucumber-rest-bdd.gemspec +1 -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 +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb1d9233bd18d88c3a16492812de62b582ad2dae
|
4
|
+
data.tar.gz: e874e9bd715a41facadd47f02ed6be5f7f75d442
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57f0046b7719f6f35c1f6de7f9fc8f825d9fa8ba913699abf47bbd4cadef25e1819e8e0d0929b2eb2e31b368ed733b68ce7b1810463bf57ad2ce8c21a57ca4aa
|
7
|
+
data.tar.gz: 9cfa198f99325aa0dc96d648eb9f7c44df37735b083c2e63b43d898d3983e55cb93a1e5f01f3e111d29d2048aad4868af0a8c8db65453bd2f5aaa6104f95db90
|
data/Dockerfile
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
FROM ruby
|
2
2
|
|
3
3
|
MAINTAINER "Harry Bragg <harry.bragg@graze.com>"
|
4
|
-
LABEL version="0.
|
4
|
+
LABEL version="0.5.1" \
|
5
5
|
license="MIT"
|
6
6
|
|
7
7
|
COPY . /usr/local/cucumber-rest-bdd
|
@@ -18,6 +18,7 @@ ENV field_camel=false
|
|
18
18
|
ENV resource_single=false
|
19
19
|
ENV cucumber_api_verbose=false
|
20
20
|
ENV data_key=
|
21
|
+
ENV error_key=error
|
21
22
|
ENV set_parent_id=false
|
22
23
|
|
23
24
|
CMD ["cucumber"]
|
data/LICENSE
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
@@ -35,6 +35,7 @@ The following environment variables modify how this will operate:
|
|
35
35
|
|
36
36
|
- `endpoint` - (string) the base url to call for each request
|
37
37
|
- `data_key` - (string) the root data key (if applicable) (for example: `"data"` if all responses have a `{"data":{}}` field)
|
38
|
+
- `error_key` - (string) this will ignore the `data_key` when checking for errors
|
38
39
|
- `field_separator` - (string) the separator used between words by the api
|
39
40
|
- `field_camel` - (bool [`true`|`false`]) does this endpoint use camelCase for fields (default: `false`)
|
40
41
|
- `resource_single` - (bool [`true`|`false`]) if each resource should be singularized or not (default: `false`)
|
@@ -154,6 +155,31 @@ Then more than 10 posts have five comments
|
|
154
155
|
Then less than 200 posts have five comments
|
155
156
|
```
|
156
157
|
|
158
|
+
#### Errors
|
159
|
+
|
160
|
+
If the `error_key` environment variable is set, if that key is used as the initial step it will ignore any `data_key`
|
161
|
+
setting.
|
162
|
+
|
163
|
+
Example: `error_key=error`, `data_key=data`
|
164
|
+
|
165
|
+
```gherkin
|
166
|
+
Then the response has a list of posts | {"data":[{"id": 12}]}
|
167
|
+
|
168
|
+
Then the response has one error | {"errors":[{"message": "Error"}]}
|
169
|
+
|
170
|
+
Then the response has an error | {"error": {"message": "Error}}
|
171
|
+
```
|
172
|
+
|
173
|
+
Example: `error_key=`, `data_key=data`
|
174
|
+
|
175
|
+
```gherkin
|
176
|
+
Then the response has a list of posts | {"data":[{"id": 12}]}
|
177
|
+
|
178
|
+
Then the response has one error | {"data": {"errors":[{"message": "Error"}]}}
|
179
|
+
|
180
|
+
Then the response has an error | {"data": {"error": {"message": "Error}}}
|
181
|
+
```
|
182
|
+
|
157
183
|
### Creation
|
158
184
|
|
159
185
|
```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/cucumber-rest-bdd.gemspec
CHANGED
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
|
+
version: 0.5.1.pre.140
|
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:
|
@@ -104,12 +106,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
104
106
|
version: '0'
|
105
107
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
108
|
requirements:
|
107
|
-
- - "
|
109
|
+
- - ">"
|
108
110
|
- !ruby/object:Gem::Version
|
109
|
-
version:
|
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
|