roda 3.28.0 → 3.29.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.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +10 -0
  3. data/README.rdoc +10 -0
  4. data/doc/release_notes/3.29.0.txt +15 -0
  5. data/lib/roda.rb +1 -0
  6. data/lib/roda/plugins/caching.rb +2 -0
  7. data/lib/roda/plugins/common_logger.rb +1 -1
  8. data/lib/roda/plugins/exception_page.rb +7 -1
  9. data/lib/roda/plugins/indifferent_params.rb +2 -0
  10. data/lib/roda/version.rb +1 -1
  11. metadata +4 -214
  12. data/Rakefile +0 -108
  13. data/doc/release_notes/1.0.0.txt +0 -329
  14. data/doc/release_notes/1.1.0.txt +0 -226
  15. data/doc/release_notes/1.2.0.txt +0 -406
  16. data/doc/release_notes/1.3.0.txt +0 -109
  17. data/doc/release_notes/2.0.0.txt +0 -75
  18. data/doc/release_notes/2.1.0.txt +0 -124
  19. data/doc/release_notes/2.10.0.txt +0 -27
  20. data/doc/release_notes/2.11.0.txt +0 -70
  21. data/doc/release_notes/2.12.0.txt +0 -40
  22. data/doc/release_notes/2.13.0.txt +0 -10
  23. data/doc/release_notes/2.14.0.txt +0 -44
  24. data/doc/release_notes/2.15.0.txt +0 -53
  25. data/doc/release_notes/2.16.0.txt +0 -48
  26. data/doc/release_notes/2.17.0.txt +0 -62
  27. data/doc/release_notes/2.18.0.txt +0 -69
  28. data/doc/release_notes/2.19.0.txt +0 -30
  29. data/doc/release_notes/2.2.0.txt +0 -97
  30. data/doc/release_notes/2.20.0.txt +0 -5
  31. data/doc/release_notes/2.21.0.txt +0 -17
  32. data/doc/release_notes/2.22.0.txt +0 -41
  33. data/doc/release_notes/2.23.0.txt +0 -29
  34. data/doc/release_notes/2.24.0.txt +0 -65
  35. data/doc/release_notes/2.25.0.txt +0 -14
  36. data/doc/release_notes/2.26.0.txt +0 -13
  37. data/doc/release_notes/2.27.0.txt +0 -56
  38. data/doc/release_notes/2.28.0.txt +0 -17
  39. data/doc/release_notes/2.29.0.txt +0 -156
  40. data/doc/release_notes/2.3.0.txt +0 -109
  41. data/doc/release_notes/2.4.0.txt +0 -55
  42. data/doc/release_notes/2.5.0.txt +0 -23
  43. data/doc/release_notes/2.5.1.txt +0 -4
  44. data/doc/release_notes/2.6.0.txt +0 -21
  45. data/doc/release_notes/2.7.0.txt +0 -75
  46. data/doc/release_notes/2.8.0.txt +0 -44
  47. data/doc/release_notes/2.9.0.txt +0 -6
  48. data/spec/all.rb +0 -1
  49. data/spec/assets/css/app.scss +0 -1
  50. data/spec/assets/css/no_access.css +0 -1
  51. data/spec/assets/css/raw.css +0 -1
  52. data/spec/assets/js/head/app.js +0 -1
  53. data/spec/composition_spec.rb +0 -31
  54. data/spec/define_roda_method_spec.rb +0 -274
  55. data/spec/env_spec.rb +0 -11
  56. data/spec/freeze_spec.rb +0 -37
  57. data/spec/integration_spec.rb +0 -209
  58. data/spec/matchers_spec.rb +0 -832
  59. data/spec/opts_spec.rb +0 -42
  60. data/spec/plugin/_after_hook_spec.rb +0 -19
  61. data/spec/plugin/all_verbs_spec.rb +0 -29
  62. data/spec/plugin/assets_preloading_spec.rb +0 -98
  63. data/spec/plugin/assets_spec.rb +0 -745
  64. data/spec/plugin/backtracking_array_spec.rb +0 -42
  65. data/spec/plugin/branch_locals_spec.rb +0 -106
  66. data/spec/plugin/caching_spec.rb +0 -337
  67. data/spec/plugin/chunked_spec.rb +0 -201
  68. data/spec/plugin/class_level_routing_spec.rb +0 -164
  69. data/spec/plugin/class_matchers_spec.rb +0 -40
  70. data/spec/plugin/common_logger_spec.rb +0 -85
  71. data/spec/plugin/content_for_spec.rb +0 -162
  72. data/spec/plugin/content_security_policy_spec.rb +0 -175
  73. data/spec/plugin/cookies_spec.rb +0 -51
  74. data/spec/plugin/csrf_spec.rb +0 -111
  75. data/spec/plugin/default_headers_spec.rb +0 -82
  76. data/spec/plugin/default_status_spec.rb +0 -95
  77. data/spec/plugin/delay_build_spec.rb +0 -23
  78. data/spec/plugin/delegate_spec.rb +0 -23
  79. data/spec/plugin/delete_empty_headers_spec.rb +0 -27
  80. data/spec/plugin/direct_call_spec.rb +0 -28
  81. data/spec/plugin/disallow_file_uploads_spec.rb +0 -25
  82. data/spec/plugin/drop_body_spec.rb +0 -24
  83. data/spec/plugin/early_hints_spec.rb +0 -19
  84. data/spec/plugin/empty_root_spec.rb +0 -14
  85. data/spec/plugin/environments_spec.rb +0 -42
  86. data/spec/plugin/error_email_spec.rb +0 -97
  87. data/spec/plugin/error_handler_spec.rb +0 -216
  88. data/spec/plugin/error_mail_spec.rb +0 -93
  89. data/spec/plugin/exception_page_spec.rb +0 -168
  90. data/spec/plugin/flash_spec.rb +0 -121
  91. data/spec/plugin/h_spec.rb +0 -11
  92. data/spec/plugin/halt_spec.rb +0 -119
  93. data/spec/plugin/hash_matcher_spec.rb +0 -27
  94. data/spec/plugin/hash_routes_spec.rb +0 -535
  95. data/spec/plugin/head_spec.rb +0 -52
  96. data/spec/plugin/header_matchers_spec.rb +0 -98
  97. data/spec/plugin/heartbeat_spec.rb +0 -74
  98. data/spec/plugin/hooks_spec.rb +0 -152
  99. data/spec/plugin/indifferent_params_spec.rb +0 -14
  100. data/spec/plugin/json_parser_spec.rb +0 -141
  101. data/spec/plugin/json_spec.rb +0 -83
  102. data/spec/plugin/mail_processor_spec.rb +0 -451
  103. data/spec/plugin/mailer_spec.rb +0 -282
  104. data/spec/plugin/match_affix_spec.rb +0 -43
  105. data/spec/plugin/match_hook_spec.rb +0 -79
  106. data/spec/plugin/middleware_spec.rb +0 -237
  107. data/spec/plugin/middleware_stack_spec.rb +0 -81
  108. data/spec/plugin/module_include_spec.rb +0 -48
  109. data/spec/plugin/multi_route_spec.rb +0 -268
  110. data/spec/plugin/multi_run_spec.rb +0 -87
  111. data/spec/plugin/multi_view_spec.rb +0 -50
  112. data/spec/plugin/multibyte_string_matcher_spec.rb +0 -44
  113. data/spec/plugin/named_templates_spec.rb +0 -96
  114. data/spec/plugin/not_allowed_spec.rb +0 -69
  115. data/spec/plugin/not_found_spec.rb +0 -128
  116. data/spec/plugin/optimized_string_matchers_spec.rb +0 -43
  117. data/spec/plugin/padrino_render_spec.rb +0 -34
  118. data/spec/plugin/param_matchers_spec.rb +0 -69
  119. data/spec/plugin/params_capturing_spec.rb +0 -33
  120. data/spec/plugin/partials_spec.rb +0 -43
  121. data/spec/plugin/pass_spec.rb +0 -29
  122. data/spec/plugin/path_matchers_spec.rb +0 -42
  123. data/spec/plugin/path_rewriter_spec.rb +0 -45
  124. data/spec/plugin/path_spec.rb +0 -222
  125. data/spec/plugin/placeholder_string_matchers_spec.rb +0 -126
  126. data/spec/plugin/precompile_templates_spec.rb +0 -61
  127. data/spec/plugin/public_spec.rb +0 -85
  128. data/spec/plugin/render_each_spec.rb +0 -82
  129. data/spec/plugin/render_locals_spec.rb +0 -114
  130. data/spec/plugin/render_spec.rb +0 -912
  131. data/spec/plugin/request_aref_spec.rb +0 -51
  132. data/spec/plugin/request_headers_spec.rb +0 -39
  133. data/spec/plugin/response_request_spec.rb +0 -43
  134. data/spec/plugin/route_block_args_spec.rb +0 -86
  135. data/spec/plugin/route_csrf_spec.rb +0 -305
  136. data/spec/plugin/run_append_slash_spec.rb +0 -77
  137. data/spec/plugin/run_handler_spec.rb +0 -53
  138. data/spec/plugin/sessions_spec.rb +0 -452
  139. data/spec/plugin/shared_vars_spec.rb +0 -45
  140. data/spec/plugin/sinatra_helpers_spec.rb +0 -537
  141. data/spec/plugin/slash_path_empty_spec.rb +0 -22
  142. data/spec/plugin/static_routing_spec.rb +0 -192
  143. data/spec/plugin/static_spec.rb +0 -30
  144. data/spec/plugin/status_303_spec.rb +0 -28
  145. data/spec/plugin/status_handler_spec.rb +0 -158
  146. data/spec/plugin/streaming_spec.rb +0 -246
  147. data/spec/plugin/strip_path_prefix_spec.rb +0 -24
  148. data/spec/plugin/symbol_matchers_spec.rb +0 -51
  149. data/spec/plugin/symbol_status_spec.rb +0 -25
  150. data/spec/plugin/symbol_views_spec.rb +0 -32
  151. data/spec/plugin/timestamp_public_spec.rb +0 -85
  152. data/spec/plugin/type_routing_spec.rb +0 -348
  153. data/spec/plugin/typecast_params_spec.rb +0 -1370
  154. data/spec/plugin/unescape_path_spec.rb +0 -22
  155. data/spec/plugin/view_options_spec.rb +0 -170
  156. data/spec/plugin_spec.rb +0 -71
  157. data/spec/redirect_spec.rb +0 -41
  158. data/spec/request_spec.rb +0 -97
  159. data/spec/response_spec.rb +0 -199
  160. data/spec/route_spec.rb +0 -39
  161. data/spec/session_middleware_spec.rb +0 -129
  162. data/spec/session_spec.rb +0 -37
  163. data/spec/spec_helper.rb +0 -137
  164. data/spec/version_spec.rb +0 -14
  165. data/spec/views/_test.erb +0 -1
  166. data/spec/views/a.erb +0 -1
  167. data/spec/views/a.rdoc +0 -2
  168. data/spec/views/about.erb +0 -1
  169. data/spec/views/about.str +0 -1
  170. data/spec/views/about/_test.css.gz +0 -0
  171. data/spec/views/about/_test.erb +0 -1
  172. data/spec/views/about/_test.erb.gz +0 -0
  173. data/spec/views/about/comp_test.erb +0 -1
  174. data/spec/views/b.erb +0 -1
  175. data/spec/views/c.erb +0 -1
  176. data/spec/views/comp_layout.erb +0 -1
  177. data/spec/views/comp_test.erb +0 -1
  178. data/spec/views/content-yield.erb +0 -1
  179. data/spec/views/each.str +0 -1
  180. data/spec/views/home.erb +0 -2
  181. data/spec/views/home.str +0 -2
  182. data/spec/views/iv.erb +0 -1
  183. data/spec/views/layout-alternative.erb +0 -2
  184. data/spec/views/layout-yield.erb +0 -3
  185. data/spec/views/layout.erb +0 -2
  186. data/spec/views/layout.str +0 -2
  187. data/spec/views/multiple-layout.erb +0 -1
  188. 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