unpoly-rails 0.62.1 → 2.0.0.pre.rc6

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of unpoly-rails might be problematic. Click here for more details.

Files changed (340) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/CHANGELOG.md +60 -1
  4. data/README.md +3 -11
  5. data/README_RAILS.md +295 -14
  6. data/dist/unpoly-bootstrap3.css +9 -14
  7. data/dist/unpoly-bootstrap3.js +4 -18
  8. data/dist/unpoly-bootstrap3.min.css +1 -1
  9. data/dist/unpoly-bootstrap3.min.js +1 -1
  10. data/dist/unpoly-bootstrap4.css +9 -0
  11. data/dist/unpoly-bootstrap4.js +16 -0
  12. data/dist/unpoly-bootstrap4.min.css +1 -0
  13. data/dist/unpoly-bootstrap4.min.js +1 -0
  14. data/dist/unpoly-bootstrap5.css +9 -0
  15. data/dist/unpoly-bootstrap5.js +14 -0
  16. data/dist/unpoly-bootstrap5.min.css +1 -0
  17. data/dist/unpoly-bootstrap5.min.js +1 -0
  18. data/dist/unpoly-migrate.js +1225 -0
  19. data/dist/unpoly-migrate.min.js +1 -0
  20. data/dist/unpoly.css +109 -140
  21. data/dist/unpoly.js +15805 -10558
  22. data/dist/unpoly.min.css +1 -1
  23. data/dist/unpoly.min.js +6 -4
  24. data/lib/unpoly-rails.rb +9 -3
  25. data/lib/unpoly/rails/change.rb +372 -0
  26. data/lib/unpoly/rails/change/cache.rb +26 -0
  27. data/lib/unpoly/rails/change/context.rb +80 -0
  28. data/lib/unpoly/rails/change/field.rb +117 -0
  29. data/lib/unpoly/rails/change/field_definition.rb +74 -0
  30. data/lib/unpoly/rails/change/layer.rb +60 -0
  31. data/lib/unpoly/rails/controller.rb +47 -0
  32. data/lib/unpoly/rails/error.rb +5 -0
  33. data/lib/unpoly/rails/request_echo_headers.rb +2 -2
  34. data/lib/unpoly/rails/version.rb +1 -1
  35. data/lib/unpoly/tasks.rb +55 -0
  36. metadata +43 -313
  37. data/.gitignore +0 -10
  38. data/.ruby-version +0 -1
  39. data/Gemfile +0 -8
  40. data/Gemfile.lock +0 -45
  41. data/Rakefile +0 -145
  42. data/bower.json +0 -27
  43. data/design/animation-ghosting.txt +0 -72
  44. data/design/design.txt +0 -34
  45. data/design/draft.html.erb +0 -48
  46. data/design/draft.rb +0 -9
  47. data/design/es6.js +0 -32
  48. data/design/ghost-debugging.txt +0 -118
  49. data/design/homepage.txt +0 -236
  50. data/design/ie11.txt +0 -9
  51. data/design/measure_import_node.js +0 -330
  52. data/design/measure_jquery/element_list.js +0 -41
  53. data/design/measure_jquery/up.on_vs_addEventListener.js +0 -56
  54. data/design/positioning.txt +0 -28
  55. data/design/query-params-in-form-actions/cases.html +0 -125
  56. data/design/rename.txt +0 -0
  57. data/design/test_rejected_promise.txt +0 -5
  58. data/design/unpoly errors.txt +0 -19
  59. data/lib/assets/javascripts/unpoly-bootstrap3.coffee +0 -2
  60. data/lib/assets/javascripts/unpoly-bootstrap3/feedback-ext.coffee +0 -5
  61. data/lib/assets/javascripts/unpoly-bootstrap3/form-ext.coffee +0 -1
  62. data/lib/assets/javascripts/unpoly-bootstrap3/modal-ext.coffee +0 -14
  63. data/lib/assets/javascripts/unpoly-bootstrap3/viewport-ext.coffee +0 -5
  64. data/lib/assets/javascripts/unpoly.coffee +0 -28
  65. data/lib/assets/javascripts/unpoly/browser.coffee.erb +0 -240
  66. data/lib/assets/javascripts/unpoly/classes/body_shifter.coffee +0 -45
  67. data/lib/assets/javascripts/unpoly/classes/cache.coffee +0 -127
  68. data/lib/assets/javascripts/unpoly/classes/compile_pass.coffee +0 -93
  69. data/lib/assets/javascripts/unpoly/classes/config.coffee +0 -9
  70. data/lib/assets/javascripts/unpoly/classes/css_transition.coffee +0 -118
  71. data/lib/assets/javascripts/unpoly/classes/divertible_chain.coffee +0 -39
  72. data/lib/assets/javascripts/unpoly/classes/event_listener.coffee +0 -116
  73. data/lib/assets/javascripts/unpoly/classes/extract_cascade.coffee +0 -86
  74. data/lib/assets/javascripts/unpoly/classes/extract_plan.coffee +0 -111
  75. data/lib/assets/javascripts/unpoly/classes/field_observer.coffee +0 -80
  76. data/lib/assets/javascripts/unpoly/classes/focus_follower.coffee +0 -29
  77. data/lib/assets/javascripts/unpoly/classes/follow_variant.coffee +0 -64
  78. data/lib/assets/javascripts/unpoly/classes/html_parser.coffee +0 -46
  79. data/lib/assets/javascripts/unpoly/classes/motion_controller.coffee +0 -157
  80. data/lib/assets/javascripts/unpoly/classes/params.coffee.erb +0 -544
  81. data/lib/assets/javascripts/unpoly/classes/record.coffee +0 -22
  82. data/lib/assets/javascripts/unpoly/classes/rect.js +0 -21
  83. data/lib/assets/javascripts/unpoly/classes/request.coffee +0 -246
  84. data/lib/assets/javascripts/unpoly/classes/response.coffee +0 -157
  85. data/lib/assets/javascripts/unpoly/classes/reveal_motion.coffee +0 -102
  86. data/lib/assets/javascripts/unpoly/classes/scroll_motion.coffee +0 -67
  87. data/lib/assets/javascripts/unpoly/classes/selector.coffee +0 -60
  88. data/lib/assets/javascripts/unpoly/classes/store/memory.coffee +0 -26
  89. data/lib/assets/javascripts/unpoly/classes/store/session.coffee +0 -59
  90. data/lib/assets/javascripts/unpoly/classes/tether.coffee +0 -105
  91. data/lib/assets/javascripts/unpoly/classes/url_set.coffee +0 -32
  92. data/lib/assets/javascripts/unpoly/cookie.coffee +0 -56
  93. data/lib/assets/javascripts/unpoly/element.coffee.erb +0 -1126
  94. data/lib/assets/javascripts/unpoly/event.coffee.erb +0 -445
  95. data/lib/assets/javascripts/unpoly/feedback.coffee +0 -353
  96. data/lib/assets/javascripts/unpoly/form.coffee.erb +0 -1075
  97. data/lib/assets/javascripts/unpoly/fragment.coffee.erb +0 -928
  98. data/lib/assets/javascripts/unpoly/framework.coffee +0 -67
  99. data/lib/assets/javascripts/unpoly/history.coffee +0 -268
  100. data/lib/assets/javascripts/unpoly/legacy.coffee +0 -60
  101. data/lib/assets/javascripts/unpoly/link.coffee.erb +0 -622
  102. data/lib/assets/javascripts/unpoly/log.coffee +0 -248
  103. data/lib/assets/javascripts/unpoly/modal.coffee.erb +0 -827
  104. data/lib/assets/javascripts/unpoly/motion.coffee.erb +0 -668
  105. data/lib/assets/javascripts/unpoly/namespace.coffee.erb +0 -5
  106. data/lib/assets/javascripts/unpoly/popup.coffee.erb +0 -515
  107. data/lib/assets/javascripts/unpoly/protocol.coffee +0 -298
  108. data/lib/assets/javascripts/unpoly/proxy.coffee +0 -672
  109. data/lib/assets/javascripts/unpoly/radio.coffee +0 -60
  110. data/lib/assets/javascripts/unpoly/rails.coffee +0 -24
  111. data/lib/assets/javascripts/unpoly/syntax.coffee.erb +0 -476
  112. data/lib/assets/javascripts/unpoly/toast.coffee +0 -67
  113. data/lib/assets/javascripts/unpoly/tooltip.coffee +0 -276
  114. data/lib/assets/javascripts/unpoly/util.coffee.erb +0 -1676
  115. data/lib/assets/javascripts/unpoly/viewport.coffee.erb +0 -830
  116. data/lib/assets/stylesheets/unpoly-bootstrap3.sass +0 -1
  117. data/lib/assets/stylesheets/unpoly-bootstrap3/modal-ext.sass +0 -27
  118. data/lib/assets/stylesheets/unpoly.sass +0 -1
  119. data/lib/assets/stylesheets/unpoly/close.sass +0 -2
  120. data/lib/assets/stylesheets/unpoly/dom.sass +0 -5
  121. data/lib/assets/stylesheets/unpoly/layout.sass +0 -2
  122. data/lib/assets/stylesheets/unpoly/link.sass +0 -2
  123. data/lib/assets/stylesheets/unpoly/modal.sass +0 -116
  124. data/lib/assets/stylesheets/unpoly/popup.sass +0 -7
  125. data/lib/assets/stylesheets/unpoly/toast.sass +0 -33
  126. data/lib/assets/stylesheets/unpoly/tooltip.sass +0 -62
  127. data/lib/unpoly/rails/inspector.rb +0 -149
  128. data/lib/unpoly/rails/inspector_accessor.rb +0 -30
  129. data/package.json +0 -38
  130. data/spec_app/.firefox-version +0 -1
  131. data/spec_app/.gitignore +0 -17
  132. data/spec_app/.rspec +0 -2
  133. data/spec_app/Gemfile +0 -30
  134. data/spec_app/Gemfile.lock +0 -229
  135. data/spec_app/README.rdoc +0 -28
  136. data/spec_app/Rakefile +0 -6
  137. data/spec_app/app/assets/images/.keep +0 -0
  138. data/spec_app/app/assets/images/favicon.png +0 -0
  139. data/spec_app/app/assets/images/grid.png +0 -0
  140. data/spec_app/app/assets/javascripts/bootstrap_manifest.coffee +0 -6
  141. data/spec_app/app/assets/javascripts/integration_test.coffee +0 -6
  142. data/spec_app/app/assets/javascripts/jasmine_specs.coffee +0 -6
  143. data/spec_app/app/assets/stylesheets/_helpers.sass +0 -5
  144. data/spec_app/app/assets/stylesheets/bootstrap_manifest.sass +0 -2
  145. data/spec_app/app/assets/stylesheets/integration_test.sass +0 -88
  146. data/spec_app/app/assets/stylesheets/jasmine_specs.sass +0 -20
  147. data/spec_app/app/controllers/application_controller.rb +0 -14
  148. data/spec_app/app/controllers/binding_test_controller.rb +0 -51
  149. data/spec_app/app/controllers/compiler_test_controller.rb +0 -5
  150. data/spec_app/app/controllers/css_test_controller.rb +0 -5
  151. data/spec_app/app/controllers/error_test_controller.rb +0 -5
  152. data/spec_app/app/controllers/form_test/basics_controller.rb +0 -14
  153. data/spec_app/app/controllers/form_test/redirects_controller.rb +0 -17
  154. data/spec_app/app/controllers/form_test/uploads_controller.rb +0 -15
  155. data/spec_app/app/controllers/hash_test_controller.rb +0 -5
  156. data/spec_app/app/controllers/method_test_controller.rb +0 -16
  157. data/spec_app/app/controllers/motion_test_controller.rb +0 -5
  158. data/spec_app/app/controllers/pages_controller.rb +0 -9
  159. data/spec_app/app/controllers/replace_test_controller.rb +0 -5
  160. data/spec_app/app/controllers/reveal_test_controller.rb +0 -5
  161. data/spec_app/app/controllers/scroll_test_controller.rb +0 -5
  162. data/spec_app/app/helpers/application_helper.rb +0 -2
  163. data/spec_app/app/mailers/.keep +0 -0
  164. data/spec_app/app/models/concerns/.keep +0 -0
  165. data/spec_app/app/views/compiler_test/timestamp.erb +0 -9
  166. data/spec_app/app/views/css_test/modal.erb +0 -47
  167. data/spec_app/app/views/css_test/modal_contents.erb +0 -5
  168. data/spec_app/app/views/css_test/modal_contents_wide.erb +0 -5
  169. data/spec_app/app/views/css_test/popup.erb +0 -81
  170. data/spec_app/app/views/css_test/popup_contents.erb +0 -5
  171. data/spec_app/app/views/css_test/tooltip.erb +0 -48
  172. data/spec_app/app/views/error_test/trigger.erb +0 -80
  173. data/spec_app/app/views/error_test/unexpected_response.erb +0 -3
  174. data/spec_app/app/views/form_test/basics/new.erb +0 -60
  175. data/spec_app/app/views/form_test/redirects/new.erb +0 -27
  176. data/spec_app/app/views/form_test/redirects/target.erb +0 -4
  177. data/spec_app/app/views/form_test/submission_result.erb +0 -30
  178. data/spec_app/app/views/form_test/uploads/new.erb +0 -44
  179. data/spec_app/app/views/hash_test/unpoly.erb +0 -30
  180. data/spec_app/app/views/hash_test/vanilla.erb +0 -13
  181. data/spec_app/app/views/layouts/integration_test.erb +0 -22
  182. data/spec_app/app/views/layouts/jasmine_rails/spec_runner.html.erb +0 -20
  183. data/spec_app/app/views/method_test/form_target.erb +0 -17
  184. data/spec_app/app/views/method_test/page1.erb +0 -11
  185. data/spec_app/app/views/method_test/page2.erb +0 -6
  186. data/spec_app/app/views/motion_test/animations.erb +0 -16
  187. data/spec_app/app/views/motion_test/transitions.erb +0 -13
  188. data/spec_app/app/views/pages/start.erb +0 -79
  189. data/spec_app/app/views/replace_test/_nav.erb +0 -6
  190. data/spec_app/app/views/replace_test/page1.erb +0 -14
  191. data/spec_app/app/views/replace_test/page2.erb +0 -14
  192. data/spec_app/app/views/replace_test/table.erb +0 -16
  193. data/spec_app/app/views/reveal_test/long1.erb +0 -17
  194. data/spec_app/app/views/reveal_test/long2.erb +0 -17
  195. data/spec_app/app/views/reveal_test/within_document_viewport.erb +0 -24
  196. data/spec_app/app/views/reveal_test/within_overflowing_div_viewport.erb +0 -28
  197. data/spec_app/app/views/scroll_test/long1.erb +0 -30
  198. data/spec_app/bin/bundle +0 -3
  199. data/spec_app/bin/rails +0 -8
  200. data/spec_app/bin/rake +0 -8
  201. data/spec_app/bin/setup +0 -29
  202. data/spec_app/bin/spring +0 -18
  203. data/spec_app/config.ru +0 -4
  204. data/spec_app/config/application.rb +0 -28
  205. data/spec_app/config/boot.rb +0 -3
  206. data/spec_app/config/database.yml +0 -25
  207. data/spec_app/config/environment.rb +0 -5
  208. data/spec_app/config/environments/development.rb +0 -41
  209. data/spec_app/config/environments/production.rb +0 -79
  210. data/spec_app/config/environments/test.rb +0 -42
  211. data/spec_app/config/initializers/assets.rb +0 -19
  212. data/spec_app/config/initializers/backtrace_silencers.rb +0 -7
  213. data/spec_app/config/initializers/bower_rails.rb +0 -16
  214. data/spec_app/config/initializers/cookies_serializer.rb +0 -3
  215. data/spec_app/config/initializers/filter_parameter_logging.rb +0 -4
  216. data/spec_app/config/initializers/inflections.rb +0 -16
  217. data/spec_app/config/initializers/mime_types.rb +0 -4
  218. data/spec_app/config/initializers/session_store.rb +0 -3
  219. data/spec_app/config/initializers/wrap_parameters.rb +0 -14
  220. data/spec_app/config/locales/en.yml +0 -23
  221. data/spec_app/config/routes.rb +0 -30
  222. data/spec_app/config/secrets.yml +0 -22
  223. data/spec_app/db/schema.rb +0 -23
  224. data/spec_app/db/seeds.rb +0 -7
  225. data/spec_app/lib/assets/.keep +0 -0
  226. data/spec_app/lib/tasks/.keep +0 -0
  227. data/spec_app/lib/tasks/cucumber.rake +0 -65
  228. data/spec_app/log/.keep +0 -0
  229. data/spec_app/public/404.html +0 -67
  230. data/spec_app/public/422.html +0 -67
  231. data/spec_app/public/500.html +0 -66
  232. data/spec_app/public/favicon.ico +0 -0
  233. data/spec_app/public/robots.txt +0 -5
  234. data/spec_app/script/cucumber +0 -10
  235. data/spec_app/spec/controllers/binding_test_controller_spec.rb +0 -248
  236. data/spec_app/spec/javascripts/helpers/agent_detector.coffee +0 -20
  237. data/spec_app/spec/javascripts/helpers/async_sequence.js.coffee +0 -103
  238. data/spec_app/spec/javascripts/helpers/browser_switches.js.coffee +0 -21
  239. data/spec_app/spec/javascripts/helpers/enable_logging.js.coffee +0 -2
  240. data/spec_app/spec/javascripts/helpers/fixture.js.coffee +0 -25
  241. data/spec_app/spec/javascripts/helpers/index.js.coffee +0 -1
  242. data/spec_app/spec/javascripts/helpers/jquery_no_conflict.js +0 -1
  243. data/spec_app/spec/javascripts/helpers/knife.js.coffee +0 -69
  244. data/spec_app/spec/javascripts/helpers/last_request.js.coffee +0 -25
  245. data/spec_app/spec/javascripts/helpers/mock_ajax.js.coffee +0 -8
  246. data/spec_app/spec/javascripts/helpers/mock_clock.js.coffee +0 -2
  247. data/spec_app/spec/javascripts/helpers/parse_form_data.js.coffee +0 -24
  248. data/spec_app/spec/javascripts/helpers/promise_state.js +0 -18
  249. data/spec_app/spec/javascripts/helpers/protect_jasmine_runner.coffee +0 -12
  250. data/spec_app/spec/javascripts/helpers/remove_body_margin.js.coffee +0 -8
  251. data/spec_app/spec/javascripts/helpers/reset_history.js.coffee +0 -23
  252. data/spec_app/spec/javascripts/helpers/reset_knife.js.coffee +0 -2
  253. data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +0 -25
  254. data/spec_app/spec/javascripts/helpers/restore_body_scroll.js.coffee +0 -5
  255. data/spec_app/spec/javascripts/helpers/show_lib_versions.coffee +0 -12
  256. data/spec_app/spec/javascripts/helpers/spec_util.coffee +0 -47
  257. data/spec_app/spec/javascripts/helpers/to_be_around.js.coffee +0 -8
  258. data/spec_app/spec/javascripts/helpers/to_be_array.coffee +0 -5
  259. data/spec_app/spec/javascripts/helpers/to_be_attached.coffee +0 -9
  260. data/spec_app/spec/javascripts/helpers/to_be_blank.js.coffee +0 -8
  261. data/spec_app/spec/javascripts/helpers/to_be_detached.coffee +0 -9
  262. data/spec_app/spec/javascripts/helpers/to_be_element.js.coffee +0 -8
  263. data/spec_app/spec/javascripts/helpers/to_be_error.coffee +0 -8
  264. data/spec_app/spec/javascripts/helpers/to_be_given.js.coffee +0 -8
  265. data/spec_app/spec/javascripts/helpers/to_be_hidden.js.coffee +0 -8
  266. data/spec_app/spec/javascripts/helpers/to_be_jquery.js.coffee +0 -5
  267. data/spec_app/spec/javascripts/helpers/to_be_missing.js.coffee +0 -8
  268. data/spec_app/spec/javascripts/helpers/to_be_present.js.coffee +0 -8
  269. data/spec_app/spec/javascripts/helpers/to_be_scrolled_to.coffee +0 -11
  270. data/spec_app/spec/javascripts/helpers/to_be_visible.js.coffee +0 -9
  271. data/spec_app/spec/javascripts/helpers/to_contain.js.coffee +0 -8
  272. data/spec_app/spec/javascripts/helpers/to_end_with.js.coffee +0 -11
  273. data/spec_app/spec/javascripts/helpers/to_equal_jquery.js.coffee +0 -8
  274. data/spec_app/spec/javascripts/helpers/to_equal_node_list.coffee +0 -7
  275. data/spec_app/spec/javascripts/helpers/to_equal_via_is_equal.js.coffee +0 -7
  276. data/spec_app/spec/javascripts/helpers/to_have_class.js.coffee +0 -10
  277. data/spec_app/spec/javascripts/helpers/to_have_descendant.js.coffee +0 -10
  278. data/spec_app/spec/javascripts/helpers/to_have_length.js.coffee +0 -8
  279. data/spec_app/spec/javascripts/helpers/to_have_opacity.coffee +0 -15
  280. data/spec_app/spec/javascripts/helpers/to_have_own_property.js.coffee +0 -8
  281. data/spec_app/spec/javascripts/helpers/to_have_request_method.js.coffee +0 -16
  282. data/spec_app/spec/javascripts/helpers/to_have_text.js.coffee +0 -9
  283. data/spec_app/spec/javascripts/helpers/to_have_unhandled_rejections.coffee +0 -18
  284. data/spec_app/spec/javascripts/helpers/to_match_list.coffee +0 -14
  285. data/spec_app/spec/javascripts/helpers/to_match_selector.coffee +0 -8
  286. data/spec_app/spec/javascripts/helpers/to_match_text.js.coffee +0 -13
  287. data/spec_app/spec/javascripts/helpers/to_match_url.coffee +0 -14
  288. data/spec_app/spec/javascripts/helpers/trigger.js.coffee +0 -200
  289. data/spec_app/spec/javascripts/helpers/wait_until_dom_ready.js.coffee +0 -5
  290. data/spec_app/spec/javascripts/support/jasmine.yml +0 -51
  291. data/spec_app/spec/javascripts/up/browser_spec.js.coffee +0 -150
  292. data/spec_app/spec/javascripts/up/classes/cache_spec.js.coffee +0 -82
  293. data/spec_app/spec/javascripts/up/classes/config_spec.coffee +0 -24
  294. data/spec_app/spec/javascripts/up/classes/divertible_chain_spec.coffee +0 -45
  295. data/spec_app/spec/javascripts/up/classes/focus_tracker_spec.coffee +0 -34
  296. data/spec_app/spec/javascripts/up/classes/params_spec.coffee +0 -557
  297. data/spec_app/spec/javascripts/up/classes/request_spec.coffee +0 -50
  298. data/spec_app/spec/javascripts/up/classes/scroll_motion_spec.js.coffee +0 -51
  299. data/spec_app/spec/javascripts/up/classes/store/memory_spec.js.coffee +0 -70
  300. data/spec_app/spec/javascripts/up/classes/store/session_spec.js.coffee +0 -114
  301. data/spec_app/spec/javascripts/up/element_spec.coffee +0 -897
  302. data/spec_app/spec/javascripts/up/event_spec.js.coffee +0 -530
  303. data/spec_app/spec/javascripts/up/feedback_spec.js.coffee +0 -401
  304. data/spec_app/spec/javascripts/up/form_spec.js.coffee +0 -1527
  305. data/spec_app/spec/javascripts/up/fragment_spec.js.coffee +0 -2624
  306. data/spec_app/spec/javascripts/up/history_spec.js.coffee +0 -340
  307. data/spec_app/spec/javascripts/up/jquery_spec.js.coffee +0 -4
  308. data/spec_app/spec/javascripts/up/legacy_spec.js.coffee +0 -27
  309. data/spec_app/spec/javascripts/up/link_spec.js.coffee +0 -1098
  310. data/spec_app/spec/javascripts/up/log_spec.js.coffee +0 -119
  311. data/spec_app/spec/javascripts/up/modal_spec.js.coffee +0 -939
  312. data/spec_app/spec/javascripts/up/motion_spec.js.coffee +0 -582
  313. data/spec_app/spec/javascripts/up/popup_spec.js.coffee +0 -508
  314. data/spec_app/spec/javascripts/up/protocol_spec.js.coffee +0 -39
  315. data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +0 -1137
  316. data/spec_app/spec/javascripts/up/radio_spec.js.coffee +0 -212
  317. data/spec_app/spec/javascripts/up/rails_spec.js.coffee +0 -118
  318. data/spec_app/spec/javascripts/up/spec_spec.js.coffee +0 -9
  319. data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +0 -304
  320. data/spec_app/spec/javascripts/up/toast_spec.js.coffee +0 -37
  321. data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +0 -163
  322. data/spec_app/spec/javascripts/up/util_spec.js.coffee +0 -1420
  323. data/spec_app/spec/javascripts/up/viewport_spec.js.coffee +0 -655
  324. data/spec_app/spec/spec_helper.rb +0 -62
  325. data/spec_app/test/controllers/.keep +0 -0
  326. data/spec_app/test/fixtures/.keep +0 -0
  327. data/spec_app/test/helpers/.keep +0 -0
  328. data/spec_app/test/integration/.keep +0 -0
  329. data/spec_app/test/mailers/.keep +0 -0
  330. data/spec_app/test/models/.keep +0 -0
  331. data/spec_app/test/test_helper.rb +0 -10
  332. data/spec_app/vendor/asset-libs/es6-promise-4.1.6/es6-promise.auto.js +0 -1159
  333. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.bower.json +0 -43
  334. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.gitignore +0 -6
  335. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.npmignore +0 -10
  336. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.pairs +0 -6
  337. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/.travis.yml +0 -56
  338. data/spec_app/vendor/asset-libs/jasmine-ajax-3.3.1/jasmine-ajax.js +0 -790
  339. data/spec_app/vendor/assets/.keep +0 -0
  340. data/unpoly-rails.gemspec +0 -24
@@ -1,37 +0,0 @@
1
- u = up.util
2
- $ = jQuery
3
-
4
- describe 'up.toast', ->
5
-
6
- describe 'JavaScript functions', ->
7
-
8
- describe 'up.toast.open()', ->
9
-
10
- it 'opens a toast box with the given message', ->
11
- up.toast.open('This is a message')
12
- expect('.up-toast').toBeAttached()
13
- expect($('.up-toast-message').text()).toContain('This is a message')
14
-
15
- it 'opens a toast box with a close link', ->
16
- up.toast.open('This is a message')
17
- expect('.up-toast').toBeAttached()
18
- $closeButton = $('.up-toast-action:contains("Close")')
19
- expect($closeButton).toBeAttached()
20
-
21
- Trigger.clickSequence($closeButton)
22
-
23
- expect('.up-toast').not.toBeAttached()
24
-
25
- it 'opens a toast box with the given custom action', ->
26
- action =
27
- label: 'Custom action'
28
- callback: jasmine.createSpy('action callback')
29
- up.toast.open('This is a message', { action })
30
- $actionButton = $('.up-toast-action:contains("Custom action")')
31
- expect($actionButton).toBeAttached()
32
- expect(action.callback).not.toHaveBeenCalled()
33
-
34
- Trigger.clickSequence($actionButton)
35
-
36
- expect(action.callback).toHaveBeenCalled()
37
-
@@ -1,163 +0,0 @@
1
- u = up.util
2
- e = up.element
3
- $ = jQuery
4
-
5
- describe 'up.tooltip', ->
6
-
7
- describe 'JavaScript functions', ->
8
-
9
- describe 'up.tooltip.attach', ->
10
-
11
- it 'opens a tooltip with the given text', (done) ->
12
- $link = $fixture('span')
13
- up.tooltip.attach($link, html: 'tooltip text').then ->
14
- $tooltip = $('.up-tooltip')
15
- expect($tooltip).toHaveText('tooltip text')
16
- done()
17
-
18
- it 'allows HTML for the tooltip text when contents are given as { html } option', (done) ->
19
- $link = $fixture('span')
20
- up.tooltip.attach($link, html: '<b>text</b>').then ->
21
- $tooltip = $('.up-tooltip')
22
- expect($tooltip.html()).toContain('<b>text</b>')
23
- done()
24
-
25
- it 'escapes HTML for the tooltip text when contents given as { text } option', (done) ->
26
- $link = $fixture('span')
27
- up.tooltip.attach($link, text: '<b>text</b>').then ->
28
- $tooltip = $('.up-tooltip')
29
- expect($tooltip.html()).toContain('&lt;b&gt;text&lt;/b&gt;')
30
- done()
31
-
32
- describe 'positioning', ->
33
-
34
- beforeEach ->
35
- @$link = $fixture('span').text('button label')
36
- @$link.css(
37
- position: 'absolute'
38
- left: '200px'
39
- top: '200px'
40
- width: '50px'
41
- height: '50px'
42
- )
43
-
44
- beforeEach ->
45
- @restoreBodyHeight = e.setTemporaryStyle(document.body, minHeight: '3000px')
46
-
47
- afterEach ->
48
- @restoreBodyHeight()
49
-
50
- distanceFromOrigin = 10
51
-
52
- describe 'with { position: "top" }', ->
53
-
54
- it 'centers the tooltip above the given element', (done) ->
55
- @linkBox = @$link.get(0).getBoundingClientRect()
56
- up.tooltip.attach(@$link, html: 'tooltip text', position: 'top').then =>
57
- $tooltip = $('.up-tooltip')
58
- tooltipBox = $tooltip.get(0).getBoundingClientRect()
59
- expect(tooltipBox.top).toBeAround(@linkBox.top - tooltipBox.height - distanceFromOrigin, 1)
60
- expect(tooltipBox.left).toBeAround(@linkBox.left + 0.5 * (@linkBox.width - tooltipBox.width), 1)
61
- done()
62
-
63
- describe 'with { position: "right" }', ->
64
-
65
- it 'centers the tooltip at the right side of the given element', (done) ->
66
- @linkBox = @$link.get(0).getBoundingClientRect()
67
- up.tooltip.attach(@$link, html: 'tooltip text', position: 'right').then =>
68
- $tooltip = $('.up-tooltip')
69
- tooltipBox = $tooltip.get(0).getBoundingClientRect()
70
- expect(tooltipBox.top).toBeAround(@linkBox.top + 0.5 * (@linkBox.height - tooltipBox.height), 1)
71
- expect(tooltipBox.left).toBeAround(@linkBox.left + @linkBox.width + distanceFromOrigin, 1)
72
- done()
73
-
74
- describe 'with { position: "bottom" }', ->
75
-
76
- it 'centers the tooltip below the given element', (done) ->
77
- @linkBox = @$link.get(0).getBoundingClientRect()
78
- up.tooltip.attach(@$link, html: 'tooltip text', position: 'bottom').then =>
79
- $tooltip = $('.up-tooltip')
80
- tooltipBox = $tooltip.get(0).getBoundingClientRect()
81
- expect(tooltipBox.top).toBeAround(@linkBox.top + @linkBox.height + distanceFromOrigin, 1)
82
- expect(tooltipBox.left).toBeAround(@linkBox.left + 0.5 * (@linkBox.width - tooltipBox.width), 1)
83
- done()
84
-
85
- describe 'with { position: "left" }', ->
86
-
87
- it 'centers the tooltip at the left side of the given element', (done) ->
88
- @linkBox = @$link.get(0).getBoundingClientRect()
89
- up.tooltip.attach(@$link, html: 'tooltip text', position: 'left').then =>
90
- $tooltip = $('.up-tooltip')
91
- tooltipBox = $tooltip.get(0).getBoundingClientRect()
92
- expect(tooltipBox.top).toBeAround(@linkBox.top + 0.5 * (@linkBox.height - tooltipBox.height), 1)
93
- expect(tooltipBox.left).toBeAround(@linkBox.left - tooltipBox.width - distanceFromOrigin, 1)
94
- done()
95
-
96
- describe 'up.tooltip.close', ->
97
-
98
- it 'closes an existing tooltip'
99
-
100
- describe 'unobtrusive behavior', ->
101
-
102
- describe '[up-tooltip]', ->
103
-
104
- it 'should have tests'
105
-
106
- describe '[up-tooltip-html]', ->
107
-
108
- it 'should have tests'
109
-
110
- describe 'when clicking on the body', ->
111
-
112
- beforeEach ->
113
- up.motion.config.enabled = false
114
-
115
- it 'closes the tooltip', asyncSpec (next) ->
116
- $link = $fixture('.link')
117
- up.tooltip.attach($link, text: 'Tooltip text')
118
-
119
- next =>
120
- expect(up.tooltip.isOpen()).toBe(true)
121
- Trigger.clickSequence($('body'))
122
-
123
- next =>
124
- expect(up.tooltip.isOpen()).toBe(false)
125
-
126
- it 'closes the tooltip when a an [up-instant] link removes its parent (and thus a click event never bubbles up to the document)', asyncSpec (next) ->
127
- $parent = $fixture('.parent')
128
- $parentReplacingLink = $parent.affix('a[href="/foo"][up-target=".parent"][up-instant]')
129
- $tooltipOpener = $fixture('.link')
130
- up.tooltip.attach($tooltipOpener, text: 'Tooltip text')
131
-
132
- next =>
133
- expect(up.tooltip.isOpen()).toBe(true)
134
- Trigger.clickSequence($parentReplacingLink)
135
-
136
- next =>
137
- expect(up.tooltip.isOpen()).toBe(false)
138
-
139
- it 'closes a tooltip when the user clicks on an [up-target] link outside the tooltip', asyncSpec (next) ->
140
- $target = $fixture('.target')
141
- $outsideLink = $fixture('a[href="/foo"][up-target=".target"]')
142
- $tooltipOpener = $fixture('.link')
143
- up.tooltip.attach($tooltipOpener, text: 'Tooltip text')
144
-
145
- next =>
146
- expect(up.tooltip.isOpen()).toBe(true)
147
- Trigger.clickSequence($outsideLink)
148
-
149
- next =>
150
- expect(up.tooltip.isOpen()).toBe(false)
151
-
152
- it 'closes a tooltip when the user clicks on an [up-instant] link outside the tooltip', asyncSpec (next) ->
153
- $target = $fixture('.target')
154
- $outsideLink = $fixture('a[href="/foo"][up-target=".target"][up-instant]')
155
- $tooltipOpener = $fixture('.link')
156
- up.tooltip.attach($tooltipOpener, text: 'Tooltip text')
157
-
158
- next =>
159
- expect(up.tooltip.isOpen()).toBe(true)
160
- Trigger.clickSequence($outsideLink)
161
-
162
- next =>
163
- expect(up.tooltip.isOpen()).toBe(false)
@@ -1,1420 +0,0 @@
1
- u = up.util
2
- e = up.element
3
- $ = jQuery
4
-
5
- describe 'up.util', ->
6
-
7
- describe 'JavaScript functions', ->
8
-
9
- describe 'up.util.isEqual', ->
10
-
11
- describe 'for an Element', ->
12
-
13
- it 'returns true for the same Element reference', ->
14
- div = document.createElement('div')
15
- expect(up.util.isEqual(div, div)).toBe(true)
16
-
17
- it 'returns false for a different Element reference', ->
18
- div1 = document.createElement('div')
19
- div2 = document.createElement('div')
20
- expect(up.util.isEqual(div1, div2)).toBe(false)
21
-
22
- it 'returns false for a value this is no Element', ->
23
- div = document.createElement('div')
24
- expect(up.util.isEqual(div, 'other')).toBe(false)
25
-
26
- describe 'for an Array', ->
27
-
28
- it 'returns true for a different Array reference with the same elements', ->
29
- array1 = ['foo', 'bar']
30
- array2 = ['foo', 'bar']
31
- expect(up.util.isEqual(array1, array2)).toBe(true)
32
-
33
- it 'returns false for an Array with different elements', ->
34
- array1 = ['foo', 'bar']
35
- array2 = ['foo', 'qux']
36
- expect(up.util.isEqual(array1, array2)).toBe(false)
37
-
38
- it 'returns false for an Array that is a suffix', ->
39
- array1 = ['foo', 'bar']
40
- array2 = [ 'bar']
41
- expect(up.util.isEqual(array1, array2)).toBe(false)
42
-
43
- it 'returns false for an Array that is a prefix', ->
44
- array1 = ['foo', 'bar']
45
- array2 = ['foo' ]
46
- expect(up.util.isEqual(array1, array2)).toBe(false)
47
-
48
- it 'returns true for a NodeList with the same elements', ->
49
- parent = e.affix(document.body, '.parent')
50
- child1 = e.affix(parent, '.child.one')
51
- child2 = e.affix(parent, '.child.two')
52
-
53
- array = [child1, child2]
54
- nodeList = parent.querySelectorAll('.child')
55
-
56
- expect(up.util.isEqual(array, nodeList)).toBe(true)
57
-
58
- it 'returns true for a HTMLCollection with the same elements', ->
59
- parent = e.affix(document.body, '.parent')
60
- child1 = e.affix(parent, '.child.one')
61
- child2 = e.affix(parent, '.child.two')
62
-
63
- array = [child1, child2]
64
- htmlCollection = parent.children
65
-
66
- expect(up.util.isEqual(array, htmlCollection)).toBe(true)
67
-
68
- it 'returns true for an arguments object with the same elements', ->
69
- toArguments = -> return arguments
70
- array = ['foo', 'bar']
71
- args = toArguments('foo', 'bar')
72
-
73
- expect(up.util.isEqual(array, args)).toBe(true)
74
-
75
- it 'returns false for a value that is no Array', ->
76
- array = ['foo', 'bar']
77
- expect(up.util.isEqual(array, 'foobar')).toBe(false)
78
-
79
- describe 'for a string', ->
80
-
81
- it 'returns true for a different string reference with the same characters', ->
82
- string1 = 'bar'
83
- string2 = 'bar'
84
- expect(up.util.isEqual(string1, string2)).toBe(true)
85
-
86
- it 'returns false for a string with different characters', ->
87
- string1 = 'foo'
88
- string2 = 'bar'
89
- expect(up.util.isEqual(string1, string2)).toBe(false)
90
-
91
- it 'returns true for a String() object with the same characters', ->
92
- stringLiteral = 'bar'
93
- stringObject = new String('bar')
94
- expect(up.util.isEqual(stringLiteral, stringObject)).toBe(true)
95
-
96
- it 'returns false for a String() object with different characters', ->
97
- stringLiteral = 'foo'
98
- stringObject = new String('bar')
99
- expect(up.util.isEqual(stringLiteral, stringObject)).toBe(false)
100
-
101
- it 'returns false for a value that is no string', ->
102
- expect(up.util.isEqual('foo', ['foo'])).toBe(false)
103
-
104
- describe 'for a number', ->
105
-
106
- it 'returns true for a different number reference with the same integer value', ->
107
- number1 = 123
108
- number2 = 123
109
- expect(up.util.isEqual(number1, number2)).toBe(true)
110
-
111
- it 'returns true for a different number reference with the same floating point value', ->
112
- number1 = 123.4
113
- number2 = 123.4
114
- expect(up.util.isEqual(number1, number2)).toBe(true)
115
-
116
- it 'returns false for a number with a different value', ->
117
- number1 = 123
118
- number2 = 124
119
- expect(up.util.isEqual(number1, number2)).toBe(false)
120
-
121
- it 'returns true for a Number() object with the same value', ->
122
- numberLiteral = 123
123
- numberObject = new Number(123)
124
- expect(up.util.isEqual(numberLiteral, numberObject)).toBe(true)
125
-
126
- it 'returns false for a Number() object with a different value', ->
127
- numberLiteral = 123
128
- numberObject = new Object(124)
129
- expect(up.util.isEqual(numberLiteral, numberObject)).toBe(false)
130
-
131
- it 'returns false for a value that is no number', ->
132
- expect(up.util.isEqual(123, '123')).toBe(false)
133
-
134
- describe 'for undefined', ->
135
-
136
- it 'returns true for undefined', ->
137
- expect(up.util.isEqual(undefined, undefined)).toBe(true)
138
-
139
- it 'returns false for null', ->
140
- expect(up.util.isEqual(undefined, null)).toBe(false)
141
-
142
- it 'returns false for NaN', ->
143
- expect(up.util.isEqual(undefined, NaN)).toBe(false)
144
-
145
- it 'returns false for an empty Object', ->
146
- expect(up.util.isEqual(undefined, {})).toBe(false)
147
-
148
- it 'returns false for an empty string', ->
149
- expect(up.util.isEqual(undefined, '')).toBe(false)
150
-
151
- describe 'for null', ->
152
-
153
- it 'returns true for null', ->
154
- expect(up.util.isEqual(null, null)).toBe(true)
155
-
156
- it 'returns false for undefined', ->
157
- expect(up.util.isEqual(null, undefined)).toBe(false)
158
-
159
- it 'returns false for NaN', ->
160
- expect(up.util.isEqual(null, NaN)).toBe(false)
161
-
162
- it 'returns false for an empty Object', ->
163
- expect(up.util.isEqual(null, {})).toBe(false)
164
-
165
- it 'returns false for an empty string', ->
166
- expect(up.util.isEqual(null, '')).toBe(false)
167
-
168
- describe 'for NaN', ->
169
-
170
- it "returns false for NaN because it represents multiple values", ->
171
- expect(up.util.isEqual(NaN, NaN)).toBe(false)
172
-
173
- it 'returns false for null', ->
174
- expect(up.util.isEqual(NaN, null)).toBe(false)
175
-
176
- it 'returns false for undefined', ->
177
- expect(up.util.isEqual(NaN, undefined)).toBe(false)
178
-
179
- it 'returns false for an empty Object', ->
180
- expect(up.util.isEqual(NaN, {})).toBe(false)
181
-
182
- it 'returns false for an empty string', ->
183
- expect(up.util.isEqual(NaN, '')).toBe(false)
184
-
185
- describe 'for a Date', ->
186
-
187
- it 'returns true for another Date object that points to the same millisecond', ->
188
- d1 = new Date('1995-12-17T03:24:00')
189
- d2 = new Date('1995-12-17T03:24:00')
190
- expect(up.util.isEqual(d1, d2)).toBe(true)
191
-
192
- it 'returns false for another Date object that points to another millisecond', ->
193
- d1 = new Date('1995-12-17T03:24:00')
194
- d2 = new Date('1995-12-17T03:24:01')
195
- expect(up.util.isEqual(d1, d2)).toBe(false)
196
-
197
- it 'returns true for another Date object that points to the same millisecond in another time zone', ->
198
- d1 = new Date('2019-01-20T17:35:00+01:00')
199
- d2 = new Date('2019-01-20T16:35:00+00:00')
200
- expect(up.util.isEqual(d1, d2)).toBe(true)
201
-
202
- it 'returns false for a value that is not a Date', ->
203
- d1 = new Date('1995-12-17T03:24:00')
204
- d2 = '1995-12-17T03:24:00'
205
- expect(up.util.isEqual(d1, d2)).toBe(false)
206
-
207
- describe 'for a plain Object', ->
208
-
209
- it 'returns true for the same reference', ->
210
- obj = {}
211
- reference = obj
212
- expect(up.util.isEqual(obj, reference)).toBe(true)
213
-
214
- it 'returns true for another plain object with the same keys and values', ->
215
- obj1 = { foo: 'bar', baz: 'bam' }
216
- obj2 = { foo: 'bar', baz: 'bam' }
217
- expect(up.util.isEqual(obj1, obj2)).toBe(true)
218
-
219
- it 'returns false for another plain object with the same keys, but different values', ->
220
- obj1 = { foo: 'bar', baz: 'bam' }
221
- obj2 = { foo: 'bar', baz: 'qux' }
222
- expect(up.util.isEqual(obj1, obj2)).toBe(false)
223
-
224
- it 'returns false for another plain object that is missing a key', ->
225
- obj1 = { foo: 'bar', baz: 'bam' }
226
- obj2 = { foo: 'bar' }
227
- expect(up.util.isEqual(obj1, obj2)).toBe(false)
228
-
229
- it 'returns false for another plain object that has an additional key', ->
230
- obj1 = { foo: 'bar' }
231
- obj2 = { foo: 'bar', baz: 'bam' }
232
- expect(up.util.isEqual(obj1, obj2)).toBe(false)
233
-
234
- it 'returns false for a non-plain Object, even if it has the same keys and values', ->
235
- class Account
236
- constructor: (@email) ->
237
-
238
- accountInstance = new Account('foo@example.com')
239
- accountPlain = {}
240
- for key, value of accountInstance
241
- accountPlain[key] = value
242
- expect(up.util.isEqual(accountPlain, accountInstance)).toBe(false)
243
-
244
- it 'returns false for a value that is no object', ->
245
- obj = { foo: 'bar' }
246
- expect(up.util.isEqual(obj, 'foobar')).toBe(false)
247
-
248
- describe 'for a non-Plain object', ->
249
-
250
- it 'returns true for the same reference', ->
251
- obj = new FormData()
252
- reference = obj
253
- expect(up.util.isEqual(obj, reference)).toBe(true)
254
-
255
- it 'returns false for different references', ->
256
- obj1 = new FormData()
257
- obj2 = new FormData()
258
- expect(up.util.isEqual(obj1, obj2)).toBe(false)
259
-
260
- it 'returns false for a different object with the same keys and values', ->
261
- class Account
262
- constructor: (@email) ->
263
-
264
- account1 = new Account('foo@example.com')
265
- account2 = new Account('bar@example.com')
266
-
267
- expect(up.util.isEqual(account1, account2)).toBe(false)
268
-
269
- it 'allows the object to hook into the comparison protocol by implementing a method called `up.util.isEqual.key`', ->
270
- class Account
271
- constructor: (@email) ->
272
- "#{up.util.isEqual.key}": (other) ->
273
- @email == other.email
274
-
275
- account1 = new Account('foo@example.com')
276
- account2 = new Account('bar@example.com')
277
- account3 = new Account('foo@example.com')
278
-
279
- expect(up.util.isEqual(account1, account2)).toBe(false)
280
- expect(up.util.isEqual(account1, account3)).toBe(true)
281
-
282
- it 'returns false for a value that is no object', ->
283
- class Account
284
- constructor: (@email) ->
285
-
286
- account = new Account('foo@example.com')
287
-
288
- expect(up.util.isEqual(account, 'foo@example.com')).toBe(false)
289
-
290
- describe 'up.util.flatMap', ->
291
-
292
- it 'collects the Array results of the given map function, then concatenates the result arrays into one flat array', ->
293
- fun = (x) -> [x, x]
294
- result = up.util.flatMap([1, 2, 3], fun)
295
- expect(result).toEqual([1, 1, 2, 2, 3, 3])
296
-
297
- it 'builds an array from mixed function return values of scalar values and lists', ->
298
- fun = (x) ->
299
- if x == 1
300
- 1
301
- else
302
- [x, x]
303
-
304
- result = up.util.flatMap([0, 1, 2], fun)
305
- expect(result).toEqual [0, 0, 1, 2, 2]
306
-
307
-
308
- it 'flattens return values that are NodeLists', ->
309
- fun = (selector) -> document.querySelectorAll(selector)
310
-
311
- foo1 = $fixture('.foo-element')[0]
312
- foo2 = $fixture('.foo-element')[0]
313
- bar = $fixture('.bar-element')[0]
314
-
315
- result = up.util.flatMap(['.foo-element', '.bar-element'], fun)
316
-
317
- expect(result).toEqual [foo1, foo2, bar]
318
-
319
-
320
- describe 'up.util.uniq', ->
321
-
322
- it 'returns the given array with duplicates elements removed', ->
323
- input = [1, 2, 1, 1, 3]
324
- result = up.util.uniq(input)
325
- expect(result).toEqual [1, 2, 3]
326
-
327
- it 'works on DOM elements', ->
328
- one = document.createElement("div")
329
- two = document.createElement("div")
330
- input = [one, one, two, two]
331
- result = up.util.uniq(input)
332
- expect(result).toEqual [one, two]
333
-
334
- it 'preserves insertion order', ->
335
- input = [1, 2, 1]
336
- result = up.util.uniq(input)
337
- expect(result).toEqual [1, 2]
338
-
339
- describe 'up.util.uniqBy', ->
340
-
341
- it 'returns the given array with duplicate elements removed, calling the given function to determine value for uniqueness', ->
342
- input = ["foo", "bar", "apple", 'orange', 'banana']
343
- result = up.util.uniqBy(input, (element) -> element.length)
344
- expect(result).toEqual ['foo', 'apple', 'orange']
345
-
346
- it 'accepts a property name instead of a function, which collects that property from each item to compute uniquness', ->
347
- input = ["foo", "bar", "apple", 'orange', 'banana']
348
- result = up.util.uniqBy(input, 'length')
349
- expect(result).toEqual ['foo', 'apple', 'orange']
350
-
351
- # describe 'up.util.parsePath', ->
352
- #
353
- # it 'parses a plain name', ->
354
- # path = up.util.parsePath("foo")
355
- # expect(path).toEqual ['foo']
356
- #
357
- # it 'considers underscores to be part of a name', ->
358
- # path = up.util.parsePath("foo_bar")
359
- # expect(path).toEqual ['foo_bar']
360
- #
361
- # it 'considers dashes to be part of a name', ->
362
- # path = up.util.parsePath("foo-bar")
363
- # expect(path).toEqual ['foo-bar']
364
- #
365
- # it 'parses dot-separated names into multiple path segments', ->
366
- # path = up.util.parsePath('foo.bar.baz')
367
- # expect(path).toEqual ['foo', 'bar', 'baz']
368
- #
369
- # it 'parses nested params notation with square brackets', ->
370
- # path = up.util.parsePath('user[account][email]')
371
- # expect(path).toEqual ['user', 'account', 'email']
372
- #
373
- # it 'parses double quotes in square brackets', ->
374
- # path = up.util.parsePath('user["account"]["email"]')
375
- # expect(path).toEqual ['user', 'account', 'email']
376
- #
377
- # it 'parses single quotes in square brackets', ->
378
- # path = up.util.parsePath("user['account']['email']")
379
- # expect(path).toEqual ['user', 'account', 'email']
380
- #
381
- # it 'allows square brackets inside quotes', ->
382
- # path = up.util.parsePath("element['a[up-href]']")
383
- # expect(path).toEqual ['element', 'a[up-href]']
384
- #
385
- # it 'allows single quotes inside double quotes', ->
386
- # path = up.util.parsePath("element[\"a[up-href='foo']\"]")
387
- # expect(path).toEqual ['element', "a[up-href='foo']"]
388
- #
389
- # it 'allows double quotes inside single quotes', ->
390
- # path = up.util.parsePath("element['a[up-href=\"foo\"]']")
391
- # expect(path).toEqual ['element', 'a[up-href="foo"]']
392
- #
393
- # it 'allows dots in square brackets when it is quoted', ->
394
- # path = up.util.parsePath('elements[".foo"]')
395
- # expect(path).toEqual ['elements', '.foo']
396
- #
397
- # it 'allows different notation for each segment', ->
398
- # path = up.util.parsePath('foo.bar[baz]["bam"][\'qux\']')
399
- # expect(path).toEqual ['foo', 'bar', 'baz', 'bam', 'qux']
400
-
401
- describe 'up.util.parseUrl', ->
402
-
403
- it 'parses a full URL', ->
404
- url = up.util.parseUrl('https://subdomain.domain.tld:123/path?search#hash')
405
- expect(url.protocol).toEqual('https:')
406
- expect(url.hostname).toEqual('subdomain.domain.tld')
407
- expect(url.port).toEqual('123')
408
- expect(url.pathname).toEqual('/path')
409
- expect(url.search).toEqual('?search')
410
- expect(url.hash).toEqual('#hash')
411
-
412
- it 'parses an absolute path', ->
413
- url = up.util.parseUrl('/qux/foo?search#bar')
414
- expect(url.protocol).toEqual(location.protocol)
415
- expect(url.hostname).toEqual(location.hostname)
416
- expect(url.port).toEqual(location.port)
417
- expect(url.pathname).toEqual('/qux/foo')
418
- expect(url.search).toEqual('?search')
419
- expect(url.hash).toEqual('#bar')
420
-
421
- it 'parses a relative path', ->
422
- up.history.config.enabled = true
423
- up.history.replace('/qux/')
424
- url = up.util.parseUrl('foo?search#bar')
425
- expect(url.protocol).toEqual(location.protocol)
426
- expect(url.hostname).toEqual(location.hostname)
427
- expect(url.port).toEqual(location.port)
428
- expect(url.pathname).toEqual('/qux/foo')
429
- expect(url.search).toEqual('?search')
430
- expect(url.hash).toEqual('#bar')
431
-
432
- it 'allows to pass a link element', ->
433
- link = document.createElement('a')
434
- link.href = '/qux/foo?search#bar'
435
- url = up.util.parseUrl(link)
436
- expect(url.protocol).toEqual(location.protocol)
437
- expect(url.hostname).toEqual(location.hostname)
438
- expect(url.port).toEqual(location.port)
439
- expect(url.pathname).toEqual('/qux/foo')
440
- expect(url.search).toEqual('?search')
441
- expect(url.hash).toEqual('#bar')
442
-
443
- it 'allows to pass a link element as a jQuery collection', ->
444
- $link = $('<a></a>').attr(href: '/qux/foo?search#bar')
445
- url = up.util.parseUrl($link)
446
- expect(url.protocol).toEqual(location.protocol)
447
- expect(url.hostname).toEqual(location.hostname)
448
- expect(url.port).toEqual(location.port)
449
- expect(url.pathname).toEqual('/qux/foo')
450
- expect(url.search).toEqual('?search')
451
- expect(url.hash).toEqual('#bar')
452
-
453
- describe 'up.util.map', ->
454
-
455
- it 'creates a new array of values by calling the given function on each item of the given array', ->
456
- array = ["apple", "orange", "cucumber"]
457
- mapped = up.util.map(array, (element) -> element.length)
458
- expect(mapped).toEqual [5, 6, 8]
459
-
460
- it 'accepts a property name instead of a function, which collects that property from each item', ->
461
- array = ["apple", "orange", "cucumber"]
462
- mapped = up.util.map(array, 'length')
463
- expect(mapped).toEqual [5, 6, 8]
464
-
465
- it 'passes the iteration index as second argument to the given function', ->
466
- array = ["apple", "orange", "cucumber"]
467
- mapped = up.util.map(array, (element, i) -> i)
468
- expect(mapped).toEqual [0, 1, 2]
469
-
470
- describe 'up.util.mapObject', ->
471
-
472
- it 'creates an object from the given array and pairer', ->
473
- array = ['foo', 'bar', 'baz']
474
- object = up.util.mapObject(array, (str) -> ["#{str}Key", "#{str}Value"])
475
- expect(object).toEqual
476
- fooKey: 'fooValue'
477
- barKey: 'barValue'
478
- bazKey: 'bazValue'
479
-
480
- describe 'up.util.each', ->
481
-
482
- it 'calls the given function once for each item of the given array', ->
483
- args = []
484
- array = ["apple", "orange", "cucumber"]
485
- up.util.each array, (item) -> args.push(item)
486
- expect(args).toEqual ["apple", "orange", "cucumber"]
487
-
488
- it 'passes the iteration index as second argument to the given function', ->
489
- args = []
490
- array = ["apple", "orange", "cucumber"]
491
- up.util.each array, (item, index) -> args.push(index)
492
- expect(args).toEqual [0, 1, 2]
493
-
494
- it 'iterates over an array-like value', ->
495
- one = fixture('.qwertz')
496
- two = fixture('.qwertz')
497
- nodeList = document.querySelectorAll('.qwertz')
498
-
499
- callback = jasmine.createSpy()
500
-
501
- up.util.each nodeList, callback
502
- expect(callback.calls.allArgs()).toEqual [[one, 0], [two, 1]]
503
-
504
- describe 'up.util.filter', ->
505
-
506
- it 'returns an array of those elements in the given array for which the given function returns true', ->
507
- array = ["foo", "orange", "cucumber"]
508
- results = up.util.filter array, (item) -> item.length > 3
509
- expect(results).toEqual ['orange', 'cucumber']
510
-
511
- it 'passes the iteration index as second argument to the given function', ->
512
- array = ["apple", "orange", "cucumber", "banana"]
513
- results = up.util.filter array, (item, index) -> index % 2 == 0
514
- expect(results).toEqual ['apple', 'cucumber']
515
-
516
- it 'accepts a property name instead of a function, which checks that property from each item', ->
517
- array = [ { name: 'a', prop: false }, { name: 'b', prop: true } ]
518
- results = up.util.filter array, 'prop'
519
- expect(results).toEqual [{ name: 'b', prop: true }]
520
-
521
- it 'iterates over an array-like value', ->
522
- one = fixture('.qwertz')
523
- two = fixture('.qwertz')
524
- nodeList = document.querySelectorAll('.qwertz')
525
-
526
- callback = jasmine.createSpy()
527
-
528
- up.util.filter nodeList, callback
529
- expect(callback.calls.allArgs()).toEqual [[one, 0], [two, 1]]
530
-
531
- describe 'up.util.reject', ->
532
-
533
- it 'returns an array of those elements in the given array for which the given function returns false', ->
534
- array = ["foo", "orange", "cucumber"]
535
- results = up.util.reject array, (item) -> item.length < 4
536
- expect(results).toEqual ['orange', 'cucumber']
537
-
538
- it 'passes the iteration index as second argument to the given function', ->
539
- array = ["apple", "orange", "cucumber", "banana"]
540
- results = up.util.reject array, (item, index) -> index % 2 == 0
541
- expect(results).toEqual ['orange', 'banana']
542
-
543
- it 'accepts a property name instead of a function, which checks that property from each item', ->
544
- array = [ { name: 'a', prop: false }, { name: 'b', prop: true } ]
545
- results = up.util.reject array, 'prop'
546
- expect(results).toEqual [{ name: 'a', prop: false }]
547
-
548
- it 'iterates over an array-like value', ->
549
- one = fixture('.qwertz')
550
- two = fixture('.qwertz')
551
- nodeList = document.querySelectorAll('.qwertz')
552
-
553
- callback = jasmine.createSpy()
554
-
555
- up.util.reject nodeList, callback
556
- expect(callback.calls.allArgs()).toEqual [[one, 0], [two, 1]]
557
-
558
- describe 'up.util.previewable', ->
559
-
560
- it 'wraps a function into a proxy function with an additional .promise attribute', ->
561
- fun = -> 'return value'
562
- proxy = up.util.previewable(fun)
563
- expect(u.isFunction(proxy)).toBe(true)
564
- expect(u.isPromise(proxy.promise)).toBe(true)
565
- expect(proxy()).toEqual('return value')
566
-
567
- it "resolves the proxy's .promise when the inner function returns", (done) ->
568
- fun = -> 'return value'
569
- proxy = up.util.previewable(fun)
570
- callback = jasmine.createSpy('promise callback')
571
- proxy.promise.then(callback)
572
- u.task ->
573
- expect(callback).not.toHaveBeenCalled()
574
- proxy()
575
- u.task ->
576
- expect(callback).toHaveBeenCalledWith('return value')
577
- done()
578
-
579
- it "delays resolution of the proxy's .promise if the inner function returns a promise", (done) ->
580
- funDeferred = u.newDeferred()
581
- fun = -> funDeferred
582
- proxy = up.util.previewable(fun)
583
- callback = jasmine.createSpy('promise callback')
584
- proxy.promise.then(callback)
585
- proxy()
586
- u.task ->
587
- expect(callback).not.toHaveBeenCalled()
588
- funDeferred.resolve('return value')
589
- u.task ->
590
- expect(callback).toHaveBeenCalledWith('return value')
591
- done()
592
-
593
- describe 'up.util.sequence', ->
594
-
595
- it 'combines the given functions into a single function', ->
596
- values = []
597
- one = -> values.push('one')
598
- two = -> values.push('two')
599
- three = -> values.push('three')
600
- sequence = up.util.sequence([one, two, three])
601
- expect(values).toEqual([])
602
- sequence()
603
- expect(values).toEqual(['one', 'two', 'three'])
604
-
605
- describe 'up.util.muteRejection', ->
606
-
607
- it 'returns a promise that fulfills when the given promise fulfills', (done) ->
608
- fulfilledPromise = Promise.resolve()
609
- mutedPromise = up.util.muteRejection(fulfilledPromise)
610
-
611
- u.task ->
612
- promiseState(mutedPromise).then (result) ->
613
- expect(result.state).toEqual('fulfilled')
614
- done()
615
-
616
- it 'returns a promise that fulfills when the given promise rejects', (done) ->
617
- rejectedPromise = Promise.reject()
618
- mutedPromise = up.util.muteRejection(rejectedPromise)
619
-
620
- u.task ->
621
- promiseState(mutedPromise).then (result) ->
622
- expect(result.state).toEqual('fulfilled')
623
- done()
624
-
625
- describe 'up.util.simpleEase', ->
626
-
627
- it 'returns 0 for 0', ->
628
- expect(up.util.simpleEase(0)).toBe(0)
629
-
630
- it 'returns 1 for 1', ->
631
- expect(up.util.simpleEase(1)).toBe(1)
632
-
633
- it 'returns steadily increasing values between 0 and 1', ->
634
- expect(up.util.simpleEase(0.25)).toBeAround(0.25, 0.2)
635
- expect(up.util.simpleEase(0.50)).toBeAround(0.50, 0.2)
636
- expect(up.util.simpleEase(0.75)).toBeAround(0.75, 0.2)
637
-
638
- describe 'up.util.timer', ->
639
-
640
- it 'calls the given function after waiting the given milliseconds', (done) ->
641
- callback = jasmine.createSpy()
642
- expectNotCalled = -> expect(callback).not.toHaveBeenCalled()
643
- expectCalled = -> expect(callback).toHaveBeenCalled()
644
-
645
- up.util.timer(100, callback)
646
-
647
- expectNotCalled()
648
- setTimeout(expectNotCalled, 50)
649
- setTimeout(expectCalled, 50 + 75)
650
- setTimeout(done, 50 + 75)
651
-
652
- describe 'if the delay is zero', ->
653
-
654
- it 'calls the given function in the next execution frame', ->
655
- callback = jasmine.createSpy()
656
- up.util.timer(0, callback)
657
- expect(callback).not.toHaveBeenCalled()
658
-
659
- setTimeout((-> expect(callback).toHaveBeenCalled()), 0)
660
-
661
- # describe 'up.util.argNames', ->
662
- #
663
- # it 'returns an array of argument names for the given function', ->
664
- # fun = ($element, data) ->
665
- # expect(up.util.argNames(fun)).toEqual(['$element', 'data'])
666
-
667
- describe 'up.util.only', ->
668
-
669
- it 'returns a copy of the given object with only the given whitelisted properties', ->
670
- original =
671
- foo: 'foo-value'
672
- bar: 'bar-value'
673
- baz: 'baz-value'
674
- bam: 'bam-value'
675
- whitelisted = up.util.only(original, 'bar', 'bam')
676
- expect(whitelisted).toEqual
677
- bar: 'bar-value'
678
- bam: 'bam-value'
679
- # Show that original did not change
680
- expect(original).toEqual
681
- foo: 'foo-value'
682
- bar: 'bar-value'
683
- baz: 'baz-value'
684
- bam: 'bam-value'
685
-
686
- it 'does not add empty keys to the returned object if the given object does not have that key', ->
687
- original =
688
- foo: 'foo-value'
689
- whitelisted = up.util.only(original, 'foo', 'bar')
690
- expect(whitelisted).toHaveOwnProperty('foo')
691
- expect(whitelisted).not.toHaveOwnProperty('bar')
692
-
693
- describe 'up.util.except', ->
694
-
695
- it 'returns a copy of the given object but omits the given blacklisted properties', ->
696
- original =
697
- foo: 'foo-value'
698
- bar: 'bar-value'
699
- baz: 'baz-value'
700
- bam: 'bam-value'
701
- whitelisted = up.util.except(original, 'foo', 'baz')
702
- expect(whitelisted).toEqual
703
- bar: 'bar-value'
704
- bam: 'bam-value'
705
- # Show that original did not change
706
- expect(original).toEqual
707
- foo: 'foo-value'
708
- bar: 'bar-value'
709
- baz: 'baz-value'
710
- bam: 'bam-value'
711
-
712
- describe 'up.util.every', ->
713
-
714
- it 'returns true if all element in the array returns true for the given function', ->
715
- result = up.util.every ['foo', 'bar', 'baz'], up.util.isPresent
716
- expect(result).toBe(true)
717
-
718
- it 'returns false if an element in the array returns false for the given function', ->
719
- result = up.util.every ['foo', 'bar', null, 'baz'], up.util.isPresent
720
- expect(result).toBe(false)
721
-
722
- it 'short-circuits once an element returns false', ->
723
- count = 0
724
- up.util.every ['foo', 'bar', '', 'baz'], (element) ->
725
- count += 1
726
- up.util.isPresent(element)
727
- expect(count).toBe(3)
728
-
729
- it 'passes the iteration index as second argument to the given function', ->
730
- array = ["apple", "orange", "cucumber"]
731
- args = []
732
- up.util.every array, (item, index) ->
733
- args.push(index)
734
- true
735
- expect(args).toEqual [0, 1, 2]
736
-
737
- it 'accepts a property name instead of a function, which collects that property from each item', ->
738
- allTrue = [ { prop: true }, { prop: true } ]
739
- someFalse = [ { prop: true }, { prop: false } ]
740
- expect(up.util.every(allTrue, 'prop')).toBe(true)
741
- expect(up.util.every(someFalse, 'prop')).toBe(false)
742
-
743
- # describe 'up.util.none', ->
744
- #
745
- # it 'returns true if no element in the array returns true for the given function', ->
746
- # result = up.util.none ['foo', 'bar', 'baz'], up.util.isBlank
747
- # expect(result).toBe(true)
748
- #
749
- # it 'returns false if an element in the array returns false for the given function', ->
750
- # result = up.util.none ['foo', 'bar', null, 'baz'], up.util.isBlank
751
- # expect(result).toBe(false)
752
- #
753
- # it 'short-circuits once an element returns true', ->
754
- # count = 0
755
- # up.util.none ['foo', 'bar', '', 'baz'], (element) ->
756
- # count += 1
757
- # up.util.isBlank(element)
758
- # expect(count).toBe(3)
759
- #
760
- # it 'passes the iteration index as second argument to the given function', ->
761
- # array = ["apple", "orange", "cucumber"]
762
- # args = []
763
- # up.util.none array, (item, index) ->
764
- # args.push(index)
765
- # false
766
- # expect(args).toEqual [0, 1, 2]
767
- #
768
- # it 'accepts a property name instead of a function, which collects that property from each item', ->
769
- # allFalse = [ { prop: false }, { prop: false } ]
770
- # someTrue = [ { prop: true }, { prop: false } ]
771
- # expect(up.util.none(allFalse, 'prop')).toBe(true)
772
- # expect(up.util.none(someTrue, 'prop')).toBe(false)
773
-
774
- describe 'up.util.some', ->
775
-
776
- it 'returns true if at least one element in the array returns true for the given function', ->
777
- result = up.util.some ['', 'bar', null], up.util.isPresent
778
- expect(result).toBe(true)
779
-
780
- it 'returns false if no element in the array returns true for the given function', ->
781
- result = up.util.some ['', null, undefined], up.util.isPresent
782
- expect(result).toBe(false)
783
-
784
- it 'passes the iteration index as second argument to the given function', ->
785
- array = ["apple", "orange", "cucumber"]
786
- args = []
787
- up.util.some array, (item, index) ->
788
- args.push(index)
789
- false
790
- expect(args).toEqual [0, 1, 2]
791
-
792
- it 'accepts a property name instead of a function, which collects that property from each item', ->
793
- someTrue = [ { prop: true }, { prop: false } ]
794
- allFalse = [ { prop: false }, { prop: false } ]
795
- expect(up.util.some(someTrue, 'prop')).toBe(true)
796
- expect(up.util.some(allFalse, 'prop')).toBe(false)
797
-
798
- it 'short-circuits once an element returns true', ->
799
- count = 0
800
- up.util.some [null, undefined, 'foo', ''], (element) ->
801
- count += 1
802
- up.util.isPresent(element)
803
- expect(count).toBe(3)
804
-
805
- it 'iterates over an array-like value', ->
806
- one = fixture('.qwertz')
807
- two = fixture('.qwertz')
808
- nodeList = document.querySelectorAll('.qwertz')
809
-
810
- callback = jasmine.createSpy()
811
-
812
- up.util.some nodeList, callback
813
- expect(callback.calls.allArgs()).toEqual [[one, 0], [two, 1]]
814
-
815
- describe 'up.util.findResult', ->
816
-
817
- it 'consecutively applies the function to each array element and returns the first truthy return value', ->
818
- map = {
819
- a: '',
820
- b: null,
821
- c: undefined,
822
- d: 'DEH',
823
- e: 'EH'
824
- }
825
- fn = (el) -> map[el]
826
-
827
- result = up.util.findResult ['a', 'b', 'c', 'd', 'e'], fn
828
- expect(result).toEqual('DEH')
829
-
830
- it 'returns undefined if the function does not return a truthy value for any element in the array', ->
831
- map = {}
832
- fn = (el) -> map[el]
833
-
834
- result = up.util.findResult ['a', 'b', 'c'], fn
835
- expect(result).toBeUndefined()
836
-
837
- it 'iterates over an array-like value', ->
838
- one = fixture('.qwertz')
839
- two = fixture('.qwertz')
840
- nodeList = document.querySelectorAll('.qwertz')
841
-
842
- callback = jasmine.createSpy()
843
-
844
- up.util.findResult nodeList, callback
845
- expect(callback.calls.allArgs()).toEqual [[one, 0], [two, 1]]
846
-
847
- describe 'up.util.isBlank', ->
848
-
849
- it 'returns false for false', ->
850
- expect(up.util.isBlank(false)).toBe(false)
851
-
852
- it 'returns false for true', ->
853
- expect(up.util.isBlank(true)).toBe(false)
854
-
855
- it 'returns true for null', ->
856
- expect(up.util.isBlank(null)).toBe(true)
857
-
858
- it 'returns true for undefined', ->
859
- expect(up.util.isBlank(undefined)).toBe(true)
860
-
861
- it 'returns true for an empty String', ->
862
- expect(up.util.isBlank('')).toBe(true)
863
-
864
- it 'returns false for a String with at least one character', ->
865
- expect(up.util.isBlank('string')).toBe(false)
866
-
867
- it 'returns true for an empty array', ->
868
- expect(up.util.isBlank([])).toBe(true)
869
-
870
- it 'returns false for an array with at least one element', ->
871
- expect(up.util.isBlank(['element'])).toBe(false)
872
-
873
- it 'returns true for an empty jQuery collection', ->
874
- expect(up.util.isBlank($([]))).toBe(true)
875
-
876
- it 'returns false for a jQuery collection with at least one element', ->
877
- expect(up.util.isBlank($('body'))).toBe(false)
878
-
879
- it 'returns true for an empty object', ->
880
- expect(up.util.isBlank({})).toBe(true)
881
-
882
- it 'returns false for a function', ->
883
- expect(up.util.isBlank((->))).toBe(false)
884
-
885
- it 'returns true for an object with at least one key', ->
886
- expect(up.util.isBlank({key: 'value'})).toBe(false)
887
-
888
- it 'returns true for an object with an [up.util.isBlank.key] method that returns true', ->
889
- value = {}
890
- value[up.util.isBlank.key] = -> true
891
- expect(up.util.isBlank(value)).toBe(true)
892
-
893
- it 'returns false for an object with an [up.util.isBlank.key] method that returns false', ->
894
- value = {}
895
- value[up.util.isBlank.key] = -> false
896
- expect(up.util.isBlank(value)).toBe(false)
897
-
898
- it 'returns false for a DOM element', ->
899
- value = document.body
900
- expect(up.util.isBlank(value)).toBe(false)
901
-
902
- describe 'up.util.normalizeUrl', ->
903
-
904
- it 'normalizes a relative path', ->
905
- up.history.config.enabled = true
906
- up.history.replace('/qux/')
907
- expect(up.util.normalizeUrl('foo')).toBe("http://#{location.hostname}:#{location.port}/qux/foo")
908
-
909
- it 'normalizes an absolute path', ->
910
- expect(up.util.normalizeUrl('/foo')).toBe("http://#{location.hostname}:#{location.port}/foo")
911
-
912
- it 'normalizes a full URL', ->
913
- expect(up.util.normalizeUrl('http://example.com/foo/bar')).toBe('http://example.com/foo/bar')
914
-
915
- it 'preserves a query string', ->
916
- expect(up.util.normalizeUrl('http://example.com/foo/bar?key=value')).toBe('http://example.com/foo/bar?key=value')
917
-
918
- it 'strips a query string with { search: false } option', ->
919
- expect(up.util.normalizeUrl('http://example.com/foo/bar?key=value', search: false)).toBe('http://example.com/foo/bar')
920
-
921
- it 'does not strip a trailing slash by default', ->
922
- expect(up.util.normalizeUrl('/foo/')).toEqual("http://#{location.hostname}:#{location.port}/foo/")
923
-
924
- it 'normalizes redundant segments', ->
925
- expect(up.util.normalizeUrl('/foo/../foo')).toBe("http://#{location.hostname}:#{location.port}/foo")
926
-
927
- it 'strips a #hash by default', ->
928
- expect(up.util.normalizeUrl('http://example.com/foo/bar#fragment')).toBe('http://example.com/foo/bar')
929
-
930
- it 'preserves a #hash with { hash: true } option', ->
931
- expect(up.util.normalizeUrl('http://example.com/foo/bar#fragment', hash: true)).toBe('http://example.com/foo/bar#fragment')
932
-
933
- it 'puts a #hash behind the query string', ->
934
- expect(up.util.normalizeUrl('http://example.com/foo/bar?key=value#fragment', hash: true)).toBe('http://example.com/foo/bar?key=value#fragment')
935
-
936
- describe 'up.util.find', ->
937
-
938
- it 'finds the first element in the given array that matches the given tester', ->
939
- array = ['foo', 'bar', 'baz']
940
- tester = (element) -> element[0] == 'b'
941
- expect(up.util.find(array, tester)).toEqual('bar')
942
-
943
- it "returns undefined if the given array doesn't contain a matching element", ->
944
- array = ['foo', 'bar', 'baz']
945
- tester = (element) -> element[0] == 'z'
946
- expect(up.util.find(array, tester)).toBeUndefined()
947
-
948
- describe 'up.util.remove', ->
949
-
950
- it 'removes the given string from the given array', ->
951
- array = ['a', 'b', 'c']
952
- up.util.remove(array, 'b')
953
- expect(array).toEqual ['a', 'c']
954
-
955
- it 'removes the given object from the given array', ->
956
- obj1 = { 'key': 1 }
957
- obj2 = { 'key': 2 }
958
- obj3 = { 'key': 3 }
959
- array = [obj1, obj2, obj3]
960
- up.util.remove(array, obj2)
961
- expect(array).toEqual [obj1, obj3]
962
-
963
- describe 'up.util.unresolvablePromise', ->
964
-
965
- it 'return a pending promise', (done) ->
966
- promise = up.util.unresolvablePromise()
967
- promiseState(promise).then (result) ->
968
- expect(result.state).toEqual('pending')
969
- done()
970
-
971
- it 'returns a different object every time (to prevent memory leaks)', ->
972
- one = up.util.unresolvablePromise()
973
- two = up.util.unresolvablePromise()
974
- expect(one).not.toBe(two)
975
-
976
- describe 'up.util.flatten', ->
977
-
978
- it 'flattens the given array', ->
979
- array = [1, [2, 3], 4]
980
- expect(u.flatten(array)).toEqual([1, 2, 3, 4])
981
-
982
- it 'only flattens one level deep for performance reasons', ->
983
- array = [1, [2, [3,4]], 5]
984
- expect(u.flatten(array)).toEqual([1, 2, [3, 4], 5])
985
-
986
- describe 'up.util.renameKey', ->
987
-
988
- it 'renames a key in the given property', ->
989
- object = { a: 'a value', b: 'b value'}
990
- u.renameKey(object, 'a', 'c')
991
- expect(object.a).toBeUndefined()
992
- expect(object.b).toBe('b value')
993
- expect(object.c).toBe('a value')
994
-
995
- # describe 'up.util.offsetParent', ->
996
- #
997
- # it 'returns the first ascendant that has a "position" style', ->
998
- # $a = $fixture('.a')
999
- # $b = $a.affix('.b').css(position: 'relative')
1000
- # $c = $b.affix('.c')
1001
- # $d = $c.affix('.d')
1002
- #
1003
- # expect(up.util.offsetParent($d[0])).toBe($b[0])
1004
- #
1005
- # it 'does not return the given element, even when it has position', ->
1006
- # $a = $fixture('.a').css(position: 'absolute')
1007
- # $b = $a.affix('.b').css(position: 'relative')
1008
- #
1009
- # expect(up.util.offsetParent($b[0])).toBe($a[0])
1010
- #
1011
- # it 'returns the <body> element if there is no closer offset parent', ->
1012
- # $a = $fixture('.a')
1013
- # $b = $a.affix('.b')
1014
- #
1015
- # expect(up.util.offsetParent($b[0])).toBe(document.body)
1016
- #
1017
- # it 'returns the offset parent for a detached element', ->
1018
- # $a = $fixture('.a').detach()
1019
- # $b = $a.affix('.b').css(position: 'relative')
1020
- # $c = $b.affix('.c')
1021
- # $d = $c.affix('.d')
1022
- #
1023
- # expect(up.util.offsetParent($d[0])).toBe($b[0])
1024
- #
1025
- # it 'returns a missing value (and not <body>) if the given detached element has no ancestor with position', ->
1026
- # $a = $fixture('.a').detach()
1027
- # $b = $a.affix('.b')
1028
- #
1029
- # expect(up.util.offsetParent($b[0])).toBeMissing()
1030
-
1031
- describe 'up.util.isCrossDomain', ->
1032
-
1033
- it 'returns false for an absolute path', ->
1034
- expect(up.util.isCrossDomain('/foo')).toBe(false)
1035
-
1036
- it 'returns false for an relative path', ->
1037
- expect(up.util.isCrossDomain('foo')).toBe(false)
1038
-
1039
- it 'returns false for a fully qualified URL with the same protocol and hostname as the current location', ->
1040
- fullUrl = "#{location.protocol}//#{location.host}/foo"
1041
- expect(up.util.isCrossDomain(fullUrl)).toBe(false)
1042
-
1043
- it 'returns true for a fully qualified URL with a different protocol than the current location', ->
1044
- fullUrl = "otherprotocol://#{location.host}/foo"
1045
- expect(up.util.isCrossDomain(fullUrl)).toBe(true)
1046
-
1047
- it 'returns false for a fully qualified URL with a different hostname than the current location', ->
1048
- fullUrl = "#{location.protocol}//other-host.tld/foo"
1049
- expect(up.util.isCrossDomain(fullUrl)).toBe(true)
1050
-
1051
- describe 'up.util.isOptions', ->
1052
-
1053
- it 'returns true for an Object instance', ->
1054
- expect(up.util.isOptions(new Object())).toBe(true)
1055
-
1056
- it 'returns true for an object literal', ->
1057
- expect(up.util.isOptions({ foo: 'bar'})).toBe(true)
1058
-
1059
- it 'returns true for a prototype-less object', ->
1060
- expect(up.util.isOptions(Object.create(null))).toBe(true)
1061
-
1062
- it 'returns false for undefined', ->
1063
- expect(up.util.isOptions(undefined)).toBe(false)
1064
-
1065
- it 'returns false for null', ->
1066
- expect(up.util.isOptions(null)).toBe(false)
1067
-
1068
- it 'returns false for a function (which is technically an object)', ->
1069
- fn = -> 'foo'
1070
- fn.key = 'value'
1071
- expect(up.util.isOptions(fn)).toBe(false)
1072
-
1073
- it 'returns false for an Array', ->
1074
- expect(up.util.isOptions(['foo'])).toBe(false)
1075
-
1076
- it 'returns false for a jQuery collection', ->
1077
- expect(up.util.isOptions($('body'))).toBe(false)
1078
-
1079
- it 'returns false for a Promise', ->
1080
- expect(up.util.isOptions(Promise.resolve())).toBe(false)
1081
-
1082
- it 'returns false for a FormData object', ->
1083
- expect(up.util.isOptions(new FormData())).toBe(false)
1084
-
1085
- it 'returns false for a Date', ->
1086
- expect(up.util.isOptions(new Date())).toBe(false)
1087
-
1088
- it 'returns false for a RegExp', ->
1089
- expect(up.util.isOptions(new RegExp('foo'))).toBe(false)
1090
-
1091
- describe 'up.util.isObject', ->
1092
-
1093
- it 'returns true for an Object instance', ->
1094
- expect(up.util.isObject(new Object())).toBe(true)
1095
-
1096
- it 'returns true for an object literal', ->
1097
- expect(up.util.isObject({ foo: 'bar'})).toBe(true)
1098
-
1099
- it 'returns false for undefined', ->
1100
- expect(up.util.isObject(undefined)).toBe(false)
1101
-
1102
- it 'returns false for null', ->
1103
- expect(up.util.isObject(null)).toBe(false)
1104
-
1105
- it 'returns true for a function (which is technically an object)', ->
1106
- fn = -> 'foo'
1107
- fn.key = 'value'
1108
- expect(up.util.isObject(fn)).toBe(true)
1109
-
1110
- it 'returns true for an array', ->
1111
- expect(up.util.isObject(['foo'])).toBe(true)
1112
-
1113
- it 'returns true for a jQuery collection', ->
1114
- expect(up.util.isObject($('body'))).toBe(true)
1115
-
1116
- it 'returns true for a promise', ->
1117
- expect(up.util.isObject(Promise.resolve())).toBe(true)
1118
-
1119
- it 'returns true for a FormData object', ->
1120
- expect(up.util.isObject(new FormData())).toBe(true)
1121
-
1122
- describe 'up.util.merge', ->
1123
-
1124
- it 'merges the given objects', ->
1125
- obj = { a: '1', b: '2' }
1126
- other = { b: '3', c: '4' }
1127
- obj = up.util.merge(obj, other)
1128
- expect(obj).toEqual { a: '1', b: '3', c: '4' }
1129
-
1130
- it 'overrides (not merges) keys with object value', ->
1131
- obj = { a: '1', b: { c: '2', d: '3' } }
1132
- other = { e: '4', b: { f: '5', g: '6' }}
1133
- obj = up.util.merge(obj, other)
1134
- expect(obj).toEqual { a: '1', e: '4', b: { f: '5', g: '6' } }
1135
-
1136
- it 'ignores undefined arguments', ->
1137
- obj = { a: 1, b: 2 }
1138
-
1139
- result = up.util.merge(obj, undefined)
1140
- expect(result).toEqual { a: 1, b: 2 }
1141
-
1142
- reverseResult = up.util.merge(undefined, obj)
1143
- expect(reverseResult).toEqual { a: 1, b: 2 }
1144
-
1145
- it 'ignores null arguments', ->
1146
- obj = { a: 1, b: 2 }
1147
-
1148
- result = up.util.merge(obj, null)
1149
- expect(result).toEqual { a: 1, b: 2 }
1150
-
1151
- reverseResult = up.util.merge(null, obj)
1152
- expect(reverseResult).toEqual { a: 1, b: 2 }
1153
-
1154
- # describe 'up.util.deepMerge', ->
1155
- #
1156
- # it 'recursively merges the given objects', ->
1157
- # obj = { a: '1', b: { c: '2', d: '3' } }
1158
- # other = { e: '4', b: { f: '5', g: '6' }}
1159
- # obj = up.util.deepMerge(obj, other)
1160
- # expect(obj).toEqual { a: '1', e: '4', b: { c: '2', d: '3', f: '5', g: '6' } }
1161
- #
1162
- # it 'ignores undefined arguments', ->
1163
- # obj = { a: 1, b: 2 }
1164
- #
1165
- # result = up.util.deepMerge(obj, undefined)
1166
- # expect(result).toEqual { a: 1, b: 2 }
1167
- #
1168
- # reverseResult = up.util.deepMerge(undefined, obj)
1169
- # expect(reverseResult).toEqual { a: 1, b: 2 }
1170
- #
1171
- # it 'ignores null arguments', ->
1172
- # obj = { a: 1, b: 2 }
1173
- #
1174
- # result = up.util.deepMerge(obj, null)
1175
- # expect(result).toEqual { a: 1, b: 2 }
1176
- #
1177
- # reverseResult = up.util.deepMerge(null, obj)
1178
- # expect(reverseResult).toEqual { a: 1, b: 2 }
1179
- #
1180
- # it 'overwrites (and does not concatenate) array values', ->
1181
- # obj = { a: ['1', '2'] }
1182
- # other = { a: ['3', '4'] }
1183
- # obj = up.util.deepMerge(obj, other)
1184
- # expect(obj).toEqual { a: ['3', '4'] }
1185
-
1186
- describe 'up.util.memoize', ->
1187
-
1188
- it 'returns a function that calls the memoized function', ->
1189
- fun = (a, b) -> a + b
1190
- memoized = u.memoize(fun)
1191
- expect(memoized(2, 3)).toEqual(5)
1192
-
1193
- it 'returns the cached return value of the first call when called again', ->
1194
- spy = jasmine.createSpy().and.returnValue(5)
1195
- memoized = u.memoize(spy)
1196
- expect(memoized(2, 3)).toEqual(5)
1197
- expect(memoized(2, 3)).toEqual(5)
1198
- expect(spy.calls.count()).toEqual(1)
1199
-
1200
- ['assign', 'assignPolyfill'].forEach (assignVariant) ->
1201
-
1202
- describe "up.util.#{assignVariant}", ->
1203
-
1204
- assign = up.util[assignVariant]
1205
-
1206
- it 'copies the second object into the first object', ->
1207
- target = { a: 1 }
1208
- source = { b: 2, c: 3 }
1209
-
1210
- assign(target, source)
1211
-
1212
- expect(target).toEqual { a: 1, b: 2, c: 3 }
1213
-
1214
- # Source is unchanged
1215
- expect(source).toEqual { b: 2, c: 3 }
1216
-
1217
- it 'copies null property values', ->
1218
- target = { a: 1, b: 2 }
1219
- source = { b: null }
1220
-
1221
- assign(target, source)
1222
-
1223
- expect(target).toEqual { a: 1, b: null }
1224
-
1225
- it 'copies undefined property values', ->
1226
- target = { a: 1, b: 2 }
1227
- source = { b: undefined }
1228
-
1229
- assign(target, source)
1230
-
1231
- expect(target).toEqual { a: 1, b: undefined }
1232
-
1233
- it 'returns the first object', ->
1234
- target = { a: 1 }
1235
- source = { b: 2 }
1236
-
1237
- result = assign(target, source)
1238
-
1239
- expect(result).toBe(target)
1240
-
1241
- it 'takes multiple sources to copy from', ->
1242
- target = { a: 1 }
1243
- source1 = { b: 2, c: 3 }
1244
- source2 = { d: 4, e: 5 }
1245
-
1246
- assign(target, source1, source2)
1247
-
1248
- expect(target).toEqual { a: 1, b: 2, c: 3, d: 4, e: 5 }
1249
-
1250
- describe 'up.util.copy', ->
1251
-
1252
- it 'returns a shallow copy of the given array', ->
1253
- original = ['a', { b: 'c' }, 'd']
1254
-
1255
- copy = up.util.copy(original)
1256
- expect(copy).toEqual(original)
1257
-
1258
- # Test that changes to copy don't change original
1259
- copy.pop()
1260
- expect(copy.length).toBe(2)
1261
- expect(original.length).toBe(3)
1262
-
1263
- # Test that the copy is shallow
1264
- copy[1].x = 'y'
1265
- expect(original[1].x).toEqual('y')
1266
-
1267
- it 'returns a shallow copy of the given plain object', ->
1268
- original = {a: 'b', c: [1, 2], d: 'e'}
1269
-
1270
- copy = up.util.copy(original)
1271
- expect(copy).toEqual(original)
1272
-
1273
- # Test that changes to copy don't change original
1274
- copy.f = 'g'
1275
- expect(original.f).toBeMissing()
1276
-
1277
- # Test that the copy is shallow
1278
- copy.c.push(3)
1279
- expect(original.c).toEqual [1, 2, 3]
1280
-
1281
- it 'allows custom classes to hook into the copy protocol by implementing a method named `up.util.copy.key`', ->
1282
- class TestClass
1283
- "#{up.util.copy.key}": ->
1284
- return "custom copy"
1285
-
1286
- instance = new TestClass()
1287
- expect(up.util.copy(instance)).toEqual("custom copy")
1288
-
1289
- it 'copies the given jQuery collection into an array', ->
1290
- $one = $fixture('.one')
1291
- $two = $fixture('.two')
1292
- $collection = $one.add($two)
1293
-
1294
- copy = up.util.copy($collection)
1295
-
1296
- copy[0] = document.body
1297
- expect($collection[0]).toBe($one[0])
1298
-
1299
- it 'copies the given arguments object into an array', ->
1300
- args = undefined
1301
- (-> args = arguments)(1)
1302
-
1303
- copy = up.util.copy(args)
1304
- expect(copy).toBeArray()
1305
-
1306
- copy[0] = 2
1307
- expect(args[0]).toBe(1)
1308
-
1309
- it 'returns the given string (which is immutable)', ->
1310
- str = "foo"
1311
- copy = up.util.copy(str)
1312
- expect(copy).toBe(str)
1313
-
1314
- it 'returns the given number (which is immutable)', ->
1315
- number = 123
1316
- copy = up.util.copy(number)
1317
- expect(copy).toBe(number)
1318
-
1319
- it 'copies the given Date object', ->
1320
- date = new Date('1995-12-17T03:24:00')
1321
- expect(date.getFullYear()).toBe(1995)
1322
-
1323
- copy = up.util.copy(date)
1324
-
1325
- expect(copy.getFullYear()).toBe(1995)
1326
- expect(copy.getHours()).toBe(3)
1327
- expect(copy.getMinutes()).toBe(24)
1328
-
1329
- date.setFullYear(2018)
1330
-
1331
- expect(copy.getFullYear()).toBe(1995)
1332
-
1333
-
1334
- describe 'up.util.deepCopy', ->
1335
-
1336
- it 'returns a deep copy of the given array', ->
1337
- original = ['a', { b: 'c' }, 'd']
1338
-
1339
- copy = up.util.deepCopy(original)
1340
- expect(copy).toEqual(original)
1341
-
1342
- # Test that changes to copy don't change original
1343
- copy.pop()
1344
- expect(copy.length).toBe(2)
1345
- expect(original.length).toBe(3)
1346
-
1347
- # Test that the copy is deep
1348
- copy[1].x = 'y'
1349
- expect(original[1].x).toBeUndefined()
1350
-
1351
- it 'returns a deep copy of the given object', ->
1352
- original = {a: 'b', c: [1, 2], d: 'e'}
1353
-
1354
- copy = up.util.deepCopy(original)
1355
- expect(copy).toEqual(original)
1356
-
1357
- # Test that changes to copy don't change original
1358
- copy.f = 'g'
1359
- expect(original.f).toBeMissing()
1360
-
1361
- # Test that the copy is deep
1362
- copy.c.push(3)
1363
- expect(original.c).toEqual [1, 2]
1364
-
1365
- describe 'up.util.isList', ->
1366
-
1367
- it 'returns true for an array', ->
1368
- value = [1, 2, 3]
1369
- expect(up.util.isList(value)).toBe(true)
1370
-
1371
- it 'returns true for an HTMLCollection', ->
1372
- value = document.getElementsByTagName('div')
1373
- expect(up.util.isList(value)).toBe(true)
1374
-
1375
- it 'returns true for a NodeList', ->
1376
- value = document.querySelectorAll('div')
1377
- expect(up.util.isList(value)).toBe(true)
1378
-
1379
- it 'returns true for an arguments object', ->
1380
- value = undefined
1381
- (-> value = arguments)()
1382
- expect(up.util.isList(value)).toBe(true)
1383
-
1384
- it 'returns false for an object', ->
1385
- value = { foo: 'bar' }
1386
- expect(up.util.isList(value)).toBe(false)
1387
-
1388
- it 'returns false for a string', ->
1389
- value = 'foo'
1390
- expect(up.util.isList(value)).toBe(false)
1391
-
1392
- it 'returns false for a number', ->
1393
- value = 123
1394
- expect(up.util.isList(value)).toBe(false)
1395
-
1396
- it 'returns false for undefined', ->
1397
- value = undefined
1398
- expect(up.util.isList(value)).toBe(false)
1399
-
1400
- it 'returns false for null', ->
1401
- value = null
1402
- expect(up.util.isList(value)).toBe(false)
1403
-
1404
- it 'returns false for NaN', ->
1405
- value = NaN
1406
- expect(up.util.isList(value)).toBe(false)
1407
-
1408
- describe 'up.util.isJQuery', ->
1409
-
1410
- it 'returns true for a jQuery collection', ->
1411
- value = $('body')
1412
- expect(up.util.isJQuery(value)).toBe(true)
1413
-
1414
- it 'returns false for a native element', ->
1415
- value = document.body
1416
- expect(up.util.isJQuery(value)).toBe(false)
1417
-
1418
- it 'returns false (and does not crash) for undefined', ->
1419
- value = undefined
1420
- expect(up.util.isJQuery(value)).toBe(false)