gin 1.0.4 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.rdoc +16 -0
- data/Manifest.txt +12 -2
- data/README.rdoc +33 -0
- data/Rakefile +5 -0
- data/TODO.rdoc +7 -0
- data/bin/gin +158 -0
- data/lib/gin.rb +19 -2
- data/lib/gin/app.rb +420 -173
- data/lib/gin/cache.rb +65 -0
- data/lib/gin/config.rb +174 -18
- data/lib/gin/constants.rb +4 -0
- data/lib/gin/controller.rb +219 -11
- data/lib/gin/core_ext/gin_class.rb +16 -0
- data/lib/gin/errorable.rb +16 -2
- data/lib/gin/filterable.rb +29 -19
- data/lib/gin/reloadable.rb +1 -1
- data/lib/gin/request.rb +11 -0
- data/lib/gin/router.rb +185 -61
- data/lib/gin/rw_lock.rb +109 -0
- data/lib/gin/test.rb +702 -0
- data/public/gin.css +15 -3
- data/test/app/layouts/bar.erb +9 -0
- data/test/app/layouts/foo.erb +9 -0
- data/test/app/views/bar.erb +1 -0
- data/test/mock_app.rb +94 -0
- data/test/mock_config/invalid.yml +2 -0
- data/test/test_app.rb +160 -45
- data/test/test_cache.rb +57 -0
- data/test/test_config.rb +108 -13
- data/test/test_controller.rb +201 -11
- data/test/test_errorable.rb +1 -1
- data/test/test_gin.rb +9 -0
- data/test/test_helper.rb +3 -1
- data/test/test_router.rb +33 -0
- data/test/test_rw_lock.rb +65 -0
- data/test/test_test.rb +627 -0
- metadata +86 -6
- data/.autotest +0 -23
- data/.gitignore +0 -7
data/test/test_errorable.rb
CHANGED
data/test/test_gin.rb
CHANGED
@@ -13,6 +13,15 @@ class GinTest < Test::Unit::TestCase
|
|
13
13
|
end
|
14
14
|
|
15
15
|
|
16
|
+
def test_camelize
|
17
|
+
assert_equal "FooBar", Gin.camelize("foo_bar")
|
18
|
+
assert_equal "FooBar", Gin.camelize("_foo__bar")
|
19
|
+
assert_equal "FooBar", Gin.camelize("foo_Bar")
|
20
|
+
assert_equal "FooBar123", Gin.camelize("foo_Bar_123")
|
21
|
+
assert_equal "Foo::Bar", Gin.camelize("foo/bar")
|
22
|
+
end
|
23
|
+
|
24
|
+
|
16
25
|
def test_build_query
|
17
26
|
hash = {a: "bob", b: [1,2.2,-3,{ba:"test"}], c:true, d:false}
|
18
27
|
expected = "a=bob&b[]=1&b[]=2.2&b[]=-3&b[][ba]=test&c=true&d=false"
|
data/test/test_helper.rb
CHANGED
data/test/test_router.rb
CHANGED
@@ -70,6 +70,17 @@ class RouterTest < Test::Unit::TestCase
|
|
70
70
|
end
|
71
71
|
|
72
72
|
|
73
|
+
def test_add_and_retrieve_path_matcher
|
74
|
+
@router.add MyCtrl, "/" do
|
75
|
+
get :bar, "/bar/:type/:id.:format"
|
76
|
+
end
|
77
|
+
|
78
|
+
expected_params = {'type' => 'sub', 'id' => '123', 'format' => 'json'}
|
79
|
+
assert_equal [MyCtrl, :bar, expected_params],
|
80
|
+
@router.resources_for("GET", "/bar/sub/123.json")
|
81
|
+
end
|
82
|
+
|
83
|
+
|
73
84
|
def test_add_omit_base_path
|
74
85
|
@router.add MyCtrl do
|
75
86
|
get :bar
|
@@ -207,4 +218,26 @@ class RouterTest < Test::Unit::TestCase
|
|
207
218
|
@router.path_to(MyCtrl, :show)
|
208
219
|
end
|
209
220
|
end
|
221
|
+
|
222
|
+
|
223
|
+
def test_path_to_complex_param
|
224
|
+
@router.add MyCtrl, "/" do
|
225
|
+
get :bar, "/bar/:type/:id.:format"
|
226
|
+
end
|
227
|
+
|
228
|
+
params = {'type' => 'sub', 'id' => 123, 'format' => 'json', 'more' => 'hi'}
|
229
|
+
assert_equal "/bar/sub/123.json?more=hi", @router.path_to(MyCtrl, :bar, params)
|
230
|
+
end
|
231
|
+
|
232
|
+
|
233
|
+
def test_path_to_complex_param_missing
|
234
|
+
@router.add MyCtrl, "/" do
|
235
|
+
get :bar, "/bar/:type/:id.:format"
|
236
|
+
end
|
237
|
+
|
238
|
+
params = {'type' => 'sub', 'id' => '123', 'more' => 'hi'}
|
239
|
+
assert_raises Gin::Router::PathArgumentError do
|
240
|
+
@router.path_to(MyCtrl, :bar, params)
|
241
|
+
end
|
242
|
+
end
|
210
243
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class RWLockTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@lock = Gin::RWLock.new
|
7
|
+
@value = "setup"
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
def test_local_locking
|
12
|
+
val = @lock.write_sync do
|
13
|
+
@value = "written"
|
14
|
+
@lock.read_sync{ @value }
|
15
|
+
end
|
16
|
+
|
17
|
+
assert_equal "written", val
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def test_write_timeout
|
22
|
+
Thread.new{ @lock.read_sync{ sleep 0.5 } }
|
23
|
+
sleep 0.1
|
24
|
+
assert_raises(Gin::RWLock::WriteTimeout) do
|
25
|
+
@lock.write_sync{ @value = "FOO" }
|
26
|
+
end
|
27
|
+
assert_equal "setup", @value
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def test_nested_write_locking
|
32
|
+
@lock.write_sync do
|
33
|
+
@value = "written"
|
34
|
+
@lock.write_sync{ @value = "nested" }
|
35
|
+
end
|
36
|
+
assert_equal "nested", @value
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
def test_nested_read_locking
|
41
|
+
@lock.read_sync do
|
42
|
+
@lock.read_sync{ @value }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def test_non_blocking_reads
|
48
|
+
threads = []
|
49
|
+
start = Time.now
|
50
|
+
5.times do
|
51
|
+
threads << Thread.new{ @lock.read_sync{ sleep 0.1 } }
|
52
|
+
end
|
53
|
+
threads.each(&:join)
|
54
|
+
|
55
|
+
assert(0.15 > (Time.now - start))
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
def test_read_write_nesting
|
60
|
+
@lock.read_sync do
|
61
|
+
@lock.write_sync{ @value = "written" }
|
62
|
+
end
|
63
|
+
assert_equal "written", @value
|
64
|
+
end
|
65
|
+
end
|
data/test/test_test.rb
ADDED
@@ -0,0 +1,627 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
require 'gin/test'
|
3
|
+
|
4
|
+
require 'test/mock_app'
|
5
|
+
|
6
|
+
require 'plist'
|
7
|
+
require 'bson'
|
8
|
+
require 'nokogiri'
|
9
|
+
require 'json'
|
10
|
+
|
11
|
+
|
12
|
+
class TestTest < Test::Unit::TestCase
|
13
|
+
|
14
|
+
def setup
|
15
|
+
@testclass = Class.new(MockTestClass)
|
16
|
+
@testclass.send :include, MockApp::TestHelper
|
17
|
+
@testclass.send :include, TestAccess
|
18
|
+
@tests = @testclass.new
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def test_included
|
23
|
+
assert(@testclass < Gin::Test::Assertions)
|
24
|
+
assert(@testclass < Gin::Test::Helpers)
|
25
|
+
assert_equal MockApp, @testclass.app_klass
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def test_controller
|
30
|
+
assert_nil @testclass.controller
|
31
|
+
@testclass.controller MockApp::BarController
|
32
|
+
assert_equal MockApp::BarController, @testclass.controller
|
33
|
+
assert_equal MockApp::BarController, @tests.default_controller
|
34
|
+
|
35
|
+
@tests.default_controller MockApp::FooController
|
36
|
+
assert_equal MockApp::FooController, @tests.default_controller
|
37
|
+
assert_equal MockApp::BarController, @testclass.controller
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def test_instance_init
|
42
|
+
assert(MockApp === @tests.app)
|
43
|
+
assert_nil @tests.controller
|
44
|
+
assert_equal({'rack.input' => ""}, @tests.env)
|
45
|
+
assert_equal([nil,{},[]], @tests.rack_response)
|
46
|
+
assert_nil @tests.request
|
47
|
+
assert_nil @tests.response
|
48
|
+
assert_equal [], @tests.stream
|
49
|
+
assert_equal "", @tests.body
|
50
|
+
assert_nil @tests.default_controller
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
def test_path_to
|
55
|
+
assert_nil @tests.default_controller
|
56
|
+
assert_equal "/bar/123", @tests.path_to(:show_bar, id: 123)
|
57
|
+
assert_equal "/bar/123", @tests.path_to(MockApp::BarController, :show, id: 123)
|
58
|
+
assert_equal "/bar?id=123", @tests.path_to("/bar", id: 123)
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def test_path_to_default_ctrl
|
63
|
+
@tests.default_controller MockApp::BarController
|
64
|
+
assert_equal "/bar/123", @tests.path_to(:show_bar, id: 123)
|
65
|
+
assert_equal "/bar/123", @tests.path_to(:show, id: 123)
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
def test_path_to_no_ctrl
|
70
|
+
assert_nil @tests.default_controller
|
71
|
+
assert_raises(Gin::Router::PathArgumentError) do
|
72
|
+
@tests.path_to(:show, id: 123)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
def test_make_request
|
78
|
+
resp = @tests.make_request :get, :show_bar,
|
79
|
+
{id: 123, foo: "BAR", bar: "BAZ"},'REMOTE_ADDR' => '127.0.0.1'
|
80
|
+
|
81
|
+
assert_equal "foo=BAR&bar=BAZ", @tests.req_env['QUERY_STRING']
|
82
|
+
assert_equal "/bar/123", @tests.req_env['PATH_INFO']
|
83
|
+
assert_equal "127.0.0.1", @tests.req_env['REMOTE_ADDR']
|
84
|
+
assert_equal "127.0.0.1", @tests.request.ip
|
85
|
+
assert_equal "GET", @tests.req_env['REQUEST_METHOD']
|
86
|
+
|
87
|
+
assert_equal Gin::Request, @tests.request.class
|
88
|
+
assert_equal Gin::Response, @tests.response.class
|
89
|
+
|
90
|
+
assert_equal resp, @tests.rack_response
|
91
|
+
assert_equal 200, resp[0]
|
92
|
+
assert_equal "text/html;charset=UTF-8", resp[1]["Content-Type"]
|
93
|
+
assert_equal "9", resp[1]["Content-Length"]
|
94
|
+
assert_equal ["SHOW 123!"], resp[2]
|
95
|
+
|
96
|
+
assert_equal "SHOW 123!", @tests.body
|
97
|
+
assert_equal ["SHOW 123!"], @tests.stream
|
98
|
+
assert_equal [], @tests.templates
|
99
|
+
|
100
|
+
assert_equal MockApp::BarController, @tests.controller.class
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
def test_make_request_w_views
|
105
|
+
resp = @tests.make_request :get, :index_foo
|
106
|
+
|
107
|
+
assert_equal "text/html;charset=UTF-8", resp[1]["Content-Type"]
|
108
|
+
assert(/Value is LOCAL/ === @tests.body)
|
109
|
+
|
110
|
+
assert_equal 2, @tests.templates.length
|
111
|
+
assert_equal File.join(MockApp.layouts_dir, "foo.erb"), @tests.templates[0]
|
112
|
+
assert_equal File.join(MockApp.views_dir, "bar.erb"), @tests.templates[1]
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
def test_make_request_w_cookies
|
117
|
+
resp = @tests.make_request :get, :login_foo
|
118
|
+
assert_equal "foo_session=12345; expires=Fri, 01 Jan 2100 00:00:00 -0000",
|
119
|
+
resp[1]["Set-Cookie"]
|
120
|
+
|
121
|
+
time = Time.parse "2100-01-01 00:00:00 UTC"
|
122
|
+
cookie = {name: "foo_session", value: "12345", expires_at: time}
|
123
|
+
assert_equal cookie, @tests.cookies["foo_session"]
|
124
|
+
|
125
|
+
@tests.set_cookie "bar", 5678
|
126
|
+
resp = @tests.make_request :get, :show_bar, id: 123
|
127
|
+
assert_equal "foo_session=12345; bar=5678", @tests.req_env['HTTP_COOKIE']
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
def test_cookie_parser
|
132
|
+
@tests.make_request :get, :login_foo
|
133
|
+
@tests.make_request :get, :supercookie_foo
|
134
|
+
|
135
|
+
assert_equal 2, @tests.cookies.length
|
136
|
+
|
137
|
+
time = Time.parse "2100-01-01 00:00:00 UTC"
|
138
|
+
|
139
|
+
expected = {name: "foo_session", value: "12345", expires_at: time}
|
140
|
+
assert_equal expected, @tests.cookies['foo_session']
|
141
|
+
|
142
|
+
expected = {name: "supercookie", value: "SUPER!", domain: "mockapp.com",
|
143
|
+
path: "/", expires_at: time, secure: true, http_only: true}
|
144
|
+
assert_equal expected, @tests.cookies['supercookie']
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
def test_make_request_verb_methods
|
149
|
+
%w{get post put patch delete head options}.each do |verb|
|
150
|
+
resp = @tests.send verb, :show_bar, id: 123
|
151
|
+
assert_equal verb.upcase, @tests.req_env['REQUEST_METHOD']
|
152
|
+
if verb == 'get'
|
153
|
+
assert_equal MockApp::BarController,
|
154
|
+
@tests.req_env[Gin::Constants::GIN_CTRL].class
|
155
|
+
assert_equal 200, resp[0]
|
156
|
+
else
|
157
|
+
assert_equal nil, @tests.req_env[Gin::Constants::GIN_CTRL]
|
158
|
+
assert_equal 404, resp[0]
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
def test_parsed_body_json
|
165
|
+
@tests.get '/api/json'
|
166
|
+
assert_equal({'foo' => 1234}, @tests.parsed_body)
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
def test_parsed_body_bson
|
171
|
+
@tests.get '/api/bson'
|
172
|
+
assert_equal({'foo' => 1234}, @tests.parsed_body)
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
def test_parsed_body_plist
|
177
|
+
@tests.get '/api/plist'
|
178
|
+
assert_equal({'foo' => 1234}, @tests.parsed_body)
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
def test_parsed_body_xml
|
183
|
+
@tests.get '/api/xml'
|
184
|
+
assert_equal "foo", @tests.parsed_body.children.first.name
|
185
|
+
assert_equal "1234", @tests.parsed_body.children.first.text
|
186
|
+
end
|
187
|
+
|
188
|
+
|
189
|
+
def test_parsed_body_html
|
190
|
+
@tests.get '/foo'
|
191
|
+
assert_equal "html", @tests.parsed_body.children.first.name
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
def test_parsed_body_missing_parser
|
196
|
+
@tests.get '/api/pdf'
|
197
|
+
assert_raises(RuntimeError) do
|
198
|
+
@tests.parsed_body
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
|
203
|
+
def test_assert_response_success
|
204
|
+
assert_equal 0, @tests.assertions
|
205
|
+
|
206
|
+
(200..299).each do |status|
|
207
|
+
@tests.rack_response[0] = status
|
208
|
+
assert @tests.assert_response(:success)
|
209
|
+
end
|
210
|
+
|
211
|
+
assert_equal 100, @tests.assertions
|
212
|
+
assert_nil @tests.last_message
|
213
|
+
|
214
|
+
@tests.rack_response[0] = 500
|
215
|
+
assert_raises(MockAssertionError) do
|
216
|
+
@tests.assert_response(:success)
|
217
|
+
end
|
218
|
+
|
219
|
+
assert_equal "Status expected to be in range 200..299 but was 500",
|
220
|
+
@tests.last_message
|
221
|
+
end
|
222
|
+
|
223
|
+
|
224
|
+
def test_assert_response_redirect
|
225
|
+
assert_equal 0, @tests.assertions
|
226
|
+
|
227
|
+
(301..303).each do |status|
|
228
|
+
@tests.rack_response[0] = status
|
229
|
+
assert @tests.assert_response(:redirect)
|
230
|
+
end
|
231
|
+
|
232
|
+
assert_equal 3, @tests.assertions
|
233
|
+
assert_nil @tests.last_message
|
234
|
+
|
235
|
+
@tests.rack_response[0] = 500
|
236
|
+
assert_raises(MockAssertionError) do
|
237
|
+
@tests.assert_response(:redirect)
|
238
|
+
end
|
239
|
+
|
240
|
+
assert_equal "Status expected to be in range 301..303 or 307..308 but was 500",
|
241
|
+
@tests.last_message
|
242
|
+
end
|
243
|
+
|
244
|
+
|
245
|
+
def test_assert_response_error
|
246
|
+
assert_equal 0, @tests.assertions
|
247
|
+
|
248
|
+
(500..599).each do |status|
|
249
|
+
@tests.rack_response[0] = status
|
250
|
+
assert @tests.assert_response(:error)
|
251
|
+
end
|
252
|
+
|
253
|
+
assert_equal 100, @tests.assertions
|
254
|
+
assert_nil @tests.last_message
|
255
|
+
|
256
|
+
@tests.rack_response[0] = 200
|
257
|
+
assert_raises(MockAssertionError) do
|
258
|
+
@tests.assert_response(:error)
|
259
|
+
end
|
260
|
+
|
261
|
+
assert_equal "Status expected to be in range 500..599 but was 200",
|
262
|
+
@tests.last_message
|
263
|
+
end
|
264
|
+
|
265
|
+
|
266
|
+
def test_assert_response_unauthorized
|
267
|
+
assert_equal 0, @tests.assertions
|
268
|
+
|
269
|
+
@tests.rack_response[0] = 401
|
270
|
+
assert @tests.assert_response(:unauthorized)
|
271
|
+
|
272
|
+
@tests.rack_response[0] = 500
|
273
|
+
assert_raises(MockAssertionError) do
|
274
|
+
@tests.assert_response(:unauthorized)
|
275
|
+
end
|
276
|
+
|
277
|
+
assert_equal "Status expected to be 401 but was 500", @tests.last_message
|
278
|
+
end
|
279
|
+
|
280
|
+
|
281
|
+
def test_assert_response_forbidden
|
282
|
+
assert_equal 0, @tests.assertions
|
283
|
+
|
284
|
+
@tests.rack_response[0] = 403
|
285
|
+
assert @tests.assert_response(:forbidden)
|
286
|
+
|
287
|
+
@tests.rack_response[0] = 500
|
288
|
+
assert_raises(MockAssertionError) do
|
289
|
+
@tests.assert_response(:forbidden)
|
290
|
+
end
|
291
|
+
|
292
|
+
assert_equal "Status expected to be 403 but was 500", @tests.last_message
|
293
|
+
end
|
294
|
+
|
295
|
+
|
296
|
+
def test_assert_response_not_found
|
297
|
+
assert_equal 0, @tests.assertions
|
298
|
+
|
299
|
+
@tests.rack_response[0] = 404
|
300
|
+
assert @tests.assert_response(:not_found)
|
301
|
+
|
302
|
+
@tests.rack_response[0] = 500
|
303
|
+
assert_raises(MockAssertionError) do
|
304
|
+
@tests.assert_response(:not_found)
|
305
|
+
end
|
306
|
+
|
307
|
+
assert_equal "Status expected to be 404 but was 500", @tests.last_message
|
308
|
+
end
|
309
|
+
|
310
|
+
|
311
|
+
def test_assert_response_other
|
312
|
+
assert_equal 0, @tests.assertions
|
313
|
+
|
314
|
+
@tests.rack_response[0] = 451
|
315
|
+
assert @tests.assert_response(451)
|
316
|
+
|
317
|
+
@tests.rack_response[0] = 500
|
318
|
+
assert_raises(MockAssertionError) do
|
319
|
+
@tests.assert_response(451)
|
320
|
+
end
|
321
|
+
|
322
|
+
assert_equal "Status expected to be 451 but was 500", @tests.last_message
|
323
|
+
end
|
324
|
+
|
325
|
+
|
326
|
+
def test_assert_data_json
|
327
|
+
@tests.rack_response[1]['Content-Type'] = 'application/json'
|
328
|
+
@tests.rack_response[2] =
|
329
|
+
[{name:"bob",addresses:[{street:"123 bob st"},{street:"321 foo st"}]}.to_json]
|
330
|
+
|
331
|
+
assert @tests.assert_data("name=bob")
|
332
|
+
assert @tests.assert_data("name", value: "bob", count: 1)
|
333
|
+
assert @tests.assert_data("addresses/*/street", count: 2)
|
334
|
+
end
|
335
|
+
|
336
|
+
|
337
|
+
def test_assert_data_bson
|
338
|
+
@tests.rack_response[1]['Content-Type'] = 'application/bson'
|
339
|
+
@tests.rack_response[2] =
|
340
|
+
[BSON.serialize({name:"bob",addresses:[{street:"123 bob st"},{street:"321 foo st"}]}).to_s]
|
341
|
+
|
342
|
+
assert @tests.assert_data("name=bob")
|
343
|
+
assert @tests.assert_data("name", value: "bob", count: 1)
|
344
|
+
assert @tests.assert_data("addresses/*/street", count: 2)
|
345
|
+
end
|
346
|
+
|
347
|
+
|
348
|
+
def test_assert_data_plist
|
349
|
+
@tests.rack_response[1]['Content-Type'] = 'application/plist'
|
350
|
+
@tests.rack_response[2] =
|
351
|
+
[{name:"bob",addresses:[{street:"123 bob st"},{street:"321 foo st"}]}.to_plist]
|
352
|
+
|
353
|
+
assert @tests.assert_data("name=bob")
|
354
|
+
assert @tests.assert_data("name", value: "bob", count: 1)
|
355
|
+
assert @tests.assert_data("addresses/*/street", count: 2)
|
356
|
+
end
|
357
|
+
|
358
|
+
|
359
|
+
def test_assert_xpath
|
360
|
+
data = Nokogiri::XML::Builder.new do
|
361
|
+
root{
|
362
|
+
name "bob"
|
363
|
+
address{ street "123 bob st" }
|
364
|
+
address{ street "321 foo st" }
|
365
|
+
}
|
366
|
+
end.to_xml
|
367
|
+
|
368
|
+
@tests.rack_response[1]['Content-Type'] = 'application/xml'
|
369
|
+
@tests.rack_response[2] = [data]
|
370
|
+
|
371
|
+
assert @tests.assert_xpath("/root/name", value: "bob", count: 1)
|
372
|
+
assert @tests.assert_xpath(".//street", count: 2)
|
373
|
+
end
|
374
|
+
|
375
|
+
|
376
|
+
def test_assert_css
|
377
|
+
html = <<-HTML
|
378
|
+
<!DOCTYPE html>
|
379
|
+
<html>
|
380
|
+
<body>
|
381
|
+
<h1 class="name">bob</h1>
|
382
|
+
<div class="address"><div class="street">123 bob st</div></div>
|
383
|
+
<div class="address"><div class="street">321 foo st</div></div>
|
384
|
+
</body>
|
385
|
+
</html>
|
386
|
+
HTML
|
387
|
+
|
388
|
+
@tests.rack_response[1]['Content-Type'] = 'application/html'
|
389
|
+
@tests.rack_response[2] = [html]
|
390
|
+
|
391
|
+
assert @tests.assert_css(".name", value: "bob", count: 1)
|
392
|
+
assert @tests.assert_css(".address>.street", count: 2)
|
393
|
+
end
|
394
|
+
|
395
|
+
|
396
|
+
def test_assert_select_invalid
|
397
|
+
@tests.rack_response[1]['Content-Type'] = 'application/json'
|
398
|
+
@tests.rack_response[2] = ['{"foo":123}']
|
399
|
+
assert_raises(RuntimeError) do
|
400
|
+
@tests.assert_select(".name", selector: :foo)
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
|
405
|
+
def test_assert_select_failure
|
406
|
+
@tests.rack_response[1]['Content-Type'] = 'application/json'
|
407
|
+
@tests.rack_response[2] = ['{"foo":123}']
|
408
|
+
|
409
|
+
assert_raises(MockAssertionError) do
|
410
|
+
@tests.assert_select "/name"
|
411
|
+
end
|
412
|
+
assert_equal "Expected at least one item matching '/name' but found none",
|
413
|
+
@tests.last_message
|
414
|
+
|
415
|
+
assert_raises(MockAssertionError) do
|
416
|
+
@tests.assert_select "/foo", count: 2
|
417
|
+
end
|
418
|
+
assert_equal "Expected 2 items matching '/foo' but found 1",
|
419
|
+
@tests.last_message
|
420
|
+
|
421
|
+
assert_raises(MockAssertionError) do
|
422
|
+
@tests.assert_select "/foo", value: 321
|
423
|
+
end
|
424
|
+
|
425
|
+
assert_equal "Expected at least one item matching '/foo' with value 321 but found none",
|
426
|
+
@tests.last_message
|
427
|
+
end
|
428
|
+
|
429
|
+
|
430
|
+
def test_assert_cookie
|
431
|
+
@tests.get :supercookie_foo
|
432
|
+
|
433
|
+
assert @tests.assert_cookie("supercookie")
|
434
|
+
assert @tests.assert_cookie("supercookie", value: "SUPER!")
|
435
|
+
assert @tests.assert_cookie("supercookie", domain: "mockapp.com")
|
436
|
+
|
437
|
+
attribs = {domain: "mockapp.com", value: "SUPER!", path: "/", secure: true,
|
438
|
+
http_only: true, expires_at: Time.parse("Fri, 01 Jan 2100 00:00:00 -0000")}
|
439
|
+
assert @tests.assert_cookie("supercookie", attribs)
|
440
|
+
end
|
441
|
+
|
442
|
+
|
443
|
+
def test_assert_cookie_failure_old_cookie
|
444
|
+
@tests.get :login_foo
|
445
|
+
@tests.get :supercookie_foo
|
446
|
+
|
447
|
+
assert_raises(MockAssertionError) do
|
448
|
+
@tests.assert_cookie "foo_session"
|
449
|
+
end
|
450
|
+
assert_equal "Expected cookie \"foo_session\" but it doesn't exist",
|
451
|
+
@tests.last_message
|
452
|
+
end
|
453
|
+
|
454
|
+
|
455
|
+
def test_assert_cookie_failure_bool_attr
|
456
|
+
@tests.get :supercookie_foo
|
457
|
+
|
458
|
+
[:secure, :http_only].each do |attr|
|
459
|
+
assert_raises(MockAssertionError) do
|
460
|
+
@tests.assert_cookie "supercookie", attr => false
|
461
|
+
end
|
462
|
+
assert_equal "Expected cookie #{attr} to be false but was true",
|
463
|
+
@tests.last_message
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
|
468
|
+
def test_assert_cookie_failure_value
|
469
|
+
@tests.get :supercookie_foo
|
470
|
+
|
471
|
+
assert_raises(MockAssertionError) do
|
472
|
+
@tests.assert_cookie "supercookie", value: "BLAH"
|
473
|
+
end
|
474
|
+
assert_equal "Expected cookie value to be \"BLAH\" but was \"SUPER!\"",
|
475
|
+
@tests.last_message
|
476
|
+
end
|
477
|
+
|
478
|
+
|
479
|
+
def test_assert_cookie_failure_other_attr
|
480
|
+
@tests.get :supercookie_foo
|
481
|
+
cookie = @tests.response_cookies["supercookie"]
|
482
|
+
|
483
|
+
[:domain, :expires_at, :path].each do |attr|
|
484
|
+
assert_raises(MockAssertionError) do
|
485
|
+
@tests.assert_cookie "supercookie", attr => "BLAH"
|
486
|
+
end
|
487
|
+
assert_equal "Expected cookie #{attr} to be \"BLAH\" but was #{cookie[attr].inspect}",
|
488
|
+
@tests.last_message
|
489
|
+
end
|
490
|
+
end
|
491
|
+
|
492
|
+
|
493
|
+
def test_assert_view
|
494
|
+
@tests.get :index_foo
|
495
|
+
assert @tests.assert_view("bar")
|
496
|
+
assert @tests.assert_view("bar.erb")
|
497
|
+
end
|
498
|
+
|
499
|
+
|
500
|
+
def test_assert_view_failure
|
501
|
+
@tests.get :index_foo
|
502
|
+
assert_raises(MockAssertionError) do
|
503
|
+
@tests.assert_view("bar.md")
|
504
|
+
end
|
505
|
+
assert_equal "Expected view `#{@tests.controller.template_path("bar.md")}' \
|
506
|
+
in:\n #{@tests.templates.join("\n ")}", @tests.last_message
|
507
|
+
|
508
|
+
assert_raises(MockAssertionError) do
|
509
|
+
@tests.assert_view("views/bar.erb")
|
510
|
+
end
|
511
|
+
assert_equal "Expected view `#{@tests.controller.template_path("views/bar.erb")}' \
|
512
|
+
in:\n #{@tests.templates.join("\n ")}", @tests.last_message
|
513
|
+
end
|
514
|
+
|
515
|
+
|
516
|
+
def test_assert_layout
|
517
|
+
@tests.get :index_foo
|
518
|
+
assert @tests.assert_layout("foo")
|
519
|
+
assert @tests.assert_layout("foo.erb")
|
520
|
+
end
|
521
|
+
|
522
|
+
|
523
|
+
def test_assert_layout_failure
|
524
|
+
@tests.get :index_foo
|
525
|
+
assert_raises(MockAssertionError) do
|
526
|
+
@tests.assert_layout("bar")
|
527
|
+
end
|
528
|
+
assert_equal "Expected layout `#{@tests.controller.template_path("bar", true)}' \
|
529
|
+
in:\n #{@tests.templates.join("\n ")}", @tests.last_message
|
530
|
+
|
531
|
+
assert_raises(MockAssertionError) do
|
532
|
+
@tests.assert_layout("layouts/foo.erb")
|
533
|
+
end
|
534
|
+
assert_equal "Expected layout `#{@tests.controller.template_path("layouts/foo.erb", true)}' \
|
535
|
+
in:\n #{@tests.templates.join("\n ")}", @tests.last_message
|
536
|
+
end
|
537
|
+
|
538
|
+
|
539
|
+
def test_assert_route
|
540
|
+
assert @tests.assert_route(:get, "/foo", MockApp::FooController, :index)
|
541
|
+
end
|
542
|
+
|
543
|
+
|
544
|
+
def test_assert_route_failure
|
545
|
+
assert_raises(MockAssertionError) do
|
546
|
+
@tests.assert_route :get, "/bad_route", MockApp::FooController, :bad_route
|
547
|
+
end
|
548
|
+
assert_equal "`GET /bad_route' should map to \
|
549
|
+
MockApp::FooController#bad_route but doesn't exist", @tests.last_message
|
550
|
+
|
551
|
+
assert_raises(MockAssertionError) do
|
552
|
+
@tests.assert_route :get, "/foo", MockApp::FooController, :show
|
553
|
+
end
|
554
|
+
assert_equal "`GET /foo' should map to MockApp::FooController#show but \
|
555
|
+
got MockApp::FooController#index", @tests.last_message
|
556
|
+
end
|
557
|
+
|
558
|
+
|
559
|
+
def test_assert_redirect
|
560
|
+
@tests.get :see_other_bar
|
561
|
+
assert @tests.assert_redirect("http://example.com")
|
562
|
+
assert @tests.assert_redirect("http://example.com", 301)
|
563
|
+
assert_equal 2, @tests.assertions
|
564
|
+
end
|
565
|
+
|
566
|
+
|
567
|
+
def test_assert_redirect_failure
|
568
|
+
@tests.get :see_other_bar
|
569
|
+
|
570
|
+
assert_raises(MockAssertionError) do
|
571
|
+
@tests.assert_redirect("http://foo.com")
|
572
|
+
end
|
573
|
+
assert_equal 'Expected redirect to "http://foo.com" but was "http://example.com"', @tests.last_message
|
574
|
+
|
575
|
+
assert_raises(MockAssertionError) do
|
576
|
+
@tests.assert_redirect("http://example.com", 302)
|
577
|
+
end
|
578
|
+
assert_equal "Status expected to be 302 but was 301", @tests.last_message
|
579
|
+
end
|
580
|
+
|
581
|
+
|
582
|
+
class MockAssertionError < StandardError; end
|
583
|
+
|
584
|
+
module ::Gin::Test::Assertions
|
585
|
+
module MiniTest
|
586
|
+
Assertion = MockAssertionError unless const_defined?(:Assertion)
|
587
|
+
end
|
588
|
+
|
589
|
+
def raise err, msg=nil
|
590
|
+
err, msg = RuntimeError, err if String === err && msg.nil?
|
591
|
+
@last_message = err.respond_to?(:message) ? err.message : msg
|
592
|
+
super
|
593
|
+
end
|
594
|
+
end
|
595
|
+
|
596
|
+
|
597
|
+
class MockTestClass
|
598
|
+
attr_reader :last_message, :assertions
|
599
|
+
|
600
|
+
def initialize
|
601
|
+
@assertions = 0
|
602
|
+
@last_message = nil
|
603
|
+
end
|
604
|
+
|
605
|
+
def assert value, msg=nil
|
606
|
+
@assertions += 1
|
607
|
+
if value
|
608
|
+
return true
|
609
|
+
else
|
610
|
+
msg ||= "Mock assertion failure message"
|
611
|
+
@last_message = msg
|
612
|
+
raise MockAssertionError, msg unless value
|
613
|
+
end
|
614
|
+
end
|
615
|
+
end
|
616
|
+
|
617
|
+
|
618
|
+
module TestAccess
|
619
|
+
def env
|
620
|
+
@req_env = super
|
621
|
+
end
|
622
|
+
|
623
|
+
def req_env
|
624
|
+
@req_env
|
625
|
+
end
|
626
|
+
end
|
627
|
+
end
|