PageRenderTime 53ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/test/unit/ut_22_filter.rb

http://github.com/jmettraux/ruote
Ruby | 1124 lines | 1019 code | 96 blank | 9 comment | 1 complexity | cb72cac0ffd59bb8496c0f6c88ad474e MD5 | raw file
  1. #
  2. # testing ruote
  3. #
  4. # Sun Jan 30 21:08:14 JST 2011
  5. #
  6. require File.expand_path('../../test_helper', __FILE__)
  7. require_json
  8. require 'rufus/json'
  9. require 'ruote/util/filter'
  10. class UtFilterTest < Test::Unit::TestCase
  11. def test_missing_field
  12. assert_raise ArgumentError do
  13. Ruote.filter([ { 'type' => 'string' } ], {})
  14. end
  15. end
  16. def test_not_a_filter
  17. assert_raise ArgumentError do
  18. Ruote.filter('nada', {})
  19. end
  20. end
  21. #
  22. # transformations
  23. def assert_filter(result, filter, hash, double_tilde=nil)
  24. assert_equal(
  25. result,
  26. Ruote.filter(
  27. Rufus::Json.dup(filter), hash, :double_tilde => double_tilde))
  28. end
  29. def test_remove
  30. assert_filter(
  31. {},
  32. [ { 'field' => 'x', 'remove' => true } ],
  33. { 'x' => 'y' })
  34. assert_filter(
  35. {},
  36. [ { 'field' => '/.+/', 'remove' => true } ],
  37. { 'x' => 'y', 'z' => 'a' })
  38. assert_filter(
  39. { 'x' => {} },
  40. [ { 'field' => 'x.y', 'remove' => true } ],
  41. { 'x' => { 'y' => 'z' } })
  42. end
  43. def test_default
  44. assert_filter(
  45. { 'x' => 1 },
  46. [ { 'field' => 'x', 'default' => 1 } ],
  47. {})
  48. assert_filter(
  49. { 'x' => 1 },
  50. [ { 'field' => 'x', 'default' => 1 } ],
  51. { 'x' => nil })
  52. assert_filter(
  53. {},
  54. [ { 'field' => '/.+/', 'default' => 1 } ],
  55. {})
  56. assert_filter(
  57. { 'x' => 1 },
  58. [ { 'field' => '/.+/', 'default' => 1 } ],
  59. { 'x' => nil })
  60. assert_filter(
  61. { 'x' => 2 },
  62. [ { 'field' => 'x', 'default' => 1 } ],
  63. { 'x' => 2 })
  64. assert_filter(
  65. { 'x' => { 'y' => 1 } },
  66. [ { 'field' => 'x.y', 'default' => 1 } ],
  67. { 'x' => {} })
  68. assert_filter(
  69. { 'x' => { 'y' => 2 } },
  70. [ { 'field' => 'x.y', 'default' => 1 } ],
  71. { 'x' => { 'y' => 2 } })
  72. assert_filter(
  73. { 'x' => { 'y' => 1 } },
  74. [ { 'field' => 'x', 'default' => {} },
  75. { 'field' => 'x.y', 'default' => 1 } ],
  76. {})
  77. end
  78. def test_or
  79. assert_filter(
  80. { 'x' => 'y' },
  81. [ { 'field' => 'x', 'type' => 'string', 'or' => 'z' } ],
  82. { 'x' => 'y' })
  83. assert_filter(
  84. { 'x' => 'z' },
  85. [ { 'field' => 'x', 'type' => 'string', 'or' => 'z' } ],
  86. { 'x' => 2 })
  87. assert_filter(
  88. { 'x' => 'z' },
  89. [ { 'field' => '/.+/', 'type' => 'string', 'or' => 'z' } ],
  90. { 'x' => 2 })
  91. end
  92. def test_nil_or
  93. assert_filter(
  94. { 'x' => 'y' },
  95. [ { 'field' => 'x', 'or' => 'z' } ],
  96. { 'x' => 'y' })
  97. assert_filter(
  98. { 'x' => 'z' },
  99. [ { 'field' => 'x', 'or' => 'z' } ],
  100. {})
  101. assert_filter(
  102. { 'x' => 'z' },
  103. [ { 'field' => 'x', 'or' => 'z' } ],
  104. { 'x' => nil })
  105. assert_filter(
  106. {},
  107. [ { 'field' => '/.+/', 'or' => 'z' } ],
  108. {})
  109. assert_filter(
  110. { 'x' => 'z' },
  111. [ { 'field' => '/.+/', 'or' => 'z' } ],
  112. { 'x' => nil })
  113. end
  114. def test_and
  115. assert_filter(
  116. { 'x' => 'z' },
  117. [ { 'field' => 'x', 'type' => 'string', 'and' => 'z' } ],
  118. { 'x' => 'y' })
  119. assert_filter(
  120. { 'x' => 1 },
  121. [ { 'field' => 'x', 'type' => 'string', 'and' => 'z' } ],
  122. { 'x' => 1 })
  123. assert_filter(
  124. { 'x' => 1, 'z' => 1 },
  125. [ { 'field' => '/.+/', 'type' => 'string', 'and' => 1 } ],
  126. { 'x' => 'y', 'z' => 'a' })
  127. assert_filter(
  128. { 'x' => 1, 'z' => 2 },
  129. [ { 'field' => '/.+/', 'type' => 'string', 'and' => 1 } ],
  130. { 'x' => 'y', 'z' => 2 })
  131. end
  132. def test_set
  133. assert_filter(
  134. { 'x' => 'z' },
  135. [ { 'field' => 'x', 'set' => 'z' } ],
  136. { 'x' => 'y' })
  137. assert_filter(
  138. { 'x' => 'z' },
  139. [ { 'field' => 'x', 'set' => 'z' } ],
  140. {})
  141. assert_filter(
  142. { 'x' => 'z' },
  143. [ { 'field' => '/.+/', 'set' => 'z' } ],
  144. { 'x' => 'y' })
  145. assert_filter(
  146. {},
  147. [ { 'field' => '/.+/', 'set' => 'z' } ],
  148. {})
  149. end
  150. def test_set_multiple_fields
  151. assert_filter(
  152. { 'x' => 'A', 'y' => 'A', 'z' => 'A' },
  153. [ { 'field' => 'x,y,z', 'set' => 'A' } ],
  154. {})
  155. assert_filter(
  156. { 'x' => 'A', 'y' => 'A', 'z' => 'A' },
  157. [ { 'fields' => %w[ x y z ], 'set' => 'A' } ],
  158. {})
  159. end
  160. def test_copy
  161. assert_filter(
  162. { 'x' => 'y', 'z' => 'y' },
  163. [ { 'field' => 'x', 'copy_to' => 'z' } ],
  164. { 'x' => 'y' })
  165. assert_filter(
  166. { 'x' => 'y', 'z' => 'y' },
  167. [ { 'field' => 'z', 'copy_from' => 'x' } ],
  168. { 'x' => 'y' })
  169. end
  170. def test_copy_and_regex
  171. assert_filter(
  172. { 'a' => %w[ x y ], 'b0' => 'x', 'b1' => 'y' },
  173. [ { 'field' => '/a\.(.+)/', 'copy_to' => 'b\1' } ],
  174. { 'a' => %w[ x y ]})
  175. assert_filter(
  176. { 'a' => %w[ x y ], 'b0' => 'x', 'b1' => 'y' },
  177. [ { 'field' => '/a!(.+)/', 'copy_to' => 'b\1' } ],
  178. { 'a' => %w[ x y ]})
  179. assert_filter(
  180. { 'a' => 7, 'c' => 7, 'source' => [ 7 ] },
  181. [ { 'field' => '/^.$/', 'copy_from' => 'source.0' } ],
  182. { 'a' => 'b', 'c' => 'd', 'source' => [ 7 ] })
  183. end
  184. def test_move
  185. assert_filter(
  186. { 'z' => 'y' },
  187. [ { 'field' => 'x', 'move_to' => 'z' } ],
  188. { 'x' => 'y' })
  189. assert_filter(
  190. { 'z' => 'y' },
  191. [ { 'field' => 'z', 'move_from' => 'x' } ],
  192. { 'x' => 'y' })
  193. end
  194. def test_move_and_regex
  195. assert_filter(
  196. { 'Z' => 'a' },
  197. [ { 'field' => '/.+/', 'move_to' => 'Z' } ],
  198. { 'x' => 'y', 'z' => 'a' })
  199. assert_filter(
  200. { 'prefix_x' => 'y', 'prefix_z' => 'a' },
  201. [ { 'field' => '/(.+)/', 'move_to' => 'prefix_\1' } ],
  202. { 'x' => 'y', 'z' => 'a' })
  203. assert_filter(
  204. { 'h0' => {}, 'h1' => { 'a' => 'b', 'c' => 'd' } },
  205. [ { 'field' => '/^h0!(.+)/', 'move_to' => 'h1.\1' } ],
  206. { 'h0' => { 'a' => 'b', 'c' => 'd' }, 'h1' => {} })
  207. end
  208. def test_merge_from
  209. assert_filter(
  210. { 'x' => { 'a' => 'A', 'b' => 2, 'c' => 'C' }, 'y' => { 'a' => 'A', 'c' => 'C' } },
  211. [ { 'field' => 'x', 'merge_from' => 'y' } ],
  212. { 'x' => { 'a' => 1, 'b' => 2 }, 'y' => { 'a' => 'A', 'c' => 'C' } })
  213. end
  214. def test_merge_to
  215. assert_filter(
  216. { 'x' => { 'a' => 1, 'b' => 2 }, 'y' => { 'a' => 1, 'b' => 2, 'c' => 'C' } },
  217. [ { 'field' => 'x', 'merge_to' => 'y' } ],
  218. { 'x' => { 'a' => 1, 'b' => 2 }, 'y' => { 'a' => 'A', 'c' => 'C' } })
  219. assert_filter(
  220. { 'x' => { 'a' => 1, 'b' => 2 }, 'y' => 2 },
  221. [ { 'field' => 'x', 'mg_to' => 'y' } ],
  222. { 'x' => { 'a' => 1, 'b' => 2 }, 'y' => 2 })
  223. end
  224. def test_merge_to__non_hash
  225. assert_filter(
  226. { 'x' => { 'a' => 1, 'y' => 2 }, 'y' => 2 },
  227. [ { 'field' => 'y', 'mg_to' => 'x' } ],
  228. { 'x' => { 'a' => 1 }, 'y' => 2 })
  229. assert_filter(
  230. { 'x' => { 'a' => 1 }, 'y' => 2 },
  231. [ { 'field' => 'x', 'mg_to' => 'y' } ],
  232. { 'x' => { 'a' => 1 }, 'y' => 2 })
  233. end
  234. def test_merge_to__array # push too
  235. assert_filter(
  236. { 'x' => [ 'a', 'b', 2 ], 'y' => 2 },
  237. [ { 'field' => 'y', 'mg_to' => 'x' } ],
  238. { 'x' => [ 'a', 'b' ], 'y' => 2 })
  239. assert_filter(
  240. { 'x' => [ 'a', 'b', 2 ], 'y' => 2 },
  241. [ { 'field' => 'y', 'push_to' => 'x' } ],
  242. { 'x' => [ 'a', 'b' ], 'y' => 2 })
  243. assert_filter(
  244. { 'x' => [ 'a', 'b', 2 ], 'y' => 2 },
  245. [ { 'field' => 'y', 'pu_to' => 'x' } ],
  246. { 'x' => [ 'a', 'b' ], 'y' => 2 })
  247. end
  248. def test_merge_from__non_hash
  249. assert_filter(
  250. { 'x' => { 'a' => 1, 'y' => 2 }, 'y' => 2 },
  251. [ { 'field' => 'x', 'merge_from' => 'y' } ],
  252. { 'x' => { 'a' => 1 }, 'y' => 2 })
  253. end
  254. def test_merge_from__array
  255. assert_filter(
  256. { 'x' => [ 'a', 'b', 2 ], 'y' => 2 },
  257. [ { 'field' => 'x', 'merge_from' => 'y' } ],
  258. { 'x' => [ 'a', 'b' ], 'y' => 2 })
  259. assert_filter(
  260. { 'x' => [ 'a', 'b', 2 ], 'y' => 2 },
  261. [ { 'field' => 'x', 'push_from' => 'y' } ],
  262. { 'x' => [ 'a', 'b' ], 'y' => 2 })
  263. assert_filter(
  264. { 'x' => [ 'a', 'b', 2 ], 'y' => 2 },
  265. [ { 'field' => 'x', 'pu_from' => 'y' } ],
  266. { 'x' => [ 'a', 'b' ], 'y' => 2 })
  267. end
  268. def test_merge_dot
  269. assert_filter(
  270. { 'x' => { 'a' => 1, 'b' => 2 }, 'a' => 1, 'b' => 2 },
  271. [ { 'field' => 'x', 'merge_to' => '.' } ],
  272. { 'x' => { 'a' => 1, 'b' => 2 } })
  273. assert_filter(
  274. { 'x' => { 'a' => 1, 'b' => 2, 'x' => { 'a' => 1, 'b' => 2 } } },
  275. [ { 'field' => 'x', 'merge_from' => '.' } ],
  276. { 'x' => { 'a' => 1, 'b' => 2 } })
  277. end
  278. def test_migrate
  279. assert_filter(
  280. { 'x' => { 'a' => 'A', 'b' => 2, 'c' => 'C' } },
  281. [ { 'field' => 'x', 'migrate_from' => 'y' } ],
  282. { 'x' => { 'a' => 1, 'b' => 2 }, 'y' => { 'a' => 'A', 'c' => 'C' } })
  283. assert_filter(
  284. { 'y' => { 'a' => 1, 'b' => 2, 'c' => 'C' } },
  285. [ { 'field' => 'x', 'migrate_to' => 'y' } ],
  286. { 'x' => { 'a' => 1, 'b' => 2 }, 'y' => { 'a' => 'A', 'c' => 'C' } })
  287. assert_filter(
  288. { 'x' => { 'a' => 1, 'b' => 2 }, 'y' => 2 },
  289. [ { 'field' => 'x', 'migrate_to' => 'y' } ],
  290. { 'x' => { 'a' => 1, 'b' => 2 }, 'y' => 2 })
  291. end
  292. def test_migrate_dot
  293. assert_filter(
  294. { 'a' => 1, 'b' => 2 },
  295. [ { 'field' => 'x', 'mi_to' => '.' } ],
  296. { 'x' => { 'a' => 1, 'b' => 2 } })
  297. assert_filter(
  298. { 'x' => { 'a' => 1, 'b' => 2, 'x' => { 'a' => 1, 'b' => 2 } } },
  299. [ { 'field' => 'x', 'mi_from' => '.' } ],
  300. { 'x' => { 'a' => 1, 'b' => 2 } })
  301. end
  302. def test_tilde
  303. assert_filter(
  304. { 'x' => 'a', 'y' => 'a' },
  305. [ { 'field' => 'x', 'set' => 'b' },
  306. { 'field' => 'x', 'copy_from' => '~.x' },
  307. { 'field' => 'y', 'copy_from' => '~.x' } ],
  308. { 'x' => 'a' })
  309. end
  310. def test_tilde_restoring
  311. assert_filter(
  312. { 'private_x' => 'a' },
  313. [ { 'field' => '/^private_/', 'del' => true },
  314. { 'field' => '/^~~.private_/', 'merge_to' => '.' } ],
  315. { 'private_x' => 'a' })
  316. end
  317. def test_restore
  318. assert_filter(
  319. { 'x' => 'a', 'y' => 'a' },
  320. [ { 'field' => 'x', 'set' => 'X' },
  321. { 'field' => 'y', 'set' => 'Y' },
  322. { 'field' => '/^.$/', 'restore' => true } ],
  323. { 'x' => 'a', 'y' => 'a' })
  324. end
  325. def test_restore_with_a_given_prefix
  326. assert_filter(
  327. { 'x' => 'a', 'y' => 'a' },
  328. [ { 'field' => 'A', 'set' => {} },
  329. { 'field' => '.', 'merge_to' => 'A' },
  330. { 'field' => 'x', 'set' => 'X' },
  331. { 'field' => 'y', 'set' => 'Y' },
  332. { 'field' => '/^[a-z]$/', 'restore_from' => 'A' },
  333. { 'field' => 'A', 'delete' => true } ],
  334. { 'x' => 'a', 'y' => 'a' })
  335. end
  336. def test_really_restore
  337. assert_filter(
  338. { 'x' => 'a', 'y' => 'a', 'z' => 'good' },
  339. [ { 'field' => '/./', 'del' => true },
  340. { 'field' => 'y', 'set' => 'bad' },
  341. { 'field' => 'z', 'set' => 'good' },
  342. { 'field' => '/./', 'restore' => true } ],
  343. { 'x' => 'a', 'y' => 'a' })
  344. end
  345. def test_cumulation_or
  346. assert_filter(
  347. { 'x' => { 'a' => 2 } },
  348. [ { 'field' => 'x', 't' => 'hash', 'has' => 'a', 'or' => { 'a' => 2 } } ],
  349. { 'x' => %w[ a b c ] })
  350. end
  351. def test_take
  352. assert_filter(
  353. { 'x' => 'a', 'z' => 'b' },
  354. [ { 'field' => 'x', 'take' => 'true' } ],
  355. { 'x' => 'a', 'y' => 'a' },
  356. { 'z' => 'b' }) # ~~
  357. end
  358. def test_discard
  359. assert_filter(
  360. { 'y' => 'a', 'z' => 'b' },
  361. [ { 'field' => 'x', 'discard' => 'true' } ],
  362. { 'x' => 'a', 'y' => 'a' },
  363. { 'z' => 'b' }) # ~~
  364. end
  365. def test_discard_multiple
  366. assert_filter(
  367. { 'z' => 'a', '1' => 'b' },
  368. [ { 'field' => 'x|y', 'discard' => 'true' } ],
  369. { 'x' => 'a', 'y' => 'a', 'z' => 'a' },
  370. { '1' => 'b' }) # ~~
  371. end
  372. #
  373. # validations
  374. def assert_valid(filter, hash)
  375. begin
  376. Ruote.filter(Rufus::Json.dup(filter), hash)
  377. assert true
  378. rescue Ruote::ValidationError => ve
  379. puts
  380. puts
  381. p ve
  382. p ve.deviations
  383. puts
  384. puts 'hash:'
  385. p hash
  386. puts 'filter:'
  387. filter.each { |l| p l }
  388. puts
  389. assert false
  390. end
  391. end
  392. def assert_not_valid(filter, hash, opts={ :deviations => 1 })
  393. error = nil
  394. begin
  395. Ruote.filter(Rufus::Json.dup(filter), hash)
  396. rescue => error
  397. end
  398. p error.deviations if opts[:verbose]
  399. assert_not_nil(
  400. error, "ValidationError was not raised")
  401. assert_equal(
  402. opts[:deviations], error.deviations.size, "deviation count doesn't match")
  403. @deviations = error.deviations
  404. end
  405. def test_presence
  406. assert_valid(
  407. [ { 'field' => 'x' } ], { 'x' => 'deux' })
  408. assert_not_valid(
  409. [ { 'field' => 'x' } ], { 'y' => 'trois' })
  410. assert_valid(
  411. [ { 'field' => '/x|y/' } ], { 'x' => 'deux' })
  412. assert_not_valid(
  413. [ { 'field' => '/x|y/' } ], { 'z' => 'quatre' })
  414. end
  415. def test_this_or_that_field
  416. assert_valid(
  417. [ { 'field' => 'x|y', 'type' => 'string' } ], { 'x' => 'deux' })
  418. assert_valid(
  419. [ { 'field' => 'x|y', 'type' => 'string' } ], { 'y' => 'trois' })
  420. assert_valid(
  421. [ { 'field' => 'x|y'} ], { 'x' => 'deux' })
  422. assert_not_valid(
  423. [ { 'field' => 'x|y', 'type' => 'string' } ], { 'z' => 'quatre' })
  424. assert_not_valid(
  425. [ { 'field' => 'x|y' } ], { 'z' => 'quatre' })
  426. end
  427. def test_type
  428. assert_valid(
  429. [ { 'field' => 'x', 'type' => 'string' } ], { 'x' => 'deux' })
  430. assert_valid(
  431. [ { 'field' => 'x', 'type' => 'number' } ], { 'x' => 1 })
  432. assert_valid(
  433. [ { 'field' => 'x', 'type' => 'number' } ], { 'x' => 1.0 })
  434. assert_valid(
  435. [ { 'field' => 'x', 'type' => 'object' } ], { 'x' => {} })
  436. assert_valid(
  437. [ { 'field' => 'x', 'type' => 'hash' } ], { 'x' => {} })
  438. assert_valid(
  439. [ { 'field' => 'x', 'type' => 'array' } ], { 'x' => [] })
  440. assert_valid(
  441. [ { 'field' => 'x', 'type' => 'boolean' } ], { 'x' => true })
  442. assert_valid(
  443. [ { 'field' => 'x', 'type' => 'boolean' } ], { 'x' => false })
  444. assert_valid(
  445. [ { 'field' => 'x', 'type' => 'bool' } ], { 'x' => true })
  446. assert_valid(
  447. [ { 'field' => 'x', 'type' => 'bool' } ], { 'x' => false })
  448. assert_valid(
  449. [ { 'field' => 'x', 'type' => 'null' } ], { 'x' => nil })
  450. assert_valid(
  451. [ { 'field' => 'x', 'type' => 'null' } ], {})
  452. assert_valid(
  453. [ { 'field' => 'x', 'type' => 'nil' } ], {})
  454. assert_not_valid(
  455. [ { 'field' => 'x', 'type' => 'string' } ], { 'x' => 2 })
  456. assert_not_valid(
  457. [ { 'field' => 'x', 'type' => 'number' } ], { 'x' => 'one' })
  458. assert_not_valid(
  459. [ { 'field' => 'x', 'type' => 'number' } ], { 'x' => '1.0' })
  460. assert_not_valid(
  461. [ { 'field' => 'x', 'type' => 'object' } ], { 'x' => [] })
  462. assert_not_valid(
  463. [ { 'field' => 'x', 'type' => 'hash' } ], { 'x' => [] })
  464. assert_not_valid(
  465. [ { 'field' => 'x', 'type' => 'array' } ], { 'x' => {} })
  466. assert_not_valid(
  467. [ { 'field' => 'x', 'type' => 'boolean' } ], { 'x' => 'true' })
  468. assert_not_valid(
  469. [ { 'field' => 'x', 'type' => 'boolean' } ], { 'x' => 'false' })
  470. assert_not_valid(
  471. [ { 'field' => 'x', 'type' => 'bool' } ], { 'x' => 'true' })
  472. assert_not_valid(
  473. [ { 'field' => 'x', 'type' => 'bool' } ], { 'x' => 'true' })
  474. assert_not_valid(
  475. [ { 'field' => 'x', 'type' => 'null' } ], { 'x' => false })
  476. assert_not_valid(
  477. [ { 'field' => 'x', 'type' => 'null' } ], { 'x' => 1 })
  478. assert_not_valid(
  479. [ { 'field' => 'x', 'type' => 'string' } ], {})
  480. end
  481. def test_type_deep
  482. assert_valid(
  483. [ { 'field' => 'x.y', 'type' => 'string' } ], { 'x' => { 'y' => 'z' } })
  484. assert_not_valid(
  485. [ { 'field' => 'x.y', 'type' => 'string' } ], { 'x' => { 'y' => 1 } })
  486. end
  487. def test_type_union
  488. assert_valid(
  489. [ { 'field' => 'x', 'type' => 'string,number' } ], { 'x' => 'a' })
  490. assert_valid(
  491. [ { 'field' => 'x', 'type' => 'string,number' } ], { 'x' => 1 })
  492. assert_valid(
  493. [ { 'field' => 'x', 'type' => [ 'string', 'number' ] } ], { 'x' => 'a' })
  494. assert_valid(
  495. [ { 'field' => 'x', 'type' => [ 'string', 'number' ] } ], { 'x' => 1 })
  496. end
  497. def test_type_and_null
  498. assert_valid(
  499. [ { 'field' => 'x', 'type' => 'string,null' } ], {})
  500. assert_valid(
  501. [ { 'field' => 'x', 'type' => 'string,null' } ], { 'x' => nil })
  502. assert_valid(
  503. [ { 'field' => 'x', 'type' => 'string,null' } ], { 'x' => 'x' })
  504. end
  505. def test_type_array
  506. assert_valid(
  507. [ { 'field' => 'x', 'type' => 'array<string>' } ],
  508. { 'x' => %w[ a b c ] })
  509. assert_valid(
  510. [ { 'field' => 'x', 'type' => 'array<string,number>' } ],
  511. { 'x' => [ 'a', 1 ] })
  512. assert_not_valid(
  513. [ { 'field' => 'x', 'type' => 'array<string>' } ],
  514. { 'x' => [ 'a', 1 ] })
  515. assert_not_valid(
  516. [ { 'field' => 'x', 'type' => 'array<string,number>' } ],
  517. { 'x' => [ 'a', true ] })
  518. end
  519. def test_type_array_deep
  520. assert_valid(
  521. [ { 'field' => 'x', 'type' => 'array<array<string>>' } ],
  522. { 'x' => [ %w[ a b ], %w[ c d ] ] })
  523. assert_not_valid(
  524. [ { 'field' => 'x', 'type' => 'array<array<string>>' } ],
  525. { 'x' => [ %w[ a b ], [ 2, 3 ] ] })
  526. end
  527. def test_type_hash
  528. assert_valid(
  529. [ { 'field' => 'x', 'type' => 'hash<string>' } ],
  530. { 'x' => { 'a' => 'b', 'c' => 'd' } })
  531. assert_valid(
  532. [ { 'field' => 'x', 'type' => 'hash<string,number>' } ],
  533. { 'x' => { 'a' => 'b', 'c' => 0 } })
  534. assert_not_valid(
  535. [ { 'field' => 'x', 'type' => 'hash<string>' } ],
  536. { 'x' => { 'a' => 'b', 'c' => 0 } })
  537. assert_not_valid(
  538. [ { 'field' => 'x', 'type' => 'hash<string,number>' } ],
  539. { 'x' => { 'a' => 'b', 'c' => true } })
  540. end
  541. def test_type_and_regex
  542. assert_valid(
  543. [ { 'field' => '/./', 'type' => 'string' } ],
  544. { 'x' => 'y', 'z' => 'a' })
  545. assert_not_valid(
  546. [ { 'field' => '/./', 'type' => 'string' } ],
  547. { 'x' => 'y', 'z' => 1 })
  548. assert_not_valid(
  549. [ { 'field' => '/./', 'type' => 'string' } ],
  550. { 'x' => 1, 'z' => 1 },
  551. :deviations => 2)
  552. end
  553. def test_match
  554. assert_valid(
  555. [ { 'field' => 'x', 'match' => 'to' } ],
  556. { 'x' => 'toto' })
  557. assert_valid(
  558. [ { 'field' => 'x', 'match' => '1' } ],
  559. { 'x' => 1.0 })
  560. assert_not_valid(
  561. [ { 'field' => 'x', 'match' => 'to' } ],
  562. { 'x' => 'tutu' })
  563. assert_not_valid(
  564. [ { 'field' => 'x', 'match' => '1' } ],
  565. { 'x' => 2.0 })
  566. end
  567. def test_smatch
  568. assert_valid(
  569. [ { 'field' => 'x', 'smatch' => 'to' } ],
  570. { 'x' => 'toto' })
  571. assert_not_valid(
  572. [ { 'field' => 'x', 'smatch' => '1' } ],
  573. { 'x' => 1.0 })
  574. assert_not_valid(
  575. [ { 'field' => 'x', 'smatch' => 'to' } ],
  576. { 'x' => 'tutu' })
  577. assert_not_valid(
  578. [ { 'field' => 'x', 'smatch' => '1' } ],
  579. { 'x' => 2.0 })
  580. end
  581. def test_is
  582. assert_valid(
  583. [ { 'field' => 'x', 'is' => true } ],
  584. { 'x' => true })
  585. assert_valid(
  586. [ { 'field' => 'x', 'is' => (1..3).to_a } ],
  587. { 'x' => [ 1, 2, 3 ] })
  588. assert_not_valid(
  589. [ { 'field' => 'x', 'is' => false } ],
  590. { 'x' => true })
  591. assert_not_valid(
  592. [ { 'field' => 'x', 'is' => true } ],
  593. { 'x' => 1 })
  594. assert_not_valid(
  595. [ { 'field' => 'x', 'is' => (1..3).to_a } ],
  596. { 'x' => [ 3, 2, 1 ] })
  597. end
  598. def test_size
  599. assert_valid(
  600. [ { 'field' => 'x', 'size' => 4 } ],
  601. { 'x' => 'toto' })
  602. assert_valid(
  603. [ { 'field' => 'x', 'size' => '4' } ],
  604. { 'x' => 'toto' })
  605. assert_valid(
  606. [ { 'field' => 'x', 'size' => 4 } ],
  607. { 'x' => %w[ a b c d ] })
  608. assert_valid(
  609. [ { 'field' => 'x', 'size' => 2 } ],
  610. { 'x' => { 'a' => 'b', 'c' => 'd' } })
  611. assert_not_valid(
  612. [ { 'field' => 'x', 'size' => 2 } ],
  613. {})
  614. assert_not_valid(
  615. [ { 'field' => 'x', 'size' => 2 } ],
  616. { 'x' => 3 })
  617. end
  618. def test_size_range
  619. assert_valid(
  620. [ { 'field' => 'x', 'size' => [ 2, 3 ] } ],
  621. { 'x' => %w[ a b ] })
  622. assert_valid(
  623. [ { 'field' => 'x', 'size' => [ 2, 3 ] } ],
  624. { 'x' => %w[ a b c ] })
  625. assert_not_valid(
  626. [ { 'field' => 'x', 'size' => [ 2, 3 ] } ],
  627. { 'x' => %w[ a ] })
  628. assert_not_valid(
  629. [ { 'field' => 'x', 'size' => [ 2, 3 ] } ],
  630. { 'x' => %w[ a b c d ] })
  631. end
  632. def test_size_open_range
  633. assert_valid(
  634. [ { 'field' => 'x', 'size' => [ 2 ] } ],
  635. { 'x' => %w[ a b ] })
  636. assert_valid(
  637. [ { 'field' => 'x', 'size' => [ 2, nil ] } ],
  638. { 'x' => %w[ a b ] })
  639. assert_valid(
  640. [ { 'field' => 'x', 'size' => ",3" } ],
  641. { 'x' => %w[ a b c ] })
  642. assert_not_valid(
  643. [ { 'field' => 'x', 'size' => "2," } ],
  644. { 'x' => %w[ a ] })
  645. assert_not_valid(
  646. [ { 'field' => 'x', 'size' => [ nil, 3 ] } ],
  647. { 'x' => %w[ a b c d ] })
  648. end
  649. def test_empty
  650. assert_valid(
  651. [ { 'field' => 'x', 'empty' => true } ],
  652. { 'x' => %w[] })
  653. assert_valid(
  654. [ { 'field' => 'x', 'empty' => true } ],
  655. { 'x' => {} })
  656. assert_valid(
  657. [ { 'field' => 'x', 'empty' => true } ],
  658. { 'x' => '' })
  659. assert_valid(
  660. [ { 'field' => 'x', 'empty' => false } ],
  661. { 'x' => [ 1 ] })
  662. assert_not_valid(
  663. [ { 'field' => 'x', 'empty' => true } ],
  664. { 'x' => 'deux' })
  665. assert_not_valid(
  666. [ { 'field' => 'x', 'empty' => true } ],
  667. { 'x' => %w[ a b ] })
  668. assert_not_valid(
  669. [ { 'field' => 'x', 'empty' => true } ],
  670. { 'x' => { 'a' => 'b' } })
  671. assert_not_valid(
  672. [ { 'field' => 'x', 'empty' => false } ],
  673. { 'x' => {} })
  674. end
  675. def test_string_and_empty
  676. assert_valid(
  677. [ { 'field' => 'x', 'empty' => true, 'type' => 'string' } ],
  678. { 'x' => '' })
  679. assert_valid(
  680. [ { 'field' => 'x', 'empty' => false, 'type' => 'string' } ],
  681. { 'x' => 'yyy' })
  682. assert_not_valid(
  683. [ { 'field' => 'x', 'empty' => true, 'type' => 'string' } ],
  684. { 'x' => {} })
  685. end
  686. def test_in
  687. assert_valid(
  688. [ { 'field' => 'x', 'in' => %w[ alpha bravo ] } ],
  689. { 'x' => 'alpha' })
  690. assert_valid(
  691. [ { 'field' => 'x', 'in' => "alpha, bravo" } ],
  692. { 'x' => 'alpha' })
  693. assert_valid(
  694. [ { 'field' => 'x', 'in' => [ true ] } ],
  695. { 'x' => true })
  696. assert_not_valid(
  697. [ { 'field' => 'x', 'in' => %w[ alpha bravo ] } ],
  698. { 'x' => 'charly' })
  699. assert_not_valid(
  700. [ { 'field' => 'x', 'in' => "alpha, bravo" } ],
  701. { 'x' => 'charly' })
  702. assert_not_valid(
  703. [ { 'field' => 'x', 'in' => [ false ] } ],
  704. { 'x' => true })
  705. end
  706. def test_has__keys
  707. assert_valid(
  708. [ { 'field' => '.', 'has' => 'x' } ],
  709. { 'x' => 'alpha' })
  710. assert_valid(
  711. [ { 'field' => 'x', 'has' => 'a' } ],
  712. { 'x' => { 'a' => 1 } })
  713. assert_valid(
  714. [ { 'field' => 'x', 'has' => 'a, b' } ],
  715. { 'x' => { 'a' => 1, 'b' => 2 } })
  716. assert_valid(
  717. [ { 'field' => 'x', 'has' => %w[ a b ] } ],
  718. { 'x' => { 'a' => 1, 'b' => 2 } })
  719. assert_not_valid(
  720. [ { 'field' => '.', 'has' => 'x' } ],
  721. {})
  722. assert_not_valid(
  723. [ { 'field' => 'x', 'has' => 'b' } ],
  724. { 'x' => { 'a' => 1 } })
  725. assert_not_valid(
  726. [ { 'field' => 'x', 'has' => 'a, c' } ],
  727. { 'x' => { 'a' => 1, 'b' => 2 } })
  728. assert_not_valid(
  729. [ { 'field' => 'x', 'has' => %w[ a c ] } ],
  730. { 'x' => { 'a' => 1, 'b' => 2 } })
  731. end
  732. def test_has__elts
  733. assert_valid(
  734. [ { 'field' => 'x', 'has' => 'a' } ],
  735. { 'x' => %w[ a b c ] })
  736. assert_valid(
  737. [ { 'field' => 'x', 'has' => 'a, b' } ],
  738. { 'x' => %w[ a b c ] })
  739. assert_valid(
  740. [ { 'field' => 'x', 'has' => %w[ a b ] } ],
  741. { 'x' => %w[ a b c ] })
  742. assert_not_valid(
  743. [ { 'field' => 'x', 'has' => 'd' } ],
  744. { 'x' => %w[ a b c ] })
  745. assert_not_valid(
  746. [ { 'field' => 'x', 'has' => 'a, d' } ],
  747. { 'x' => %w[ a b c ] })
  748. assert_not_valid(
  749. [ { 'field' => 'x', 'has' => %w[ a d ] } ],
  750. { 'x' => %w[ a b c ] })
  751. end
  752. def test_includes
  753. assert_valid(
  754. [ { 'field' => 'x', 'includes' => 'a' } ],
  755. { 'x' => %w[ a b c ] })
  756. assert_not_valid(
  757. [ { 'field' => 'x', 'includes' => 'z' } ],
  758. { 'x' => %w[ a b c ] })
  759. assert_not_valid(
  760. [ { 'field' => 'x', 'includes' => 'z' } ],
  761. { 'x' => 'abcz' })
  762. end
  763. def test_includes__value
  764. assert_valid(
  765. [ { 'field' => 'x', 'includes' => 1 } ],
  766. { 'x' => { 'a' => 1 } })
  767. assert_not_valid(
  768. [ { 'field' => 'x', 'includes' => '1' } ],
  769. { 'x' => { 'a' => 1 } })
  770. end
  771. def test_valid
  772. # 'valid' can be used in conjunction with the dollar notation
  773. #
  774. # field => 'x', 'valid' => '${v:accept}'
  775. assert_valid(
  776. [ { 'field' => 'x', 'valid' => true } ],
  777. {})
  778. assert_valid(
  779. [ { 'field' => 'x', 'valid' => 'true' } ],
  780. {})
  781. assert_not_valid(
  782. [ { 'field' => 'x', 'valid' => false } ],
  783. {})
  784. assert_not_valid(
  785. [ { 'field' => 'x', 'valid' => 'false' } ],
  786. {})
  787. assert_not_valid(
  788. [ { 'field' => 'x', 'valid' => 'nada' } ],
  789. {})
  790. end
  791. def test_cumulation
  792. assert_valid(
  793. [ { 'field' => 'x', 't' => 'array', 'has' => 'a' } ],
  794. { 'x' => %w[ a b c ] })
  795. assert_not_valid(
  796. [ { 'field' => 'x', 't' => 'hash', 'has' => 'a' } ],
  797. { 'x' => %w[ a b c ] })
  798. end
  799. def test_multiple_validations
  800. assert_not_valid(
  801. [
  802. { 'field' => 'x', 't' => 'array', 'has' => 1 },
  803. { 'field' => 'y', 't' => 'string' }
  804. ],
  805. {
  806. 'x' => %w[ a b c ],
  807. 'y' => true
  808. },
  809. :deviations => 2)
  810. assert_equal [
  811. [ { "has" => 1, "field" => "x", "t" => "array"}, "x", [ "a", "b", "c" ] ],
  812. [ { "field" => "y", "t" => "string" }, "y", true ]
  813. ], @deviations
  814. # not super happy with this @breaks thing
  815. end
  816. # when :no_raise => true and the validation fails, an array is returned
  817. # listing the 'deviations'
  818. #
  819. def test_no_raise
  820. r = Ruote.filter(
  821. [ { 'field' => 'x', 't' => 'hash', 'has' => 'a' } ],
  822. { 'x' => %w[ a b c ] },
  823. :no_raise => true)
  824. assert_equal(
  825. [ [ { "has" => "a", "field" => "x", "t" => "hash"}, "x", [ "a", "b", "c" ] ] ],
  826. r)
  827. end
  828. # Data passes through the filter untouched.
  829. #
  830. def test_no_raise_empty_result
  831. r = Ruote.filter(
  832. [ { 'field' => 'x', 't' => 'array', 'has' => 'a' } ],
  833. { 'x' => %w[ a b c ] },
  834. :no_raise => true)
  835. assert_equal(
  836. { 'x' => %w[ a b c ] },
  837. r)
  838. end
  839. #
  840. # flatten_keys tests
  841. def test_flatten_keys
  842. assert_equal(
  843. [
  844. 'a',
  845. 'c',
  846. 'c.d',
  847. 'c.f',
  848. 'c.f.l',
  849. 'c.f.n',
  850. 'c.f.n.0',
  851. 'c.f.n.1',
  852. 'c.f.n.2',
  853. 'c.g',
  854. 'c.g.0',
  855. 'c.g.0.i',
  856. 'c.g.1',
  857. 'h',
  858. 'h.0',
  859. 'h.1',
  860. 'h.2'
  861. ],
  862. Ruote.flatten_keys({
  863. 'a' => 'b',
  864. 'c' => {
  865. 'd' => 'e',
  866. 'f' => {
  867. 'l' => 'm',
  868. 'n' => [ 1, 2, 3 ]
  869. },
  870. 'g' => [
  871. { 'i' => 'j' },
  872. 'k'
  873. ]
  874. },
  875. 'h' => [
  876. 1, 2, 3
  877. ]
  878. }))
  879. end
  880. def test_top_level_or
  881. filter = [
  882. { 'field' => 'x', 'type' => 'string' },
  883. { 'field' => 'y', 'type' => 'number' },
  884. 'or',
  885. { 'field' => 'z', 'type' => 'bool' }
  886. ]
  887. assert_valid(filter, { 'x' => 'whatever', 'y' => 1 })
  888. assert_valid(filter, { 'z' => true })
  889. assert_valid(filter, { 'x' => -9, 'z' => false })
  890. assert_valid(filter, { 'x' => 'ah', 'y' => 2 })
  891. assert_not_valid(filter, { 'x' => 'whatever', 'y' => 'notanumber' })
  892. assert_not_valid(filter, { 'z' => 'notabool' })
  893. assert_not_valid(filter, { 'x' => 'x', 'z' => 'nada' })
  894. filter = [
  895. [ { 'field' => 'x', 'type' => 'string' },
  896. { 'field' => 'y', 'type' => 'number' } ],
  897. [ { 'field' => 'z', 'type' => 'bool' } ]
  898. ]
  899. assert_valid(filter, { 'x' => 'whatever', 'y' => 1 })
  900. assert_valid(filter, { 'z' => true })
  901. assert_valid(filter, { 'x' => -9, 'z' => false })
  902. assert_valid(filter, { 'x' => 'ah', 'y' => 2 })
  903. end
  904. def test_top_level_or_and_pipe_field
  905. filter = [
  906. { 'field' => 'x|params.x', 'type' => 'string' },
  907. 'or',
  908. { 'field' => 'y|params.y', 'type' => 'bool' }
  909. ]
  910. assert_valid(filter, { 'x' => 'out' })
  911. assert_valid(filter, { 'params' => { 'x' => 'in' } })
  912. assert_valid(filter, { 'y' => true })
  913. assert_valid(filter, { 'params' => { 'y' => false } })
  914. assert_not_valid(filter, { 'y' => 'out' })
  915. assert_not_valid(filter, { 'params' => { 'y' => 'in' } })
  916. assert_not_valid(filter, {})
  917. end
  918. def test_misc_neutralization
  919. assert_valid(
  920. [ { :field => 'x', :type => :string } ], { 'x' => 'deux' })
  921. assert_valid(
  922. [ { :field => 'x', 'smatch' => /de/ } ], { 'x' => 'deux' })
  923. end
  924. end