cucumber-api-steps 0.13 → 0.14.0
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 +7 -0
- data/.travis.yml +1 -0
- data/README.md +51 -47
- data/cucumber-api-steps.gemspec +6 -4
- data/features/fixtures/fake_app.rb +5 -1
- data/features/request.feature +9 -0
- data/features/step_definitions/api_test_steps.rb +5 -4
- data/lib/cucumber/api_steps.rb +21 -21
- data/lib/cucumber/api_steps/version.rb +1 -1
- metadata +49 -30
- data/.rvmrc +0 -1
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: beed2bd382872e4de2fc3b3b0ada4d4939a92f2d
|
4
|
+
data.tar.gz: 6adf6b1020a01d5e8ead8fe4af3ba1429e89c9d9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3a73d19cd6789f60cd0afdd36f8787832d9d2d0e30af243c1a63596668b92592eaa3f02f2ea720c16653a8d856de0c4ec7d984e2227e3488bdc9c22b34faa767
|
7
|
+
data.tar.gz: 7761f745dd825681491b9446a500314a48ffff9d6710cb56990018c75e1d06b6535cdd2c1941b2349b0f50f9f652126e02e302eb2e310effc36570cbe8d23cb7
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -3,11 +3,11 @@
|
|
3
3
|
[](https://travis-ci.org/jayzes/cucumber-api-steps)
|
4
4
|
[](http://badge.fury.io/rb/cucumber-api-steps)
|
5
5
|
|
6
|
-
A set of [Cucumber](https://github.com/
|
6
|
+
A set of [Cucumber](https://github.com/cucumber/cucumber) step definitions utilizing
|
7
7
|
[Rack-Test](https://github.com/brynary/rack-test) that ease basic
|
8
8
|
testing of REST-style APIs using either XML or JSON formats.
|
9
9
|
|
10
|
-
Adapted from [a blog post by Anthony Eden](http://
|
10
|
+
Adapted from [a blog post by Anthony Eden](http://anthonyeden.com/2013/07/10/testing-rest-apis-with-cucumber-and-rack.html) with a few additions based on my own needs. I found myself copying these step definitions around to multiple projects, and decided that it would be worthwhile to gem them up to keep things nice and DRY.
|
11
11
|
|
12
12
|
## Dependencies
|
13
13
|
|
@@ -17,60 +17,64 @@ Requires [Cucumber](https://github.com/aslakhellesoy/cucumber) (obviously). Als
|
|
17
17
|
|
18
18
|
Add the following line to your Gemfile, preferably in the test or cucumber group:
|
19
19
|
|
20
|
-
|
20
|
+
```ruby
|
21
|
+
gem 'cucumber-api-steps', :require => false
|
22
|
+
```
|
21
23
|
|
22
24
|
Then add the following line to your env.rb to make the step definitions available in your features:
|
23
25
|
|
24
|
-
|
26
|
+
```ruby
|
27
|
+
require 'cucumber/api_steps'
|
28
|
+
```
|
25
29
|
|
26
30
|
# Usage
|
27
31
|
|
28
32
|
Still a work in progress. For now, read the api_steps.rb file or check out the [stashboard-rails](https://github.com/jayzes/stashboard-rails) project - its Cucumber features make extensive use of the steps in this gem.
|
29
33
|
|
30
34
|
# Examples
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
35
|
+
```cucumber
|
36
|
+
Feature: API
|
37
|
+
|
38
|
+
Scenario: List tweets in JSON
|
39
|
+
When I send and accept JSON
|
40
|
+
And I send a GET request to "/api/tweets"
|
41
|
+
Then the response status should be "200"
|
42
|
+
And the JSON response should be:
|
43
|
+
"""
|
44
|
+
[{"tweet":"Hello World!"},{"tweet":"New Rails has been released"}]
|
45
|
+
"""
|
46
|
+
And the JSON response should have "$..tweet" with the text "Hello World!"
|
47
|
+
And the JSON response should have "$..tweet" with a length of 2
|
48
|
+
|
49
|
+
Scenario: List tweets in XML
|
50
|
+
When I send and accept XML
|
51
|
+
And I send a GET request to "/api/tweets"
|
52
|
+
Then the XML response should have "tweet" with text "Hello World!"
|
53
|
+
|
54
|
+
Scenario: Post tweet using POST-params
|
55
|
+
When I send a POST request to "/api/tweets" with the following:
|
56
|
+
| tweet | Hello World! |
|
57
|
+
| lat | 42.848282 |
|
58
|
+
| lng | 74.634933 |
|
59
|
+
Then the response status should be "201"
|
60
|
+
|
61
|
+
Scenario: Post tweet using json in POST body
|
62
|
+
When I send a POST request to "/api/tweets" with the following:
|
63
|
+
"""
|
64
|
+
{"tweet":"Hello World!","lat":"42.848282", "lng":"74.634933"}
|
65
|
+
"""
|
66
|
+
Then the response status should be "201"
|
67
|
+
|
68
|
+
Scenario: Basic authentication
|
69
|
+
When I authenticate as the user "joe" with the password "password123"
|
70
|
+
And I send a GET request to "/api/tweets"
|
71
|
+
Then the response status should be "200"
|
72
|
+
|
73
|
+
Scenario: Digest authentication
|
74
|
+
When I digest-authenticate as the user "joe" with the password "password123"
|
75
|
+
And I send a GET request to "/api/tweets"
|
76
|
+
Then the response status should be "200"
|
77
|
+
```
|
74
78
|
# Contributors
|
75
79
|
* Jay Zeschin
|
76
80
|
* Justin Smestad
|
data/cucumber-api-steps.gemspec
CHANGED
@@ -7,16 +7,18 @@ Gem::Specification.new do |s|
|
|
7
7
|
s.version = Cucumber::ApiSteps::VERSION
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
9
|
s.authors = ["Jay Zeschin"]
|
10
|
-
s.email = ["jay
|
10
|
+
s.email = ["jay@zeschin.org"]
|
11
11
|
s.homepage = "http://github.com/jayzes/cucumber-api-steps"
|
12
12
|
s.summary = %q{Cucumber steps to easily test REST-based XML and JSON APIs}
|
13
13
|
s.description = %q{Cucumber steps to easily test REST-based XML and JSON APIs}
|
14
14
|
|
15
15
|
s.required_ruby_version = '>= 1.9.3'
|
16
16
|
|
17
|
-
s.add_dependency 'jsonpath',
|
18
|
-
s.add_dependency 'cucumber',
|
19
|
-
s.
|
17
|
+
s.add_dependency 'jsonpath', '>= 0.1.2'
|
18
|
+
s.add_dependency 'cucumber', '>= 2.0.2'
|
19
|
+
s.add_development_dependency 'activesupport', '>= 3.0.0'
|
20
|
+
s.add_development_dependency 'rspec', '~> 3.3.0'
|
21
|
+
s.add_development_dependency 'sinatra', '~> 1.4.3'
|
20
22
|
|
21
23
|
s.files = `git ls-files`.split("\n")
|
22
24
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
@@ -15,7 +15,7 @@ module CucumberApiSteps
|
|
15
15
|
if request.accept.empty? || request.accept?('application/json')
|
16
16
|
content_type :json
|
17
17
|
books.to_json
|
18
|
-
elsif request.accept?('application/xml')
|
18
|
+
elsif request.accept?('application/xml')
|
19
19
|
content_type :xml
|
20
20
|
books.to_xml
|
21
21
|
end
|
@@ -25,6 +25,10 @@ module CucumberApiSteps
|
|
25
25
|
status 201 if params.values == ["Metaprograming ruby", "Pragprog"]
|
26
26
|
end
|
27
27
|
|
28
|
+
patch '/api/books' do
|
29
|
+
status 200 if params.values == ["Metaprograming ruby", "Pragprog"]
|
30
|
+
end
|
31
|
+
|
28
32
|
post '/api/publishers' do
|
29
33
|
input_data = JSON.parse request.env["rack.input"].read, symbolize_names: true
|
30
34
|
status 201 if input_data == {publisher: 'Pragprog'}
|
data/features/request.feature
CHANGED
@@ -16,6 +16,15 @@ Feature:
|
|
16
16
|
"""
|
17
17
|
Then the response status should be "201"
|
18
18
|
|
19
|
+
Scenario: PATCH request with params
|
20
|
+
When I perform the following step with table:
|
21
|
+
"""
|
22
|
+
I send a PATCH request to "/api/books" with the following:
|
23
|
+
| title | Metaprograming ruby |
|
24
|
+
| publisher | Pragprog |
|
25
|
+
"""
|
26
|
+
Then the response status should be "200"
|
27
|
+
|
19
28
|
Scenario: POST request with string
|
20
29
|
When I perform the following step with string:
|
21
30
|
"""
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'active_support'
|
1
2
|
require 'active_support/core_ext'
|
2
3
|
|
3
4
|
When /^I perform the following steps?:$/ do |step_strings|
|
@@ -6,7 +7,7 @@ When /^I perform the following steps?:$/ do |step_strings|
|
|
6
7
|
end
|
7
8
|
|
8
9
|
Then /^the response should equal:$/ do |response_body|
|
9
|
-
last_response.body.
|
10
|
+
expect(last_response.body).to eq(response_body)
|
10
11
|
end
|
11
12
|
|
12
13
|
When /^I perform the following step with table:$/ do |step_definition|
|
@@ -32,13 +33,13 @@ end
|
|
32
33
|
Then /^the request headers should be:$/ do |headers|
|
33
34
|
headers_hash = headers.rows_hash
|
34
35
|
request '/'
|
35
|
-
last_request.env.slice(*headers_hash.keys).values.
|
36
|
+
expect(last_request.env.slice(*headers_hash.keys).values).to eq(headers_hash.values)
|
36
37
|
end
|
37
38
|
|
38
39
|
Then /^I should be authenticated$/ do
|
39
|
-
last_request.env["HTTP_AUTHORIZATION"].
|
40
|
+
expect(last_request.env["HTTP_AUTHORIZATION"]).to eq("Basic #{Base64.encode64("joe:god")}")
|
40
41
|
end
|
41
42
|
|
42
43
|
Then /^I should be digest authenticated$/ do
|
43
|
-
last_request.env["HTTP_AUTHORIZATION"].starts_with?("Digest ").
|
44
|
+
expect(last_request.env["HTTP_AUTHORIZATION"].starts_with?("Digest ")).to be true
|
44
45
|
end
|
data/lib/cucumber/api_steps.rb
CHANGED
@@ -36,7 +36,7 @@ When /^I digest\-authenticate as the user "(.*?)" with the password "(.*?)"$/ do
|
|
36
36
|
digest_authorize user, pass
|
37
37
|
end
|
38
38
|
|
39
|
-
When /^I send a (GET|POST|PUT|DELETE) request (?:for|to) "([^"]*)"(?: with the following:)?$/ do |*args|
|
39
|
+
When /^I send a (GET|PATCH|POST|PUT|DELETE) request (?:for|to) "([^"]*)"(?: with the following:)?$/ do |*args|
|
40
40
|
request_type = args.shift
|
41
41
|
path = args.shift
|
42
42
|
input = args.shift
|
@@ -44,10 +44,10 @@ When /^I send a (GET|POST|PUT|DELETE) request (?:for|to) "([^"]*)"(?: with the f
|
|
44
44
|
request_opts = {method: request_type.downcase.to_sym}
|
45
45
|
|
46
46
|
unless input.nil?
|
47
|
-
if input.class == Cucumber::
|
47
|
+
if input.class == Cucumber::MultilineArgument::DataTable
|
48
48
|
request_opts[:params] = input.rows_hash
|
49
49
|
else
|
50
|
-
request_opts[:input] = input
|
50
|
+
request_opts[:input] = StringIO.new input
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
@@ -69,8 +69,8 @@ Then /^show me the (unparsed)?\s?response$/ do |unparsed|
|
|
69
69
|
end
|
70
70
|
|
71
71
|
Then /^the response status should be "([^"]*)"$/ do |status|
|
72
|
-
if self.respond_to?
|
73
|
-
last_response.status.
|
72
|
+
if self.respond_to?(:expect)
|
73
|
+
expect(last_response.status).to eq(status.to_i)
|
74
74
|
else
|
75
75
|
assert_equal status.to_i, last_response.status
|
76
76
|
end
|
@@ -79,11 +79,11 @@ end
|
|
79
79
|
Then /^the JSON response should (not)?\s?have "([^"]*)"$/ do |negative, json_path|
|
80
80
|
json = JSON.parse(last_response.body)
|
81
81
|
results = JsonPath.new(json_path).on(json).to_a.map(&:to_s)
|
82
|
-
if self.respond_to?(:
|
82
|
+
if self.respond_to?(:expect)
|
83
83
|
if negative.present?
|
84
|
-
results.
|
84
|
+
expect(results).to be_empty
|
85
85
|
else
|
86
|
-
results.
|
86
|
+
expect(results).not_to be_empty
|
87
87
|
end
|
88
88
|
else
|
89
89
|
if negative.present?
|
@@ -98,11 +98,11 @@ end
|
|
98
98
|
Then /^the JSON response should (not)?\s?have "([^"]*)" with the text "([^"]*)"$/ do |negative, json_path, text|
|
99
99
|
json = JSON.parse(last_response.body)
|
100
100
|
results = JsonPath.new(json_path).on(json).to_a.map(&:to_s)
|
101
|
-
if self.respond_to?(:
|
101
|
+
if self.respond_to?(:expect)
|
102
102
|
if negative.present?
|
103
|
-
results.
|
103
|
+
expect(results).not_to include(text)
|
104
104
|
else
|
105
|
-
results.
|
105
|
+
expect(results).to include(text)
|
106
106
|
end
|
107
107
|
else
|
108
108
|
if negative.present?
|
@@ -116,11 +116,11 @@ end
|
|
116
116
|
Then /^the XML response should (not)?\s?have "([^"]*)"$/ do |negative, xpath|
|
117
117
|
parsed_response = Nokogiri::XML(last_response.body)
|
118
118
|
elements = parsed_response.xpath(xpath)
|
119
|
-
if self.respond_to?(:
|
119
|
+
if self.respond_to?(:expect)
|
120
120
|
if negative.present?
|
121
|
-
elements.
|
121
|
+
expect(elements).to be_empty
|
122
122
|
else
|
123
|
-
elements.
|
123
|
+
expect(elements).not_to be_empty
|
124
124
|
end
|
125
125
|
else
|
126
126
|
if negative.present?
|
@@ -134,9 +134,9 @@ end
|
|
134
134
|
Then /^the XML response should have "([^"]*)" with the text "([^"]*)"$/ do |xpath, text|
|
135
135
|
parsed_response = Nokogiri::XML(last_response.body)
|
136
136
|
elements = parsed_response.xpath(xpath)
|
137
|
-
if self.respond_to?(:
|
138
|
-
elements.
|
139
|
-
elements.find { |e| e.text == text }.
|
137
|
+
if self.respond_to?(:expect)
|
138
|
+
expect(elements).not_to be_empty, "could not find #{xpath} in:\n#{last_response.body}"
|
139
|
+
expect(elements.find { |e| e.text == text }).not_to be_nil, "found elements but could not find #{text} in:\n#{elements.inspect}"
|
140
140
|
else
|
141
141
|
assert !elements.empty?, "could not find #{xpath} in:\n#{last_response.body}"
|
142
142
|
assert elements.find { |e| e.text == text }, "found elements but could not find #{text} in:\n#{elements.inspect}"
|
@@ -147,8 +147,8 @@ Then /^the JSON response should be:$/ do |json|
|
|
147
147
|
expected = JSON.parse(json)
|
148
148
|
actual = JSON.parse(last_response.body)
|
149
149
|
|
150
|
-
if self.respond_to?(:
|
151
|
-
actual.
|
150
|
+
if self.respond_to?(:expect)
|
151
|
+
expect(actual).to eq(expected)
|
152
152
|
else
|
153
153
|
assert_equal actual, response
|
154
154
|
end
|
@@ -157,8 +157,8 @@ end
|
|
157
157
|
Then /^the JSON response should have "([^"]*)" with a length of (\d+)$/ do |json_path, length|
|
158
158
|
json = JSON.parse(last_response.body)
|
159
159
|
results = JsonPath.new(json_path).on(json)
|
160
|
-
if self.respond_to?(:
|
161
|
-
results.length.
|
160
|
+
if self.respond_to?(:expect)
|
161
|
+
expect(results.length).to eq(length.to_i)
|
162
162
|
else
|
163
163
|
assert_equal length.to_i, results.length
|
164
164
|
end
|
metadata
CHANGED
@@ -1,74 +1,94 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cucumber-api-steps
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
5
|
-
prerelease:
|
4
|
+
version: 0.14.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Jay Zeschin
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2017-10-25 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: jsonpath
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: 0.1.2
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: 0.1.2
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: cucumber
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - ">="
|
36
32
|
- !ruby/object:Gem::Version
|
37
|
-
version:
|
33
|
+
version: 2.0.2
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - ">="
|
44
39
|
- !ruby/object:Gem::Version
|
45
|
-
version:
|
40
|
+
version: 2.0.2
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activesupport
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.0.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.0.0
|
46
55
|
- !ruby/object:Gem::Dependency
|
47
56
|
name: rspec
|
48
57
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
58
|
requirements:
|
51
|
-
- -
|
59
|
+
- - "~>"
|
52
60
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
54
|
-
type: :
|
61
|
+
version: 3.3.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 3.3.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sinatra
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.4.3
|
76
|
+
type: :development
|
55
77
|
prerelease: false
|
56
78
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
79
|
requirements:
|
59
|
-
- -
|
80
|
+
- - "~>"
|
60
81
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
82
|
+
version: 1.4.3
|
62
83
|
description: Cucumber steps to easily test REST-based XML and JSON APIs
|
63
84
|
email:
|
64
|
-
- jay
|
85
|
+
- jay@zeschin.org
|
65
86
|
executables: []
|
66
87
|
extensions: []
|
67
88
|
extra_rdoc_files: []
|
68
89
|
files:
|
69
|
-
- .gitignore
|
70
|
-
- .
|
71
|
-
- .travis.yml
|
90
|
+
- ".gitignore"
|
91
|
+
- ".travis.yml"
|
72
92
|
- Gemfile
|
73
93
|
- README.md
|
74
94
|
- Rakefile
|
@@ -84,27 +104,26 @@ files:
|
|
84
104
|
- lib/cucumber/api_steps/version.rb
|
85
105
|
homepage: http://github.com/jayzes/cucumber-api-steps
|
86
106
|
licenses: []
|
107
|
+
metadata: {}
|
87
108
|
post_install_message:
|
88
109
|
rdoc_options: []
|
89
110
|
require_paths:
|
90
111
|
- lib
|
91
112
|
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
-
none: false
|
93
113
|
requirements:
|
94
|
-
- -
|
114
|
+
- - ">="
|
95
115
|
- !ruby/object:Gem::Version
|
96
116
|
version: 1.9.3
|
97
117
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
-
none: false
|
99
118
|
requirements:
|
100
|
-
- -
|
119
|
+
- - ">="
|
101
120
|
- !ruby/object:Gem::Version
|
102
121
|
version: '0'
|
103
122
|
requirements: []
|
104
123
|
rubyforge_project:
|
105
|
-
rubygems_version:
|
124
|
+
rubygems_version: 2.5.2
|
106
125
|
signing_key:
|
107
|
-
specification_version:
|
126
|
+
specification_version: 4
|
108
127
|
summary: Cucumber steps to easily test REST-based XML and JSON APIs
|
109
128
|
test_files:
|
110
129
|
- features/authentication.feature
|
data/.rvmrc
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
rvm use 1.9.3@cucumber-api-steps
|