cucumber-api 0.3 → 0.4
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/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
|