rest-assured 2.0.2 → 2.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5c35115ced77a2089492a155ef70c877a7f79155
4
- data.tar.gz: 3d0869cf86b0874e797e40054776213c87d7c145
3
+ metadata.gz: 7f22fb40a5da375669712d668d450c79397ddd9a
4
+ data.tar.gz: ee5916c4ee0dac3b82230c24bb606c90205091ab
5
5
  SHA512:
6
- metadata.gz: db3e43f69330695ba514f99c3851e78020828700aab04104e000149799941ac7d83b74ac147712a6355269c807ab5afa585f5acffae7215c9994289853fb7556
7
- data.tar.gz: 0c9b77fe69ea6dbf572130f7e998557ef0a89ed2c76b1bcad92bb5f8b2fa1f08a402726185bafa82bcb5a90f83cb44ac956f4d5f77a742787c210dbfed721d3b
6
+ metadata.gz: 5333399d35149cd78f6fbb8a2c404a2535fcb75845a77b8352de6955bbbfe332ce429bc4ada5044c0ef8146e986e13385642c4cbbf09ec8c61f72c61ba926721
7
+ data.tar.gz: 5e90dbf790b43165c31efc5ae29094ae2af86e9ef5acfd3be0ba5a4a1d98fa215f62ddbeb570044375e84d68a196c3bd9945ef5f710034d309ef4ec4e0c26d19
@@ -111,6 +111,15 @@ JSON.parse(req.params).should == expected_params_hash
111
111
  JSON.parse(req.rack_env)['HTTP_ACCEPT'].should == 'text/html'
112
112
  ```
113
113
 
114
+ If you want to simulate a delayed time to first byte to test how your application handles latency or time outs you can
115
+ use the delay property when you create the double.
116
+
117
+ ```ruby
118
+ @double = RestAssured::Double.create(fullpath: '/slow-products', delay: 5)
119
+ ```
120
+
121
+ Now, when a request is made to `http://localhost:4578/slow-products`, then the server will pause for 5 seconds before responding.
122
+
114
123
  Use REST api to clear doubles/redirects between tests:
115
124
 
116
125
  ```ruby
@@ -132,6 +141,7 @@ For using REST-assured from non-ruby environments.
132
141
  - __verb__ - one of http the following http verbs: `GET`, `POST`, `PUT`, `PATCH`, `DELETE`. Optional. `GET` is default.
133
142
  - __status__ - status returned when double is requested. Optional. `200` is default.
134
143
  - __response_headers__ - key/value map of headers. Optional.
144
+ - __delay__ - the length of time in seconds the server should pause before sending the response. Optional.
135
145
 
136
146
  Example:
137
147
 
@@ -173,7 +183,8 @@ For using REST-assured from non-ruby environments.
173
183
  "content": "awesome",
174
184
  "description": null,
175
185
  "status": 200,
176
- "active": true
186
+ "active": true,
187
+ "delay" : 0
177
188
  }
178
189
  }
179
190
 
@@ -219,7 +230,7 @@ Here is the rest API for managing redirects:
219
230
 
220
231
  ## Running tests
221
232
 
222
- Tests require sqlite. Cucumber tests also need Chrome.
233
+ Tests require postgres. Connection params are read from environment variables `DB_HOST`, `DB_PORT` and `DB_USER` (defaults are `localhost`, `5432` and `postgres`). Cucumber tests also need Chrome.
223
234
 
224
235
  $ git clone git://github.com/artemave/REST-assured.git
225
236
  $ cd rest-assured && bundle install
@@ -19,7 +19,7 @@ OptionParser.new do |opts|
19
19
  end
20
20
 
21
21
  opts.on('-u', '--dbuser DBUSER', "Db username (mysql, postgresql only)") do |user|
22
- user_opts[:user] = user
22
+ user_opts[:dbuser] = user
23
23
  end
24
24
 
25
25
  opts.on('--dbpass DBPASSWORD', 'Db password (mysql, postgresql only). Defaults to empty') do |password|
@@ -0,0 +1,9 @@
1
+ class AddDelayToDoubles < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :doubles, :delay, :integer
4
+ end
5
+
6
+ def self.down
7
+ remove_column :doubles, :delay
8
+ end
9
+ end
data/db/test.db CHANGED
Binary file
@@ -4,19 +4,19 @@ Feature: use doubles via api
4
4
  I want to mock rest services my app is consuming from
5
5
 
6
6
  Scenario Outline: create double
7
- When I create a double with "<fullpath>" as fullpath, "<content>" as response content, "<verb>" as request verb and status as "<status>"
8
- Then there should be 1 double with "<fullpath>" as fullpath, "<content>" as response content, "<result_verb>" as request verb and status as "<result_status>"
7
+ When I create a double with "<fullpath>" as fullpath, "<content>" as response content, "<verb>" as request verb, status as "<status>" and delay as "<delay>"
8
+ Then there should be 1 double with "<fullpath>" as fullpath, "<content>" as response content, "<result_verb>" as request verb, status as "<result_status>" and delay as "<result_delay>"
9
9
 
10
10
  Examples:
11
- | fullpath | content | verb | result_verb | status | result_status |
12
- | /api/something | created | POST | POST | 200 | 200 |
13
- | /api/sss | changed | PUT | PUT | 201 | 201 |
14
- | /api/asdfsf | removed | DELETE | DELETE | 300 | 300 |
15
- | /api/some | text content | GET | GET | 303 | 303 |
16
- | /api/some?a=3&b=dd | more content | | GET | | 200 |
17
- | /api/empty | | POST | POST | | 200 |
18
- | /api/file | | HEAD | HEAD | | 200 |
19
- | /api/file | | PATCH | PATCH | | 200 |
11
+ | fullpath | content | verb | result_verb | status | result_status | delay | result_delay |
12
+ | /api/something | created | POST | POST | 200 | 200 | | 0 |
13
+ | /api/sss | changed | PUT | PUT | 201 | 201 | 0 | 0 |
14
+ | /api/asdfsf | removed | DELETE | DELETE | 300 | 300 | 1 | 1 |
15
+ | /api/some | text content | GET | GET | 303 | 303 | 2 | 2 |
16
+ | /api/some?a=3&b=dd | more content | | GET | | 200 | 3 | 3 |
17
+ | /api/empty | | POST | POST | | 200 | 4 | 4 |
18
+ | /api/file | | HEAD | HEAD | | 200 | 5 | 5 |
19
+ | /api/file | | PATCH | PATCH | | 200 | 6 | 6 |
20
20
 
21
21
  Scenario: view created double details
22
22
  When I create a double
@@ -74,3 +74,22 @@ Feature: create double
74
74
  get @double.fullpath
75
75
  last_response.status == 302
76
76
  """
77
+
78
+ Scenario: specify a delay
79
+ When I create a double:
80
+ """
81
+ @double = RestAssured::Double.create(:fullpath => '/some/api', :delay => 4)
82
+ """
83
+ Then the following should be true:
84
+ """
85
+ start_time = Time.now
86
+
87
+ get @double.fullpath
88
+
89
+ end_time = Time.now
90
+
91
+ time_elapsed = end_time - start_time
92
+
93
+ expect(time_elapsed).to be > 3
94
+
95
+ """
@@ -4,8 +4,8 @@ Given /^there are no doubles$/ do
4
4
  RestAssured::Models::Double.destroy_all
5
5
  end
6
6
 
7
- When /^I create a double with "([^""]*)" as fullpath, "([^""]*)" as response content, "([^""]*)" as request verb and status as "([^""]*)"$/ do |fullpath, content, verb, status|
8
- post '/doubles.json', { :fullpath => fullpath, :content => content, :verb => verb, :status => status }
7
+ When /^I create a double with "([^""]*)" as fullpath, "([^""]*)" as response content, "([^""]*)" as request verb, status as "([^""]*)" and delay as "([^""]*)"$/ do |fullpath, content, verb, status, delay|
8
+ post '/doubles.json', { :fullpath => fullpath, :content => content, :verb => verb, :status => status, :delay => delay}
9
9
  last_response.should be_ok
10
10
  end
11
11
 
@@ -23,8 +23,8 @@ Then /^I should get (#{CAPTURE_A_NUMBER}) in response status$/ do |status|
23
23
  last_response.status.should == status
24
24
  end
25
25
 
26
- Then /^there should be (#{CAPTURE_A_NUMBER}) double with "([^""]*)" as fullpath, "([^""]*)" as response content, "([^""]*)" as request verb and status as "(#{CAPTURE_A_NUMBER})"$/ do |n, fullpath, content, verb, status|
27
- RestAssured::Models::Double.where(:fullpath => fullpath, :content => content, :verb => verb, :status => status).count.should == n
26
+ Then /^there should be (#{CAPTURE_A_NUMBER}) double with "([^""]*)" as fullpath, "([^""]*)" as response content, "([^""]*)" as request verb, status as "(#{CAPTURE_A_NUMBER})" and delay as "(#{CAPTURE_A_NUMBER})"$/ do |n, fullpath, content, verb, status, delay|
27
+ RestAssured::Models::Double.where(:fullpath => fullpath, :content => content, :verb => verb, :status => status, :delay => delay).count.should == n
28
28
  end
29
29
 
30
30
  Given /^there is double with "([^"]*)" as fullpath and "([^"]*)" as response content$/ do |fullpath, content|
@@ -152,7 +152,7 @@ Given /^I choose to delete double with fullpath "([^"]*)"$/ do |fullpath|
152
152
  end
153
153
 
154
154
  Then /^I should be asked to confirm delete$/ do
155
- page.driver.browser.switch_to.alert.accept
155
+ js_confirm
156
156
  end
157
157
 
158
158
  Given /^there are the following doubles:$/ do |table|
@@ -5,6 +5,7 @@ require 'rspec'
5
5
  require 'rack/test'
6
6
  require 'capybara'
7
7
  require 'capybara/cucumber'
8
+ require 'capybara/poltergeist'
8
9
  require 'database_cleaner'
9
10
  require 'anticipate'
10
11
  require 'awesome_print'
@@ -29,11 +30,17 @@ end
29
30
  Capybara.register_driver :selenium do |app|
30
31
  Capybara::Selenium::Driver.new(app, :browser => :chrome)
31
32
  end
33
+ Capybara.javascript_driver = ENV['FF'] ? :selenium : :poltergeist
32
34
 
33
35
  World(Capybara, Rack::Test::Methods, RackHeaderHack, WorldHelpers, Anticipate)
34
36
 
35
37
  require 'rest-assured/config'
36
- db_opts = { :adapter => 'sqlite' }
38
+ db_opts = {
39
+ adapter: 'postgres',
40
+ dbhost: ENV.fetch('DB_HOST', 'localhost'),
41
+ dbport: ENV.fetch('DB_PORT', 5432),
42
+ dbuser: ENV.fetch('DB_USER', 'postgres')
43
+ }
37
44
  RestAssured::Config.build(db_opts)
38
45
 
39
46
  require 'rest-assured'
@@ -22,4 +22,10 @@ module WorldHelpers
22
22
 
23
23
  YAML.load(config_yaml)
24
24
  end
25
+
26
+ def js_confirm
27
+ if Capybara.current_driver == :selenium
28
+ page.driver.browser.switch_to.alert.accept
29
+ end
30
+ end
25
31
  end
@@ -6,28 +6,28 @@ Feature: manage doubles via ui
6
6
 
7
7
  Scenario: view existing doubles
8
8
  Given the following doubles exist:
9
- | fullpath | description | content | verb |
10
- | /url1/aaa | twitter | test content | GET |
11
- | /url2/bbb | geo location | more content | POST |
12
- | /u/b?c=1 | wikipedia | article | PUT |
9
+ | fullpath | description | content | verb | delay |
10
+ | /url1/aaa | twitter | test content | GET | 0 |
11
+ | /url2/bbb | geo location | more content | POST | 1 |
12
+ | /u/b?c=1 | wikipedia | article | PUT | 2 |
13
13
  When I visit "doubles" page
14
14
  Then I should see existing doubles:
15
- | fullpath | description | verb |
16
- | /url1/aaa | twitter | GET |
17
- | /url2/bbb | geo location | POST |
18
- | /u/b?c=1 | wikipedia | PUT |
15
+ | fullpath | description | verb | delay |
16
+ | /url1/aaa | twitter | GET | 0 |
17
+ | /url2/bbb | geo location | POST | 1 |
18
+ | /u/b?c=1 | wikipedia | PUT | 2 |
19
19
 
20
20
  Scenario: add new double
21
21
  Given I am on "doubles" page
22
22
  When I choose to create a double
23
23
  And I enter double details:
24
- | fullpath | description | content | verb | status |
25
- | /url2/bb?a=b5 | google api | test content | POST | 200 |
24
+ | fullpath | description | content | verb | status | delay |
25
+ | /url2/bb?a=b5 | google api | test content | POST | 200 | 1 |
26
26
  And I save it
27
27
  Then I should see "Double created"
28
28
  And I should see existing doubles:
29
- | fullpath | description | verb | status |
30
- | /url2/bb?a=b5 | google api | POST | 200 |
29
+ | fullpath | description | verb | status | delay |
30
+ | /url2/bb?a=b5 | google api | POST | 200 | 1 |
31
31
 
32
32
  @javascript
33
33
  Scenario: choose active double
@@ -40,22 +40,22 @@ Feature: manage doubles via ui
40
40
 
41
41
  Scenario: edit double
42
42
  Given the following doubles exist:
43
- | fullpath | description | content | verb | status |
44
- | /url1/aaa | twitter | test content | POST | 404 |
43
+ | fullpath | description | content | verb | status | delay |
44
+ | /url1/aaa | twitter | test content | POST | 404 | 0 |
45
45
  And I visit "doubles" page
46
46
  And I choose to edit double
47
47
  When I change "double" "description" to "google"
48
48
  And I save it
49
49
  Then I should see existing doubles:
50
- | fullpath | description | verb | status |
51
- | /url1/aaa | google | POST | 404 |
50
+ | fullpath | description | verb | status | delay |
51
+ | /url1/aaa | google | POST | 404 | 0 |
52
52
 
53
53
  @javascript
54
54
  Scenario: delete double
55
55
  Given the following doubles exist:
56
- | fullpath | description | content |
57
- | /url1/aaa | twitter | test content |
58
- | /url/cc/bb | google | other content |
56
+ | fullpath | description | content | delay |
57
+ | /url1/aaa | twitter | test content | 0 |
58
+ | /url/cc/bb | google | other content | 1 |
59
59
  And I visit "doubles" page
60
60
  And I choose to delete double with fullpath "/url1/aaa"
61
61
  Then I should be asked to confirm delete
@@ -139,7 +139,7 @@ module RestAssured
139
139
 
140
140
  opts = {
141
141
  :adapter => 'postgresql',
142
- :username => AppConfig.user || 'root',
142
+ :username => AppConfig.dbuser || 'root',
143
143
  :database => AppConfig.database || default_database,
144
144
  :pool => 20
145
145
  }
@@ -8,6 +8,7 @@ module RestAssured
8
8
 
9
9
  VERBS = %w{GET POST PUT DELETE HEAD PATCH}
10
10
  STATUSES = Net::HTTPResponse::CODE_TO_OBJ.keys.map(&:to_i)
11
+ MAX_DELAY = 30
11
12
 
12
13
  validates_presence_of :fullpath
13
14
  validates_inclusion_of :verb, :in => VERBS
@@ -16,6 +17,7 @@ module RestAssured
16
17
  after_initialize :set_status
17
18
  after_initialize :set_verb
18
19
  after_initialize :set_response_headers
20
+ after_initialize :set_delay
19
21
 
20
22
  before_save :toggle_active
21
23
  after_destroy :set_active
@@ -50,6 +52,14 @@ module RestAssured
50
52
  f.save
51
53
  end
52
54
  end
55
+
56
+ def set_delay
57
+ self.delay = 0 unless delay.present?
58
+ if self.delay > MAX_DELAY
59
+ puts "delay #{self.delay} exceeds maxmium. Defaulting to #{MAX_DELAY}"
60
+ self.delay = MAX_DELAY
61
+ end
62
+ end
53
63
  end
54
64
  end
55
65
  end
@@ -51,7 +51,7 @@ module RestAssured
51
51
  end
52
52
  rescue
53
53
  d = params['double'] ||
54
- params.slice(*%w[fullpath content description verb status response_headers])
54
+ params.slice(*%w[fullpath content description verb status response_headers delay])
55
55
  end
56
56
 
57
57
  @double = Models::Double.create(d)
@@ -24,6 +24,8 @@ module RestAssured
24
24
 
25
25
  d.requests.create!(:rack_env => env.to_json, :body => body, :params => request.params.to_json)
26
26
 
27
+ sleep d.delay
28
+
27
29
  app.headers d.response_headers
28
30
  app.body d.content
29
31
  app.status d.status
@@ -1,3 +1,3 @@
1
1
  module RestAssured
2
- VERSION = '2.0.2'
2
+ VERSION = '2.1.0'
3
3
  end
@@ -29,7 +29,8 @@ module RestAssured
29
29
  :fullpath => '/some/path',
30
30
  :content => 'content',
31
31
  :response_headers => { 'ACCEPT' => 'text/html' },
32
- :status => 201
32
+ :status => 201,
33
+ :delay => 0
33
34
 
34
35
  allow(request).to receive(:fullpath).and_return(@double.fullpath)
35
36
  end
@@ -54,7 +55,7 @@ module RestAssured
54
55
 
55
56
  it 'records request' do
56
57
  requests = double
57
- allow(Models::Double).to receive_message_chain('where.first').and_return(double(:requests => requests).as_null_object)
58
+ allow(Models::Double).to receive_message_chain('where.first').and_return(double(:requests => requests, :delay => 0).as_null_object)
58
59
 
59
60
  expect(requests).to receive(:create!).with(:rack_env => 'env', :body => 'body', :params => 'params')
60
61
 
@@ -96,12 +97,22 @@ module RestAssured
96
97
  # TODO change to instead exclude anything that does not respond_to?(:to_s)
97
98
  it 'excludes "rack.input" and "rack.errors" as they break with "IOError - not opened for reading:" on consequent #to_json (as they are IO and StringIO)' do
98
99
  requests = double.as_null_object
99
- allow(Models::Double).to receive_message_chain('where.first').and_return(double(:requests => requests).as_null_object)
100
+ allow(Models::Double).to receive_message_chain('where.first').and_return(double(:requests => requests, :delay => 0).as_null_object)
100
101
 
101
102
  expect(env).to receive(:except).with('rack.input', 'rack.errors', 'rack.logger')
102
103
 
103
104
  Response.perform(rest_assured_app)
104
105
  end
105
106
 
107
+ it 'it sleeps for delay seconds' do
108
+ requests = double.as_null_object
109
+ allow(Models::Double).to receive_message_chain('where.first').and_return(double(:requests => requests, :delay => 10).as_null_object)
110
+
111
+ Response.stub(:sleep)
112
+ expect(Response).to receive(:sleep).with(10)
113
+
114
+ Response.perform(rest_assured_app)
115
+ end
116
+
106
117
  end
107
118
  end
@@ -8,7 +8,8 @@ module RestAssured::Models
8
8
  :content => 'some content',
9
9
  :verb => 'GET',
10
10
  :status => '303',
11
- :response_headers => { 'ACCEPT' => 'text/html' }
11
+ :response_headers => { 'ACCEPT' => 'text/html' },
12
+ :delay => 5
12
13
  }
13
14
  end
14
15
 
@@ -38,6 +39,16 @@ module RestAssured::Models
38
39
  expect(f.active).to be true
39
40
  end
40
41
 
42
+ it "defaults delay to 0" do
43
+ f = Double.create valid_params.except(:delay)
44
+ expect(f.delay).to be 0
45
+ end
46
+
47
+ it "defaults delay of greater than 30 seconds to 30 seconds" do
48
+ f = Double.create valid_params.merge(:delay => 99)
49
+ expect(f.delay).to be 30
50
+ end
51
+
41
52
  describe 'when created' do
42
53
  it "toggles active double for the same fullpath and verb" do
43
54
  f1 = Double.create valid_params
@@ -20,7 +20,12 @@ require 'rack/test'
20
20
  require 'awesome_print'
21
21
  require 'rest-assured/config'
22
22
 
23
- DB_OPTS = { :adapter => 'sqlite' }
23
+ DB_OPTS = {
24
+ adapter: 'postgres',
25
+ dbhost: ENV.fetch('DB_HOST', 'localhost'),
26
+ dbport: ENV.fetch('DB_PORT', 5432),
27
+ dbuser: ENV.fetch('DB_USER', 'postgres')
28
+ }
24
29
  RestAssured::Config.build(DB_OPTS)
25
30
 
26
31
  require 'rest-assured'
@@ -18,6 +18,10 @@
18
18
  - statuses.each do |s|
19
19
  %option{:name => s, :selected => (@double.status == s)}= s
20
20
 
21
+ %p
22
+ %label{:for => 'double_delay'} Delay
23
+ %input.wide#double_delay{:type => 'text', :name => 'double[delay]', :value => @double.delay}
24
+
21
25
  %p
22
26
  %label{:for => 'double_description'} Description
23
27
  %textarea.wide#double_description{:name => 'double[description]', :rows => 3}= @double.description
@@ -7,6 +7,7 @@
7
7
  %th Description
8
8
  %th Verb
9
9
  %th Status
10
+ %th Delay
10
11
  %th Active?
11
12
  %th &nbsp;
12
13
  %tbody
@@ -22,6 +23,7 @@
22
23
  %td= f.description
23
24
  %td= f.verb
24
25
  %td= f.status
26
+ %td= f.delay
25
27
  %td.label.text-center
26
28
  - if fs.size > 1
27
29
  %input.active-double-toggle{:type => 'radio', :name => group, :checked => f.active, :data => { 'double-id' => f.id }}
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rest-assured
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Artem Avetisyan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-24 00:00:00.000000000 Z
11
+ date: 2017-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra
@@ -133,6 +133,7 @@ files:
133
133
  - db/migrate/20111021113953_add_status_to_doubles.rb
134
134
  - db/migrate/20111208155906_add_response_headers_to_doubles.rb
135
135
  - db/migrate/20120320200820_change_fullpath_to_text.rb
136
+ - db/migrate/20170713000515_add_delay_to_doubles.rb
136
137
  - db/test.db
137
138
  - features/command_line_options.feature
138
139
  - features/rest_api/doubles.feature
@@ -229,7 +230,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
229
230
  version: '0'
230
231
  requirements: []
231
232
  rubyforge_project: rest-assured
232
- rubygems_version: 2.5.1
233
+ rubygems_version: 2.6.11
233
234
  signing_key:
234
235
  specification_version: 4
235
236
  summary: Real stubs and spies for HTTP(S) services