rest-assured 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -17,7 +17,11 @@ gem 'launchy'
17
17
  gem 'rake'
18
18
  gem "spork", "> 0.9.0.rc"
19
19
  gem "guard-spork"
20
- gem 'rb-fsevent' if RUBY_PLATFORM =~ /darwin/
20
+ if RUBY_PLATFORM =~ /darwin/
21
+ gem 'growl_notify'
22
+ gem 'rb-fsevent'
23
+ end
21
24
  gem 'sinatra-activerecord'
22
25
  gem 'mysql'
23
26
  gem 'sqlite3', '~> 1.3.4'
27
+ gem 'thin'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rest-assured (0.2.0)
4
+ rest-assured (0.3.0)
5
5
  activerecord (~> 3.1.0)
6
6
  activeresource (~> 3.1.0)
7
7
  haml (>= 3.1.3)
@@ -11,21 +11,22 @@ PATH
11
11
  GEM
12
12
  remote: http://rubygems.org/
13
13
  specs:
14
- activemodel (3.1.1)
15
- activesupport (= 3.1.1)
14
+ activemodel (3.1.3)
15
+ activesupport (= 3.1.3)
16
16
  builder (~> 3.0.0)
17
17
  i18n (~> 0.6)
18
- activerecord (3.1.1)
19
- activemodel (= 3.1.1)
20
- activesupport (= 3.1.1)
18
+ activerecord (3.1.3)
19
+ activemodel (= 3.1.3)
20
+ activesupport (= 3.1.3)
21
21
  arel (~> 2.2.1)
22
22
  tzinfo (~> 0.3.29)
23
- activeresource (3.1.1)
24
- activemodel (= 3.1.1)
25
- activesupport (= 3.1.1)
26
- activesupport (3.1.1)
23
+ activeresource (3.1.3)
24
+ activemodel (= 3.1.3)
25
+ activesupport (= 3.1.3)
26
+ activesupport (3.1.3)
27
27
  multi_json (~> 1.0)
28
28
  addressable (2.2.6)
29
+ archive-tar-minitar (0.5.2)
29
30
  arel (2.2.1)
30
31
  awesome_print (0.4.0)
31
32
  builder (3.0.0)
@@ -40,18 +41,22 @@ GEM
40
41
  capybara (~> 1.0)
41
42
  childprocess (0.2.2)
42
43
  ffi (~> 1.0.6)
43
- columnize (0.3.4)
44
+ columnize (0.3.5)
44
45
  cucumber (1.1.0)
45
46
  builder (>= 2.1.2)
46
47
  diff-lcs (>= 1.1.2)
47
48
  gherkin (~> 2.5.0)
48
49
  json (>= 1.4.6)
49
50
  term-ansicolor (>= 1.0.6)
51
+ daemons (1.1.4)
50
52
  database_cleaner (0.6.7)
51
53
  diff-lcs (1.1.3)
52
- ffi (1.0.9)
54
+ eventmachine (0.12.10)
55
+ ffi (1.0.11)
53
56
  gherkin (2.5.4)
54
57
  json (>= 1.4.6)
58
+ growl_notify (0.0.3)
59
+ rb-appscript
55
60
  guard (0.8.8)
56
61
  thor (~> 0.14.6)
57
62
  guard-spork (0.3.1)
@@ -65,10 +70,10 @@ GEM
65
70
  json_pure (1.6.1)
66
71
  launchy (2.0.5)
67
72
  addressable (~> 2.2.6)
68
- linecache (0.46)
69
- rbx-require-relative (> 0.0.4)
73
+ linecache19 (0.5.12)
74
+ ruby_core_source (>= 0.1.4)
70
75
  mime-types (1.16)
71
- multi_json (1.0.3)
76
+ multi_json (1.0.4)
72
77
  mysql (2.8.1)
73
78
  nokogiri (1.5.0)
74
79
  rack (1.3.5)
@@ -79,8 +84,8 @@ GEM
79
84
  rack-test (0.6.1)
80
85
  rack (>= 1.0)
81
86
  rake (0.9.2.2)
87
+ rb-appscript (0.6.1)
82
88
  rb-fsevent (0.4.3.1)
83
- rbx-require-relative (0.0.5)
84
89
  rspec (2.7.0)
85
90
  rspec-core (~> 2.7.0)
86
91
  rspec-expectations (~> 2.7.0)
@@ -89,15 +94,20 @@ GEM
89
94
  rspec-expectations (2.7.0)
90
95
  diff-lcs (~> 1.1.2)
91
96
  rspec-mocks (2.7.0)
92
- ruby-debug (0.10.4)
93
- columnize (>= 0.1)
94
- ruby-debug-base (~> 0.10.4.0)
95
- ruby-debug-base (0.10.4)
96
- linecache (>= 0.3)
97
+ ruby-debug-base19 (0.11.25)
98
+ columnize (>= 0.3.1)
99
+ linecache19 (>= 0.5.11)
100
+ ruby_core_source (>= 0.1.4)
101
+ ruby-debug19 (0.11.6)
102
+ columnize (>= 0.3.1)
103
+ linecache19 (>= 0.5.11)
104
+ ruby-debug-base19 (>= 0.11.19)
105
+ ruby_core_source (0.1.5)
106
+ archive-tar-minitar (>= 0.5.2)
97
107
  rubyzip (0.9.4)
98
- selenium-webdriver (2.9.1)
108
+ selenium-webdriver (2.12.2)
99
109
  childprocess (>= 0.2.1)
100
- ffi (= 1.0.9)
110
+ ffi (~> 1.0.9)
101
111
  json_pure
102
112
  rubyzip
103
113
  shoulda-matchers (1.0.0.beta3)
@@ -111,6 +121,10 @@ GEM
111
121
  spork (0.9.0.rc9)
112
122
  sqlite3 (1.3.4)
113
123
  term-ansicolor (1.0.7)
124
+ thin (1.3.1)
125
+ daemons (>= 1.0.9)
126
+ eventmachine (>= 0.12.6)
127
+ rack (>= 1.0.0)
114
128
  thor (0.14.6)
115
129
  tilt (1.3.3)
116
130
  tzinfo (0.3.31)
@@ -126,6 +140,7 @@ DEPENDENCIES
126
140
  capybara-firebug
127
141
  cucumber
128
142
  database_cleaner
143
+ growl_notify
129
144
  guard-spork
130
145
  interactive_editor
131
146
  launchy
@@ -135,8 +150,9 @@ DEPENDENCIES
135
150
  rb-fsevent
136
151
  rest-assured!
137
152
  rspec
138
- ruby-debug
153
+ ruby-debug19
139
154
  shoulda-matchers
140
155
  sinatra-activerecord
141
156
  spork (> 0.9.0.rc)
142
157
  sqlite3 (~> 1.3.4)
158
+ thin
@@ -15,9 +15,13 @@ You are going to need ruby >= 1.8.7.
15
15
 
16
16
  First make sure there is database adapter:
17
17
 
18
- bash$ gem install mysql # or sqlite
18
+ bash$ gem install sqlite3 # or mysql
19
19
 
20
- If using mysql, rest-assured expects database 'rest\_assured' to be accessible by user 'root' with no password. Those are defaults and are changeable with command line options.
20
+ If using mysql, rest-assured expects database 'rest\_assured' to be accessible by user 'root' with no password. Those are defaults and can be changed with cli options.
21
+
22
+ It is also recommended to have thin installed. This improves startup time (over default webrick) and also it works in-memory sqlite (which webrick does not):
23
+
24
+ bash$ gem install thin
21
25
 
22
26
  Then install gem and run:
23
27
 
@@ -28,23 +32,21 @@ Or clone from github and run:
28
32
 
29
33
  bash$ git clone git@github.com:BBC/rest-assured.git
30
34
  bash$ cd rest-assured && bundle install
31
- bash$ ./bin/rest-assured -a mysql &
35
+ bash$ ./bin/rest-assured -d :memory: & # in-memory sqlite db
32
36
 
33
- This starts an instance of rest-assured on port 4578 (changable with --port option). You can now access it via REST or web interfaces on 'http://localhost:4578'
37
+ This starts an instance of rest-assured on port 4578. It is accessible via REST or web interfaces on 'http://localhost:4578'
34
38
 
35
39
  Various options (such as ssl, port, db credentials, etc.) are available through command line options. Check out `rest-assured -h` to see what they are.
36
40
 
37
- NOTE that although sqlite is an option, I found it locking under any non-trivial load. Mysql feels much more reliable. But may be that is me sqliting it wrong.
38
-
39
- ## REST API
41
+ NOTE that although sqlite is an extremely handy option (especially with :memory:), I found it sometimes locking tables under non-trivial load. Hence there is mysql - more setup, but always works. But may be that is just me sqliting it wrong.
40
42
 
41
- ### Doubles
43
+ ## Doubles
42
44
 
43
- Double is a stub/mock of a particular external call.
45
+ Double is a stub/mock of HTTP request.
44
46
 
45
- #### Ruby Client API
47
+ ### Ruby Client API
46
48
 
47
- Rest-assured provides client library which partially implements ActiveResource (create and get). To make it available put the following in your test setup code (e.g. env.rb)
49
+ Rest-assured provides client library to work with doubles. Set it up in env.rb/spec_helper.rb first:
48
50
 
49
51
  ```ruby
50
52
  require 'rest-assured/client'
@@ -52,107 +54,127 @@ require 'rest-assured/client'
52
54
  RestAssured::Client.config.server_address = 'http://localhost:4578' # or wherever your rest-assured is
53
55
  ```
54
56
 
55
- You can then create doubles in your tests
57
+ You can then create doubles in your tests:
56
58
 
57
59
  ```ruby
58
60
  RestAssured::Double.create(fullpath: '/products', content: 'this is content')
59
61
  ```
60
62
 
61
- Or, in case you need verifications, create double in a Given part
63
+ Now GET 'http://localhost:4578/products' will be returning 'this is content'.
64
+
65
+ You can also verify what requests happen on a double. Say this is a Given part of a test:
62
66
 
63
67
  ```ruby
64
68
  @double = RestAssured::Double.create(fullpath: '/products', verb: 'POST')
65
69
  ```
66
70
 
67
- And verify requests happened on that double in a Then part
71
+ Then let us assume that 'http://localhost:4578/products' got POSTed as a result of some actions in When part. Now we can examine requests happened on that double in Then part:
68
72
 
69
73
  ```ruby
70
- @double.wait_for_requests(1, :timeout => 10) # default timeout 5 seconds
74
+ @double.wait_for_requests(1, :timeout => 10) # defaults to 5 seconds
71
75
 
72
76
  req = @double.requests.first
73
77
 
74
78
  req.body.should == expected_payload
75
79
  JSON.parse(req.params).should == expected_params_hash
76
- JSON.parse(req.rack_env)['ACCEPT'].should == 'Application/json'
80
+ JSON.parse(req.rack_env)['ACCEPT'].should == 'text/html'
77
81
  ```
78
82
 
79
- #### Plain REST API
83
+ Use plain rest api to clear doubles/redirects between tests:
84
+
85
+ ```ruby
86
+ RestClient.delete "#{RestAssured::Client.config.server_address}/redirects/all"
87
+ RestClient.delete "#{RestAssured::Client.config.server_address}/doubles/all"
88
+ ```
89
+
90
+ ### Plain REST API
91
+
92
+ #### Create double
80
93
 
81
- ##### Create double
82
- HTTP POST to '/doubles.json' creates double and returns its json representation.
94
+ HTTP POST to '/doubles' creates double and returns its json representation.
83
95
  The following options can be passed as request parameters:
84
96
 
85
97
  - __fullpath__ - e.g., '/some/api/object', or with parameters in query string (useful for doubling GETs) - '/some/other/api/object?a=2&b=c'. Mandatory.
86
98
  - __content__ - whatever you want this double to respond with. Optional.
87
99
  - __verb__ - one of http the following http verbs: GET, POST, PUT, DELETE. Optional. GET is default.
88
100
  - __status__ - status returned when double is requested. Optional. 200 is default.
89
-
90
- Example (using ruby RestClient):
101
+ - __response_headers__ - key/value map of headers. Optional.
91
102
 
92
- ```ruby
93
- response = RestClient.post 'http://localhost:4578/doubles', { fullpath: '/api/v2/products?type=fresh', verb: 'GET', content: 'this is list of products', status: 200 }
94
- puts response.body
95
- ```
96
- Produces:
103
+ Example:
97
104
 
98
- "{\"double\":{\"fullpath\":\"/api/v2/products?type=fresh\",\"verb\":\"GET\",\"id\":123,\"content\":\"this is list of products\",\"description\":null,\"status\":null,\"active\":true}}"
105
+ bash$ curl -d 'fullpath=/api/something&content=awesome&response_headers%5BContent-Type%5D=text%2Fhtml' http://localhost:4578/doubles
106
+ {"double":{"active":true,"content":"awesome","description":null,"fullpath":"/api/something","id":1,"response_headers":{"Content-Type":"text/html"},"status":200,"verb":"GET"}}
99
107
 
100
- And then GETting 'http://localhost:4578/api/v2/products?type=fresh' (in browser for instance) should return "this is list of products".
108
+ bash$ curl http://localhost:4578/api/something
109
+ awesome
101
110
 
102
111
  If there is more than one double for the same fullpath and verb, the last created one gets served. In UI you can manually control which double is 'active' (gets served).
103
112
 
104
- ##### Get double state
105
- HTTP GET to '/double/:id.json' returns json with double current state. Use id from create json as :id.
106
-
107
- Example (using ruby RestClient):
108
-
109
- ```ruby
110
- response = RestClient.get 'http://localhost:4578/doubles/123.json'
111
- puts response.body
112
- ```
113
-
114
- Assuming the above double has been requested once, this call would produce
113
+ #### Get double state
115
114
 
116
- "{\"double\":{\"fullpath\":\"/api/v2/products?type=fresh\",\"verb\":\"GET\",\"id\":123,\"requests\":[{\"rack_env\":\"LOOK FOR YOUR HEADERS HERE\",\"created_at\":\"2011-11-07T18:34:21+00:00\",\"body\":\"\",\"params\":\"{}\"}],\"content\":\"this is list of products\",\"description\":null,\"status\":null,\"active\":true}}"
117
-
118
- The important bit here is 'requests' array. This is history of requests for that double (in chronological order). Each element contains the following data (keys):
115
+ HTTP GET to '/doubles/:id.json' returns json with double current state. Use id from create json as :id.
116
+
117
+ Example:
118
+
119
+ bash$ curl http://localhost:4578/doubles/1.json | prettify_json.rb
120
+ {
121
+ "double": {
122
+ "verb": "GET",
123
+ "fullpath": "/api/something",
124
+ "response_headers": {
125
+ "Content-Type": "text/html"
126
+ },
127
+ "id": 1,
128
+ "requests": [
129
+ {
130
+ "double_id": 1,
131
+ "created_at": "2011-12-12T11:13:33+00:00",
132
+ "body": "",
133
+ "rack_env": "{\"SERVER_SOFTWARE\":\"thin 1.3.1 codename Triple Espresso\",\"SERVER_NAME\":\"localhost\",\"rack.version\":[1,0],\"rack.multithread\":false,\"rack.multiprocess\":false,\"rack.run_once\":false,\"REQUEST_METHOD\":\"GET\",\"REQUEST_PATH\":\"/api/something\",\"PATH_INFO\":\"/api/something\",\"REQUEST_URI\":\"/api/something\",\"HTTP_VERSION\":\"HTTP/1.1\",\"HTTP_USER_AGENT\":\"curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8l zlib/1.2.3\",\"HTTP_HOST\":\"localhost:4578\",\"HTTP_ACCEPT\":\"*/*\",\"GATEWAY_INTERFACE\":\"CGI/1.2\",\"SERVER_PORT\":\"4578\",\"QUERY_STRING\":\"\",\"SERVER_PROTOCOL\":\"HTTP/1.1\",\"rack.url_scheme\":\"http\",\"SCRIPT_NAME\":\"\",\"REMOTE_ADDR\":\"127.0.0.1\",\"async.callback\":{},\"async.close\":{},\"rack.session\":{\"session_id\":\"2d206d4edb880d41ae098bf0551c6904a4914f8632d101606b5304d4f651ce52\",\"tracking\":{\"HTTP_USER_AGENT\":\"06e79511d71287ca292dced4ef07c8fff9400376\",\"HTTP_ACCEPT_ENCODING\":\"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\"HTTP_ACCEPT_LANGUAGE\":\"da39a3ee5e6b4b0d3255bfef95601890afd80709\"},\"__FLASH__\":{}},\"rack.session.options\":{\"key\":\"rack.session\",\"path\":\"/\",\"domain\":null,\"expire_after\":null,\"secure\":false,\"httponly\":true,\"defer\":false,\"renew\":false,\"sidbits\":128,\"secure_random\":{\"pid\":7885},\"secret\":\"bf80c75d713c92d2e3f94ea58be318c3f8988a3ed79d997f9cf883cc7aab1141225477ed81da7fe62ac77ecac3f979d255328dcbe8caa1bb342f4be6cb850983\",\"coder\":{},\"id\":\"2d206d4edb880d41ae098bf0551c6904a4914f8632d101606b5304d4f651ce52\"},\"rack.request.cookie_hash\":{},\"rack.session.unpacked_cookie_data\":{\"session_id\":\"2d206d4edb880d41ae098bf0551c6904a4914f8632d101606b5304d4f651ce52\"},\"x-rack.flash\":{\"opts\":{\"sweep\":true},\"store\":{\"session_id\":\"2d206d4edb880d41ae098bf0551c6904a4914f8632d101606b5304d4f651ce52\",\"tracking\":{\"HTTP_USER_AGENT\":\"06e79511d71287ca292dced4ef07c8fff9400376\",\"HTTP_ACCEPT_ENCODING\":\"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\"HTTP_ACCEPT_LANGUAGE\":\"da39a3ee5e6b4b0d3255bfef95601890afd80709\"},\"__FLASH__\":{}},\"flagged\":[]},\"rack.request.query_string\":\"\",\"rack.request.query_hash\":{}}",
134
+ "id": 1,
135
+ "params": "{}"
136
+ }
137
+ ],
138
+ "content": "awesome",
139
+ "description": null,
140
+ "status": 200,
141
+ "active": true
142
+ }
143
+ }
144
+
145
+ The above assumes that that double has been requested once. Request history is in "requests" array (in chronological order). Each element contains the following data (keys):
119
146
 
120
147
  - __body__ - request payload
121
- - __params__ - request parameters
148
+ - __params__ - request parameters. json
122
149
  - __created_at__ - request timestamp
123
- - __rack_env__ - raw request dump (key value pairs). Including request headers
150
+ - __rack_env__ - raw request dump (json) including request headers
151
+
152
+ #### Delete all doubles
124
153
 
125
- ##### Delete all doubles
126
154
  HTTP DELETE to '/doubles/all' deletes all doubles. Useful for cleaning up between tests.
127
155
 
128
- ### Redirects
156
+ ## Redirects
129
157
 
130
158
  It is sometimes desirable to only double certain calls while letting others through to the 'real' services. Meet Redirects. Kind of "rewrite rules" for requests that didn't match any double. Here is the rest API for managing redirects:
131
159
 
132
- #### Create redirect
160
+ ### Create redirect
161
+
133
162
  HTTP POST to '/redirects' creates redirect.
134
163
  The following options can be passed as request parameters:
135
164
 
136
165
  - __pattern__ - regex (perl5 style) tested against request fullpath. Mandatory
137
166
  - __to__ - url base e.g., 'https://myserver:8787/api'. Mandatory
138
167
 
139
- Example (using ruby RestClient):
140
-
141
- ```ruby
142
- RestClient.post 'http://localhost:4578/redirects', { pattern: '^/auth', to: 'https://myserver.com/api' }
143
- ```
168
+ Example:
169
+
170
+ bash$ curl -d 'pattern=^/auth&to=https://myserver.com/api' http://localhost:4578/redirects
144
171
 
145
172
  Now request (any verb) to 'http://localhost:4578/auth/services/1' will get redirected to 'https://myserver.com/api/auth/services/1.' Provided of course there is no double matched for that fullpath and verb.
146
173
  Much like rewrite rules, redirects are evaluated in order (of creation). In UI you can manually rearrange the order.
147
174
 
148
- #### Delete all redirects
149
- HTTP DELETE to '/redirects/all' deletes all redirects. Useful for cleaning up between tests.
150
-
151
- ## TODO
175
+ ### Delete all redirects
152
176
 
153
- * Hide wiring rest-assured into ruby project behind client api
154
- * Bring UI upto date with rest-api (add verbs, statuses, request history)
155
- * Add custom response headers
177
+ HTTP DELETE to '/redirects/all' deletes all redirects. Useful for cleaning up between tests.
156
178
 
157
179
  ## Author
158
180
 
@@ -160,11 +182,19 @@ RestClient.post 'http://localhost:4578/redirects', { pattern: '^/auth', to: 'htt
160
182
 
161
183
  ## Changelog
162
184
 
163
- 0.2
164
- - adds verifications
165
- - adds ruby client
166
- - adds custom return statuses
167
- - adds ssl
168
- - adds mysql support
169
- 0.1 initial public release
185
+ #### 0.3 (12 Dec 2011)
186
+
187
+ * you can now specify response headers for double to respond with
188
+
189
+ #### 0.2
190
+
191
+ * adds verifications
192
+ * adds ruby client
193
+ * adds custom return statuses
194
+ * adds ssl
195
+ * adds mysql support
196
+
197
+ #### 0.1
198
+
199
+ * initial public release
170
200
 
@@ -0,0 +1,9 @@
1
+ class AddResponseHeadersToDoubles < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :doubles, :response_headers, :string
4
+ end
5
+
6
+ def self.down
7
+ remove_column :doubles, :response_headers
8
+ end
9
+ end
@@ -16,6 +16,11 @@ Feature: use doubles via api
16
16
  | /api/some?a=3&b=dd | more content | | GET | | 200 |
17
17
  | /api/empty | | POST | POST | | 200 |
18
18
 
19
+ @now
20
+ Scenario: view created double details
21
+ When I create a double
22
+ Then I should be able to get json representation of that double from response
23
+
19
24
  Scenario Outline: request fullpath that matches double
20
25
  Given there is double with "<fullpath>" as fullpath, "<content>" as response content, "<verb>" as request verb and "<status>" as status
21
26
  When I "<verb>" "<fullpath>"
@@ -0,0 +1,40 @@
1
+ Feature: create double using ruby client api
2
+ As ruby developer
3
+ I want to be able to create doubles via client api
4
+ So that interactions with rest-assured server are completely hidden from me
5
+
6
+ Background:
7
+ Given rest-assured is running locally:
8
+ """
9
+ RestAssured::Client.config.server_address = 'http://localhost:9876'
10
+ """
11
+
12
+ Scenario: create double with defaults
13
+ When I create a double:
14
+ """
15
+ @double = RestAssured::Double.create(:fullpath => '/some/api')
16
+ """
17
+ Then it should have the following defaults:
18
+ """
19
+ @double.verb.should == 'GET'
20
+ @double.response_headers.should == {}
21
+ @double.status.should == 200
22
+ @double.content.should == nil
23
+
24
+ get @double.fullpath
25
+ last_response.should be_ok
26
+ """
27
+
28
+ Scenario: create double with specified response headers
29
+ When I create a double:
30
+ """
31
+ @double = RestAssured::Double.create(:fullpath => '/some/api', :response_headers => { 'Content-Type' => 'text/html' })
32
+ """
33
+ Then it should have the following defaults:
34
+ """
35
+ @double.response_headers.should == { 'Content-Type' => 'text/html' }
36
+
37
+ get @double.fullpath
38
+ last_response.headers['Content-Type'].should == 'text/html'
39
+ """
40
+
@@ -1,15 +1,49 @@
1
- Feature: check double's call history
2
- In order to verify outcomes of my app that take form of http requests
1
+ Feature: verify requests that happened on double
2
+ In order to check that my app is performing correct requests
3
3
  As test developer
4
4
  I want to be able to get double 'call history'
5
5
 
6
+ Background:
7
+ Given rest-assured is running locally:
8
+ """
9
+ RestAssured::Client.config.server_address = 'http://localhost:9876'
10
+ """
11
+
6
12
  Scenario: no calls made to double
7
- Given there is a double
8
- When I request call history for that double
9
- Then it should be empty
13
+ Given I created a double:
14
+ """
15
+ @double = RestAssured::Double.create(:fullpath => '/some/api')
16
+ """
17
+ When I request call history for that double:
18
+ """
19
+ @requests = @double.reload.requests
20
+ """
21
+ Then it should be empty:
22
+ """
23
+ @requests.should be_empty
24
+ """
10
25
 
11
26
  Scenario: some calls made to double
12
- Given there is a double
13
- When that double gets requested
14
- And I request call history for that double
15
- Then I should see history records for those requests
27
+ Given I created a double:
28
+ """
29
+ @double = RestAssured::Double.create(:fullpath => '/some/path', :content => 'some content', :verb => 'POST')
30
+ """
31
+ When that double gets requested:
32
+ """
33
+ post @double.fullpath, { :foo => 'bar' }.to_json, "CONTENT_TYPE" => "application/json"
34
+ post @double.fullpath, { :fooz => 'baaz'}, 'SOME_HEADER' => 'header_data'
35
+ """
36
+ And I request call history for that double:
37
+ """
38
+ @requests = @double.reload.requests
39
+ """
40
+ Then I should see history records for those requests:
41
+ """
42
+ @requests.first.body.should == { :foo => 'bar' }.to_json
43
+ @requests.first.params.should == '{}'
44
+ JSON.parse( @requests.first.rack_env )["CONTENT_TYPE"].should == 'application/json'
45
+
46
+ @requests.last.body.should == 'fooz=baaz'
47
+ JSON.parse( @requests.last.params ).should == { 'fooz' => 'baaz' }
48
+ JSON.parse( @requests.last.rack_env )["SOME_HEADER"].should == 'header_data'
49
+ """
@@ -4,7 +4,11 @@ Feature: wait for requests on double to happen
4
4
  I want to be able to wait until specified number of requests happen
5
5
 
6
6
  Background:
7
- Given I created a double:
7
+ Given rest-assured is running locally:
8
+ """
9
+ RestAssured::Client.config.server_address = 'http://localhost:9876'
10
+ """
11
+ And I created a double:
8
12
  """
9
13
  @double = RestAssured::Double.create(:fullpath => '/some/api')
10
14
  """
@@ -29,7 +33,6 @@ Feature: wait for requests on double to happen
29
33
  Expected 3 requests. Got 2.
30
34
  """
31
35
 
32
- @now
33
36
  Scenario: custom timeout
34
37
  When I wait for 3 requests:
35
38
  """
@@ -4,22 +4,23 @@ 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 and "([^"]*)" as response content$/ do |fullpath, content|
8
- post '/doubles', { :fullpath => fullpath, :content => content }
9
- last_response.should be_ok
10
- end
11
-
12
7
  When /^I create a double with "([^""]*)" as fullpath, "([^""]*)" as response content, "([^""]*)" as request verb and status as "([^""]*)"$/ do |fullpath, content, verb, status|
13
8
  post '/doubles', { :fullpath => fullpath, :content => content, :verb => verb, :status => status }
14
9
  last_response.should be_ok
15
10
  end
16
11
 
17
- Then /^I should get (#{CAPTURE_A_NUMBER}) in response status$/ do |status|
18
- last_response.status.should == status
12
+ When /^I create a double$/ do
13
+ post '/doubles', { :fullpath => '/api/something' }
14
+ @create_a_double_response = last_response.body
15
+ end
16
+
17
+ Then /^I should be able to get json representation of that double from response$/ do
18
+ d = RestAssured::Models::Double.last
19
+ JSON.parse( @create_a_double_response ).should == JSON.parse( d.to_json )
19
20
  end
20
21
 
21
- Then /^there should be (#{CAPTURE_A_NUMBER}) double with "([^"]*)" as fullpath and "([^"]*)" as response content$/ do |n, fullpath, content|
22
- RestAssured::Models::Double.where(:fullpath => fullpath, :content => content).count.should == n
22
+ Then /^I should get (#{CAPTURE_A_NUMBER}) in response status$/ do |status|
23
+ last_response.status.should == status
23
24
  end
24
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|
@@ -34,11 +35,6 @@ Given /^there is double with "([^"]*)" as fullpath, "([^"]*)" as response conten
34
35
  RestAssured::Models::Double.create(:fullpath => fullpath, :content => content, :verb => verb, :status => status)
35
36
  end
36
37
 
37
- Given /^I register "([^"]*)" as fullpath and "([^"]*)" as response content$/ do |fullpath, content|
38
- post '/doubles', { :fullpath => fullpath, :content => content }
39
- last_response.should be_ok
40
- end
41
-
42
38
  When /^I request "([^"]*)"$/ do |fullpath|
43
39
  get fullpath
44
40
  end
@@ -1,7 +1,3 @@
1
- Given /^there are no redirect rules$/ do
2
- RestAssured::Models::Redirect.destroy_all
3
- end
4
-
5
1
  Then /^I should get (\d+)$/ do |code|
6
2
  last_response.status.should.to_s == code
7
3
  end
@@ -1,29 +1,24 @@
1
- Given /^there is a double$/ do
2
- @double = RestAssured::Double.create(:fullpath => '/some/path', :content => 'some content', :verb => 'POST')
1
+ Given /^rest\-assured is running locally:$/ do |code|
2
+ eval code
3
3
  end
4
4
 
5
- When /^that double gets requested$/ do
6
- post @double.fullpath, { :foo => 'bar' }.to_json, "CONTENT_TYPE" => "application/json"
7
- post @double.fullpath, { :fooz => 'baaz'}, 'SOME_HEADER' => 'header_data'
5
+ When /^that double gets requested:$/ do |code|
6
+ eval code
8
7
  end
9
8
 
10
- When /^I request call history for that double$/ do
11
- @requests = @double.reload.requests
9
+ When /^I request call history for that double:$/ do |code|
10
+ eval code
12
11
  end
13
12
 
14
- Then /^I should see history records for those requests$/ do
15
- @requests.first.body.should == { :foo => 'bar' }.to_json
16
- JSON.parse( @requests.first.rack_env )["CONTENT_TYPE"].should == 'application/json'
17
-
18
- JSON.parse( @requests.last.params ).should == { 'fooz' => 'baaz' }
19
- JSON.parse( @requests.last.rack_env )["SOME_HEADER"].should == 'header_data'
13
+ Then /^I should see history records for those requests:$/ do |code|
14
+ eval code
20
15
  end
21
16
 
22
- Then /^it should be empty$/ do
23
- @requests.size.should == 0
17
+ Then /^it should be empty:$/ do |code|
18
+ eval code
24
19
  end
25
20
 
26
- Given /^I created a double:$/ do |string|
21
+ Given /^I created? a double:$/ do |string|
27
22
  # expected string is:
28
23
  # @double = RestAssured::Double.create(:fullpath => '/some/api', :verb => 'POST')
29
24
  eval string
@@ -67,3 +62,7 @@ Then /^it should raise MoreRequestsExpected error after with the following messa
67
62
  @more_reqs_exc.should be_instance_of RestAssured::MoreRequestsExpected
68
63
  @more_reqs_exc.message.should =~ /#{string}/
69
64
  end
65
+
66
+ Then /^it should have the following defaults:$/ do |code|
67
+ eval code
68
+ end
@@ -57,8 +57,6 @@ Spork.each_run do
57
57
  sleep 1
58
58
  end
59
59
 
60
- RestAssured::Client.config.server_address = 'http://localhost:9876'
61
-
62
60
  def app
63
61
  RestAssured::Application
64
62
  end
@@ -1,4 +1,3 @@
1
- require 'rubygems'
2
1
  require 'sinatra/base'
3
2
  require 'sinatra/handler_options_patch'
4
3
  require 'haml'
@@ -4,6 +4,10 @@ module RestAssured
4
4
  class MoreRequestsExpected < StandardError; end
5
5
 
6
6
  class Double < ActiveResource::Base
7
+ def response_headers
8
+ attributes[:response_headers].attributes
9
+ end
10
+
7
11
  def wait_for_requests(n, opts = {})
8
12
  timeout = opts[:timeout] || 5
9
13
 
@@ -3,7 +3,9 @@ require 'net/http'
3
3
  module RestAssured
4
4
  module Models
5
5
  class Double < ActiveRecord::Base
6
- attr_accessible :fullpath, :content, :description, :verb, :status
6
+ attr_accessible :fullpath, :content, :description, :verb, :status, :response_headers
7
+
8
+ serialize :response_headers, Hash
7
9
 
8
10
  VERBS = %w{GET POST PUT DELETE}
9
11
  STATUSES = Net::HTTPResponse::CODE_TO_OBJ.keys.map(&:to_i)
@@ -20,28 +22,29 @@ module RestAssured
20
22
  has_many :requests, :dependent => :destroy
21
23
 
22
24
  private
23
- def toggle_active
24
- ne = id ? '!=' : 'IS NOT'
25
25
 
26
- if active && Double.where("fullpath = ? AND active = ? AND id #{ne} ?", fullpath, true, id).exists?
27
- Double.where("fullpath = ? AND id #{ne} ?", fullpath, id).update_all :active => false
26
+ def toggle_active
27
+ ne = id ? '!=' : 'IS NOT'
28
+
29
+ if active && Double.where("fullpath = ? AND active = ? AND id #{ne} ?", fullpath, true, id).exists?
30
+ Double.where("fullpath = ? AND id #{ne} ?", fullpath, id).update_all :active => false
31
+ end
28
32
  end
29
- end
30
33
 
31
- def set_verb
32
- self.verb = 'GET' unless verb.present?
33
- end
34
+ def set_verb
35
+ self.verb = 'GET' unless verb.present?
36
+ end
34
37
 
35
- def set_status
36
- self.status = 200 unless status.present?
37
- end
38
+ def set_status
39
+ self.status = 200 unless status.present?
40
+ end
38
41
 
39
- def set_active
40
- if active && f = Double.where(:fullpath => fullpath).last
41
- f.active = true
42
- f.save
42
+ def set_active
43
+ if active && f = Double.where(:fullpath => fullpath).last
44
+ f.active = true
45
+ f.save
46
+ end
43
47
  end
44
- end
45
48
  end
46
49
  end
47
50
  end
@@ -26,10 +26,22 @@ module RestAssured
26
26
  end
27
27
  end
28
28
 
29
- router.post /^\/doubles(\.json)?$/ do |passes_json|
30
- f = { :fullpath => params['fullpath'], :content => params['content'], :description => params['description'], :verb => params['verb'], :status => params['status'] }
29
+ router.post /^\/doubles(\.json)?$/ do
30
+ begin
31
+ data = request.body.read
32
+ d = JSON.parse(data)['double']
33
+ rescue
34
+ d = params['double'] || {
35
+ :fullpath => params['fullpath'],
36
+ :content => params['content'],
37
+ :description => params['description'],
38
+ :verb => params['verb'],
39
+ :status => params['status']
40
+ }
41
+ d.merge!(:response_headers => params['response_headers']) if params['response_headers']
42
+ end
31
43
 
32
- @double = Models::Double.create(passes_json ? JSON.parse(request.body.read)['double'] : ( params['double'] || f ))
44
+ @double = Models::Double.create(d)
33
45
 
34
46
  if browser?
35
47
  if @double.errors.blank?
@@ -10,6 +10,7 @@ module RestAssured
10
10
 
11
11
  d.requests.create!(:rack_env => env.to_json, :body => body, :params => request.params.to_json)
12
12
 
13
+ app.headers d.response_headers
13
14
  app.body d.content
14
15
  app.status d.status
15
16
  elsif r = Models::Redirect.ordered.find { |r| request.fullpath =~ /#{r.pattern}/ }
@@ -1,3 +1,3 @@
1
1
  module RestAssured
2
- VERSION = '0.2.0'
2
+ VERSION = '0.3.0'
3
3
  end
@@ -3,11 +3,27 @@ require File.expand_path('../../spec_helper', __FILE__)
3
3
  module RestAssured
4
4
  describe 'Double routes' do
5
5
  let :test_double do
6
- { :fullpath => '/api/google?a=5', :content => 'some awesome content', :verb => 'POST', :status => '201' }
6
+ {
7
+ :fullpath => '/api/google?a=5',
8
+ :content => 'some awesome content',
9
+ :verb => 'POST',
10
+ :status => '201',
11
+ :response_headers => { 'ACCEPT' => 'text/html' }
12
+ }
7
13
  end
14
+
8
15
  let :valid_params do
9
- { 'double[fullpath]' => test_double[:fullpath], 'double[content]' => test_double[:content], 'double[verb]' => test_double[:verb], 'double[status]' => test_double[:status] }
16
+ params = {
17
+ 'double[fullpath]' => test_double[:fullpath],
18
+ 'double[content]' => test_double[:content],
19
+ 'double[verb]' => test_double[:verb],
20
+ 'double[status]' => test_double[:status],
21
+ 'double[response_headers]' => test_double[:response_headers]
22
+ }
23
+
24
+ params
10
25
  end
26
+
11
27
  let :invalid_params do
12
28
  valid_params.except('double[fullpath]')
13
29
  end
@@ -40,7 +56,9 @@ module RestAssured
40
56
 
41
57
  last_request.fullpath.should == '/doubles'
42
58
  last_response.body.should =~ /Double created/
43
- Models::Double.exists?(test_double).should be true
59
+
60
+ d = Models::Double.where(test_double.except(:response_headers)).first
61
+ d.response_headers['ACCEPT'].should == 'text/html'
44
62
  end
45
63
 
46
64
  it "reports failure when creating with invalid parameters" do
@@ -87,7 +105,7 @@ module RestAssured
87
105
  last_response.should be_ok
88
106
  last_response.body.should =~ /Double deleted/
89
107
 
90
- Models::Double.exists?(test_double).should be_false
108
+ Models::Double.exists?(test_double.except(:response_headers)).should be_false
91
109
  end
92
110
  end
93
111
 
@@ -96,7 +114,9 @@ module RestAssured
96
114
  post '/doubles', test_double
97
115
 
98
116
  last_response.should be_ok
99
- Models::Double.exists?(test_double).should be_true
117
+
118
+ d = Models::Double.where(test_double.except(:response_headers)).first
119
+ d.response_headers['ACCEPT'].should == 'text/html'
100
120
  end
101
121
 
102
122
  it "reports failure when creating with invalid parameters" do
@@ -121,8 +141,10 @@ module RestAssured
121
141
  post '/doubles.json', { :double => test_double }.to_json, 'CONTENT_TYPE' => 'Application/json'
122
142
 
123
143
  last_response.should be_ok
124
- Models::Double.exists?(test_double).should be_true
125
- last_response.body.should == Models::Double.where(test_double).first.to_json
144
+
145
+ d = Models::Double.where(test_double.except(:response_headers)).first
146
+ d.response_headers['ACCEPT'].should == 'text/html'
147
+ last_response.body.should == d.to_json
126
148
  end
127
149
 
128
150
  it "reports failure when creating with invalid parameters" do
@@ -25,7 +25,12 @@ module RestAssured
25
25
 
26
26
  context 'when double matches request' do
27
27
  before do
28
- @double = Models::Double.create :fullpath => '/some/path', :content => 'content', :status => 201
28
+ @double = Models::Double.create \
29
+ :fullpath => '/some/path',
30
+ :content => 'content',
31
+ :response_headers => { 'ACCEPT' => 'text/html' },
32
+ :status => 201
33
+
29
34
  request.stub(:fullpath).and_return(@double.fullpath)
30
35
  end
31
36
 
@@ -41,6 +46,12 @@ module RestAssured
41
46
  Response.perform(rest_assured_app)
42
47
  end
43
48
 
49
+ it 'sets response headers to those in Double#response_headers' do
50
+ rest_assured_app.should_receive(:headers).with(@double.response_headers)
51
+
52
+ Response.perform(rest_assured_app)
53
+ end
54
+
44
55
  it 'records request' do
45
56
  requests = double
46
57
  Models::Double.stub_chain('where.first').and_return(double(:requests => requests).as_null_object)
@@ -3,7 +3,13 @@ require File.expand_path('../../spec_helper', __FILE__)
3
3
  module RestAssured::Models
4
4
  describe Double do
5
5
  let :valid_params do
6
- { :fullpath => '/some/api', :content => 'some content', :verb => 'GET', :status => '303' }
6
+ {
7
+ :fullpath => '/some/api',
8
+ :content => 'some content',
9
+ :verb => 'GET',
10
+ :status => '303',
11
+ :response_headers => { 'ACCEPT' => 'text/html' }
12
+ }
7
13
  end
8
14
 
9
15
  it { should validate_presence_of(:fullpath) }
@@ -13,6 +19,7 @@ module RestAssured::Models
13
19
  it { should allow_mass_assignment_of(:content) }
14
20
  it { should allow_mass_assignment_of(:verb) }
15
21
  it { should allow_mass_assignment_of(:status) }
22
+ it { should allow_mass_assignment_of(:response_headers) }
16
23
 
17
24
  it { should have_many(:requests) }
18
25
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rest-assured
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 2
8
+ - 3
9
9
  - 0
10
- version: 0.2.0
10
+ version: 0.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Artem Avetisyan
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-11-14 00:00:00 Z
18
+ date: 2011-12-12 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: sinatra
@@ -128,9 +128,11 @@ files:
128
128
  - db/migrate/20111013122857_create_requests.rb
129
129
  - db/migrate/20111016174101_rename_method_to_verb.rb
130
130
  - db/migrate/20111021113953_add_status_to_doubles.rb
131
+ - db/migrate/20111208155906_add_response_headers_to_doubles.rb
131
132
  - features/command_line_options.feature
132
133
  - features/rest_api/doubles.feature
133
134
  - features/rest_api/redirects.feature
135
+ - features/ruby_api/create_double.feature
134
136
  - features/ruby_api/verify_requests.feature
135
137
  - features/ruby_api/wait_for_requests.feature
136
138
  - features/step_definitions/command_line_options_steps.rb
@@ -235,6 +237,7 @@ test_files:
235
237
  - features/command_line_options.feature
236
238
  - features/rest_api/doubles.feature
237
239
  - features/rest_api/redirects.feature
240
+ - features/ruby_api/create_double.feature
238
241
  - features/ruby_api/verify_requests.feature
239
242
  - features/ruby_api/wait_for_requests.feature
240
243
  - features/step_definitions/command_line_options_steps.rb
@@ -258,3 +261,4 @@ test_files:
258
261
  - spec/models/redirect_spec.rb
259
262
  - spec/models/request_spec.rb
260
263
  - spec/spec_helper.rb
264
+ has_rdoc: