gin 1.0.4 → 1.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.
- 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
|