cucumber-api 0.3 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -1
- data/README.md +34 -6
- data/features/sample.feature +23 -2
- data/lib/cucumber-api/response.rb +16 -1
- data/lib/cucumber-api/steps.rb +48 -14
- data/lib/cucumber-api/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4ee88961920f3ccbf02d62d5ea0c7343d2f483f0
|
4
|
+
data.tar.gz: 5967edd044ec97f27368cf5a4c4a187004508fc5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8c3e01637543cf39ad990443fb82759520b4412d5da5d6c45e1a73036d8401930af194f67e3600ea131bc10753ee27b40137213aaabc54915c6b571e349d8ca
|
7
|
+
data.tar.gz: b1d4cbd828bbb829706ce0124e0a9e500f42cc2e1cc309b660e898797cd747f81c4806a20afd32d0ad8267cd87989dc9af22b2760dd5fb85f07be544a86aa5bd
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [Current](https://github.com/hidroh/cucumber-api/compare/0.
|
3
|
+
## [Current](https://github.com/hidroh/cucumber-api/compare/0.4...master)
|
4
|
+
|
5
|
+
## [0.4](https://github.com/hidroh/cucumber-api/compare/0.3...0.4) (November 03, 2016)
|
6
|
+
* Support additional request headers
|
7
|
+
* Allow specifying JSON request body with docstring
|
8
|
+
* Support simple JSON response value verification
|
9
|
+
* Grabbed values now persist until overridden within scenario, or when scenario exits
|
10
|
+
|
11
|
+
## [0.3](https://github.com/hidroh/cucumber-api/compare/0.2...0.3) (March 27, 2015)
|
12
|
+
|
13
|
+
* Bumped up gem dependencies, relax to minor versions
|
14
|
+
* Added gem license
|
4
15
|
|
5
16
|
## [0.2](https://github.com/hidroh/cucumber-api/compare/0.1...0.2) (March 07, 2015)
|
6
17
|
|
data/README.md
CHANGED
@@ -44,6 +44,15 @@ Given I send and accept JSON
|
|
44
44
|
Given I send "(.*?)" and accept JSON
|
45
45
|
```
|
46
46
|
|
47
|
+
You could also others header's information like:
|
48
|
+
|
49
|
+
```gherkin
|
50
|
+
Given I send and accept JSON
|
51
|
+
And I add Headers:
|
52
|
+
| name1 | value |
|
53
|
+
| name2 | other |
|
54
|
+
```
|
55
|
+
|
47
56
|
Specify POST body
|
48
57
|
|
49
58
|
```gherkin
|
@@ -52,6 +61,13 @@ When I set form request body to:
|
|
52
61
|
| key1 | value1 |
|
53
62
|
| key2 | {value2} |
|
54
63
|
| key3 | file://path-to-file |
|
64
|
+
When I set JSON request body to:
|
65
|
+
"""
|
66
|
+
{
|
67
|
+
"key1": "jsonString",
|
68
|
+
"key2": 1
|
69
|
+
}
|
70
|
+
"""
|
55
71
|
```
|
56
72
|
|
57
73
|
Or from YAML/JSON file
|
@@ -83,13 +99,20 @@ When I send a (GET|POST|PATCH|PUT|DELETE) request to "(.*?)" with:
|
|
83
99
|
| value1 | value2 | ... |
|
84
100
|
```
|
85
101
|
|
86
|
-
Temporarily save values from the last request to use in
|
102
|
+
Temporarily save values from the last request to use in subsequent steps in the same scenario:
|
87
103
|
|
88
104
|
```gherkin
|
89
105
|
When I grab "(.*?)" as "(.*?)"
|
90
106
|
```
|
91
107
|
|
92
|
-
|
108
|
+
Optionally, auto infer placeholder from grabbed JSON path:
|
109
|
+
|
110
|
+
```gherkin
|
111
|
+
# Grab and auto assign {id} as placeholder
|
112
|
+
When I grab "$..id"
|
113
|
+
```
|
114
|
+
|
115
|
+
The saved value can then be used to replace `{placeholder}` in the subsequent steps.
|
93
116
|
|
94
117
|
Example:
|
95
118
|
|
@@ -97,16 +120,19 @@ Example:
|
|
97
120
|
When I send a POST request to "http://example.com/token"
|
98
121
|
And I grab "$..request_token" as "token"
|
99
122
|
And I grab "$..access_type" as "type"
|
100
|
-
And I
|
123
|
+
And I grab "$..id"
|
124
|
+
And I send a GET request to "http://example.com/{token}" with:
|
101
125
|
| type | pretty |
|
102
126
|
| {type} | true |
|
127
|
+
Then the JSON response should have required key "id" of type string and value "{id}"
|
103
128
|
```
|
104
129
|
|
105
|
-
Assume that [http://example.com/token](http://example.com/token) have an element `{"request_token": 1, "access_type": "full"}`, **cucumber-api** will execute the followings:
|
130
|
+
Assume that [http://example.com/token](http://example.com/token) have an element `{"request_token": 1, "access_type": "full", "id": "user1"}`, **cucumber-api** will execute the followings:
|
106
131
|
|
107
132
|
* POST [http://example.com/token](http://example.com/token)
|
108
|
-
* Extract the first `request_token` and `
|
133
|
+
* Extract the first `request_token`, `access_type` and `id` from JSON response and save it for subsequent steps
|
109
134
|
* GET [http://example.com/1?type=full&pretty=true](http://example.com/1?type=full&pretty=true)
|
135
|
+
* Verify that JSON response has a pair of JSON key-value: `"id": "user1"`
|
110
136
|
* Clear all saved values
|
111
137
|
|
112
138
|
This will be handy when one needs to make a sequence of calls to authenticate/authorize API access.
|
@@ -123,7 +149,8 @@ Then the response status should be "(\d+)"
|
|
123
149
|
Then the JSON response should follow "(.*?)"
|
124
150
|
Then the JSON response root should be (object|array)
|
125
151
|
Then the JSON response should have key "([^\"]*)"
|
126
|
-
Then the JSON response should have (required|optional) key "(.*?)" of type (numeric|string|
|
152
|
+
Then the JSON response should have (required|optional) key "(.*?)" of type (numeric|string|boolean|numeric_string|object|array|any)( or null)
|
153
|
+
Then the JSON response should have (required|optional) key "(.*?)" of type (numeric|string|boolean|numeric_string|object|array|any)( or null) and value "(.*?)"
|
127
154
|
```
|
128
155
|
|
129
156
|
Example:
|
@@ -134,6 +161,7 @@ Then the JSON response should follow "features/schemas/example_all.json"
|
|
134
161
|
Then the JSON response root should be array
|
135
162
|
Then the JSON response should have key "id"
|
136
163
|
Then the JSON response should have optional key "format" of type string or null
|
164
|
+
Then the JSON response should have required key "status" of type string and value "foobar"
|
137
165
|
```
|
138
166
|
|
139
167
|
Also checkout [sample](/features/sample.feature) for real examples. Run sample with the following command:
|
data/features/sample.feature
CHANGED
@@ -2,8 +2,10 @@
|
|
2
2
|
Feature: Hacker News REST API validation
|
3
3
|
|
4
4
|
Scenario: Verify top stories JSON schema
|
5
|
-
|
6
|
-
And I
|
5
|
+
Given I send and accept JSON
|
6
|
+
And I add Headers:
|
7
|
+
| Cache-Control | no-cache |
|
8
|
+
When I send a GET request to "https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty"
|
7
9
|
Then the response status should be "200"
|
8
10
|
And the JSON response should follow "features/schemas/topstories.json"
|
9
11
|
|
@@ -19,9 +21,28 @@ Feature: Hacker News REST API validation
|
|
19
21
|
Then the response status should be "200"
|
20
22
|
And the JSON response root should be object
|
21
23
|
And the JSON response should have <optionality> key "<key>" of type <value type>
|
24
|
+
And the JSON response should have "id" of type numeric and value "{id}"
|
22
25
|
|
23
26
|
Examples:
|
24
27
|
| key | value type | optionality |
|
25
28
|
| id | numeric | required |
|
26
29
|
| score | numeric | required |
|
27
30
|
| url | string | optional |
|
31
|
+
|
32
|
+
Scenario: Demonstrate setting the JSON body with a docstring
|
33
|
+
Given I send and accept JSON
|
34
|
+
And I set JSON request body to:
|
35
|
+
"""
|
36
|
+
{
|
37
|
+
"title": "foo",
|
38
|
+
"body": "bar",
|
39
|
+
"userId": 1
|
40
|
+
}
|
41
|
+
"""
|
42
|
+
When I send a POST request to "http://jsonplaceholder.typicode.com/posts"
|
43
|
+
Then the response status should be "201"
|
44
|
+
And the JSON response should have "id" of type numeric and value "101"
|
45
|
+
And the JSON response should have "title" of type string and value "foo"
|
46
|
+
And the JSON response should have "body" of type string and value "bar"
|
47
|
+
And the JSON response should have "userId" of type numeric and value "1"
|
48
|
+
|
@@ -91,6 +91,21 @@ module CucumberApi
|
|
91
91
|
value.nil? ? value : get_as_type(json_path, type, json)
|
92
92
|
end
|
93
93
|
|
94
|
+
# Retrieve value of the first JSON element with given JSON path as given type, and check for a given value
|
95
|
+
# @param json_path [String] a valid JSON path expression
|
96
|
+
# @param type [String] required type, possible values are 'numeric', 'string', 'boolean', or 'numeric_string'
|
97
|
+
# @param value [String] value to check for
|
98
|
+
# @param json [String] optional JSON from which to apply JSON path, default to response body
|
99
|
+
# @return [Object] value of first retrieved JSON element in form of given type or nil
|
100
|
+
# @raise [Exception] if JSON path is invalid or no matching JSON element found or matching element does not match
|
101
|
+
# required type or value
|
102
|
+
def get_as_type_and_check_value json_path, type, value, json=nil
|
103
|
+
v = get_as_type json_path, type, json
|
104
|
+
if value != v.to_s
|
105
|
+
raise %/Expect '#{json_path}' to be '#{value}' but was '#{v}'\n#{to_json_s}/
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
94
109
|
# Retrieve pretty JSON response for logging
|
95
110
|
# @return [String] pretty JSON response if verbose setting is true, empty string otherwise
|
96
111
|
def to_json_s
|
@@ -101,4 +116,4 @@ module CucumberApi
|
|
101
116
|
end
|
102
117
|
end
|
103
118
|
end
|
104
|
-
end
|
119
|
+
end
|
data/lib/cucumber-api/steps.rb
CHANGED
@@ -21,10 +21,44 @@ Given(/^I send "(.*?)" and accept JSON$/) do |content_type|
|
|
21
21
|
}
|
22
22
|
end
|
23
23
|
|
24
|
+
Given(/^I add Headers:$/) do |params|
|
25
|
+
params.rows_hash.each do |key, value|
|
26
|
+
@headers[key.to_sym] = value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
When(/^I grab "([^"]+)"$/) do |k|
|
31
|
+
if @response.nil?
|
32
|
+
raise 'No response found.'
|
33
|
+
end
|
34
|
+
|
35
|
+
if k[0] == '$'
|
36
|
+
v = k
|
37
|
+
else
|
38
|
+
v = "$.#{k}"
|
39
|
+
end
|
40
|
+
|
41
|
+
k.gsub!(/[^0-9a-zA-Z_]/, '')
|
42
|
+
instance_variable_set("@#{k}", @response.get(v))
|
43
|
+
end
|
44
|
+
|
45
|
+
When(/^I grab "([^"]+)" as "([^"]+)"$/) do |k, v|
|
46
|
+
if @response.nil?
|
47
|
+
raise 'No response found.'
|
48
|
+
end
|
49
|
+
|
50
|
+
k = "$.#{k}" unless k[0] == '$'
|
51
|
+
instance_variable_set("@#{v}", @response.get(k))
|
52
|
+
end
|
53
|
+
|
24
54
|
When(/^I set JSON request body to '(.*?)'$/) do |body|
|
25
55
|
@body = JSON.parse body
|
26
56
|
end
|
27
57
|
|
58
|
+
When(/^I set JSON request body to:$/) do |body|
|
59
|
+
@body = JSON.dump(JSON.parse(body))
|
60
|
+
end
|
61
|
+
|
28
62
|
When(/^I set form request body to:$/) do |params|
|
29
63
|
@body = {}
|
30
64
|
params.rows_hash.each do |key, value|
|
@@ -51,15 +85,6 @@ When(/^I set request body from "(.*?).(yml|json)"$/) do |filename, extension|
|
|
51
85
|
end
|
52
86
|
end
|
53
87
|
|
54
|
-
When(/^I grab "(.*?)" as "(.*?)"$/) do |json_path, place_holder|
|
55
|
-
if @response.nil?
|
56
|
-
raise 'No response found, a request need to be made first before you can grab response'
|
57
|
-
end
|
58
|
-
|
59
|
-
@grabbed = {} if @grabbed.nil?
|
60
|
-
@grabbed[%/#{place_holder}/] = @response.get json_path
|
61
|
-
end
|
62
|
-
|
63
88
|
When(/^I send a (GET|POST|PATCH|PUT|DELETE) request to "(.*?)" with:$/) do |method, url, params|
|
64
89
|
unless params.hashes.empty?
|
65
90
|
query = params.hashes.first.map{|key, value| %/#{key}=#{value}/}.join("&")
|
@@ -76,7 +101,6 @@ When(/^I send a (GET|POST|PATCH|PUT|DELETE) request to "(.*?)"$/) do |method, ur
|
|
76
101
|
@response = $cache[%/#{request_url}/]
|
77
102
|
@headers = nil
|
78
103
|
@body = nil
|
79
|
-
@grabbed = nil
|
80
104
|
next
|
81
105
|
end
|
82
106
|
|
@@ -100,7 +124,6 @@ When(/^I send a (GET|POST|PATCH|PUT|DELETE) request to "(.*?)"$/) do |method, ur
|
|
100
124
|
@response = CucumberApi::Response.create response
|
101
125
|
@headers = nil
|
102
126
|
@body = nil
|
103
|
-
@grabbed = nil
|
104
127
|
$cache[%/#{request_url}/] = @response if 'GET' == %/#{method}/
|
105
128
|
end
|
106
129
|
|
@@ -136,7 +159,7 @@ Then(/^the JSON response should have key "([^\"]*)"$/) do |json_path|
|
|
136
159
|
end
|
137
160
|
|
138
161
|
Then(/^the JSON response should have (required|optional) key "(.*?)" of type \
|
139
|
-
(numeric|string|
|
162
|
+
(numeric|string|boolean|numeric_string|object|array|any)( or null)?$/) do |optionality, json_path, type, null_allowed|
|
140
163
|
next if optionality == 'optional' and not @response.has(json_path) # if optional and no such key then skip
|
141
164
|
if 'any' == type
|
142
165
|
@response.get json_path
|
@@ -147,13 +170,24 @@ Then(/^the JSON response should have (required|optional) key "(.*?)" of type \
|
|
147
170
|
end
|
148
171
|
end
|
149
172
|
|
173
|
+
Then(/^the JSON response should have "([^"]*)" of type \
|
174
|
+
(numeric|string|boolean|numeric_string) and value "([^"]*)"$/) do |json_path, type, value|
|
175
|
+
@response.get_as_type_and_check_value json_path, type, resolve(value)
|
176
|
+
end
|
177
|
+
|
150
178
|
# Bind grabbed values into placeholders in given URL
|
151
179
|
# Ex: http://example.com?id={id} with {id => 1} becomes http://example.com?id=1
|
152
180
|
# @param url [String] parameterized URL with placeholders
|
153
181
|
# @return [String] binded URL or original URL if no placeholders
|
154
182
|
def resolve url
|
155
|
-
|
156
|
-
|
183
|
+
url.gsub!(/\{([a-zA-Z0-9_]+)\}/) do |s|
|
184
|
+
s.gsub!(/[\{\}]/, '')
|
185
|
+
if instance_variable_defined?("@#{s}")
|
186
|
+
instance_variable_get("@#{s}")
|
187
|
+
else
|
188
|
+
raise 'Did you forget to "grab" ' + s + '?'
|
189
|
+
end
|
157
190
|
end
|
158
191
|
url
|
159
192
|
end
|
193
|
+
|
data/lib/cucumber-api/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cucumber-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.4'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ha Duy Trung
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-11-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cucumber
|