cucumber-apis 0.10 → 0.12
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/.DS_Store +0 -0
- data/lib/cucumber-api/helpers.rb +21 -0
- data/lib/cucumber-api/response.rb +117 -0
- data/lib/cucumber-api/steps.rb +180 -0
- data/lib/cucumber-api/version.rb +3 -0
- data/lib/cucumber-api.rb +1 -0
- metadata +12 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e87d8d57cf08d02cbc711ddf04c6639a59aaecf0780f5aa375ce81127545462
|
4
|
+
data.tar.gz: 5b637a0bb285ce98c9c0d2a699da0f320cd76d8dcdda8eabf4e4889935095003
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ee18f7f9bee4f1186796bc3aa01d39e2131781ec29d38248922b78e7fbbe8a196544ef1160edf497f010565f30805d3cb348bbae3d09d1640b9b62423091fa7
|
7
|
+
data.tar.gz: f3c87a52a414b24cb3066f1f37dae8e5fe4e04df6c0b26ecade0e89edf8b05bc01c33c2c442f44f818a5f0891315eb0ff8cacebff5e952e880515e5e24efd7b8
|
data/lib/.DS_Store
ADDED
Binary file
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module CucumberApi
|
2
|
+
module Helpers
|
3
|
+
# Bind grabbed values into placeholders in given URL
|
4
|
+
# Ex: http://example.com?id={id} with {id => 1} becomes http://example.com?id=1
|
5
|
+
# @param url [String] parameterized URL with placeholders
|
6
|
+
# @return [String] binded URL or original URL if no placeholders
|
7
|
+
def resolve url
|
8
|
+
url.gsub!(/\{([a-zA-Z0-9_]+)\}/) do |s|
|
9
|
+
s.gsub!(/[\{\}]/, '')
|
10
|
+
if instance_variable_defined?("@#{s}")
|
11
|
+
CGI.escape %/#{instance_variable_get("@#{s}")}/
|
12
|
+
else
|
13
|
+
raise 'Did you forget to "grab" ' + s + '?'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
url
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
World(CucumberApi::Helpers)
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'jsonpath'
|
3
|
+
require 'rest-client'
|
4
|
+
|
5
|
+
module CucumberApi
|
6
|
+
|
7
|
+
# Extension of {RestClient::Response} with support for JSON path traversal and validation
|
8
|
+
module Response
|
9
|
+
# Create a Response with JSON path support
|
10
|
+
# @param response [RestClient::Response] original response
|
11
|
+
# @return [Response] self
|
12
|
+
def self.create response
|
13
|
+
result = response
|
14
|
+
result.extend Response
|
15
|
+
result
|
16
|
+
end
|
17
|
+
|
18
|
+
# Check if given JSON path exists
|
19
|
+
# @param json_path [String] a valid JSON path expression
|
20
|
+
# @param json [String] optional JSON from which to check JSON path, default to response body
|
21
|
+
# @return [true, false] true if JSON path is valid and exists, false otherwise
|
22
|
+
def has json_path, json=nil
|
23
|
+
if json.nil?
|
24
|
+
json = JSON.parse body
|
25
|
+
end
|
26
|
+
not JsonPath.new(json_path).on(json).empty?
|
27
|
+
end
|
28
|
+
|
29
|
+
# Retrieve value of the first JSON element with given JSON path
|
30
|
+
# @param json_path [String] a valid JSON path expression
|
31
|
+
# @param json [String] optional JSON from which to apply JSON path, default to response body
|
32
|
+
# @return [Object] value of first retrieved JSON element in form of Ruby object
|
33
|
+
# @raise [Exception] if JSON path is invalid or no matching JSON element found
|
34
|
+
def get json_path, json=nil
|
35
|
+
if json.nil?
|
36
|
+
json = JSON.parse body
|
37
|
+
end
|
38
|
+
results = JsonPath.new(json_path).on(json)
|
39
|
+
if results.empty?
|
40
|
+
raise %/Expected json path '#{json_path}' not found\n#{to_json_s}/
|
41
|
+
end
|
42
|
+
results.first
|
43
|
+
end
|
44
|
+
|
45
|
+
# Retrieve value of the first JSON element with given JSON path as given type
|
46
|
+
# @param json_path [String] a valid JSON path expression
|
47
|
+
# @param type [String] required type, possible values are 'numeric', 'array', 'string', 'boolean', 'numeric_string'
|
48
|
+
# or 'object'
|
49
|
+
# @param json [String] optional JSON from which to apply JSON path, default to response body
|
50
|
+
# @return [Object] value of first retrieved JSON element in form of given type
|
51
|
+
# @raise [Exception] if JSON path is invalid or no matching JSON element found or matching element does not match
|
52
|
+
# required type
|
53
|
+
def get_as_type json_path, type, json=nil
|
54
|
+
value = get json_path, json
|
55
|
+
case type
|
56
|
+
when 'numeric'
|
57
|
+
valid = value.is_a? Numeric
|
58
|
+
when 'array'
|
59
|
+
valid = value.is_a? Array
|
60
|
+
when 'string'
|
61
|
+
valid = value.is_a? String
|
62
|
+
when 'boolean'
|
63
|
+
valid = !!value == value
|
64
|
+
when 'numeric_string'
|
65
|
+
valid = value.is_a?(Numeric) or value.is_a?(String)
|
66
|
+
when 'object'
|
67
|
+
valid = value.is_a? Hash
|
68
|
+
else
|
69
|
+
raise %/Invalid expected type '#{type}'/
|
70
|
+
end
|
71
|
+
|
72
|
+
unless valid
|
73
|
+
raise %/Expect '#{json_path}' as a '#{type}' but was '#{value.class}'\n#{to_json_s}/
|
74
|
+
end
|
75
|
+
value
|
76
|
+
end
|
77
|
+
|
78
|
+
# Retrieve value of the first JSON element with given JSON path as given type, with nil value allowed
|
79
|
+
# @param json_path [String] a valid JSON path expression
|
80
|
+
# @param type [String] required type, possible values are 'numeric', 'array', 'string', 'boolean', 'numeric_string'
|
81
|
+
# or 'object'
|
82
|
+
# @param json [String] optional JSON from which to apply JSON path, default to response body
|
83
|
+
# @return [Object] value of first retrieved JSON element in form of given type or nil
|
84
|
+
# @raise [Exception] if JSON path is invalid or no matching JSON element found or matching element does not match
|
85
|
+
# required type
|
86
|
+
def get_as_type_or_null json_path, type, json=nil
|
87
|
+
value = get json_path, json
|
88
|
+
value.nil? ? value : get_as_type(json_path, type, json)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Retrieve value of the first JSON element with given JSON path as given type, and check for a given value
|
92
|
+
# @param json_path [String] a valid JSON path expression
|
93
|
+
# @param type [String] required type, possible values are 'numeric', 'string', 'boolean', or 'numeric_string'
|
94
|
+
# @param value [String] value to check for
|
95
|
+
# @param json [String] optional JSON from which to apply JSON path, default to response body
|
96
|
+
# @return [Object] value of first retrieved JSON element in form of given type or nil
|
97
|
+
# @raise [Exception] if JSON path is invalid or no matching JSON element found or matching element does not match
|
98
|
+
# required type or value
|
99
|
+
def get_as_type_and_check_value json_path, type, value, json=nil
|
100
|
+
v = get_as_type json_path, type, json
|
101
|
+
if value != v.to_s
|
102
|
+
raise %/Expect '#{json_path}' to be '#{value}' but was '#{v}'\n#{to_json_s}/
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Retrieve pretty JSON response for logging
|
107
|
+
# @return [String] pretty JSON response if verbose setting is true, empty string otherwise
|
108
|
+
def to_json_s
|
109
|
+
if ENV['cucumber_api_verbose'] == 'true'
|
110
|
+
JSON.pretty_generate(JSON.parse to_s)
|
111
|
+
else
|
112
|
+
''
|
113
|
+
end
|
114
|
+
end
|
115
|
+
RestClient::Response.send(:include, self)
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
require 'cucumber-api/response'
|
2
|
+
require 'cucumber-api/helpers'
|
3
|
+
require 'rest-client'
|
4
|
+
require 'json-schema'
|
5
|
+
|
6
|
+
if ENV['cucumber_api_verbose'] == 'true'
|
7
|
+
RestClient.log = 'stdout'
|
8
|
+
end
|
9
|
+
|
10
|
+
$cache = {}
|
11
|
+
|
12
|
+
Given(/^I clear the response cache$/) do
|
13
|
+
$cache = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
Given(/^I send and accept JSON$/) do
|
17
|
+
steps %Q{
|
18
|
+
Given I send "application/json" and accept JSON
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
Given(/^I send "(.*?)" and accept JSON$/) do |content_type|
|
23
|
+
@headers = {
|
24
|
+
:Accept => 'application/json',
|
25
|
+
:'Content-Type' => %/#{content_type}/
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
Given(/^I add Headers:$/) do |params|
|
30
|
+
params.rows_hash.each do |key, value|
|
31
|
+
@headers[key.to_sym] = resolve(value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
When(/^I grab "([^"]+)"$/) do |k|
|
36
|
+
if @response.nil?
|
37
|
+
raise 'No response found.'
|
38
|
+
end
|
39
|
+
|
40
|
+
if k[0] == '$'
|
41
|
+
v = k
|
42
|
+
else
|
43
|
+
v = "$.#{k}"
|
44
|
+
end
|
45
|
+
|
46
|
+
k.gsub!(/[^0-9a-zA-Z_]/, '')
|
47
|
+
instance_variable_set("@#{k}", @response.get(v))
|
48
|
+
end
|
49
|
+
|
50
|
+
When(/^I grab "([^"]+)" as "([^"]+)"$/) do |k, v|
|
51
|
+
if @response.nil?
|
52
|
+
raise 'No response found.'
|
53
|
+
end
|
54
|
+
|
55
|
+
k = "$.#{k}" unless k[0] == '$'
|
56
|
+
instance_variable_set("@#{v}", @response.get(k))
|
57
|
+
end
|
58
|
+
|
59
|
+
When(/^I set JSON request body to '(.*?)'$/) do |body|
|
60
|
+
@body = JSON.parse body
|
61
|
+
end
|
62
|
+
|
63
|
+
When(/^I set JSON request body to:$/) do |body|
|
64
|
+
@body = JSON.dump(JSON.parse(body))
|
65
|
+
end
|
66
|
+
|
67
|
+
When(/^I set form request body to:$/) do |params|
|
68
|
+
@body = {}
|
69
|
+
params.rows_hash.each do |key, value|
|
70
|
+
p_value = value
|
71
|
+
@grabbed.each { |k, v| p_value = v if value == %/{#{k}}/ } unless @grabbed.nil?
|
72
|
+
p_value = File.new %-#{Dir.pwd}/#{p_value.sub 'file://', ''}- if %/#{p_value}/.start_with? "file://"
|
73
|
+
@body[%/#{key}/] = p_value
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
When(/^I set request body from "(.*?).(yml|json)"$/) do |filename, extension|
|
78
|
+
path = %-#{Dir.pwd}/#{filename}.#{extension}-
|
79
|
+
if File.file? path
|
80
|
+
case extension
|
81
|
+
when 'yml'
|
82
|
+
@body = YAML.load File.open(path)
|
83
|
+
when 'json'
|
84
|
+
@body = JSON.parse File.read(path)
|
85
|
+
else
|
86
|
+
raise %/Unsupported file type: '#{path}'/
|
87
|
+
end
|
88
|
+
else
|
89
|
+
raise %/File not found: '#{path}'/
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
When(/^I send a (GET|POST|PATCH|PUT|DELETE) request to "(.*?)" with:$/) do |method, url, params|
|
94
|
+
unless params.hashes.empty?
|
95
|
+
query = params.hashes.first.map{|key, value| %/CGI.escape #{key}=#{value}/}.join("&")
|
96
|
+
url = url.include?('?') ? %/#{url}&#{query}/ : %/#{url}?#{query}/
|
97
|
+
end
|
98
|
+
steps %Q{
|
99
|
+
When I send a #{method} request to "#{url}"
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
When(/^I send a (GET|POST|PATCH|PUT|DELETE) request to "(.*?)"$/) do |method, url|
|
104
|
+
request_url = resolve(url)
|
105
|
+
if 'GET' == %/#{method}/ and $cache.has_key? %/#{request_url}/
|
106
|
+
@response = $cache[%/#{request_url}/]
|
107
|
+
@headers = nil
|
108
|
+
@body = nil
|
109
|
+
next
|
110
|
+
end
|
111
|
+
|
112
|
+
@headers = {} if @headers.nil?
|
113
|
+
begin
|
114
|
+
case method
|
115
|
+
when 'GET'
|
116
|
+
response = RestClient.get request_url, @headers
|
117
|
+
when 'POST'
|
118
|
+
response = RestClient.post request_url, @body, @headers
|
119
|
+
when 'PATCH'
|
120
|
+
response = RestClient.patch request_url, @body, @headers
|
121
|
+
when 'PUT'
|
122
|
+
response = RestClient.put request_url, @body, @headers
|
123
|
+
else
|
124
|
+
response = RestClient.delete request_url, @headers
|
125
|
+
end
|
126
|
+
rescue RestClient::Exception => e
|
127
|
+
response = e.response
|
128
|
+
end
|
129
|
+
@response = CucumberApi::Response.create response
|
130
|
+
@headers = nil
|
131
|
+
@body = nil
|
132
|
+
$cache[%/#{request_url}/] = @response if 'GET' == %/#{method}/
|
133
|
+
end
|
134
|
+
|
135
|
+
Then(/^the response status should be "(\d+)"$/) do |status_code|
|
136
|
+
raise %/Expect #{status_code} but was #{@response.code}/ if @response.code != status_code.to_i
|
137
|
+
end
|
138
|
+
|
139
|
+
Then(/^the JSON response should follow "(.*?)"$/) do |schema|
|
140
|
+
file_path = %-#{Dir.pwd}/#{schema}-
|
141
|
+
if File.file? file_path
|
142
|
+
begin
|
143
|
+
JSON::Validator.validate!(file_path, @response.to_s)
|
144
|
+
rescue JSON::Schema::ValidationError => e
|
145
|
+
raise JSON::Schema::ValidationError.new(%/#{$!.message}\n#{@response.to_json_s}/,
|
146
|
+
$!.fragments, $!.failed_attribute, $!.schema)
|
147
|
+
end
|
148
|
+
else
|
149
|
+
raise %/Schema not found: '#{file_path}'/
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
Then(/^the JSON response root should be (object|array)$/) do |type|
|
154
|
+
steps %Q{
|
155
|
+
Then the JSON response should have required key "$" of type #{type}
|
156
|
+
}
|
157
|
+
end
|
158
|
+
|
159
|
+
Then(/^the JSON response should have key "([^\"]*)"$/) do |json_path|
|
160
|
+
steps %Q{
|
161
|
+
Then the JSON response should have required key "#{json_path}" of type any
|
162
|
+
}
|
163
|
+
end
|
164
|
+
|
165
|
+
Then(/^the JSON response should have (required|optional) key "(.*?)" of type \
|
166
|
+
(numeric|string|boolean|numeric_string|object|array|any)( or null)?$/) do |optionality, json_path, type, null_allowed|
|
167
|
+
next if optionality == 'optional' and not @response.has(json_path) # if optional and no such key then skip
|
168
|
+
if 'any' == type
|
169
|
+
@response.get json_path
|
170
|
+
elsif null_allowed.nil?
|
171
|
+
@response.get_as_type json_path, type
|
172
|
+
else
|
173
|
+
@response.get_as_type_or_null json_path, type
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
Then(/^the JSON response should have "([^"]*)" of type \
|
178
|
+
(numeric|string|boolean|numeric_string) and value "([^"]*)"$/) do |json_path, type, value|
|
179
|
+
@response.get_as_type_and_check_value json_path, type, resolve(value)
|
180
|
+
end
|
data/lib/cucumber-api.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'cucumber-api/steps'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cucumber-apis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.12'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ha Duy Trung
|
@@ -29,22 +29,16 @@ dependencies:
|
|
29
29
|
name: cucumber
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
|
-
- - "
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version: '3.0'
|
35
|
-
- - ">"
|
32
|
+
- - ">="
|
36
33
|
- !ruby/object:Gem::Version
|
37
|
-
version:
|
34
|
+
version: '0'
|
38
35
|
type: :runtime
|
39
36
|
prerelease: false
|
40
37
|
version_requirements: !ruby/object:Gem::Requirement
|
41
38
|
requirements:
|
42
|
-
- - "
|
43
|
-
- !ruby/object:Gem::Version
|
44
|
-
version: '3.0'
|
45
|
-
- - ">"
|
39
|
+
- - ">="
|
46
40
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
41
|
+
version: '0'
|
48
42
|
- !ruby/object:Gem::Dependency
|
49
43
|
name: jsonpath
|
50
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,7 +89,13 @@ email:
|
|
95
89
|
executables: []
|
96
90
|
extensions: []
|
97
91
|
extra_rdoc_files: []
|
98
|
-
files:
|
92
|
+
files:
|
93
|
+
- lib/.DS_Store
|
94
|
+
- lib/cucumber-api.rb
|
95
|
+
- lib/cucumber-api/helpers.rb
|
96
|
+
- lib/cucumber-api/response.rb
|
97
|
+
- lib/cucumber-api/steps.rb
|
98
|
+
- lib/cucumber-api/version.rb
|
99
99
|
homepage: https://github.com/hidroh/cucumber-api
|
100
100
|
licenses:
|
101
101
|
- Apache-2.0
|