roda 3.28.0 → 3.33.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (208) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +40 -0
  3. data/README.rdoc +15 -1
  4. data/doc/conventions.rdoc +17 -8
  5. data/doc/release_notes/3.29.0.txt +15 -0
  6. data/doc/release_notes/3.30.0.txt +14 -0
  7. data/doc/release_notes/3.31.0.txt +11 -0
  8. data/doc/release_notes/3.32.0.txt +42 -0
  9. data/doc/release_notes/3.33.0.txt +8 -0
  10. data/lib/roda.rb +3 -0
  11. data/lib/roda/plugins/_symbol_regexp_matchers.rb +2 -0
  12. data/lib/roda/plugins/assets.rb +26 -5
  13. data/lib/roda/plugins/caching.rb +2 -0
  14. data/lib/roda/plugins/common_logger.rb +1 -1
  15. data/lib/roda/plugins/content_security_policy.rb +2 -0
  16. data/lib/roda/plugins/default_headers.rb +2 -0
  17. data/lib/roda/plugins/exception_page.rb +9 -5
  18. data/lib/roda/plugins/hash_matcher.rb +1 -1
  19. data/lib/roda/plugins/header_matchers.rb +5 -1
  20. data/lib/roda/plugins/indifferent_params.rb +4 -0
  21. data/lib/roda/plugins/partials.rb +33 -6
  22. data/lib/roda/plugins/path.rb +42 -15
  23. data/lib/roda/plugins/placeholder_string_matchers.rb +2 -0
  24. data/lib/roda/plugins/public.rb +25 -17
  25. data/lib/roda/plugins/relative_path.rb +73 -0
  26. data/lib/roda/plugins/render.rb +17 -5
  27. data/lib/roda/plugins/render_each.rb +11 -3
  28. data/lib/roda/plugins/run_append_slash.rb +1 -1
  29. data/lib/roda/plugins/symbol_matchers.rb +2 -2
  30. data/lib/roda/version.rb +1 -1
  31. metadata +13 -214
  32. data/Rakefile +0 -108
  33. data/doc/release_notes/1.0.0.txt +0 -329
  34. data/doc/release_notes/1.1.0.txt +0 -226
  35. data/doc/release_notes/1.2.0.txt +0 -406
  36. data/doc/release_notes/1.3.0.txt +0 -109
  37. data/doc/release_notes/2.0.0.txt +0 -75
  38. data/doc/release_notes/2.1.0.txt +0 -124
  39. data/doc/release_notes/2.10.0.txt +0 -27
  40. data/doc/release_notes/2.11.0.txt +0 -70
  41. data/doc/release_notes/2.12.0.txt +0 -40
  42. data/doc/release_notes/2.13.0.txt +0 -10
  43. data/doc/release_notes/2.14.0.txt +0 -44
  44. data/doc/release_notes/2.15.0.txt +0 -53
  45. data/doc/release_notes/2.16.0.txt +0 -48
  46. data/doc/release_notes/2.17.0.txt +0 -62
  47. data/doc/release_notes/2.18.0.txt +0 -69
  48. data/doc/release_notes/2.19.0.txt +0 -30
  49. data/doc/release_notes/2.2.0.txt +0 -97
  50. data/doc/release_notes/2.20.0.txt +0 -5
  51. data/doc/release_notes/2.21.0.txt +0 -17
  52. data/doc/release_notes/2.22.0.txt +0 -41
  53. data/doc/release_notes/2.23.0.txt +0 -29
  54. data/doc/release_notes/2.24.0.txt +0 -65
  55. data/doc/release_notes/2.25.0.txt +0 -14
  56. data/doc/release_notes/2.26.0.txt +0 -13
  57. data/doc/release_notes/2.27.0.txt +0 -56
  58. data/doc/release_notes/2.28.0.txt +0 -17
  59. data/doc/release_notes/2.29.0.txt +0 -156
  60. data/doc/release_notes/2.3.0.txt +0 -109
  61. data/doc/release_notes/2.4.0.txt +0 -55
  62. data/doc/release_notes/2.5.0.txt +0 -23
  63. data/doc/release_notes/2.5.1.txt +0 -4
  64. data/doc/release_notes/2.6.0.txt +0 -21
  65. data/doc/release_notes/2.7.0.txt +0 -75
  66. data/doc/release_notes/2.8.0.txt +0 -44
  67. data/doc/release_notes/2.9.0.txt +0 -6
  68. data/spec/all.rb +0 -1
  69. data/spec/assets/css/app.scss +0 -1
  70. data/spec/assets/css/no_access.css +0 -1
  71. data/spec/assets/css/raw.css +0 -1
  72. data/spec/assets/js/head/app.js +0 -1
  73. data/spec/composition_spec.rb +0 -31
  74. data/spec/define_roda_method_spec.rb +0 -274
  75. data/spec/env_spec.rb +0 -11
  76. data/spec/freeze_spec.rb +0 -37
  77. data/spec/integration_spec.rb +0 -209
  78. data/spec/matchers_spec.rb +0 -832
  79. data/spec/opts_spec.rb +0 -42
  80. data/spec/plugin/_after_hook_spec.rb +0 -19
  81. data/spec/plugin/all_verbs_spec.rb +0 -29
  82. data/spec/plugin/assets_preloading_spec.rb +0 -98
  83. data/spec/plugin/assets_spec.rb +0 -745
  84. data/spec/plugin/backtracking_array_spec.rb +0 -42
  85. data/spec/plugin/branch_locals_spec.rb +0 -106
  86. data/spec/plugin/caching_spec.rb +0 -337
  87. data/spec/plugin/chunked_spec.rb +0 -201
  88. data/spec/plugin/class_level_routing_spec.rb +0 -164
  89. data/spec/plugin/class_matchers_spec.rb +0 -40
  90. data/spec/plugin/common_logger_spec.rb +0 -85
  91. data/spec/plugin/content_for_spec.rb +0 -162
  92. data/spec/plugin/content_security_policy_spec.rb +0 -175
  93. data/spec/plugin/cookies_spec.rb +0 -51
  94. data/spec/plugin/csrf_spec.rb +0 -111
  95. data/spec/plugin/default_headers_spec.rb +0 -82
  96. data/spec/plugin/default_status_spec.rb +0 -95
  97. data/spec/plugin/delay_build_spec.rb +0 -23
  98. data/spec/plugin/delegate_spec.rb +0 -23
  99. data/spec/plugin/delete_empty_headers_spec.rb +0 -27
  100. data/spec/plugin/direct_call_spec.rb +0 -28
  101. data/spec/plugin/disallow_file_uploads_spec.rb +0 -25
  102. data/spec/plugin/drop_body_spec.rb +0 -24
  103. data/spec/plugin/early_hints_spec.rb +0 -19
  104. data/spec/plugin/empty_root_spec.rb +0 -14
  105. data/spec/plugin/environments_spec.rb +0 -42
  106. data/spec/plugin/error_email_spec.rb +0 -97
  107. data/spec/plugin/error_handler_spec.rb +0 -216
  108. data/spec/plugin/error_mail_spec.rb +0 -93
  109. data/spec/plugin/exception_page_spec.rb +0 -168
  110. data/spec/plugin/flash_spec.rb +0 -121
  111. data/spec/plugin/h_spec.rb +0 -11
  112. data/spec/plugin/halt_spec.rb +0 -119
  113. data/spec/plugin/hash_matcher_spec.rb +0 -27
  114. data/spec/plugin/hash_routes_spec.rb +0 -535
  115. data/spec/plugin/head_spec.rb +0 -52
  116. data/spec/plugin/header_matchers_spec.rb +0 -98
  117. data/spec/plugin/heartbeat_spec.rb +0 -74
  118. data/spec/plugin/hooks_spec.rb +0 -152
  119. data/spec/plugin/indifferent_params_spec.rb +0 -14
  120. data/spec/plugin/json_parser_spec.rb +0 -141
  121. data/spec/plugin/json_spec.rb +0 -83
  122. data/spec/plugin/mail_processor_spec.rb +0 -451
  123. data/spec/plugin/mailer_spec.rb +0 -282
  124. data/spec/plugin/match_affix_spec.rb +0 -43
  125. data/spec/plugin/match_hook_spec.rb +0 -79
  126. data/spec/plugin/middleware_spec.rb +0 -237
  127. data/spec/plugin/middleware_stack_spec.rb +0 -81
  128. data/spec/plugin/module_include_spec.rb +0 -48
  129. data/spec/plugin/multi_route_spec.rb +0 -268
  130. data/spec/plugin/multi_run_spec.rb +0 -87
  131. data/spec/plugin/multi_view_spec.rb +0 -50
  132. data/spec/plugin/multibyte_string_matcher_spec.rb +0 -44
  133. data/spec/plugin/named_templates_spec.rb +0 -96
  134. data/spec/plugin/not_allowed_spec.rb +0 -69
  135. data/spec/plugin/not_found_spec.rb +0 -128
  136. data/spec/plugin/optimized_string_matchers_spec.rb +0 -43
  137. data/spec/plugin/padrino_render_spec.rb +0 -34
  138. data/spec/plugin/param_matchers_spec.rb +0 -69
  139. data/spec/plugin/params_capturing_spec.rb +0 -33
  140. data/spec/plugin/partials_spec.rb +0 -43
  141. data/spec/plugin/pass_spec.rb +0 -29
  142. data/spec/plugin/path_matchers_spec.rb +0 -42
  143. data/spec/plugin/path_rewriter_spec.rb +0 -45
  144. data/spec/plugin/path_spec.rb +0 -222
  145. data/spec/plugin/placeholder_string_matchers_spec.rb +0 -126
  146. data/spec/plugin/precompile_templates_spec.rb +0 -61
  147. data/spec/plugin/public_spec.rb +0 -85
  148. data/spec/plugin/render_each_spec.rb +0 -82
  149. data/spec/plugin/render_locals_spec.rb +0 -114
  150. data/spec/plugin/render_spec.rb +0 -912
  151. data/spec/plugin/request_aref_spec.rb +0 -51
  152. data/spec/plugin/request_headers_spec.rb +0 -39
  153. data/spec/plugin/response_request_spec.rb +0 -43
  154. data/spec/plugin/route_block_args_spec.rb +0 -86
  155. data/spec/plugin/route_csrf_spec.rb +0 -305
  156. data/spec/plugin/run_append_slash_spec.rb +0 -77
  157. data/spec/plugin/run_handler_spec.rb +0 -53
  158. data/spec/plugin/sessions_spec.rb +0 -452
  159. data/spec/plugin/shared_vars_spec.rb +0 -45
  160. data/spec/plugin/sinatra_helpers_spec.rb +0 -537
  161. data/spec/plugin/slash_path_empty_spec.rb +0 -22
  162. data/spec/plugin/static_routing_spec.rb +0 -192
  163. data/spec/plugin/static_spec.rb +0 -30
  164. data/spec/plugin/status_303_spec.rb +0 -28
  165. data/spec/plugin/status_handler_spec.rb +0 -158
  166. data/spec/plugin/streaming_spec.rb +0 -246
  167. data/spec/plugin/strip_path_prefix_spec.rb +0 -24
  168. data/spec/plugin/symbol_matchers_spec.rb +0 -51
  169. data/spec/plugin/symbol_status_spec.rb +0 -25
  170. data/spec/plugin/symbol_views_spec.rb +0 -32
  171. data/spec/plugin/timestamp_public_spec.rb +0 -85
  172. data/spec/plugin/type_routing_spec.rb +0 -348
  173. data/spec/plugin/typecast_params_spec.rb +0 -1370
  174. data/spec/plugin/unescape_path_spec.rb +0 -22
  175. data/spec/plugin/view_options_spec.rb +0 -170
  176. data/spec/plugin_spec.rb +0 -71
  177. data/spec/redirect_spec.rb +0 -41
  178. data/spec/request_spec.rb +0 -97
  179. data/spec/response_spec.rb +0 -199
  180. data/spec/route_spec.rb +0 -39
  181. data/spec/session_middleware_spec.rb +0 -129
  182. data/spec/session_spec.rb +0 -37
  183. data/spec/spec_helper.rb +0 -137
  184. data/spec/version_spec.rb +0 -14
  185. data/spec/views/_test.erb +0 -1
  186. data/spec/views/a.erb +0 -1
  187. data/spec/views/a.rdoc +0 -2
  188. data/spec/views/about.erb +0 -1
  189. data/spec/views/about.str +0 -1
  190. data/spec/views/about/_test.css.gz +0 -0
  191. data/spec/views/about/_test.erb +0 -1
  192. data/spec/views/about/_test.erb.gz +0 -0
  193. data/spec/views/about/comp_test.erb +0 -1
  194. data/spec/views/b.erb +0 -1
  195. data/spec/views/c.erb +0 -1
  196. data/spec/views/comp_layout.erb +0 -1
  197. data/spec/views/comp_test.erb +0 -1
  198. data/spec/views/content-yield.erb +0 -1
  199. data/spec/views/each.str +0 -1
  200. data/spec/views/home.erb +0 -2
  201. data/spec/views/home.str +0 -2
  202. data/spec/views/iv.erb +0 -1
  203. data/spec/views/layout-alternative.erb +0 -2
  204. data/spec/views/layout-yield.erb +0 -3
  205. data/spec/views/layout.erb +0 -2
  206. data/spec/views/layout.str +0 -2
  207. data/spec/views/multiple-layout.erb +0 -1
  208. data/spec/views/multiple.erb +0 -1
@@ -1,1370 +0,0 @@
1
- require_relative "../spec_helper"
2
- require 'tempfile'
3
-
4
- describe "typecast_params plugin" do
5
- def tp(arg='a=1&b[]=2&b[]=3&c[d]=4&c[e]=5&f=&g[]=&h[i]=')
6
- @tp.call(arg)
7
- end
8
-
9
- def error
10
- yield
11
- rescue @tp_error => e
12
- e
13
- end
14
-
15
- before do
16
- res = nil
17
- app(:typecast_params) do |r|
18
- res = typecast_params
19
- nil
20
- end
21
-
22
- @tp = lambda do |params|
23
- req('QUERY_STRING'=>params, 'rack.input'=>StringIO.new)
24
- res
25
- end
26
-
27
- @tp_error = Roda::RodaPlugins::TypecastParams::Error
28
- end
29
-
30
- it ".new should raise error if params is not a hash" do
31
- lambda{Roda::RodaPlugins::TypecastParams::Params.new('a')}.must_raise @tp_error
32
- end
33
-
34
- it ".new should raise for non String/Array args passed to conversion method" do
35
- lambda{tp.any({})}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
36
- lambda{tp.any(Object.new)}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
37
- lambda{tp.any(:a)}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
38
- end
39
-
40
- it "#present should return whether the key is in the obj if given String" do
41
- tp.present?('a').must_equal true
42
- tp.present?('b').must_equal true
43
- tp.present?('c').must_equal true
44
- tp.present?('d').must_equal false
45
- end
46
-
47
- it "#present should return whether all keys are in the obj if given an Array" do
48
- tp.present?(%w'a b c').must_equal true
49
- tp.present?(%w'a b c d').must_equal false
50
- end
51
-
52
- it "#present should raise if given an unexpected object" do
53
- lambda{tp.present?(:a)}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
54
- lambda{tp.present?([:a])}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
55
- lambda{tp.present?([['a']])}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
56
- end
57
-
58
- it "conversion methods should only support one level deep array of keys" do
59
- lambda{tp.any([['a']])}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
60
- end
61
-
62
- it "#any should not do any conversion" do
63
- tp.any('a').must_equal '1'
64
- tp.any('b').must_equal ["2", "3"]
65
- tp.any('c').must_equal('d'=>'4', 'e'=>'5')
66
- tp.any('d').must_be_nil
67
- tp.any(%w'g h').must_equal([[''], {'i'=>''}])
68
-
69
- tp.any!('a').must_equal '1'
70
- tp.any!(%w'a').must_equal %w'1'
71
- lambda{tp.any!('d')}.must_raise @tp_error
72
- lambda{tp.any!(%w'd j')}.must_raise @tp_error
73
-
74
- lambda{tp.array(:any, 'a')}.must_raise @tp_error
75
- tp.array(:any, 'b').must_equal ["2", "3"]
76
- lambda{tp.array(:any, 'c')}.must_raise @tp_error
77
- tp.array(:any, 'd').must_be_nil
78
- tp.array(:any, %w'g').must_equal([['']])
79
- lambda{tp.array(:any, 'h')}.must_raise @tp_error
80
-
81
- tp.array!(:any, 'b').must_equal ["2", "3"]
82
- lambda{tp.array!(:any, 'd')}.must_raise @tp_error
83
- tp.array!(:any, %w'g').must_equal([['']])
84
- end
85
-
86
- it "#str should require strings" do
87
- tp.str('a').must_equal '1'
88
- lambda{tp.str('b')}.must_raise @tp_error
89
- lambda{tp.str('c')}.must_raise @tp_error
90
- lambda{tp.str(%w'b c')}.must_raise @tp_error
91
- tp.str('d').must_be_nil
92
- tp.str('f').must_equal ''
93
- lambda{tp.str('g')}.must_raise @tp_error
94
- lambda{tp.str('h')}.must_raise @tp_error
95
-
96
- tp.str!('a').must_equal '1'
97
- lambda{tp.str!('d')}.must_raise @tp_error
98
- tp.str!('f').must_equal ''
99
-
100
- lambda{tp.array(:str, 'a')}.must_raise @tp_error
101
- tp.array(:str, 'b').must_equal ["2", "3"]
102
- lambda{tp.array(:str, 'c')}.must_raise @tp_error
103
- tp.array(:str, 'd').must_be_nil
104
- tp.array(:str, 'g').must_equal [""]
105
- lambda{tp.array(:str, 'h')}.must_raise @tp_error
106
-
107
- tp.array!(:str, 'b').must_equal ["2", "3"]
108
- lambda{tp.array!(:str, 'd')}.must_raise @tp_error
109
- tp.array!(:str, 'g').must_equal [""]
110
- end
111
-
112
- it "#nonempty_str should require nonempty strings" do
113
- tp.nonempty_str('a').must_equal '1'
114
- tp('a=%201').nonempty_str('a').must_equal ' 1'
115
- tp('a=1%20').nonempty_str('a').must_equal '1 '
116
- tp('a=%201%20').nonempty_str('a').must_equal ' 1 '
117
- tp('a=%20').nonempty_str('a').must_be_nil
118
- lambda{tp.nonempty_str('b')}.must_raise @tp_error
119
- lambda{tp.nonempty_str('c')}.must_raise @tp_error
120
- tp.nonempty_str('d').must_be_nil
121
- tp.nonempty_str('f').must_be_nil
122
- lambda{tp.nonempty_str('g')}.must_raise @tp_error
123
- lambda{tp.nonempty_str('h')}.must_raise @tp_error
124
-
125
- tp.nonempty_str!('a').must_equal '1'
126
- lambda{tp.nonempty_str!('d')}.must_raise @tp_error
127
- lambda{tp.nonempty_str!('f')}.must_raise @tp_error
128
-
129
- lambda{tp.array(:nonempty_str, 'a')}.must_raise @tp_error
130
- tp.array(:nonempty_str, 'b').must_equal ["2", "3"]
131
- lambda{tp.array(:nonempty_str, 'c')}.must_raise @tp_error
132
- tp.array(:nonempty_str, 'd').must_be_nil
133
- tp.array(:nonempty_str, 'g').must_equal [nil]
134
- lambda{tp.array(:nonempty_str, 'h')}.must_raise @tp_error
135
-
136
- tp.array!(:nonempty_str, 'b').must_equal ["2", "3"]
137
- lambda{tp.array!(:nonempty_str, 'd')}.must_raise @tp_error
138
- lambda{tp.array!(:nonempty_str, 'g')}.must_raise @tp_error
139
- end
140
-
141
- it "#bool should convert to boolean" do
142
- tp('a=0').bool('a').must_equal false
143
- tp('a=f').bool('a').must_equal false
144
- tp('a=false').bool('a').must_equal false
145
- tp('a=FALSE').bool('a').must_equal false
146
- tp('a=F').bool('a').must_equal false
147
- tp('a=n').bool('a').must_equal false
148
- tp('a=no').bool('a').must_equal false
149
- tp('a=N').bool('a').must_equal false
150
- tp('a=NO').bool('a').must_equal false
151
- tp('a=off').bool('a').must_equal false
152
- tp('a=OFF').bool('a').must_equal false
153
-
154
- tp('a=1').bool('a').must_equal true
155
- tp('a=t').bool('a').must_equal true
156
- tp('a=true').bool('a').must_equal true
157
- tp('a=TRUE').bool('a').must_equal true
158
- tp('a=T').bool('a').must_equal true
159
- tp('a=y').bool('a').must_equal true
160
- tp('a=yes').bool('a').must_equal true
161
- tp('a=Y').bool('a').must_equal true
162
- tp('a=YES').bool('a').must_equal true
163
- tp('a=on').bool('a').must_equal true
164
- tp('a=ON').bool('a').must_equal true
165
-
166
- tp.bool('a').must_equal true
167
- lambda{tp.bool('b')}.must_raise @tp_error
168
- lambda{tp.bool('c')}.must_raise @tp_error
169
- tp.bool('d').must_be_nil
170
- tp.bool('f').must_be_nil
171
-
172
- tp.bool!('a').must_equal true
173
- lambda{tp.bool!('d')}.must_raise @tp_error
174
- lambda{tp.bool!('f')}.must_raise @tp_error
175
-
176
- lambda{tp.array(:bool, 'a')}.must_raise @tp_error
177
- tp('b[]=1&b[]=0').array(:bool, 'b').must_equal [true, false]
178
- lambda{tp('b[]=1&b[]=a').array(:bool, 'b')}.must_raise @tp_error
179
- lambda{tp.array(:bool, 'c')}.must_raise @tp_error
180
- tp.array(:bool, 'd').must_be_nil
181
- tp.array(:bool, 'g').must_equal [nil]
182
- lambda{tp.array(:bool, 'h')}.must_raise @tp_error
183
-
184
- tp('b[]=1&b[]=0').array!(:bool, 'b').must_equal [true, false]
185
- lambda{tp.array!(:bool, 'd')}.must_raise @tp_error
186
- lambda{tp.array!(:bool, 'g')}.must_raise @tp_error
187
- end
188
-
189
- it "#int should convert to integer" do
190
- tp('a=-1').int('a').must_equal(-1)
191
- tp('a=0').int('a').must_equal 0
192
- tp('a=a').int('a').must_equal 0
193
- tp.int('a').must_equal 1
194
- tp.int('a').must_be_kind_of Integer
195
- lambda{tp.int('b')}.must_raise @tp_error
196
- lambda{tp.int('c')}.must_raise @tp_error
197
- tp.int('d').must_be_nil
198
- tp.int('f').must_be_nil
199
- lambda{tp.int('g')}.must_raise @tp_error
200
- lambda{tp.int('h')}.must_raise @tp_error
201
-
202
- tp.int!('a').must_equal 1
203
- lambda{tp.int!('d')}.must_raise @tp_error
204
- lambda{tp.int!('f')}.must_raise @tp_error
205
-
206
- lambda{tp.array(:int, 'a')}.must_raise @tp_error
207
- tp.array(:int, 'b').must_equal [2, 3]
208
- lambda{tp.array(:int, 'c')}.must_raise @tp_error
209
- tp.array(:int, 'd').must_be_nil
210
- tp.array(:int, 'g').must_equal [nil]
211
- lambda{tp.array(:int, 'h')}.must_raise @tp_error
212
-
213
- tp.array!(:int, 'b').must_equal [2, 3]
214
- lambda{tp.array!(:int, 'd')}.must_raise @tp_error
215
- lambda{tp.array!(:int, 'g')}.must_raise @tp_error
216
- end
217
-
218
- it "#pos_int should convert to positive integer" do
219
- tp('a=-1').pos_int('a').must_be_nil
220
- tp('a=0').pos_int('a').must_be_nil
221
- tp('a=a').pos_int('a').must_be_nil
222
- tp.pos_int('a').must_equal 1
223
- tp.pos_int('a').must_be_kind_of Integer
224
- lambda{tp.pos_int('b')}.must_raise @tp_error
225
- lambda{tp.pos_int('c')}.must_raise @tp_error
226
- tp.pos_int('d').must_be_nil
227
- tp.pos_int('f').must_be_nil
228
- lambda{tp.pos_int('g')}.must_raise @tp_error
229
- lambda{tp.pos_int('h')}.must_raise @tp_error
230
-
231
- lambda{tp('a=-1').pos_int!('a')}.must_raise @tp_error
232
- lambda{tp('a=0').pos_int!('a')}.must_raise @tp_error
233
- lambda{tp('a=a').pos_int!('a')}.must_raise @tp_error
234
- tp.pos_int!('a').must_equal 1
235
- lambda{tp.pos_int!('d')}.must_raise @tp_error
236
- lambda{tp.pos_int!('f')}.must_raise @tp_error
237
-
238
- lambda{tp.array(:pos_int, 'a')}.must_raise @tp_error
239
- tp.array(:pos_int, 'b').must_equal [2, 3]
240
- lambda{tp.array(:pos_int, 'c')}.must_raise @tp_error
241
- tp.array(:pos_int, 'd').must_be_nil
242
- tp.array(:pos_int, 'g').must_equal [nil]
243
- lambda{tp.array(:pos_int, 'h')}.must_raise @tp_error
244
-
245
- tp.array!(:pos_int, 'b').must_equal [2, 3]
246
- lambda{tp.array!(:pos_int, 'd')}.must_raise @tp_error
247
- lambda{tp.array!(:pos_int, 'g')}.must_raise @tp_error
248
- end
249
-
250
- it "#Integer should convert to integer strictly" do
251
- tp('a=-1').Integer('a').must_equal(-1)
252
- tp('a=0').Integer('a').must_equal 0
253
- lambda{tp('a=a').Integer('a')}.must_raise @tp_error
254
- tp.Integer('a').must_equal 1
255
- tp.Integer('a').must_be_kind_of Integer
256
- lambda{tp.Integer('b')}.must_raise @tp_error
257
- lambda{tp.Integer('c')}.must_raise @tp_error
258
- tp.Integer('d').must_be_nil
259
- tp.Integer('f').must_be_nil
260
- lambda{tp.Integer('g')}.must_raise @tp_error
261
- lambda{tp.Integer('h')}.must_raise @tp_error
262
-
263
- tp.Integer!('a').must_equal 1
264
- lambda{tp.Integer!('d')}.must_raise @tp_error
265
- lambda{tp.Integer!('f')}.must_raise @tp_error
266
-
267
- lambda{tp.array(:Integer, 'a')}.must_raise @tp_error
268
- tp.array(:Integer, 'b').must_equal [2, 3]
269
- lambda{tp.array(:Integer, 'c')}.must_raise @tp_error
270
- tp.array(:Integer, 'd').must_be_nil
271
- tp.array(:Integer, 'g').must_equal [nil]
272
- lambda{tp.array(:Integer, 'h')}.must_raise @tp_error
273
-
274
- tp.array!(:Integer, 'b').must_equal [2, 3]
275
- lambda{tp.array!(:Integer, 'd')}.must_raise @tp_error
276
- lambda{tp.array!(:Integer, 'g')}.must_raise @tp_error
277
-
278
- a = 1
279
- @app.plugin :hooks
280
- @app.before do
281
- request.define_singleton_method(:params){{'a'=>a}}
282
- end
283
- tp.Integer('a').must_equal 1
284
- a = 1.0
285
- tp.Integer('a').must_equal 1
286
- a = 1.1
287
- lambda{tp.Integer('a')}.must_raise @tp_error
288
- end
289
-
290
- it "#float should convert to float" do
291
- tp('a=-1').float('a').must_equal(-1)
292
- tp('a=0').float('a').must_equal 0
293
- tp('a=a').float('a').must_equal 0
294
- tp.float('a').must_equal 1
295
- tp.float('a').must_be_kind_of Float
296
- lambda{tp.float('b')}.must_raise @tp_error
297
- lambda{tp.float('c')}.must_raise @tp_error
298
- tp.float('d').must_be_nil
299
- tp.float('f').must_be_nil
300
- lambda{tp.float('g')}.must_raise @tp_error
301
- lambda{tp.float('h')}.must_raise @tp_error
302
-
303
- tp.float!('a').must_equal 1
304
- lambda{tp.float!('d')}.must_raise @tp_error
305
- lambda{tp.float!('f')}.must_raise @tp_error
306
-
307
- lambda{tp.array(:float, 'a')}.must_raise @tp_error
308
- tp.array(:float, 'b').must_equal [2, 3]
309
- lambda{tp.array(:float, 'c')}.must_raise @tp_error
310
- tp.array(:float, 'd').must_be_nil
311
- tp.array(:float, 'g').must_equal [nil]
312
- lambda{tp.array(:float, 'h')}.must_raise @tp_error
313
-
314
- tp.array!(:float, 'b').must_equal [2, 3]
315
- lambda{tp.array!(:float, 'd')}.must_raise @tp_error
316
- lambda{tp.array!(:float, 'g')}.must_raise @tp_error
317
- end
318
-
319
- it "#Float should convert to float strictly" do
320
- tp('a=-1').Float('a').must_equal(-1)
321
- tp('a=0').Float('a').must_equal 0
322
- lambda{tp('a=a').Float('a')}.must_raise @tp_error
323
- tp.Float('a').must_equal 1
324
- tp.Float('a').must_be_kind_of Float
325
- lambda{tp.Float('b')}.must_raise @tp_error
326
- lambda{tp.Float('c')}.must_raise @tp_error
327
- tp.Float('d').must_be_nil
328
- tp.Float('f').must_be_nil
329
- lambda{tp.Float('g')}.must_raise @tp_error
330
- lambda{tp.Float('h')}.must_raise @tp_error
331
-
332
- tp.Float!('a').must_equal 1
333
- lambda{tp.Float!('d')}.must_raise @tp_error
334
- lambda{tp.Float!('f')}.must_raise @tp_error
335
-
336
- lambda{tp.array(:Float, 'a')}.must_raise @tp_error
337
- tp.array(:Float, 'b').must_equal [2, 3]
338
- lambda{tp.array(:Float, 'c')}.must_raise @tp_error
339
- tp.array(:Float, 'd').must_be_nil
340
- tp.array(:Float, 'g').must_equal [nil]
341
- lambda{tp.array(:Float, 'h')}.must_raise @tp_error
342
-
343
- tp.array!(:Float, 'b').must_equal [2, 3]
344
- lambda{tp.array!(:Float, 'd')}.must_raise @tp_error
345
- lambda{tp.array!(:Float, 'g')}.must_raise @tp_error
346
- end
347
-
348
- it "#Hash should require hashes" do
349
- lambda{tp.Hash('a')}.must_raise @tp_error
350
- lambda{tp.Hash('b')}.must_raise @tp_error
351
- tp.Hash('c').must_equal('d'=>'4', 'e'=>'5')
352
- tp.Hash('d').must_be_nil
353
- lambda{tp.Hash('f')}.must_raise @tp_error
354
- lambda{tp.Hash('g')}.must_raise @tp_error
355
- tp.Hash('h').must_equal('i'=>'')
356
-
357
- tp.Hash!('c').must_equal('d'=>'4', 'e'=>'5')
358
- lambda{tp.Hash!('d')}.must_raise @tp_error
359
- tp.Hash!('h').must_equal('i'=>'')
360
-
361
- lambda{tp.array(:Hash, 'c')}.must_raise @tp_error
362
- lambda{tp('a[][b]=2&a[]=3').array(:Hash, 'a')}.must_raise @tp_error
363
- tp('a[][b]=2&a[][b]=3').array(:Hash, 'a').must_equal [{'b'=>'2'}, {'b'=>'3'}]
364
- tp.array(:Hash, 'd').must_be_nil
365
-
366
- tp('a[][b]=2&a[][b]=3').array!(:Hash, 'a').must_equal [{'b'=>'2'}, {'b'=>'3'}]
367
- lambda{tp.array!(:Hash, 'd')}.must_raise @tp_error
368
- end
369
-
370
- it "#Date should parse strings into Date instances" do
371
- tp('a=').date('a').must_be_nil
372
- tp('a=2017-10-11').date('a').must_equal Date.new(2017, 10, 11)
373
- tp('a=17/10/11').date('a').must_equal Date.new(2017, 10, 11)
374
- lambda{tp.date('b')}.must_raise @tp_error
375
- lambda{tp('a=a').date('a')}.must_raise @tp_error
376
-
377
- lambda{tp('a=').date!('a')}.must_raise @tp_error
378
- tp('a=2017-10-11').date!('a').must_equal Date.new(2017, 10, 11)
379
-
380
- tp('a[]=2017-10-11&a[]=2017-10-12').array(:date, 'a').must_equal [Date.new(2017, 10, 11), Date.new(2017, 10, 12)]
381
- tp('a[]=2017-10-11&a[]=2017-10-12').array(:date, 'b').must_be_nil
382
-
383
- tp('a[]=2017-10-11&a[]=2017-10-12').array!(:date, 'a').must_equal [Date.new(2017, 10, 11), Date.new(2017, 10, 12)]
384
- lambda{tp('a[]=2017-10-11&a[]=a').array!(:date, 'a')}.must_raise @tp_error
385
- lambda{tp('a[]=2017-10-11&a[]=2017-10-12').array!(:date, 'b')}.must_raise @tp_error
386
- end
387
-
388
- it "#Time should parse strings into Time instances" do
389
- tp('a=').time('a').must_be_nil
390
- tp('a=2017-10-11%2012:13:14').time('a').must_equal Time.local(2017, 10, 11, 12, 13, 14)
391
- tp('a=17/10/11%2012:13:14').time('a').must_equal Time.local(2017, 10, 11, 12, 13, 14)
392
- lambda{tp.time('b')}.must_raise @tp_error
393
- lambda{tp('a=a').time('a')}.must_raise @tp_error
394
-
395
- lambda{tp('a=').time!('a')}.must_raise @tp_error
396
- tp('a=2017-10-11%2012:13:14').time!('a').must_equal Time.new(2017, 10, 11, 12, 13, 14)
397
-
398
- tp('a[]=2017-10-11%2012:13:14&a[]=2017-10-12%2012:13:14').array(:time, 'a').must_equal [Time.local(2017, 10, 11, 12, 13, 14), Time.local(2017, 10, 12, 12, 13, 14)]
399
- tp('a[]=2017-10-11%2012:13:14&a[]=2017-10-12%2012:13:14').array(:time, 'b').must_be_nil
400
-
401
- tp('a[]=2017-10-11%2012:13:14&a[]=2017-10-12%2012:13:14').array!(:time, 'a').must_equal [Time.local(2017, 10, 11, 12, 13, 14), Time.local(2017, 10, 12, 12, 13, 14)]
402
- lambda{tp('a[]=2017-10-11%2012:13:14&a[]=a').array!(:time, 'a')}.must_raise @tp_error
403
- lambda{tp('a[]=2017-10-11%2012:13:14&a[]=2017-10-12%2012:13:14').array!(:time, 'b')}.must_raise @tp_error
404
- end
405
-
406
- it "#DateTime should parse strings into DateTime instances" do
407
- tp('a=').datetime('a').must_be_nil
408
- tp('a=2017-10-11%2012:13:14').datetime('a').must_equal DateTime.new(2017, 10, 11, 12, 13, 14)
409
- tp('a=17/10/11%2012:13:14').datetime('a').must_equal DateTime.new(2017, 10, 11, 12, 13, 14)
410
- lambda{tp.datetime('b')}.must_raise @tp_error
411
- lambda{tp('a=a').datetime('a')}.must_raise @tp_error
412
-
413
- lambda{tp('a=').datetime!('a')}.must_raise @tp_error
414
- tp('a=2017-10-11%2012:13:14').datetime!('a').must_equal DateTime.new(2017, 10, 11, 12, 13, 14)
415
-
416
- tp('a[]=2017-10-11%2012:13:14&a[]=2017-10-12%2012:13:14').array(:datetime, 'a').must_equal [DateTime.new(2017, 10, 11, 12, 13, 14), DateTime.new(2017, 10, 12, 12, 13, 14)]
417
- tp('a[]=2017-10-11%2012:13:14&a[]=2017-10-12%2012:13:14').array(:datetime, 'b').must_be_nil
418
-
419
- tp('a[]=2017-10-11%2012:13:14&a[]=2017-10-12%2012:13:14').array!(:datetime, 'a').must_equal [DateTime.new(2017, 10, 11, 12, 13, 14), DateTime.new(2017, 10, 12, 12, 13, 14)]
420
- lambda{tp('a[]=2017-10-11%2012:13:14&a[]=a').array!(:datetime, 'a')}.must_raise @tp_error
421
- lambda{tp('a[]=2017-10-11%2012:13:14&a[]=2017-10-12%2012:13:14').array!(:datetime, 'b')}.must_raise @tp_error
422
- end
423
-
424
- it "#array should handle defaults" do
425
- tp = tp('b[]=1&c[]=')
426
- tp.array(:int, 'b', [2]).must_equal [1]
427
- tp.array(:int, 'c', [2]).must_equal [nil]
428
- tp.array(:int, 'd', []).must_equal []
429
- tp.array(:int, 'e', [1]).must_equal [1]
430
-
431
- tp('b[]=1&c[]=').array(:int, %w'b c', [2]).must_equal [[1], [nil]]
432
- tp('b[]=1&c[]=').array(:int, %w'b d', [2]).must_equal [[1], [2]]
433
- end
434
-
435
- it "#array! should handle defaults" do
436
- tp = tp('b[]=1&c[]=')
437
- tp.array!(:int, 'b', [2]).must_equal [1]
438
- lambda{tp.array!(:int, 'c', [2])}.must_raise @tp_error
439
- tp.array!(:int, 'd', []).must_equal []
440
- tp.array!(:int, 'e', [1]).must_equal [1]
441
-
442
- lambda{tp('b[]=1&c[]=').array!(:int, %w'b c', [2])}.must_raise @tp_error
443
- tp('b[]=1&c[]=').array!(:int, %w'b d', [2]).must_equal [[1], [2]]
444
- end
445
-
446
- it "#array should handle key arrays" do
447
- tp('b[]=1&c[]=2').array(:int, %w'b c').must_equal [[1], [2]]
448
- tp('b[]=1&c[]=').array(:int, %w'b c').must_equal [[1], [nil]]
449
- end
450
-
451
- it "#array! should handle key arrays" do
452
- tp('b[]=1&c[]=2').array!(:int, %w'b c').must_equal [[1], [2]]
453
- lambda{tp('b[]=1&c[]=').array!(:int, %w'b c')}.must_raise @tp_error
454
- end
455
-
456
- it "#[] should access nested values" do
457
- tp['c'].must_be_kind_of tp.class
458
- tp['c'].int('d').must_equal 4
459
- tp['c'].int('e').must_equal 5
460
- tp['c'].int(%w'd e').must_equal [4, 5]
461
- end
462
-
463
- it "#[] should handle deeply nested structures" do
464
- tp('a[b][c][d][e]=1')['a']['b']['c']['d'].int('e').must_equal 1
465
- tp('a[][b][][e]=1')['a'][0]['b'][0].int('e').must_equal 1
466
- end
467
-
468
- it "#[] should raise error for non-Array/Hash parameters" do
469
- lambda{tp['a']}.must_raise @tp_error
470
- end
471
-
472
- it "#[] should raise error for accessing hash with integer value (thinking it is an array)" do
473
- lambda{tp[1]}.must_raise @tp_error
474
- end
475
-
476
- it "#[] should raise error for accessing array with non-integer value non-Array/Hash parameters" do
477
- lambda{tp['b']['a']}.must_raise @tp_error
478
- end
479
-
480
- it "#convert! should return a hash of converted parameters" do
481
- tp = tp()
482
- tp.convert! do |ptp|
483
- ptp.int!('a')
484
- ptp.array!(:int, 'b')
485
- ptp['c'].convert! do |stp|
486
- stp.int!(%w'd e')
487
- end
488
- end.must_equal("a"=>1, "b"=>[2, 3], "c"=>{"d"=>4, "e"=>5})
489
- end
490
-
491
- it "#convert! hash should only include changes made inside block" do
492
- tp = tp()
493
- tp.convert! do |ptp|
494
- ptp.int!('a')
495
- ptp.array!(:int, 'b')
496
- end.must_equal("a"=>1, "b"=>[2, 3])
497
-
498
- tp.convert! do |ptp|
499
- ptp['c'].convert! do |stp|
500
- stp.int!(%w'd e')
501
- end
502
- end.must_equal("c"=>{"d"=>4, "e"=>5})
503
- end
504
-
505
- it "#convert! should handle deeply nested structures" do
506
- tp = tp('a[b][c][d][e]=1')
507
- tp.convert! do |tp0|
508
- tp0['a'].convert! do |tp1|
509
- tp1['b'].convert! do |tp2|
510
- tp2['c'].convert! do |tp3|
511
- tp3['d'].convert! do |tp4|
512
- tp4.int('e')
513
- end
514
- end
515
- end
516
- end
517
- end.must_equal('a'=>{'b'=>{'c'=>{'d'=>{'e'=>1}}}})
518
-
519
- tp = tp('a[][b][][e]=1')
520
- tp.convert! do |tp0|
521
- tp0['a'].convert! do |tp1|
522
- tp1[0].convert! do |tp2|
523
- tp2['b'].convert! do |tp3|
524
- tp3[0].convert! do |tp4|
525
- tp4.int('e')
526
- end
527
- end
528
- end
529
- end
530
- end.must_equal('a'=>[{'b'=>[{'e'=>1}]}])
531
- end
532
-
533
- it "#convert! should not raise errors for missing keys if :raise option is false" do
534
- tp = tp('a[b]=1')
535
- tp.convert! do |tp0|
536
- tp0.convert!('a') do |tp1|
537
- tp1.convert!('c', :raise=>false) do |tp2|
538
- tp2.convert!('d') do |tp2|
539
- end
540
- end
541
- end
542
- end.must_equal('a'=>{})
543
-
544
- tp.convert!('b', :raise=>false){}.must_equal({})
545
-
546
- tp.convert!('b', :raise=>false) do |tp0|
547
- tp1.convert!('c'){}
548
- end.must_equal({})
549
- end
550
-
551
- it "#convert! should handle #[] without #convert! at each level" do
552
- tp = tp('a[b][c][d][e]=1')
553
- tp.convert! do |tp0|
554
- tp0['a'].convert! do |tp1|
555
- tp1['b']['c']['d'].convert! do |tp4|
556
- tp4.int('e')
557
- end
558
- end
559
- end.must_equal('a'=>{'b'=>{'c'=>{'d'=>{'e'=>1}}}})
560
- end
561
-
562
- it "#convert! should handle #[] without #convert! below" do
563
- tp = tp('a[b][c][d][e]=1')
564
- tp.convert! do |tp0|
565
- tp0['a']['b']['c']['d'].int('e')
566
- end.must_equal('a'=>{'b'=>{'c'=>{'d'=>{'e'=>1}}}})
567
- end
568
-
569
- it "#convert! should handle multiple calls to #[] and #convert! below" do
570
- tp = tp('a[b]=2&a[c]=3&a[d]=4&a[e]=5&a[f]=6')
571
- tp.convert! do |tp0|
572
- tp0['a'].int('b')
573
- tp0['a'].convert! do |tp1|
574
- tp1.int('c')
575
- end
576
- tp0['a'].int('d')
577
- tp0['a'].convert! do |tp1|
578
- tp1.int('e')
579
- end
580
- tp0['a'].int('f')
581
- end.must_equal('a'=>{'b'=>2, 'c'=>3, 'd'=>4, 'e'=>5, 'f'=>6})
582
- end
583
-
584
- it "#convert! should handle defaults" do
585
- tp.convert! do |tp0|
586
- tp0.int('d', 12)
587
- end.must_equal('d'=>12)
588
-
589
- tp.convert! do |tp0|
590
- tp0.int(%w'a d', 12)
591
- end.must_equal('a'=>1, 'd'=>12)
592
-
593
- tp.convert! do |tp0|
594
- tp0.array(:int, 'g', [])
595
- end.must_equal('g'=>[nil])
596
-
597
- tp.convert! do |tp0|
598
- tp0.array(:int, 'j', [])
599
- end.must_equal('j'=>[])
600
-
601
- tp('a[]=1&g[]=').convert! do |tp0|
602
- tp0.array(:int, %w'a d g', [2])
603
- end.must_equal('a'=>[1], 'd'=>[2], 'g'=>[nil])
604
- end
605
-
606
- it "#convert! should handle multiple convert! calls inside" do
607
- tp = tp('a[b]=1&c[d]=2')
608
- tp.convert! do |tp0|
609
- tp0.convert!('a'){|d| d.int('b')}
610
- tp0.convert!('c'){|d| d.int('d')}
611
- end.must_equal('a'=>{'b'=>1}, 'c'=>{'d'=>2})
612
-
613
- tp.convert!(:symbolize=>true) do |tp0|
614
- tp0.convert!('a'){|d| d.int('b')}
615
- tp0.convert!('c'){|d| d.int('d')}
616
- end.must_equal(:a=>{:b=>1}, :c=>{:d=>2})
617
- end
618
-
619
- it "#convert! should include missing values as nil" do
620
- tp = tp()
621
- tp.convert! do |ptp|
622
- ptp.int('x')
623
- ptp.array(:int, 'y')
624
- ptp['c'].convert! do |stp|
625
- stp.int(%w'x z')
626
- end
627
- end.must_equal("x"=>nil, "y"=>nil, "c"=>{"x"=>nil, "z"=>nil})
628
- end
629
-
630
- it "#convert! with :missing=>:skip should not include missing values" do
631
- tp = tp()
632
- tp.convert!(:skip_missing=>true) do |ptp|
633
- ptp.int('x')
634
- ptp.array(:int, 'y')
635
- ptp['c'].convert! do |stp|
636
- stp.int(%w'x z')
637
- end
638
- end.must_equal("c"=>{})
639
-
640
- tp.convert! do |ptp|
641
- ptp.int('x')
642
- ptp.array(:int, 'y')
643
- ptp['c'].convert!(:skip_missing=>true) do |stp|
644
- stp.int(%w'x z')
645
- end
646
- end.must_equal("x"=>nil, "y"=>nil, "c"=>{})
647
-
648
- tp.convert!(:skip_missing=>true) do |ptp|
649
- ptp.int('x')
650
- ptp.array(:int, 'y')
651
- ptp['c'].convert!(:skip_missing=>false) do |stp|
652
- stp.int(%w'x z')
653
- end
654
- end.must_equal("c"=>{"x"=>nil, "z"=>nil})
655
- end
656
-
657
- it "#convert_each! should convert each entry in an array" do
658
- tp = tp('a[][b]=1&a[][c]=2&a[][b]=3&a[][c]=4')
659
- tp['a'].convert_each! do |tp0|
660
- tp0.int(%w'b c')
661
- end.must_equal [{'b'=>1, 'c'=>2}, {'b'=>3, 'c'=>4}]
662
- end
663
-
664
- it "#convert_each! without :keys option should convert each named entry in a hash when keys are '0'..'N'" do
665
- tp = tp('a[0][b]=1&a[0][c]=2&a[1][b]=3&a[1][c]=4')
666
- tp['a'].convert_each! do |tp0|
667
- tp0.int(%w'b c')
668
- end.must_equal [{'b'=>1, 'c'=>2}, {'b'=>3, 'c'=>4}]
669
- end
670
-
671
- it "#convert_each! with :keys option should convert each named entry in a hash when keys are '0'..'N'" do
672
- tp = tp('a[0][b]=1&a[0][c]=2&a[1][b]=3&a[1][c]=4')
673
- tp['a'].convert_each!(:keys=>%w'0 1') do |tp0|
674
- tp0.int(%w'b c')
675
- end.must_equal [{'b'=>1, 'c'=>2}, {'b'=>3, 'c'=>4}]
676
- end
677
-
678
- it "#convert_each! with :keys option should convert each named entry in a hash" do
679
- tp = tp('a[d][b]=1&a[d][c]=2&a[e][b]=3&a[e][c]=4')
680
- tp['a'].convert_each!(:keys=>%w'd e') do |tp0|
681
- tp0.int(%w'b c')
682
- end.must_equal [{'b'=>1, 'c'=>2}, {'b'=>3, 'c'=>4}]
683
- end
684
-
685
- it "#convert_each! with :keys option should store entries when called inside convert" do
686
- tp('a[0][b]=1&a[0][c]=2&a[1][b]=3&a[1][c]=4').convert! do |tp|
687
- tp['a'].convert_each!(:keys=>%w'0 1') do |tp0|
688
- tp0.int(%w'b c')
689
- end
690
- end.must_equal("a"=>{"0"=>{'b'=>1, 'c'=>2}, "1"=>{'b'=>3, 'c'=>4}})
691
- end
692
-
693
- it "#convert_each! :keys option should accept a Proc" do
694
- tp('a[0][b]=1&a[0][c]=2&a[1][b]=3&a[1][c]=4').convert! do |tp|
695
- tp['a'].convert_each!(:keys=>proc{|obj| obj.keys}) do |tp0|
696
- tp0.int(%w'b c')
697
- end
698
- end.must_equal("a"=>{"0"=>{'b'=>1, 'c'=>2}, "1"=>{'b'=>3, 'c'=>4}})
699
- end
700
-
701
- it "#convert_each! should raise if :keys option is given and not an Array/Proc/Method" do
702
- tp = tp('a[0][b]=1&a[0][c]=2&a[2][b]=3&a[2][c]=4')
703
- lambda{tp['a'].convert_each!(:keys=>Object.new){}}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
704
- end
705
-
706
- it "#convert_each! should raise if obj is a hash without '0' keys" do
707
- lambda{tp.convert_each!{}}.must_raise @tp_error
708
- end
709
-
710
- it "#convert_each! should raise if obj is not a hash with '0' but not '0'..'N' keys" do
711
- tp = tp('a[0][b]=1&a[0][c]=2&a[2][b]=3&a[2][c]=4')
712
- lambda{tp['b'].convert_each!{}}.must_raise @tp_error
713
- end
714
-
715
- it "#convert_each! should raise if obj is a scalar" do
716
- tp = tp('a[d][b]=1&a[d][c]=2&a[e][b]=3&a[e][c]=4')
717
- lambda{tp['d']['b'].convert_each!{}}.must_raise @tp_error
718
- end
719
-
720
- it "#convert_each! should raise if obj is a array of non-hashes" do
721
- lambda{tp['b'].convert_each!{}}.must_raise @tp_error
722
- end
723
-
724
- it "#convert_each! should not raise errors for missing keys if :raise option is false" do
725
- tp = tp('a[0][b]=1&a[0][c]=2&a[1][b]=3&a[1][c]=4')
726
- tp['a'].convert_each!(:keys=>%w'0 2', :raise=>false) do |tp0|
727
- tp0.int(%w'b c')
728
- end.must_equal [{'b'=>1, 'c'=>2}, nil]
729
- end
730
-
731
- it "#convert! with :symbolize option should return a hash of converted parameters" do
732
- tp = tp()
733
- tp.convert!(:symbolize=>true) do |ptp|
734
- ptp.int!('a')
735
- ptp.array!(:int, 'b')
736
- ptp['c'].convert! do |stp|
737
- stp.int!(%w'd e')
738
- end
739
- end.must_equal(:a=>1, :b=>[2, 3], :c=>{:d=>4, :e=>5})
740
- end
741
-
742
- it "#convert! with :symbolize option should not persist" do
743
- tp = tp()
744
- tp.convert!(:symbolize=>true) do |ptp|
745
- ptp.int!('a')
746
- ptp.array!(:int, 'b')
747
- ptp['c'].convert! do |stp|
748
- stp.int!(%w'd e')
749
- end
750
- end.must_equal(:a=>1, :b=>[2, 3], :c=>{:d=>4, :e=>5})
751
-
752
- tp.convert! do |ptp|
753
- ptp.int!('a')
754
- ptp.array!(:int, 'b')
755
- ptp['c'].convert! do |stp|
756
- stp.int!(%w'd e')
757
- end
758
- end.must_equal("a"=>1, "b"=>[2, 3], "c"=>{"d"=>4, "e"=>5})
759
- end
760
-
761
- it "#convert! with :symbolize option hash should only include changes made inside block" do
762
- tp = tp()
763
- tp.convert!(:symbolize=>true) do |ptp|
764
- ptp.int!('a')
765
- ptp.array!(:int, 'b')
766
- end.must_equal(:a=>1, :b=>[2, 3])
767
-
768
- tp.convert!(:symbolize=>true) do |ptp|
769
- ptp['c'].convert! do |stp|
770
- stp.int!(%w'd e')
771
- end
772
- end.must_equal(:c=>{:d=>4, :e=>5})
773
- end
774
-
775
- it "#convert! with :symbolize option should handle deeply nested structures" do
776
- tp = tp('a[b][c][d][e]=1')
777
- tp.convert!(:symbolize=>true) do |tp0|
778
- tp0['a'].convert! do |tp1|
779
- tp1['b'].convert! do |tp2|
780
- tp2['c'].convert! do |tp3|
781
- tp3['d'].convert! do |tp4|
782
- tp4.int('e')
783
- end
784
- end
785
- end
786
- end
787
- end.must_equal(:a=>{:b=>{:c=>{:d=>{:e=>1}}}})
788
-
789
- tp = tp('a[][b][][e]=1')
790
- tp.convert!(:symbolize=>true) do |tp0|
791
- tp0['a'].convert! do |tp1|
792
- tp1[0].convert! do |tp2|
793
- tp2['b'].convert! do |tp3|
794
- tp3[0].convert! do |tp4|
795
- tp4.int('e')
796
- end
797
- end
798
- end
799
- end
800
- end.must_equal(:a=>[{:b=>[{:e=>1}]}])
801
- end
802
-
803
- it "#convert! with :symbolize option should handle #[] without #convert! at each level" do
804
- tp = tp('a[b][c][d][e]=1')
805
- tp.convert!(:symbolize=>true) do |tp0|
806
- tp0['a'].convert! do |tp1|
807
- tp1['b']['c']['d'].convert! do |tp4|
808
- tp4.int('e')
809
- end
810
- end
811
- end.must_equal(:a=>{:b=>{:c=>{:d=>{:e=>1}}}})
812
- end
813
-
814
- it "#convert! with :symbolize option should handle #[] without #convert! below" do
815
- tp = tp('a[b][c][d][e]=1')
816
- tp.convert!(:symbolize=>true) do |tp0|
817
- tp0['a']['b']['c']['d'].int('e')
818
- end.must_equal(:a=>{:b=>{:c=>{:d=>{:e=>1}}}})
819
- end
820
-
821
- it "#convert! with :symbolize option should handle multiple calls to #[] and #convert! below" do
822
- tp = tp('a[b]=2&a[c]=3&a[d]=4&a[e]=5&a[f]=6')
823
- tp.convert!(:symbolize=>true) do |tp0|
824
- tp0['a'].int('b')
825
- tp0['a'].convert! do |tp1|
826
- tp1.int('c')
827
- end
828
- tp0['a'].int('d')
829
- tp0['a'].convert! do |tp1|
830
- tp1.int('e')
831
- end
832
- tp0['a'].int('f')
833
- end.must_equal(:a=>{:b=>2, :c=>3, :d=>4, :e=>5, :f=>6})
834
- end
835
-
836
- it "#convert! with :symbolize option should handle defaults" do
837
- tp.convert!(:symbolize=>true) do |tp0|
838
- tp0.int('d', 12)
839
- end.must_equal(:d=>12)
840
-
841
- tp.convert!(:symbolize=>true) do |tp0|
842
- tp0.int(%w'a d', 12)
843
- end.must_equal(:a=>1, :d=>12)
844
-
845
- tp.convert!(:symbolize=>true) do |tp0|
846
- tp0.array(:int, 'g', [])
847
- end.must_equal(:g=>[nil])
848
-
849
- tp.convert!(:symbolize=>true) do |tp0|
850
- tp0.array(:int, 'j', [])
851
- end.must_equal(:j=>[])
852
-
853
- tp('a[]=1&g[]=').convert!(:symbolize=>true) do |tp0|
854
- tp0.array(:int, %w'a d g', [2])
855
- end.must_equal(:a=>[1], :d=>[2], :g=>[nil])
856
- end
857
-
858
- it "#convert_each! with :symbolize option should convert each entry in an array" do
859
- tp = tp('a[][b]=1&a[][c]=2&a[][b]=3&a[][c]=4')
860
- tp['a'].convert_each!(:symbolize=>true) do |tp0|
861
- tp0.int(%w'b c')
862
- end.must_equal [{:b=>1, :c=>2}, {:b=>3, :c=>4}]
863
- end
864
-
865
- it "#convert_each! with :symbolize and :keys options should convert each named entry in a hash" do
866
- tp = tp('a[0][b]=1&a[0][c]=2&a[1][b]=3&a[1][c]=4')
867
- tp['a'].convert_each!(:keys=>%w'0 1', :symbolize=>true) do |tp0|
868
- tp0.int(%w'b c')
869
- end.must_equal [{:b=>1, :c=>2}, {:b=>3, :c=>4}]
870
- end
871
-
872
- it "#convert_each! with :symbolize and :keys options should store entries when called inside convert" do
873
- tp('a[0][b]=1&a[0][c]=2&a[1][b]=3&a[1][c]=4').convert!(:symbolize=>true) do |tp|
874
- tp['a'].convert_each!(:keys=>%w'0 1') do |tp0|
875
- tp0.int(%w'b c')
876
- end
877
- end.must_equal(:a=>{:'0'=>{:b=>1, :c=>2}, :'1'=>{:b=>3, :c=>4}})
878
- end
879
-
880
- it "#convert_each! with :symbolize option should not persist" do
881
- tp = tp('a[][b]=1&a[][c]=2&a[][b]=3&a[][c]=4')
882
- tp['a'].convert_each!(:symbolize=>true) do |tp0|
883
- tp0.int(%w'b c')
884
- end.must_equal [{:b=>1, :c=>2}, {:b=>3, :c=>4}]
885
-
886
- tp = tp('a[][b]=1&a[][c]=2&a[][b]=3&a[][c]=4')
887
- tp['a'].convert_each! do |tp0|
888
- tp0.int(%w'b c')
889
- end.must_equal [{'b'=>1, 'c'=>2}, {'b'=>3, 'c'=>4}]
890
- end
891
-
892
- it "#convert! with :symbolize options specified at different levels should work" do
893
- tp = tp('a[b][c][d][e]=1')
894
- tp.convert!(:symbolize=>true) do |tp0|
895
- tp0['a'].convert!(:symbolize=>false) do |tp1|
896
- tp1['b'].convert!(:symbolize=>true) do |tp2|
897
- tp2['c'].convert!(:symbolize=>false) do |tp3|
898
- tp3['d'].convert!(:symbolize=>true) do |tp4|
899
- tp4.int('e')
900
- end
901
- end
902
- end
903
- end
904
- end.must_equal(:a=>{'b'=>{:c=>{'d'=>{:e=>1}}}})
905
-
906
- tp = tp('a[][b][][e]=1')
907
- tp.convert!(:symbolize=>true) do |tp0|
908
- tp0['a'].convert! do |tp1|
909
- tp1[0].convert!(:symbolize=>false) do |tp2|
910
- tp2['b'].convert! do |tp3|
911
- tp3[0].convert!(:symbolize=>true) do |tp4|
912
- tp4.int('e')
913
- end
914
- end
915
- end
916
- end
917
- end.must_equal(:a=>[{'b'=>[{:e=>1}]}])
918
- end
919
-
920
- it "#dig should return nested values or nil if there is no value" do
921
- tp = tp('a[b][c][d][e]=1&b=2')
922
- tp.dig(:int, 'a', 'b', 'c', 'd', 'e').must_equal 1
923
- tp.dig(:int, 'b').must_equal 2
924
- tp.dig(:int, 'a', 0, 'c', 'd', 'e').must_be_nil
925
- tp.dig(:int, 'a', 'd', 'c', 'd', 'e').must_be_nil
926
- tp.dig(:int, 'a', 'b', 'c', 'd', 'f').must_be_nil
927
- tp.dig(:int, 'c').must_be_nil
928
- tp.dig(:int, 'c', 'd').must_be_nil
929
-
930
- tp = tp('a[][c][][e]=1')
931
- tp.dig(:int, 'a', 0, 'c', 0, 'e').must_equal 1
932
- tp.dig(:int, 'a', 1, 'c', 0, 'e').must_be_nil
933
- tp.dig(:int, 'a', 'b', 'c', 0, 'e').must_be_nil
934
- tp.dig(:int, 'a', 0, 'c', 0, 'f').must_be_nil
935
- end
936
-
937
- it "#dig should raise when accessing past the end of the expected structure" do
938
- tp = tp('a[b][c][d][e]=1&b=2')
939
- lambda{tp.dig(:int, 'a', 'b', 'c', 'd', 'e', 'f')}.must_raise @tp_error
940
- lambda{tp.dig(:int, 'b', 'c')}.must_raise @tp_error
941
-
942
- tp = tp('a[][c][][e]=1')
943
- lambda{tp.dig(:int, 'a', 0, 'c', 0, 'e', 'f')}.must_raise @tp_error
944
- end
945
-
946
- it "#dig and #dig! should handle array keys" do
947
- tp('a[b][c][d][e]=1&a[b][c][d][f]=2').dig(:int, 'a', 'b', 'c', 'd', %w'e f').must_equal [1, 2]
948
- tp('a[b][c][d][e]=1&a[b][c][d][f]=').dig(:int, 'a', 'b', 'c', 'd', %w'e f').must_equal [1, nil]
949
-
950
- tp('a[b][c][d][e]=1&a[b][c][d][f]=2').dig!(:int, 'a', 'b', 'c', 'd', %w'e f').must_equal [1, 2]
951
- lambda{tp('a[b][c][d][e]=1&a[b][c][d][f]=').dig!(:int, 'a', 'b', 'c', 'd', %w'e f')}.must_raise @tp_error
952
- end
953
-
954
- it "#dig and #dig! should be able to handle arrays using an array for the type" do
955
- tp('a[b][c][d][]=1&a[b][c][d][]=2').dig(:array, :int, 'a', 'b', 'c', 'd').must_equal [1, 2]
956
- tp('a[b][c][d][]=1&a[b][c][d][]=').dig(:array, :int, 'a', 'b', 'c', 'd').must_equal [1, nil]
957
-
958
- tp('a[b][c][d][]=1&a[b][c][d][]=2').dig!(:array!, :int, 'a', 'b', 'c', 'd').must_equal [1, 2]
959
- lambda{tp('a[b][c][d][]=1&a[b][c][d][]=').dig!(:array!, :int, 'a', 'b', 'c', 'd')}.must_raise @tp_error
960
- end
961
-
962
- it "#dig should raise for unsupported types" do
963
- lambda{tp.dig(:foo, 'a')}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
964
- end
965
-
966
- it "#dig should raise for array without subtype" do
967
- lambda{tp.dig(:array, 'foo', 'a')}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
968
- end
969
-
970
-
971
- it "#dig should raise for unsupported nest values" do
972
- lambda{tp.dig(:int, :foo, 'a')}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
973
- lambda{tp.dig(:array, :int, :foo, 'a')}.must_raise Roda::RodaPlugins::TypecastParams::ProgrammerError
974
- end
975
-
976
- it "#dig! should return nested values or raise Error if thers is no value" do
977
- tp = tp('a[b][c][d][e]=1&b=2')
978
- tp.dig!(:int, 'a', 'b', 'c', 'd', 'e').must_equal 1
979
- tp.dig!(:int, 'b').must_equal 2
980
- lambda{tp.dig!(:int, 'a', 'd', 'c', 'd', 'e')}.must_raise @tp_error
981
- lambda{tp.dig!(:int, 'a', 'b', 'c', 'd', 'f')}.must_raise @tp_error
982
- lambda{tp.dig!(:int, 'a', 0, 'c', 'd', 'f')}.must_raise @tp_error
983
- lambda{tp.dig!(:int, 'c')}.must_raise @tp_error
984
- lambda{tp.dig!(:int, 'b', 'c')}.must_raise @tp_error
985
- lambda{tp.dig!(:int, 'c', 'd')}.must_raise @tp_error
986
- error{tp.dig!(:int, 'a', 'd', 'c', 'd', 'e')}.keys.must_equal %w'a d'
987
- error{tp.dig!(:int, 'a', 'b', 'c', 'e', 'e')}.keys.must_equal %w'a b c e'
988
-
989
- tp = tp('a[][c][][e]=1')
990
- tp.dig!(:int, 'a', 0, 'c', 0, 'e').must_equal 1
991
- lambda{tp.dig!(:int, 'a', 1, 'c', 0, 'e')}.must_raise @tp_error
992
- lambda{tp.dig!(:int, 'a', 'b', 'c', 0, 'e')}.must_raise @tp_error
993
- lambda{tp.dig!(:int, 'a', 0, 'c', 0, 'f')}.must_raise @tp_error
994
- end
995
-
996
- it "#convert! should work with dig" do
997
- tp('a[b][c][d][e]=1').convert! do |tp|
998
- tp.dig(:int, 'a', 'b', 'c', 'd', 'e')
999
- end.must_equal('a'=>{'b'=>{'c'=>{'d'=>{'e'=>1}}}})
1000
- end
1001
-
1002
- it "#convert! with :symbolize option should work with dig" do
1003
- tp('a[b][c][d][e]=1').convert!(:symbolize=>true) do |tp|
1004
- tp.dig(:int, 'a', 'b', 'c', 'd', 'e')
1005
- end.must_equal(:a=>{:b=>{:c=>{:d=>{:e=>1}}}})
1006
- end
1007
-
1008
- it "#fetch should be the same as #[] if the key is present" do
1009
- tp.fetch('c').int('d').must_equal 4
1010
- end
1011
-
1012
- it "#fetch should return nil if the key is not present and no block is given" do
1013
- tp.fetch('d').must_be_nil
1014
- end
1015
-
1016
- it "#fetch should call the block if the key is not present and a block is given" do
1017
- tp.fetch('d'){1}.must_equal 1
1018
- end
1019
-
1020
- it "Error#keys should be a path to the error" do
1021
- error{tp.int!('b')}.keys.must_equal ['b']
1022
- error{tp.int!(%w'b f')}.keys.must_equal ['b']
1023
- error{tp['c'].int!('f')}.keys.must_equal ['c', 'f']
1024
- error{tp('a[b][c][d][e]=1')['a']['b']['c']['d'].date('e')}.keys.must_equal %w'a b c d e'
1025
- end
1026
-
1027
- it "Error#param_name should be the name of the parameter" do
1028
- error{tp.int!('b')}.param_name.must_equal 'b'
1029
- error{tp.int!(%w'b f')}.param_name.must_equal 'b'
1030
- error{tp['c'].int!('f')}.param_name.must_equal 'c[f]'
1031
- error{tp('a[b][c][d][e]=1')['a']['b']['c']['d'].date('e')}.param_name.must_equal 'a[b][c][d][e]'
1032
- error{tp('a[][c][][e]=1')['a'][0]['c'][0].date('e')}.param_name.must_equal 'a[][c][][e]'
1033
- error{tp('a[][c][][e]=1').dig(:date, 'a', 0, 'c', 0, 'e')}.param_name.must_equal 'a[][c][][e]'
1034
- end
1035
-
1036
- it "Error#param_names and #reason should be correct for errors" do
1037
- e = error{tp.int!('b')}
1038
- e.param_names.must_equal ['b']
1039
- e.reason.must_equal :int
1040
-
1041
- e = error{tp.int!(%w'b f')}
1042
- e.param_names.must_equal ['b']
1043
- e.reason.must_equal :int
1044
-
1045
- e = error{tp['c'].int!('f')}
1046
- e.param_names.must_equal ['c[f]']
1047
- e.reason.must_equal :missing
1048
-
1049
- e = error{tp('a[b][c][d][e]=1')['a']['b']['c']['d'].date('e')}
1050
- e.param_names.must_equal ['a[b][c][d][e]']
1051
- e.reason.must_equal :date
1052
-
1053
- e = error{tp('a[][c][][e]=1')['a'][0]['c'][0].date('e')}
1054
- e.param_names.must_equal ['a[][c][][e]']
1055
- e.reason.must_equal :date
1056
-
1057
- e = error{tp('a[][c][][e]=1').dig(:date, 'a', 0, 'c', 0, 'e')}
1058
- e.param_names.must_equal ['a[][c][][e]']
1059
- e.reason.must_equal :date
1060
-
1061
- e = error{tp('a[][c][][e]=1').dig!(:date, 'a', 1, 'c', 0, 'e')}
1062
- e.param_names.must_equal ['a[]']
1063
- e.reason.must_equal :missing
1064
-
1065
- e = error{tp('a[][c][][e]=1').dig!(:date, 'a', 'b', 'c', 0, 'e')}
1066
- e.param_names.must_equal ['a[b]']
1067
- e.reason.must_equal :invalid_type
1068
- end
1069
-
1070
- it "Error#param_names and #all_errors should handle array submission" do
1071
- tp = tp('a[][b]=0')
1072
- e = error do
1073
- tp.convert!('a') do |tp0|
1074
- tp0.int(%w'a b c')
1075
- tp0.array(:int, %w'a b c')
1076
- end
1077
- end
1078
- e.param_names.must_equal %w'a'
1079
- e.all_errors.map(&:reason).must_equal [:invalid_type]
1080
- end
1081
-
1082
- it "Error#param_names and #all_errors should include all errors raised in convert! blocks" do
1083
- tp = tp('a[][b][][e]=0')
1084
- e = error do
1085
- tp.convert! do |tp0|
1086
- tp0['a'].convert! do |tp1|
1087
- tp1[0].convert! do |tp2|
1088
- tp2['b'].convert! do |tp3|
1089
- tp3[0].convert! do |tp4|
1090
- tp4.pos_int!('e')
1091
- end
1092
- end
1093
- end
1094
- end
1095
- tp0.dig!(:pos_int, 'a', 0, 'b', 0, %w'f g')
1096
- tp0.dig!(:pos_int, 'a', 0, 'b')
1097
- tp0.int!('c')
1098
- tp0.array!(:int, %w'd e')
1099
- tp0['b']
1100
- end
1101
- end
1102
- e.param_names.must_equal %w'a[][b][][e] a[][b][][f] a[][b][][g] a[][b] c d e b'
1103
- e.all_errors.map(&:reason).must_equal [:missing, :missing, :missing, :pos_int, :missing, :missing, :missing, :missing]
1104
- end
1105
-
1106
- it "Error#param_names and #all_errors should handle #[] failures by skipping the rest of the block" do
1107
- tp = tp('a[][b][][e]=0')
1108
- e = error do
1109
- tp.convert! do |tp0|
1110
- tp0['b']
1111
- tp0.int!('c')
1112
- end
1113
- end
1114
- e.param_names.must_equal %w'b'
1115
- e.all_errors.map(&:reason).must_equal [:missing]
1116
-
1117
- e = error do
1118
- tp.convert! do |tp0|
1119
- tp0['a'][0].convert! do |tp1|
1120
- tp1['c']
1121
- tp1.int!('d')
1122
- end
1123
- tp0.int!('c')
1124
- end
1125
- end
1126
- e.param_names.must_equal %w'a[][c] c'
1127
- e.all_errors.map(&:reason).must_equal [:missing, :missing]
1128
- end
1129
-
1130
- it "Error#param_names and #all_errorsshould handle array! with array of keys where one of the keys is not present" do
1131
- e = error do
1132
- tp('e[]=0').convert! do |tp0|
1133
- tp0.array!(:pos_int, %w'd e')
1134
- end
1135
- end
1136
- e.param_names.must_equal %w'd e'
1137
- e.all_errors.map(&:reason).must_equal [:missing, :invalid_type]
1138
- end
1139
-
1140
- it "Error#param_names and #all_errors should handle keys given to convert" do
1141
- tp = tp('e[][b][][e]=0')
1142
- e = error do
1143
- tp.convert! do |tp0|
1144
- tp0.convert!(['a', 0, 'b', 0]) do |tp1|
1145
- tp1.pos_int!('e')
1146
- end
1147
- tp0.convert!('f') do |tp1|
1148
- tp1.dig!(:pos_int, 0, 'b', 0, %w'f g')
1149
- end
1150
- tp0.dig!(:pos_int, 'e', 0, 'b')
1151
- tp0.int!('c')
1152
- tp0.array!(:int, 'd')
1153
- end
1154
- end
1155
- e.param_names.must_equal %w'a f e[][b] c d'
1156
- e.all_errors.map(&:reason).must_equal [:missing, :missing, :pos_int, :missing, :missing]
1157
- end
1158
-
1159
- it "Error#param_names and #all_errors should include all errors raised in convert_each! blocks" do
1160
- e = error do
1161
- tp('a[][b]=0&a[][b]=1')['a'].convert_each! do |tp0|
1162
- tp0.dig!(:pos_int, 'b', 0, 'e')
1163
- tp0.dig!(:int, 'b', 0, %w'f g')
1164
- tp0.int!(%w'd e')
1165
- tp0.pos_int!('b')
1166
- tp0['c']
1167
- end
1168
- end
1169
- e.param_names.must_equal %w'a[][b] a[][b] a[][d] a[][e] a[][b] a[][c] a[][b] a[][b] a[][d] a[][e] a[][c]'
1170
- e.all_errors.map(&:reason).must_equal [:invalid_type, :invalid_type, :missing, :missing, :missing, :missing, :invalid_type, :invalid_type, :missing, :missing, :missing]
1171
- end
1172
-
1173
- it "Error#param_names and #all_errors should include all errors for invalid keys used in convert_each!" do
1174
- tp = tp('a[0][b]=1&a[0][c]=2&a[1][b]=3&a[1][c]=4')
1175
- e = error do
1176
- tp['a'].convert_each!(:keys=>%w'0 2 3') do |tp0|
1177
- tp0.int(%w'b c')
1178
- end
1179
- end
1180
- e.param_names.must_equal %w'a[2] a[3]'
1181
- e.all_errors.map(&:reason).must_equal [:missing, :missing]
1182
- end
1183
- end
1184
-
1185
- describe "typecast_params plugin with customized params" do
1186
- def tp(arg='a=1&b[]=2&b[]=3&c[d]=4&c[e]=5&f=&g[]=&h[i]=')
1187
- @tp.call(arg)
1188
- end
1189
-
1190
- before do
1191
- res = nil
1192
- app(:bare) do
1193
- plugin :typecast_params do
1194
- handle_type(:opp_int) do |v|
1195
- -v.to_i
1196
- end
1197
- end
1198
- plugin :typecast_params do
1199
- handle_type(:double) do |v|
1200
- v*2
1201
- end
1202
- end
1203
-
1204
- route do |r|
1205
- res = typecast_params
1206
- nil
1207
- end
1208
- end
1209
-
1210
- @tp = lambda do |params|
1211
- req('QUERY_STRING'=>params, 'rack.input'=>StringIO.new)
1212
- res
1213
- end
1214
-
1215
- @tp_error = Roda::RodaPlugins::TypecastParams::Error
1216
- end
1217
-
1218
- it "should not allow typecast params changes after freezing the app" do
1219
- app.freeze
1220
- lambda{app::TypecastParams.handle_type(:foo){|v| v}}.must_raise RuntimeError
1221
- end
1222
-
1223
- it "should pass through non-ArgumentError exceptions raised by conversion blocks" do
1224
- app::TypecastParams.handle_type(:foo){|v| raise}
1225
- lambda{tp.foo('a')}.must_raise RuntimeError
1226
- end
1227
-
1228
- it "should respect custom typecasting methods" do
1229
- tp.opp_int('a').must_equal(-1)
1230
- tp.opp_int!('a').must_equal(-1)
1231
- tp.opp_int('d').must_be_nil
1232
- lambda{tp.opp_int!('d')}.must_raise @tp_error
1233
-
1234
- tp.array(:opp_int, 'b').must_equal [-2, -3]
1235
- tp.array!(:opp_int, 'b').must_equal [-2, -3]
1236
-
1237
- tp.double('a').must_equal '11'
1238
- tp.double!('a').must_equal '11'
1239
- tp.double('d').must_be_nil
1240
- lambda{tp.double!('d')}.must_raise @tp_error
1241
-
1242
- tp.array(:double, 'b').must_equal ['22', '33']
1243
- tp.array!(:double, 'b').must_equal ['22', '33']
1244
- end
1245
-
1246
- it "should respect custom typecasting methods when subclassing" do
1247
- @app = Class.new(@app)
1248
- @app.plugin :typecast_params do
1249
- handle_type :triple do |v|
1250
- v * 3
1251
- end
1252
- end
1253
-
1254
- tp.opp_int('a').must_equal(-1)
1255
- tp.opp_int!('a').must_equal(-1)
1256
- tp.opp_int('d').must_be_nil
1257
- lambda{tp.opp_int!('d')}.must_raise @tp_error
1258
-
1259
- tp.array(:opp_int, 'b').must_equal [-2, -3]
1260
- tp.array!(:opp_int, 'b').must_equal [-2, -3]
1261
-
1262
- tp.double('a').must_equal '11'
1263
- tp.double!('a').must_equal '11'
1264
- tp.double('d').must_be_nil
1265
- lambda{tp.double!('d')}.must_raise @tp_error
1266
-
1267
- tp.array(:double, 'b').must_equal ['22', '33']
1268
- tp.array!(:double, 'b').must_equal ['22', '33']
1269
-
1270
- tp.triple('a').must_equal '111'
1271
- tp.triple!('a').must_equal '111'
1272
- tp.triple('d').must_be_nil
1273
- lambda{tp.triple!('d')}.must_raise @tp_error
1274
-
1275
- tp.array(:triple, 'b').must_equal ['222', '333']
1276
- tp.array!(:triple, 'b').must_equal ['222', '333']
1277
- end
1278
- end
1279
-
1280
- describe "typecast_params plugin with files" do
1281
- def tp
1282
- @tp.call
1283
- end
1284
-
1285
- before do
1286
- tempfile = @tempfile = Tempfile.new(['roda_typecast_params_spec', '.txt'])
1287
- tempfile.write('tp_spec')
1288
- tempfile.rewind
1289
- res = nil
1290
- app(:typecast_params) do |r|
1291
- res = typecast_params
1292
- nil
1293
- end
1294
- app::RodaRequest.send(:define_method, :params) do
1295
- {'testfile'=>{:tempfile=>tempfile}, 'testfile2'=>{:tempfile=>tempfile},
1296
- 'testfile_array'=>[{:tempfile=>tempfile}, {:tempfile=>tempfile}],
1297
- 'a'=>{'b'=>'c', 'tempfile'=>'f'},
1298
- 'c'=>['']}
1299
- end
1300
-
1301
- @tp = lambda do
1302
- req
1303
- res
1304
- end
1305
-
1306
- @tp_error = Roda::RodaPlugins::TypecastParams::Error
1307
- end
1308
-
1309
- it "#file should require an uploaded file" do
1310
- tp.file('testfile').must_equal(:tempfile=>@tempfile)
1311
- tp.file(%w'testfile testfile2').must_equal [{:tempfile=>@tempfile}, {:tempfile=>@tempfile}]
1312
-
1313
- lambda{tp.file('a')}.must_raise @tp_error
1314
- tp.file('b').must_be_nil
1315
- lambda{tp.file('c')}.must_raise @tp_error
1316
-
1317
- tp.file!('testfile').must_equal(:tempfile=>@tempfile)
1318
- tp.file!(%w'testfile testfile2').must_equal [{:tempfile=>@tempfile}, {:tempfile=>@tempfile}]
1319
- lambda{tp.file!('a')}.must_raise @tp_error
1320
- lambda{tp.file!('b')}.must_raise @tp_error
1321
- lambda{tp.file!('c')}.must_raise @tp_error
1322
-
1323
- tp.array(:file, 'testfile_array').must_equal [{:tempfile=>@tempfile}, {:tempfile=>@tempfile}]
1324
- lambda{tp.array(:file, 'testfile')}.must_raise @tp_error
1325
- lambda{tp.array(:file, 'a')}.must_raise @tp_error
1326
- tp.array(:file, 'b').must_be_nil
1327
- lambda{tp.array(:file, 'c')}.must_raise @tp_error
1328
-
1329
- tp.array!(:file, 'testfile_array').must_equal [{:tempfile=>@tempfile}, {:tempfile=>@tempfile}]
1330
- lambda{tp.array!(:file, 'testfile')}.must_raise @tp_error
1331
- lambda{tp.array!(:file, 'a')}.must_raise @tp_error
1332
- lambda{tp.array!(:file, 'b')}.must_raise @tp_error
1333
- lambda{tp.array!(:file, 'c')}.must_raise @tp_error
1334
- end
1335
- end
1336
-
1337
- describe "typecast_params plugin with strip: :all option" do
1338
- def tp(arg='a=+1+')
1339
- @tp.call(arg)
1340
- end
1341
-
1342
-
1343
- before do
1344
- res = nil
1345
- app(:bare) do
1346
- plugin :typecast_params, strip: :all
1347
- route do |r|
1348
- res = typecast_params
1349
- nil
1350
- end
1351
- end
1352
-
1353
- @tp = lambda do |params|
1354
- req('QUERY_STRING'=>params, 'rack.input'=>StringIO.new)
1355
- res
1356
- end
1357
-
1358
- @tp_error = Roda::RodaPlugins::TypecastParams::Error
1359
- end
1360
-
1361
- it "#file should require an uploaded file" do
1362
- tp.str('a').must_equal '1'
1363
- tp.nonempty_str('a').must_equal '1'
1364
- tp.int('a').must_equal 1
1365
- tp.pos_int('a').must_equal 1
1366
- tp.Integer('a').must_equal 1
1367
- tp.float('a').must_equal 1.0
1368
- tp.Float('a').must_equal 1.0
1369
- end
1370
- end