http_router 0.8.10 → 0.8.11
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/README.md +2 -0
- data/Rakefile +16 -1
- data/http_router.gemspec +1 -0
- data/lib/http_router.rb +2 -1
- data/lib/http_router/version.rb +1 -1
- data/test/common/generate.txt +87 -0
- data/test/common/recognize.txt +263 -0
- data/test/generation.rb +119 -0
- data/test/recognition.rb +142 -0
- data/test/{test_arbitrary.rb → test_recognition.rb} +37 -2
- metadata +23 -64
- data/test/test_generate.rb +0 -110
- data/test/test_greedy.rb +0 -24
- data/test/test_interstitial.rb +0 -47
- data/test/test_recognize.rb +0 -106
- data/test/test_request.rb +0 -102
- data/test/test_variable.rb +0 -163
data/test/recognition.rb
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
recognition_file = "#{File.dirname(__FILE__)}/common/recognize.txt"
|
4
|
+
recognition = File.read(recognition_file)
|
5
|
+
|
6
|
+
class RecognitionTest
|
7
|
+
Info = Struct.new(:case, :original_line, :num)
|
8
|
+
|
9
|
+
attr_reader :routes, :tests
|
10
|
+
def initialize(file)
|
11
|
+
@tests = []
|
12
|
+
@routes = Info.new([], "", 0)
|
13
|
+
end
|
14
|
+
|
15
|
+
def error(msg)
|
16
|
+
raise("Error in case: #{@routes.original_line.strip}:#{@routes.num + 1}\n#{msg}")
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_test(line, num)
|
20
|
+
@tests << Info.new(JSON.parse(line), line, num)
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_routes(line, num)
|
24
|
+
info = Info.new(JSON.parse(line), line, num)
|
25
|
+
error("Routes have already been defined without tests") if info.case.is_a?(Array) && !@routes.case.empty?
|
26
|
+
if info.case.is_a?(Array)
|
27
|
+
@routes = info
|
28
|
+
elsif @routes.case.empty?
|
29
|
+
info.case = [info.case]
|
30
|
+
@routes = info
|
31
|
+
else
|
32
|
+
@routes.case << info.case
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def interpret_val(val)
|
37
|
+
case val
|
38
|
+
when nil
|
39
|
+
error("Unable to interpret #{val.inspect}")
|
40
|
+
when Hash
|
41
|
+
val['regex'] ? Regexp.new(val['regex']) : error("Okay serious, no idea #{val.inspect}")
|
42
|
+
else
|
43
|
+
val
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def invoke
|
48
|
+
error("invoke called with no tests or routes") if @tests.empty? || @routes.nil?
|
49
|
+
router = HttpRouter.new
|
50
|
+
@routes.case.each do |route_definition|
|
51
|
+
error("Too many keys! #{route_definition.keys.inspect}") unless route_definition.keys.size == 1
|
52
|
+
route_name, route_properties = route_definition.keys.first, route_definition.values.first
|
53
|
+
route = case route_properties
|
54
|
+
when String
|
55
|
+
router.add(route_properties)
|
56
|
+
when Hash
|
57
|
+
opts = {}
|
58
|
+
route_path = interpret_val(route_properties.delete("path"))
|
59
|
+
if route_properties.key?("conditions")
|
60
|
+
opts[:conditions] = Hash[route_properties.delete("conditions").map{|k, v| [k.to_sym, interpret_val(v)]}]
|
61
|
+
end
|
62
|
+
route_properties.each do |key, val|
|
63
|
+
opts[key.to_sym] = interpret_val(val)
|
64
|
+
end
|
65
|
+
router.add(route_path, opts)
|
66
|
+
else
|
67
|
+
error("Route isn't a String or hash")
|
68
|
+
end
|
69
|
+
route.name(route_name.to_sym)
|
70
|
+
route.to{|env| [200, {"env-to-test" => env.dup}, [route_name]]}
|
71
|
+
end
|
72
|
+
@tests.map(&:case).each do |(name, req, params)|
|
73
|
+
env = case req
|
74
|
+
when String
|
75
|
+
Rack::MockRequest.env_for(req)
|
76
|
+
when Hash
|
77
|
+
e = Rack::MockRequest.env_for(req['path'])
|
78
|
+
e['REQUEST_METHOD'] = req['method'] if req.key?('method')
|
79
|
+
e['rack.url_scheme'] = req['scheme'] if req.key?('scheme')
|
80
|
+
e
|
81
|
+
end
|
82
|
+
response = router.call(env)
|
83
|
+
case name
|
84
|
+
when nil
|
85
|
+
error("Expected no response") unless response.first == 404
|
86
|
+
when Array
|
87
|
+
name.each_with_index do |part, i|
|
88
|
+
case part
|
89
|
+
when Hash then part.keys.all? or error("#{part.inspect} didn't match #{response[i].inspect}")
|
90
|
+
else part == response[i] or error("#{part.inspect} didn't match #{response[i].inspect}")
|
91
|
+
end
|
92
|
+
end
|
93
|
+
else
|
94
|
+
error("Expected #{name} for #{req.inspect} got #{response.inspect}") unless response.last == [name]
|
95
|
+
end
|
96
|
+
env['router.params'] ||= {}
|
97
|
+
params ||= {}
|
98
|
+
if params['PATH_INFO']
|
99
|
+
path_info = params.delete("PATH_INFO")
|
100
|
+
error("path_info #{env['PATH_INFO'].inspect} is not #{path_info.inspect}") unless path_info == env['PATH_INFO']
|
101
|
+
end
|
102
|
+
|
103
|
+
env['router.params'].keys.each do |k|
|
104
|
+
p_v = params.delete(k.to_s)
|
105
|
+
v = env['router.params'].delete(k.to_sym)
|
106
|
+
error("I got #{p_v.inspect} but expected #{v.inspect}") unless p_v == v
|
107
|
+
end
|
108
|
+
error("Left over expectations: #{params.inspect}") unless params.empty?
|
109
|
+
error("Left over matched params: #{env['router.params'].inspect}") unless env['router.params'].empty?
|
110
|
+
end
|
111
|
+
print '.'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
tests = []
|
116
|
+
test = nil
|
117
|
+
num = 0
|
118
|
+
recognition.each_line do |line|
|
119
|
+
begin
|
120
|
+
case line
|
121
|
+
when /^#/, /^\s*$/
|
122
|
+
# skip
|
123
|
+
when /^( |\t)/
|
124
|
+
test.add_test(line, num)
|
125
|
+
else
|
126
|
+
if test.nil? || !test.tests.empty?
|
127
|
+
tests << test if test
|
128
|
+
test = RecognitionTest.new(recognition_file)
|
129
|
+
end
|
130
|
+
test.add_routes(line, num)
|
131
|
+
end
|
132
|
+
rescue
|
133
|
+
warn "There was a problem with #{num}:#{line}"
|
134
|
+
raise
|
135
|
+
end
|
136
|
+
num += 1
|
137
|
+
end
|
138
|
+
tests << test
|
139
|
+
|
140
|
+
puts "Running recognition tests (Routes: #{tests.size}, Tests: #{tests.inject(0){|s, t| s+=t.tests.size}})..."
|
141
|
+
tests.each(&:invoke)
|
142
|
+
puts "\ndone!"
|
@@ -1,4 +1,13 @@
|
|
1
|
-
class
|
1
|
+
class TestRecognition < MiniTest::Unit::TestCase
|
2
|
+
if //.respond_to?(:names)
|
3
|
+
eval <<-EOT
|
4
|
+
def test_match_path_with_groups
|
5
|
+
r = router { add(%r{/(?<year>\\d{4})/(?<month>\\d{2})/(?<day>\\d{2})/?}) }
|
6
|
+
assert_route r, "/1234/23/56", {:year => "1234", :month => "23", :day => "56"}
|
7
|
+
end
|
8
|
+
EOT
|
9
|
+
end
|
10
|
+
|
2
11
|
def test_match
|
3
12
|
hello, love80, love8080 = router {
|
4
13
|
add('test').arbitrary(Proc.new{|req, params| req.rack.host == 'hellodooly' })
|
@@ -55,4 +64,30 @@ class TestArbitrary < MiniTest::Unit::TestCase
|
|
55
64
|
}
|
56
65
|
assert_route yes, '/test'
|
57
66
|
end
|
58
|
-
|
67
|
+
|
68
|
+
def test_passing
|
69
|
+
passed, working = router {
|
70
|
+
add('/').to { |env| throw :pass; [200, {}, ['pass']] }
|
71
|
+
add('/').to { |env| [200, {}, ['working']] }
|
72
|
+
}
|
73
|
+
assert_body 'working', router.call(Rack::MockRequest.env_for('/'))
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_passing_with_cascade
|
77
|
+
passed, working = router {
|
78
|
+
add('/').to { |env| [200, {'X-Cascade' => 'pass'}, ['pass']] }
|
79
|
+
add('/').to { |env| [200, {}, ['working']] }
|
80
|
+
}
|
81
|
+
assert_body 'working', router.call(Rack::MockRequest.env_for('/'))
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_request_mutation
|
85
|
+
got_this_far = false
|
86
|
+
non_matching, matching = router {
|
87
|
+
add("/test/:var/:var2/*glob").matching(:var2 => /123/, :glob => /[a-z]+/).get.arbitrary{|env, params| got_this_far = true; false}
|
88
|
+
add("/test/:var/:var2/*glob").matching(:var2 => /123/, :glob => /[a-z]+/).get
|
89
|
+
}
|
90
|
+
assert_route matching, '/test/123/123/asd/aasd/zxcqwe/asdzxc', {:var => '123', :var2 => '123', :glob => %w{asd aasd zxcqwe asdzxc}}
|
91
|
+
assert got_this_far, "matching should have gotten this far"
|
92
|
+
end
|
93
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: http_router
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 43
|
5
4
|
prerelease:
|
6
|
-
|
7
|
-
- 0
|
8
|
-
- 8
|
9
|
-
- 10
|
10
|
-
version: 0.8.10
|
5
|
+
version: 0.8.11
|
11
6
|
platform: ruby
|
12
7
|
authors:
|
13
8
|
- Joshua Hull
|
@@ -15,7 +10,7 @@ autorequire:
|
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
12
|
|
18
|
-
date: 2011-
|
13
|
+
date: 2011-07-05 00:00:00 -07:00
|
19
14
|
default_executable:
|
20
15
|
dependencies:
|
21
16
|
- !ruby/object:Gem::Dependency
|
@@ -26,11 +21,6 @@ dependencies:
|
|
26
21
|
requirements:
|
27
22
|
- - ">="
|
28
23
|
- !ruby/object:Gem::Version
|
29
|
-
hash: 23
|
30
|
-
segments:
|
31
|
-
- 1
|
32
|
-
- 0
|
33
|
-
- 0
|
34
24
|
version: 1.0.0
|
35
25
|
type: :runtime
|
36
26
|
version_requirements: *id001
|
@@ -42,11 +32,6 @@ dependencies:
|
|
42
32
|
requirements:
|
43
33
|
- - ~>
|
44
34
|
- !ruby/object:Gem::Version
|
45
|
-
hash: 21
|
46
|
-
segments:
|
47
|
-
- 0
|
48
|
-
- 2
|
49
|
-
- 1
|
50
35
|
version: 0.2.1
|
51
36
|
type: :runtime
|
52
37
|
version_requirements: *id002
|
@@ -58,11 +43,6 @@ dependencies:
|
|
58
43
|
requirements:
|
59
44
|
- - ~>
|
60
45
|
- !ruby/object:Gem::Version
|
61
|
-
hash: 15
|
62
|
-
segments:
|
63
|
-
- 2
|
64
|
-
- 0
|
65
|
-
- 0
|
66
46
|
version: 2.0.0
|
67
47
|
type: :development
|
68
48
|
version_requirements: *id003
|
@@ -74,9 +54,6 @@ dependencies:
|
|
74
54
|
requirements:
|
75
55
|
- - ">="
|
76
56
|
- !ruby/object:Gem::Version
|
77
|
-
hash: 3
|
78
|
-
segments:
|
79
|
-
- 0
|
80
57
|
version: "0"
|
81
58
|
type: :development
|
82
59
|
version_requirements: *id004
|
@@ -88,11 +65,6 @@ dependencies:
|
|
88
65
|
requirements:
|
89
66
|
- - ~>
|
90
67
|
- !ruby/object:Gem::Version
|
91
|
-
hash: 49
|
92
|
-
segments:
|
93
|
-
- 0
|
94
|
-
- 8
|
95
|
-
- 7
|
96
68
|
version: 0.8.7
|
97
69
|
type: :development
|
98
70
|
version_requirements: *id005
|
@@ -104,58 +76,53 @@ dependencies:
|
|
104
76
|
requirements:
|
105
77
|
- - ">="
|
106
78
|
- !ruby/object:Gem::Version
|
107
|
-
hash: 3
|
108
|
-
segments:
|
109
|
-
- 0
|
110
79
|
version: "0"
|
111
80
|
type: :development
|
112
81
|
version_requirements: *id006
|
113
82
|
- !ruby/object:Gem::Dependency
|
114
|
-
name:
|
83
|
+
name: json
|
115
84
|
prerelease: false
|
116
85
|
requirement: &id007 !ruby/object:Gem::Requirement
|
117
86
|
none: false
|
118
87
|
requirements:
|
119
88
|
- - ">="
|
120
89
|
- !ruby/object:Gem::Version
|
121
|
-
hash: 3
|
122
|
-
segments:
|
123
|
-
- 0
|
124
90
|
version: "0"
|
125
91
|
type: :development
|
126
92
|
version_requirements: *id007
|
127
93
|
- !ruby/object:Gem::Dependency
|
128
|
-
name:
|
94
|
+
name: phocus
|
129
95
|
prerelease: false
|
130
96
|
requirement: &id008 !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: "0"
|
102
|
+
type: :development
|
103
|
+
version_requirements: *id008
|
104
|
+
- !ruby/object:Gem::Dependency
|
105
|
+
name: bundler
|
106
|
+
prerelease: false
|
107
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
131
108
|
none: false
|
132
109
|
requirements:
|
133
110
|
- - ~>
|
134
111
|
- !ruby/object:Gem::Version
|
135
|
-
hash: 23
|
136
|
-
segments:
|
137
|
-
- 1
|
138
|
-
- 0
|
139
|
-
- 0
|
140
112
|
version: 1.0.0
|
141
113
|
type: :development
|
142
|
-
version_requirements: *
|
114
|
+
version_requirements: *id009
|
143
115
|
- !ruby/object:Gem::Dependency
|
144
116
|
name: thin
|
145
117
|
prerelease: false
|
146
|
-
requirement: &
|
118
|
+
requirement: &id010 !ruby/object:Gem::Requirement
|
147
119
|
none: false
|
148
120
|
requirements:
|
149
121
|
- - "="
|
150
122
|
- !ruby/object:Gem::Version
|
151
|
-
hash: 15
|
152
|
-
segments:
|
153
|
-
- 1
|
154
|
-
- 2
|
155
|
-
- 8
|
156
123
|
version: 1.2.8
|
157
124
|
type: :development
|
158
|
-
version_requirements: *
|
125
|
+
version_requirements: *id010
|
159
126
|
description: This library allows you to recognize and build URLs in a Rack application.
|
160
127
|
email: joshbuddy@gmail.com
|
161
128
|
executables: []
|
@@ -211,18 +178,16 @@ files:
|
|
211
178
|
- lib/http_router/response.rb
|
212
179
|
- lib/http_router/route.rb
|
213
180
|
- lib/http_router/version.rb
|
181
|
+
- test/common/generate.txt
|
182
|
+
- test/common/recognize.txt
|
183
|
+
- test/generation.rb
|
214
184
|
- test/helper.rb
|
215
185
|
- test/rack/test_route.rb
|
216
|
-
- test/
|
217
|
-
- test/test_generate.rb
|
218
|
-
- test/test_greedy.rb
|
219
|
-
- test/test_interstitial.rb
|
186
|
+
- test/recognition.rb
|
220
187
|
- test/test_misc.rb
|
221
188
|
- test/test_mounting.rb
|
222
|
-
- test/
|
223
|
-
- test/test_request.rb
|
189
|
+
- test/test_recognition.rb
|
224
190
|
- test/test_trailing_slash.rb
|
225
|
-
- test/test_variable.rb
|
226
191
|
has_rdoc: true
|
227
192
|
homepage: http://github.com/joshbuddy/http_router
|
228
193
|
licenses: []
|
@@ -237,18 +202,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
237
202
|
requirements:
|
238
203
|
- - ">="
|
239
204
|
- !ruby/object:Gem::Version
|
240
|
-
hash: 3
|
241
|
-
segments:
|
242
|
-
- 0
|
243
205
|
version: "0"
|
244
206
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
245
207
|
none: false
|
246
208
|
requirements:
|
247
209
|
- - ">="
|
248
210
|
- !ruby/object:Gem::Version
|
249
|
-
hash: 3
|
250
|
-
segments:
|
251
|
-
- 0
|
252
211
|
version: "0"
|
253
212
|
requirements: []
|
254
213
|
|
data/test/test_generate.rb
DELETED
@@ -1,110 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
class TestGenerate < MiniTest::Unit::TestCase
|
3
|
-
|
4
|
-
def test_static
|
5
|
-
router {
|
6
|
-
add('/').name(:a)
|
7
|
-
add('/test').name(:b)
|
8
|
-
add('/test/time').name(:c)
|
9
|
-
add('/one/more/what').name(:d)
|
10
|
-
add('/test.html').name(:e)
|
11
|
-
}
|
12
|
-
assert_generate '/', :a
|
13
|
-
assert_generate '/test', :b
|
14
|
-
assert_generate '/test/time', :c
|
15
|
-
assert_generate '/one/more/what', :d
|
16
|
-
assert_generate '/test.html', :e
|
17
|
-
end
|
18
|
-
|
19
|
-
def test_dynamic
|
20
|
-
assert_generate '/test', '/:var', :var => 'test'
|
21
|
-
assert_generate '/test', '/:var', 'test'
|
22
|
-
end
|
23
|
-
|
24
|
-
def test_array_with_extras
|
25
|
-
assert_generate '/test?query=string', '/:var', :var => 'test', :query => 'string'
|
26
|
-
assert_generate '/test?query=string', '/:var', 'test', :query => 'string'
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_multiple_dynamics
|
30
|
-
assert_generate '/one/two', "/:var/:baz", :var => 'one', :baz => 'two'
|
31
|
-
assert_generate '/one/two', "/:var/:baz", 'one', 'two'
|
32
|
-
end
|
33
|
-
|
34
|
-
def test_extension
|
35
|
-
assert_generate '/test.html', "/test.:format", :format => 'html'
|
36
|
-
assert_generate '/test.html', "/test.:format", 'html'
|
37
|
-
end
|
38
|
-
|
39
|
-
def test_optional_extension
|
40
|
-
assert_generate '/test.html', "/test(.:format)", :format => 'html'
|
41
|
-
assert_generate '/test.html', "/test(.:format)", 'html'
|
42
|
-
assert_generate '/test', "/test(.:format)"
|
43
|
-
end
|
44
|
-
|
45
|
-
def test_variable_with_extension
|
46
|
-
assert_generate '/test.html', "/:var.:format", :var => 'test', :format => 'html'
|
47
|
-
assert_generate '/test.html', "/:var.:format", 'test', 'html'
|
48
|
-
end
|
49
|
-
|
50
|
-
def test_variable_with_optional_extension
|
51
|
-
assert_generate '/test.html', "/:var(.:format)", :var => 'test', :format => 'html'
|
52
|
-
assert_generate '/test.html', "/:var(.:format)", 'test', 'html'
|
53
|
-
assert_generate '/test', "/:var(.:format)", :var => 'test'
|
54
|
-
assert_generate '/test', "/:var(.:format)", 'test'
|
55
|
-
end
|
56
|
-
|
57
|
-
def test_optionals
|
58
|
-
assert_generate '/var', "/:var1(/:var2)", 'var'
|
59
|
-
assert_generate '/var/fooz', "/:var1(/:var2)", 'var', 'fooz'
|
60
|
-
assert_generate '/var', "/:var1(/:var2)", :var1 => 'var'
|
61
|
-
assert_generate '/var/fooz', "/:var1(/:var2)", :var1 => 'var', :var2 => 'fooz'
|
62
|
-
assert_raises(HttpRouter::InvalidRouteException) { router.url(router.add("/:var1(/:var2)").to(:test), :var2 => 'fooz') }
|
63
|
-
end
|
64
|
-
|
65
|
-
def test_optionals_with_format
|
66
|
-
assert_generate '/var', "/:var1(/:var2.:format)", 'var'
|
67
|
-
assert_generate '/var/fooz.html', "/:var1(/:var2.:format)", 'var', 'fooz', 'html'
|
68
|
-
assert_generate '/var', "/:var1(/:var2.:format)", :var1 => 'var'
|
69
|
-
assert_generate '/var/fooz.html', "/:var1(/:var2.:format)", :var1 => 'var', :var2 => 'fooz', :format => 'html'
|
70
|
-
end
|
71
|
-
|
72
|
-
def test_nested_optionals
|
73
|
-
assert_generate '/var', "/:var1(/:var2(/:var3))", 'var'
|
74
|
-
assert_generate '/var/fooz', "/:var1(/:var2(/:var3))", 'var', 'fooz'
|
75
|
-
assert_generate '/var/fooz/baz', "/:var1(/:var2(/:var3))", 'var', 'fooz', 'baz'
|
76
|
-
assert_generate '/var', "/:var1(/:var2(/:var3))", :var1 => 'var'
|
77
|
-
assert_generate '/var/fooz', "/:var1(/:var2(/:var3))", :var1 => 'var', :var2 => 'fooz'
|
78
|
-
assert_generate '/var/fooz/baz', "/:var1(/:var2(/:var3))", :var1 => 'var', :var2 => 'fooz', :var3 => 'baz'
|
79
|
-
end
|
80
|
-
|
81
|
-
def test_default_value
|
82
|
-
assert_generate "/123?page=1", router.add("/:var").default(:page => 1), 123
|
83
|
-
assert_generate "/1/123", router.add("/:page/:entry").default(:page => 1), :entry => '123'
|
84
|
-
end
|
85
|
-
|
86
|
-
def test_nil_values
|
87
|
-
assert_generate '/url', "/url(/:var)", :var => nil
|
88
|
-
end
|
89
|
-
|
90
|
-
def test_unicode
|
91
|
-
assert_generate '/%C3%A4', "/:var", :var => 'ä'
|
92
|
-
end
|
93
|
-
|
94
|
-
def test_raise
|
95
|
-
r = router { add(':var').matching(:var => /\d+/) }
|
96
|
-
assert_raises(HttpRouter::InvalidRouteException) { router.url(r, 'asd') }
|
97
|
-
end
|
98
|
-
|
99
|
-
def test_array
|
100
|
-
assert_generate '/var?foo[]=baz&foo[]=bar', '/var', :foo => ['baz', 'bar']
|
101
|
-
end
|
102
|
-
|
103
|
-
def test_hash
|
104
|
-
assert_generate '/var?foo[az]=baz', '/var', :foo => {:az => 'baz'}
|
105
|
-
end
|
106
|
-
|
107
|
-
def test_hash_with_array
|
108
|
-
assert_generate '/var?foo[ar][]=bar', '/var', :foo => {:ar => ['bar']}
|
109
|
-
end
|
110
|
-
end
|