unpoly-rails 0.20.0

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 (339) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.ruby-version +2 -0
  4. data/.yardopts +1 -0
  5. data/CHANGELOG.md +577 -0
  6. data/Gemfile +8 -0
  7. data/Gemfile.lock +42 -0
  8. data/LICENSE +22 -0
  9. data/README.md +75 -0
  10. data/README_RAILS.md +116 -0
  11. data/Rakefile +45 -0
  12. data/bower.json +26 -0
  13. data/design/animation-ghosting.txt +72 -0
  14. data/design/design.txt +34 -0
  15. data/design/draft.html.erb +48 -0
  16. data/design/draft.rb +9 -0
  17. data/design/ghost-debugging.txt +118 -0
  18. data/design/homepage.txt +236 -0
  19. data/design/rename.txt +0 -0
  20. data/dist/unpoly-bootstrap3.css +5 -0
  21. data/dist/unpoly-bootstrap3.js +28 -0
  22. data/dist/unpoly-bootstrap3.min.css +1 -0
  23. data/dist/unpoly-bootstrap3.min.js +1 -0
  24. data/dist/unpoly.css +98 -0
  25. data/dist/unpoly.js +9041 -0
  26. data/dist/unpoly.min.css +1 -0
  27. data/dist/unpoly.min.js +3 -0
  28. data/lib/assets/javascripts/unpoly-bootstrap3.js.coffee +2 -0
  29. data/lib/assets/javascripts/unpoly-bootstrap3/form-ext.js.coffee +1 -0
  30. data/lib/assets/javascripts/unpoly-bootstrap3/layout-ext.js.coffee +5 -0
  31. data/lib/assets/javascripts/unpoly-bootstrap3/modal-ext.js.coffee +11 -0
  32. data/lib/assets/javascripts/unpoly-bootstrap3/navigation-ext.js.coffee +3 -0
  33. data/lib/assets/javascripts/unpoly.js.coffee +20 -0
  34. data/lib/assets/javascripts/unpoly/browser.js.coffee +252 -0
  35. data/lib/assets/javascripts/unpoly/bus.js.coffee +393 -0
  36. data/lib/assets/javascripts/unpoly/flow.js.coffee +809 -0
  37. data/lib/assets/javascripts/unpoly/form.js.coffee +864 -0
  38. data/lib/assets/javascripts/unpoly/history.js.coffee +204 -0
  39. data/lib/assets/javascripts/unpoly/layout.js.coffee +529 -0
  40. data/lib/assets/javascripts/unpoly/link.js.coffee +496 -0
  41. data/lib/assets/javascripts/unpoly/log.js.coffee +73 -0
  42. data/lib/assets/javascripts/unpoly/modal.js.coffee +509 -0
  43. data/lib/assets/javascripts/unpoly/module.js.coffee +4 -0
  44. data/lib/assets/javascripts/unpoly/motion.js.coffee +690 -0
  45. data/lib/assets/javascripts/unpoly/navigation.js.coffee +219 -0
  46. data/lib/assets/javascripts/unpoly/popup.js.coffee +409 -0
  47. data/lib/assets/javascripts/unpoly/proxy.js.coffee +521 -0
  48. data/lib/assets/javascripts/unpoly/rails.js.coffee +36 -0
  49. data/lib/assets/javascripts/unpoly/syntax.js.coffee +337 -0
  50. data/lib/assets/javascripts/unpoly/tooltip.js.coffee +183 -0
  51. data/lib/assets/javascripts/unpoly/util.js.coffee +1593 -0
  52. data/lib/assets/stylesheets/unpoly-bootstrap3.css.sass +1 -0
  53. data/lib/assets/stylesheets/unpoly-bootstrap3/modal-ext.css.sass +9 -0
  54. data/lib/assets/stylesheets/unpoly.css.sass +1 -0
  55. data/lib/assets/stylesheets/unpoly/close.css.sass +2 -0
  56. data/lib/assets/stylesheets/unpoly/error.css.sass +15 -0
  57. data/lib/assets/stylesheets/unpoly/link.css.sass +2 -0
  58. data/lib/assets/stylesheets/unpoly/modal.css.sass +69 -0
  59. data/lib/assets/stylesheets/unpoly/popup.css.sass +8 -0
  60. data/lib/assets/stylesheets/unpoly/tooltip.css.sass +42 -0
  61. data/lib/unpoly-rails.rb +7 -0
  62. data/lib/unpoly/rails/engine.rb +6 -0
  63. data/lib/unpoly/rails/inspector.rb +78 -0
  64. data/lib/unpoly/rails/inspector_accessor.rb +30 -0
  65. data/lib/unpoly/rails/request_echo_headers.rb +27 -0
  66. data/lib/unpoly/rails/request_method_cookie.rb +36 -0
  67. data/lib/unpoly/rails/version.rb +9 -0
  68. data/spec_app/.firefox-version +1 -0
  69. data/spec_app/.gitignore +17 -0
  70. data/spec_app/.rspec +2 -0
  71. data/spec_app/Bowerfile +3 -0
  72. data/spec_app/Gemfile +29 -0
  73. data/spec_app/Gemfile.lock +212 -0
  74. data/spec_app/README.rdoc +28 -0
  75. data/spec_app/Rakefile +6 -0
  76. data/spec_app/app/assets/images/.keep +0 -0
  77. data/spec_app/app/assets/javascripts/application.js +20 -0
  78. data/spec_app/app/assets/stylesheets/application.css +17 -0
  79. data/spec_app/app/assets/stylesheets/blocks/card.css.sass +11 -0
  80. data/spec_app/app/assets/stylesheets/blocks/controls.css.sass +7 -0
  81. data/spec_app/app/assets/stylesheets/blocks/menu.css.sass +13 -0
  82. data/spec_app/app/assets/stylesheets/blocks/panel.css.sass +8 -0
  83. data/spec_app/app/assets/stylesheets/jasmine_specs.css +5 -0
  84. data/spec_app/app/controllers/application_controller.rb +6 -0
  85. data/spec_app/app/controllers/concerns/.keep +0 -0
  86. data/spec_app/app/controllers/test_controller.rb +28 -0
  87. data/spec_app/app/helpers/application_helper.rb +2 -0
  88. data/spec_app/app/mailers/.keep +0 -0
  89. data/spec_app/app/models/concerns/.keep +0 -0
  90. data/spec_app/app/views/layouts/application.html.erb +12 -0
  91. data/spec_app/bin/bundle +3 -0
  92. data/spec_app/bin/rails +8 -0
  93. data/spec_app/bin/rake +8 -0
  94. data/spec_app/bin/setup +29 -0
  95. data/spec_app/bin/spring +18 -0
  96. data/spec_app/config.ru +4 -0
  97. data/spec_app/config/application.rb +26 -0
  98. data/spec_app/config/boot.rb +3 -0
  99. data/spec_app/config/database.yml +25 -0
  100. data/spec_app/config/environment.rb +5 -0
  101. data/spec_app/config/environments/development.rb +41 -0
  102. data/spec_app/config/environments/production.rb +79 -0
  103. data/spec_app/config/environments/test.rb +42 -0
  104. data/spec_app/config/initializers/assets.rb +11 -0
  105. data/spec_app/config/initializers/backtrace_silencers.rb +7 -0
  106. data/spec_app/config/initializers/bower_rails.rb +16 -0
  107. data/spec_app/config/initializers/cookies_serializer.rb +3 -0
  108. data/spec_app/config/initializers/filter_parameter_logging.rb +4 -0
  109. data/spec_app/config/initializers/inflections.rb +16 -0
  110. data/spec_app/config/initializers/mime_types.rb +4 -0
  111. data/spec_app/config/initializers/session_store.rb +3 -0
  112. data/spec_app/config/initializers/wrap_parameters.rb +14 -0
  113. data/spec_app/config/locales/en.yml +23 -0
  114. data/spec_app/config/routes.rb +8 -0
  115. data/spec_app/config/secrets.yml +22 -0
  116. data/spec_app/db/schema.rb +23 -0
  117. data/spec_app/db/seeds.rb +7 -0
  118. data/spec_app/lib/assets/.keep +0 -0
  119. data/spec_app/lib/tasks/.keep +0 -0
  120. data/spec_app/lib/tasks/cucumber.rake +65 -0
  121. data/spec_app/log/.keep +0 -0
  122. data/spec_app/public/404.html +67 -0
  123. data/spec_app/public/422.html +67 -0
  124. data/spec_app/public/500.html +66 -0
  125. data/spec_app/public/favicon.ico +0 -0
  126. data/spec_app/public/robots.txt +5 -0
  127. data/spec_app/script/cucumber +10 -0
  128. data/spec_app/spec/controllers/test_controller_spec.rb +76 -0
  129. data/spec_app/spec/javascripts/helpers/append_fixture.js.coffee +8 -0
  130. data/spec_app/spec/javascripts/helpers/browser_switches.js.coffee +9 -0
  131. data/spec_app/spec/javascripts/helpers/index.js.coffee +1 -0
  132. data/spec_app/spec/javascripts/helpers/knife.js.coffee +69 -0
  133. data/spec_app/spec/javascripts/helpers/last_request.js.coffee +22 -0
  134. data/spec_app/spec/javascripts/helpers/mock_ajax.js.coffee +5 -0
  135. data/spec_app/spec/javascripts/helpers/mock_clock.js.coffee +2 -0
  136. data/spec_app/spec/javascripts/helpers/remove_body_margin.js.coffee +5 -0
  137. data/spec_app/spec/javascripts/helpers/reset_knife.js.coffee +2 -0
  138. data/spec_app/spec/javascripts/helpers/reset_path.js.coffee +8 -0
  139. data/spec_app/spec/javascripts/helpers/reset_up.js.coffee +4 -0
  140. data/spec_app/spec/javascripts/helpers/restore_body_scroll.js.coffee +2 -0
  141. data/spec_app/spec/javascripts/helpers/set_timer.js.coffee +3 -0
  142. data/spec_app/spec/javascripts/helpers/to_be_around.js.coffee +5 -0
  143. data/spec_app/spec/javascripts/helpers/to_be_blank.js.coffee +5 -0
  144. data/spec_app/spec/javascripts/helpers/to_be_given.js.coffee +5 -0
  145. data/spec_app/spec/javascripts/helpers/to_be_missing.js.coffee +5 -0
  146. data/spec_app/spec/javascripts/helpers/to_be_present.js.coffee +5 -0
  147. data/spec_app/spec/javascripts/helpers/to_end_with.js.coffee +8 -0
  148. data/spec_app/spec/javascripts/helpers/to_equal_jquery.js.coffee +9 -0
  149. data/spec_app/spec/javascripts/helpers/to_have_request_method.js.coffee +8 -0
  150. data/spec_app/spec/javascripts/helpers/trigger.js.coffee +68 -0
  151. data/spec_app/spec/javascripts/support/jasmine.yml +51 -0
  152. data/spec_app/spec/javascripts/up/bus_spec.js.coffee +122 -0
  153. data/spec_app/spec/javascripts/up/flow_spec.js.coffee +755 -0
  154. data/spec_app/spec/javascripts/up/form_spec.js.coffee +471 -0
  155. data/spec_app/spec/javascripts/up/history_spec.js.coffee +96 -0
  156. data/spec_app/spec/javascripts/up/layout_spec.js.coffee +318 -0
  157. data/spec_app/spec/javascripts/up/link_spec.js.coffee +340 -0
  158. data/spec_app/spec/javascripts/up/modal_spec.js.coffee +265 -0
  159. data/spec_app/spec/javascripts/up/motion_spec.js.coffee +306 -0
  160. data/spec_app/spec/javascripts/up/navigation_spec.js.coffee +132 -0
  161. data/spec_app/spec/javascripts/up/popup_spec.js.coffee +220 -0
  162. data/spec_app/spec/javascripts/up/proxy_spec.js.coffee +371 -0
  163. data/spec_app/spec/javascripts/up/rails_spec.js.coffee +101 -0
  164. data/spec_app/spec/javascripts/up/syntax_spec.js.coffee +99 -0
  165. data/spec_app/spec/javascripts/up/tooltip_spec.js.coffee +60 -0
  166. data/spec_app/spec/javascripts/up/util_spec.js.coffee +325 -0
  167. data/spec_app/spec/spec_helper.rb +62 -0
  168. data/spec_app/test/controllers/.keep +0 -0
  169. data/spec_app/test/fixtures/.keep +0 -0
  170. data/spec_app/test/helpers/.keep +0 -0
  171. data/spec_app/test/integration/.keep +0 -0
  172. data/spec_app/test/mailers/.keep +0 -0
  173. data/spec_app/test/models/.keep +0 -0
  174. data/spec_app/test/test_helper.rb +10 -0
  175. data/spec_app/vendor/assets/.bowerrc +3 -0
  176. data/spec_app/vendor/assets/bower.json +8 -0
  177. data/spec_app/vendor/assets/bower_components/jasmine-ajax/.bower.json +43 -0
  178. data/spec_app/vendor/assets/bower_components/jasmine-ajax/MIT.LICENSE +20 -0
  179. data/spec_app/vendor/assets/bower_components/jasmine-ajax/README.markdown +289 -0
  180. data/spec_app/vendor/assets/bower_components/jasmine-ajax/bower.json +35 -0
  181. data/spec_app/vendor/assets/bower_components/jasmine-ajax/lib/mock-ajax.js +733 -0
  182. data/spec_app/vendor/assets/bower_components/jasmine-ajax/package.json +26 -0
  183. data/spec_app/vendor/assets/bower_components/jasmine-ajax/release_notes/2.0.2.md +50 -0
  184. data/spec_app/vendor/assets/bower_components/jasmine-ajax/release_notes/2.99.md +14 -0
  185. data/spec_app/vendor/assets/bower_components/jasmine-ajax/release_notes/3.0.md +28 -0
  186. data/spec_app/vendor/assets/bower_components/jasmine-ajax/release_notes/3.1.0.md +24 -0
  187. data/spec_app/vendor/assets/bower_components/jasmine-ajax/release_notes/3.1.1.md +23 -0
  188. data/spec_app/vendor/assets/bower_components/jasmine-ajax/release_notes/3.2.0.md +20 -0
  189. data/spec_app/vendor/assets/bower_components/jasmine-fixture/.bower.json +27 -0
  190. data/spec_app/vendor/assets/bower_components/jasmine-fixture/.gitignore +8 -0
  191. data/spec_app/vendor/assets/bower_components/jasmine-fixture/.npmignore +8 -0
  192. data/spec_app/vendor/assets/bower_components/jasmine-fixture/LICENSE.txt +24 -0
  193. data/spec_app/vendor/assets/bower_components/jasmine-fixture/README.md +118 -0
  194. data/spec_app/vendor/assets/bower_components/jasmine-fixture/bower.json +17 -0
  195. data/spec_app/vendor/assets/bower_components/jasmine-fixture/dist/jasmine-fixture.js +433 -0
  196. data/spec_app/vendor/assets/bower_components/jasmine-fixture/dist/jasmine-fixture.min.js +5 -0
  197. data/spec_app/vendor/assets/bower_components/jasmine-fixture/spec-e2e/basic-usage-spec.coffee +14 -0
  198. data/spec_app/vendor/assets/bower_components/jasmine-fixture/spec-e2e/helpers/invariants.coffee +17 -0
  199. data/spec_app/vendor/assets/bower_components/jasmine-fixture/spec-e2e/helpers/spec-within-a-spec.coffee +24 -0
  200. data/spec_app/vendor/assets/bower_components/jasmine-fixture/spec-e2e/helpers/tmp-files.coffee +8 -0
  201. data/spec_app/vendor/assets/bower_components/jasmine-fixture/spec-e2e/support/jasmine1-testem-config.json +11 -0
  202. data/spec_app/vendor/assets/bower_components/jasmine-fixture/spec-e2e/support/jasmine2-testem-config.json +11 -0
  203. data/spec_app/vendor/assets/bower_components/jasmine-fixture/vendor/js/jquery-1.11.0.js +10337 -0
  204. data/spec_app/vendor/assets/bower_components/jasmine-fixture/vendor/js/jquery-1.8.3.js +9472 -0
  205. data/spec_app/vendor/assets/bower_components/jasmine-fixture/vendor/js/jquery-2.1.0.js +9111 -0
  206. data/spec_app/vendor/assets/bower_components/jasmine-jquery/.bower.json +26 -0
  207. data/spec_app/vendor/assets/bower_components/jasmine-jquery/CONTRIBUTING.md +28 -0
  208. data/spec_app/vendor/assets/bower_components/jasmine-jquery/Gruntfile.js +49 -0
  209. data/spec_app/vendor/assets/bower_components/jasmine-jquery/LICENSE +20 -0
  210. data/spec_app/vendor/assets/bower_components/jasmine-jquery/README.md +367 -0
  211. data/spec_app/vendor/assets/bower_components/jasmine-jquery/bower.json +15 -0
  212. data/spec_app/vendor/assets/bower_components/jasmine-jquery/lib/jasmine-jquery.js +838 -0
  213. data/spec_app/vendor/assets/bower_components/jasmine-jquery/package.json +35 -0
  214. data/spec_app/vendor/assets/bower_components/jasmine-jquery/spec/fixtures/fixture_with_checkbox_with_checked.html +6 -0
  215. data/spec_app/vendor/assets/bower_components/jasmine-jquery/spec/fixtures/fixture_with_javascript.html +1 -0
  216. data/spec_app/vendor/assets/bower_components/jasmine-jquery/spec/fixtures/fixture_with_javascript_block.html +1 -0
  217. data/spec_app/vendor/assets/bower_components/jasmine-jquery/spec/fixtures/javascripts/jasmine_javascript_click.js +1 -0
  218. data/spec_app/vendor/assets/bower_components/jasmine-jquery/spec/fixtures/javascripts/jasmine_javascript_hover.js +1 -0
  219. data/spec_app/vendor/assets/bower_components/jasmine-jquery/spec/fixtures/json/jasmine_json_test.json +1 -0
  220. data/spec_app/vendor/assets/bower_components/jasmine-jquery/spec/fixtures/real_non_mocked_fixture.html +1 -0
  221. data/spec_app/vendor/assets/bower_components/jasmine-jquery/spec/fixtures/real_non_mocked_fixture_style.css +1 -0
  222. data/spec_app/vendor/assets/bower_components/jasmine-jquery/spec/suites/jasmine-jquery-spec.js +1842 -0
  223. data/spec_app/vendor/assets/bower_components/jasmine/.bower.json +50 -0
  224. data/spec_app/vendor/assets/bower_components/jasmine/CONTRIBUTING.md +130 -0
  225. data/spec_app/vendor/assets/bower_components/jasmine/GOALS_2.0.md +64 -0
  226. data/spec_app/vendor/assets/bower_components/jasmine/MANIFEST.in +5 -0
  227. data/spec_app/vendor/assets/bower_components/jasmine/MIT.LICENSE +20 -0
  228. data/spec_app/vendor/assets/bower_components/jasmine/README.md +73 -0
  229. data/spec_app/vendor/assets/bower_components/jasmine/RELEASE.md +73 -0
  230. data/spec_app/vendor/assets/bower_components/jasmine/bower.json +41 -0
  231. data/spec_app/vendor/assets/bower_components/jasmine/images/jasmine-horizontal.png +0 -0
  232. data/spec_app/vendor/assets/bower_components/jasmine/images/jasmine-horizontal.svg +102 -0
  233. data/spec_app/vendor/assets/bower_components/jasmine/images/jasmine_favicon.png +0 -0
  234. data/spec_app/vendor/assets/bower_components/jasmine/lib/console/console.js +190 -0
  235. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core.js +37 -0
  236. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/boot.js +143 -0
  237. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/example/node_example/lib/jasmine_examples/Player.js +24 -0
  238. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/example/node_example/lib/jasmine_examples/Song.js +9 -0
  239. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/jasmine-html.js +446 -0
  240. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/jasmine.css +58 -0
  241. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/jasmine.js +3298 -0
  242. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/json2.js +489 -0
  243. data/spec_app/vendor/assets/bower_components/jasmine/lib/jasmine-core/node_boot.js +41 -0
  244. data/spec_app/vendor/assets/bower_components/jasmine/package.json +34 -0
  245. data/spec_app/vendor/assets/bower_components/jasmine/requirements.txt +1 -0
  246. data/spec_app/vendor/assets/bower_components/jquery/.bower.json +38 -0
  247. data/spec_app/vendor/assets/bower_components/jquery/MIT-LICENSE.txt +21 -0
  248. data/spec_app/vendor/assets/bower_components/jquery/bower.json +28 -0
  249. data/spec_app/vendor/assets/bower_components/jquery/dist/jquery.js +9210 -0
  250. data/spec_app/vendor/assets/bower_components/jquery/dist/jquery.min.js +5 -0
  251. data/spec_app/vendor/assets/bower_components/jquery/dist/jquery.min.map +1 -0
  252. data/spec_app/vendor/assets/bower_components/jquery/src/ajax.js +786 -0
  253. data/spec_app/vendor/assets/bower_components/jquery/src/ajax/jsonp.js +89 -0
  254. data/spec_app/vendor/assets/bower_components/jquery/src/ajax/load.js +75 -0
  255. data/spec_app/vendor/assets/bower_components/jquery/src/ajax/parseJSON.js +13 -0
  256. data/spec_app/vendor/assets/bower_components/jquery/src/ajax/parseXML.js +28 -0
  257. data/spec_app/vendor/assets/bower_components/jquery/src/ajax/script.js +64 -0
  258. data/spec_app/vendor/assets/bower_components/jquery/src/ajax/var/nonce.js +5 -0
  259. data/spec_app/vendor/assets/bower_components/jquery/src/ajax/var/rquery.js +3 -0
  260. data/spec_app/vendor/assets/bower_components/jquery/src/ajax/xhr.js +136 -0
  261. data/spec_app/vendor/assets/bower_components/jquery/src/attributes.js +11 -0
  262. data/spec_app/vendor/assets/bower_components/jquery/src/attributes/attr.js +141 -0
  263. data/spec_app/vendor/assets/bower_components/jquery/src/attributes/classes.js +158 -0
  264. data/spec_app/vendor/assets/bower_components/jquery/src/attributes/prop.js +94 -0
  265. data/spec_app/vendor/assets/bower_components/jquery/src/attributes/support.js +35 -0
  266. data/spec_app/vendor/assets/bower_components/jquery/src/attributes/val.js +161 -0
  267. data/spec_app/vendor/assets/bower_components/jquery/src/callbacks.js +205 -0
  268. data/spec_app/vendor/assets/bower_components/jquery/src/core.js +502 -0
  269. data/spec_app/vendor/assets/bower_components/jquery/src/core/access.js +60 -0
  270. data/spec_app/vendor/assets/bower_components/jquery/src/core/init.js +123 -0
  271. data/spec_app/vendor/assets/bower_components/jquery/src/core/parseHTML.js +39 -0
  272. data/spec_app/vendor/assets/bower_components/jquery/src/core/ready.js +97 -0
  273. data/spec_app/vendor/assets/bower_components/jquery/src/core/var/rsingleTag.js +4 -0
  274. data/spec_app/vendor/assets/bower_components/jquery/src/css.js +450 -0
  275. data/spec_app/vendor/assets/bower_components/jquery/src/css/addGetHookIf.js +22 -0
  276. data/spec_app/vendor/assets/bower_components/jquery/src/css/curCSS.js +57 -0
  277. data/spec_app/vendor/assets/bower_components/jquery/src/css/defaultDisplay.js +70 -0
  278. data/spec_app/vendor/assets/bower_components/jquery/src/css/hiddenVisibleSelectors.js +15 -0
  279. data/spec_app/vendor/assets/bower_components/jquery/src/css/support.js +96 -0
  280. data/spec_app/vendor/assets/bower_components/jquery/src/css/swap.js +28 -0
  281. data/spec_app/vendor/assets/bower_components/jquery/src/css/var/cssExpand.js +3 -0
  282. data/spec_app/vendor/assets/bower_components/jquery/src/css/var/getStyles.js +12 -0
  283. data/spec_app/vendor/assets/bower_components/jquery/src/css/var/isHidden.js +13 -0
  284. data/spec_app/vendor/assets/bower_components/jquery/src/css/var/rmargin.js +3 -0
  285. data/spec_app/vendor/assets/bower_components/jquery/src/css/var/rnumnonpx.js +5 -0
  286. data/spec_app/vendor/assets/bower_components/jquery/src/data.js +178 -0
  287. data/spec_app/vendor/assets/bower_components/jquery/src/data/Data.js +181 -0
  288. data/spec_app/vendor/assets/bower_components/jquery/src/data/accepts.js +20 -0
  289. data/spec_app/vendor/assets/bower_components/jquery/src/data/var/data_priv.js +5 -0
  290. data/spec_app/vendor/assets/bower_components/jquery/src/data/var/data_user.js +5 -0
  291. data/spec_app/vendor/assets/bower_components/jquery/src/deferred.js +149 -0
  292. data/spec_app/vendor/assets/bower_components/jquery/src/deprecated.js +13 -0
  293. data/spec_app/vendor/assets/bower_components/jquery/src/dimensions.js +50 -0
  294. data/spec_app/vendor/assets/bower_components/jquery/src/effects.js +648 -0
  295. data/spec_app/vendor/assets/bower_components/jquery/src/effects/Tween.js +114 -0
  296. data/spec_app/vendor/assets/bower_components/jquery/src/effects/animatedSelector.js +13 -0
  297. data/spec_app/vendor/assets/bower_components/jquery/src/event.js +868 -0
  298. data/spec_app/vendor/assets/bower_components/jquery/src/event/ajax.js +13 -0
  299. data/spec_app/vendor/assets/bower_components/jquery/src/event/alias.js +39 -0
  300. data/spec_app/vendor/assets/bower_components/jquery/src/event/support.js +9 -0
  301. data/spec_app/vendor/assets/bower_components/jquery/src/exports/amd.js +24 -0
  302. data/spec_app/vendor/assets/bower_components/jquery/src/exports/global.js +32 -0
  303. data/spec_app/vendor/assets/bower_components/jquery/src/intro.js +44 -0
  304. data/spec_app/vendor/assets/bower_components/jquery/src/jquery.js +37 -0
  305. data/spec_app/vendor/assets/bower_components/jquery/src/manipulation.js +580 -0
  306. data/spec_app/vendor/assets/bower_components/jquery/src/manipulation/_evalUrl.js +18 -0
  307. data/spec_app/vendor/assets/bower_components/jquery/src/manipulation/support.js +32 -0
  308. data/spec_app/vendor/assets/bower_components/jquery/src/manipulation/var/rcheckableType.js +3 -0
  309. data/spec_app/vendor/assets/bower_components/jquery/src/offset.js +207 -0
  310. data/spec_app/vendor/assets/bower_components/jquery/src/outro.js +1 -0
  311. data/spec_app/vendor/assets/bower_components/jquery/src/queue.js +142 -0
  312. data/spec_app/vendor/assets/bower_components/jquery/src/queue/delay.js +22 -0
  313. data/spec_app/vendor/assets/bower_components/jquery/src/selector-native.js +172 -0
  314. data/spec_app/vendor/assets/bower_components/jquery/src/selector-sizzle.js +14 -0
  315. data/spec_app/vendor/assets/bower_components/jquery/src/selector.js +1 -0
  316. data/spec_app/vendor/assets/bower_components/jquery/src/serialize.js +111 -0
  317. data/spec_app/vendor/assets/bower_components/jquery/src/sizzle/dist/sizzle.js +2067 -0
  318. data/spec_app/vendor/assets/bower_components/jquery/src/sizzle/dist/sizzle.min.js +3 -0
  319. data/spec_app/vendor/assets/bower_components/jquery/src/sizzle/dist/sizzle.min.map +1 -0
  320. data/spec_app/vendor/assets/bower_components/jquery/src/traversing.js +199 -0
  321. data/spec_app/vendor/assets/bower_components/jquery/src/traversing/findFilter.js +100 -0
  322. data/spec_app/vendor/assets/bower_components/jquery/src/traversing/var/rneedsContext.js +6 -0
  323. data/spec_app/vendor/assets/bower_components/jquery/src/var/arr.js +3 -0
  324. data/spec_app/vendor/assets/bower_components/jquery/src/var/class2type.js +4 -0
  325. data/spec_app/vendor/assets/bower_components/jquery/src/var/concat.js +5 -0
  326. data/spec_app/vendor/assets/bower_components/jquery/src/var/hasOwn.js +5 -0
  327. data/spec_app/vendor/assets/bower_components/jquery/src/var/indexOf.js +5 -0
  328. data/spec_app/vendor/assets/bower_components/jquery/src/var/pnum.js +3 -0
  329. data/spec_app/vendor/assets/bower_components/jquery/src/var/push.js +5 -0
  330. data/spec_app/vendor/assets/bower_components/jquery/src/var/rnotwhite.js +3 -0
  331. data/spec_app/vendor/assets/bower_components/jquery/src/var/slice.js +5 -0
  332. data/spec_app/vendor/assets/bower_components/jquery/src/var/strundefined.js +3 -0
  333. data/spec_app/vendor/assets/bower_components/jquery/src/var/support.js +4 -0
  334. data/spec_app/vendor/assets/bower_components/jquery/src/var/toString.js +5 -0
  335. data/spec_app/vendor/assets/bower_components/jquery/src/wrap.js +79 -0
  336. data/spec_app/vendor/assets/javascripts/.keep +0 -0
  337. data/spec_app/vendor/assets/stylesheets/.keep +0 -0
  338. data/unpoly-rails.gemspec +24 -0
  339. metadata +423 -0
@@ -0,0 +1,122 @@
1
+ describe 'up.bus', ->
2
+
3
+ describe 'Javascript functions', ->
4
+
5
+ describe 'up.on', ->
6
+
7
+ it 'registers a delagating event listener to the document body, which passes the $element as a second argument to the listener', ->
8
+
9
+ affix('.container .child')
10
+ observeClass = jasmine.createSpy()
11
+ up.on 'click', '.child', (event, $element) ->
12
+ observeClass($element.attr('class'))
13
+
14
+ $('.container').click()
15
+ $('.child').click()
16
+
17
+ expect(observeClass).not.toHaveBeenCalledWith('container')
18
+ expect(observeClass).toHaveBeenCalledWith('child')
19
+
20
+ it 'returns a method that unregisters the event listener when called', ->
21
+ $child = affix('.child')
22
+ clickSpy = jasmine.createSpy()
23
+ unsubscribe = up.on 'click', '.child', clickSpy
24
+ $('.child').click()
25
+ unsubscribe()
26
+ $('.child').click()
27
+ expect(clickSpy.calls.count()).toEqual(1)
28
+
29
+ it 'parses an up-data attribute as JSON and passes the parsed object as a third argument to the initializer', ->
30
+ $child = affix('.child')
31
+ observeArgs = jasmine.createSpy()
32
+ up.on 'click', '.child', (event, $element, data) ->
33
+ observeArgs($element.attr('class'), data)
34
+
35
+ data = { key1: 'value1', key2: 'value2' }
36
+ $tag = affix(".child").attr('up-data', JSON.stringify(data))
37
+
38
+ $('.child').click()
39
+ expect(observeArgs).toHaveBeenCalledWith('child', data)
40
+
41
+ it 'passes an empty object as a second argument to the listener if there is no up-data attribute', ->
42
+ $child = affix('.child')
43
+ observeArgs = jasmine.createSpy()
44
+ up.on 'click', '.child', (event, $element, data) ->
45
+ observeArgs($element.attr('class'), data)
46
+
47
+ $('.child').click()
48
+ expect(observeArgs).toHaveBeenCalledWith('child', {})
49
+
50
+ describe 'up.off', ->
51
+
52
+ it 'unregisters an event listener previously registered through up.on', ->
53
+ $child = affix('.child')
54
+ clickSpy = jasmine.createSpy()
55
+ up.on 'click', '.child', clickSpy
56
+ $('.child').click()
57
+ up.off 'click', '.child', clickSpy
58
+ $('.child').click()
59
+ expect(clickSpy.calls.count()).toEqual(1)
60
+
61
+ it 'throws an error if the given event listener was not registered through up.on', ->
62
+ someFunction = ->
63
+ offing = -> up.off 'click', '.child', someFunction
64
+ expect(offing).toThrowError(/(not|never) registered/i)
65
+
66
+ it 'reduces the internally tracked list of event listeners (bugfix for memory leak)', ->
67
+ getCount = -> up.bus.knife.get('Object.keys(liveUpDescriptions).length')
68
+ oldCount = getCount()
69
+ expect(oldCount).toBeGreaterThan(0)
70
+ clickSpy = jasmine.createSpy()
71
+ up.on 'click', '.child', clickSpy
72
+ expect(getCount()).toBe(oldCount + 1)
73
+ up.off 'click', '.child', clickSpy
74
+ expect(getCount()).toBe(oldCount)
75
+
76
+ describe 'up.emit', ->
77
+
78
+ it 'triggers an event on the document', ->
79
+ emittedEvent = undefined
80
+ emitted$Target = undefined
81
+
82
+ up.on 'foo', (event, $target) ->
83
+ emittedEvent = event
84
+ emitted$Target = $target
85
+
86
+ expect(emittedEvent).toBeUndefined()
87
+ expect(emitted$Target).toBeUndefined()
88
+
89
+ up.emit('foo')
90
+
91
+ expect(emittedEvent).toBeDefined()
92
+ expect(emittedEvent.preventDefault).toBeDefined()
93
+ expect(emitted$Target).toEqual($(document))
94
+
95
+ it 'accepts custom event properties', ->
96
+ emittedEvent = undefined
97
+
98
+ up.on 'foo', (event) ->
99
+ emittedEvent = event
100
+
101
+ up.emit('foo', { customField: 'custom-value' })
102
+
103
+ expect(emittedEvent.customField).toEqual('custom-value')
104
+
105
+ describe 'with .$element option', ->
106
+
107
+ it 'triggers an event on the given element', ->
108
+ emittedEvent = undefined
109
+ $emittedTarget = undefined
110
+
111
+ $element = affix('.element').text('foo')
112
+
113
+ up.on 'foo', (event, $target) ->
114
+ emittedEvent = event
115
+ $emittedTarget = $target
116
+
117
+ up.emit('foo', $element: $element)
118
+
119
+ expect(emittedEvent).toBeDefined()
120
+ expect($emittedTarget).toEqual($element)
121
+
122
+ expect(emittedEvent.$element).toEqual($element)
@@ -0,0 +1,755 @@
1
+ describe 'up.flow', ->
2
+
3
+ u = up.util
4
+
5
+ describe 'Javascript functions', ->
6
+
7
+ describe 'up.replace', ->
8
+
9
+ describeCapability 'canPushState', ->
10
+
11
+ beforeEach ->
12
+
13
+ @oldBefore = affix('.before').text('old-before')
14
+ @oldMiddle = affix('.middle').text('old-middle')
15
+ @oldAfter = affix('.after').text('old-after')
16
+
17
+ @responseText =
18
+ """
19
+ <div class="before">new-before</div>
20
+ <div class="middle">new-middle</div>
21
+ <div class="after">new-after</div>
22
+ """
23
+
24
+ @respond = (options = {}) -> @respondWith(@responseText, options)
25
+
26
+ it 'replaces the given selector with the same selector from a freshly fetched page', (done) ->
27
+ promise = up.replace('.middle', '/path')
28
+ @respond()
29
+ promise.then ->
30
+ expect($('.before')).toHaveText('old-before')
31
+ expect($('.middle')).toHaveText('new-middle')
32
+ expect($('.after')).toHaveText('old-after')
33
+ done()
34
+
35
+ it 'sends an X-Up-Target HTTP headers along with the request', ->
36
+ up.replace('.middle', '/path')
37
+ request = @lastRequest()
38
+ console.log(request.requestHeaders)
39
+ expect(request.requestHeaders['X-Up-Target']).toEqual('.middle')
40
+
41
+ describe 'with { data } option', ->
42
+
43
+ it "uses the given params as a non-GET request's payload", ->
44
+ givenParams = { 'foo-key': 'foo-value', 'bar-key': 'bar-value' }
45
+ up.replace('.middle', '/path', method: 'put', data: givenParams)
46
+ expect(@lastRequest().data()['foo-key']).toEqual(['foo-value'])
47
+ expect(@lastRequest().data()['bar-key']).toEqual(['bar-value'])
48
+
49
+ it "encodes the given params into the URL of a GET request", ->
50
+ givenParams = { 'foo-key': 'foo-value', 'bar-key': 'bar-value' }
51
+ up.replace('.middle', '/path', method: 'get', data: givenParams)
52
+ expect(@lastRequest().url).toEndWith('/path?foo-key=foo-value&bar-key=bar-value')
53
+
54
+ it 'uses a HTTP method given as { method } option', ->
55
+ up.replace('.middle', '/path', method: 'put')
56
+ expect(@lastRequest()).toHaveRequestMethod('PUT')
57
+
58
+ describe 'if the server responds with a non-200 status code', ->
59
+
60
+ it 'replaces the <body> instead of the given selector', ->
61
+ implantSpy = up.flow.knife.mock('extract') # can't have the example replace the Jasmine test runner UI
62
+ up.replace('.middle', '/path')
63
+ @respond(status: 500)
64
+ expect(implantSpy).toHaveBeenCalledWith('body', jasmine.any(String), jasmine.any(Object))
65
+
66
+ it 'uses a target selector given as { failTarget } option', ->
67
+ up.replace('.middle', '/path', failTarget: '.after')
68
+ @respond(status: 500)
69
+ expect($('.middle')).toHaveText('old-middle')
70
+ expect($('.after')).toHaveText('new-after')
71
+
72
+ describe 'history', ->
73
+
74
+ it 'should set the browser location to the given URL', (done) ->
75
+ promise = up.replace('.middle', '/path')
76
+ @respond()
77
+ promise.then ->
78
+ expect(location.href).toEndWith('/path')
79
+ done()
80
+
81
+ it 'does not add a history entry after non-GET requests', ->
82
+ promise = up.replace('.middle', '/path', method: 'post')
83
+ @respond()
84
+ expect(location.href).toEndWith(@hrefBeforeExample)
85
+
86
+ it 'adds a history entry after non-GET requests if the response includes a { X-Up-Method: "get" } header (will happen after a redirect)', ->
87
+ promise = up.replace('.middle', '/path', method: 'post')
88
+ @respond(responseHeaders: { 'X-Up-Method': 'get' })
89
+ expect(location.href).toEndWith('/path')
90
+
91
+ it 'does not a history entry after a failed GET-request', ->
92
+ promise = up.replace('.middle', '/path', method: 'post', failTarget: '.middle')
93
+ @respond(status: 500)
94
+ expect(location.href).toEndWith(@hrefBeforeExample)
95
+
96
+ it 'does not add a history entry with { history: false } option', ->
97
+ promise = up.replace('.middle', '/path', history: false)
98
+ @respond()
99
+ expect(location.href).toEndWith(@hrefBeforeExample)
100
+
101
+ it "detects a redirect's new URL when the server sets an X-Up-Location header", ->
102
+ promise = up.replace('.middle', '/path')
103
+ @respond(responseHeaders: { 'X-Up-Location': '/other-path' })
104
+ expect(location.href).toEndWith('/other-path')
105
+
106
+ it 'adds params from a { data } option to the URL of a GET request', ->
107
+ promise = up.replace('.middle', '/path', data: { 'foo-key': 'foo value', 'bar-key': 'bar value' })
108
+ @respond()
109
+ console.log("EXPECTATION COMING UP AGAINST %o", location.pathname)
110
+ expect(location.href).toEndWith('/path?foo-key=foo%20value&bar-key=bar%20value')
111
+
112
+ describe 'if a URL is given as { history } option', ->
113
+
114
+ it 'uses that URL as the new location after a GET request', ->
115
+ promise = up.replace('.middle', '/path', history: '/given-path')
116
+ @respond(failTarget: '.middle')
117
+ expect(location.href).toEndWith('/given-path')
118
+
119
+ it 'adds a history entry after a non-GET request', ->
120
+ promise = up.replace('.middle', '/path', method: 'post', history: '/given-path')
121
+ @respond(failTarget: '.middle')
122
+ expect(location.href).toEndWith('/given-path')
123
+
124
+ it 'does not add a history entry after a failed non-GET request', ->
125
+ promise = up.replace('.middle', '/path', method: 'post', history: '/given-path', failTarget: '.middle')
126
+ @respond(failTarget: '.middle', status: 500)
127
+ expect(location.href).toEndWith(@hrefBeforeExample)
128
+
129
+ describe 'source', ->
130
+
131
+ it 'remembers the source the fragment was retrieved from', (done) ->
132
+ promise = up.replace('.middle', '/path')
133
+ @respond()
134
+ promise.then ->
135
+ expect($('.middle').attr('up-source')).toMatch(/\/path$/)
136
+ done()
137
+
138
+ it 'reuses the previous source for a non-GET request (since that is reloadable)', ->
139
+ @oldMiddle.attr('up-source', '/previous-source')
140
+ up.replace('.middle', '/path', method: 'post')
141
+ @respond()
142
+ expect($('.middle')).toHaveText('new-middle')
143
+ expect(up.flow.source('.middle')).toEndWith('/previous-source')
144
+
145
+ describe 'if a URL is given as { source } option', ->
146
+
147
+ it 'uses that URL as the source for a GET request', ->
148
+ promise = up.replace('.middle', '/path', source: '/given-path')
149
+ @respond()
150
+ expect(up.flow.source('.middle')).toEndWith('/given-path')
151
+
152
+ it 'uses that URL as the source after a non-GET request', ->
153
+ promise = up.replace('.middle', '/path', method: 'post', source: '/given-path')
154
+ @respond()
155
+ expect(up.flow.source('.middle')).toEndWith('/given-path')
156
+
157
+ it 'still reuses the previous URL after a failed non-GET request', ->
158
+ promise = up.replace('.middle', '/path', method: 'post', source: '/given-path', failTarget: '.middle')
159
+ @respond(status: 500)
160
+ expect(up.flow.source('.middle')).toEndWith(@hrefBeforeExample)
161
+
162
+ it 'understands non-standard CSS selector extensions such as :has(...)', (done) ->
163
+ $first = affix('.boxx#first')
164
+ $firstChild = $('<span class="first-child">old first</span>').appendTo($first)
165
+ $second = affix('.boxx#second')
166
+ $secondChild = $('<span class="second-child">old second</span>').appendTo($second)
167
+
168
+ promise = up.replace('.boxx:has(.first-child)', '/path')
169
+ @respondWith """
170
+ <div class="boxx" id="first">
171
+ <span class="first-child">new first</span>
172
+ </div>
173
+ """
174
+
175
+ promise.then ->
176
+ expect($('#first span')).toHaveText('new first')
177
+ expect($('#second span')).toHaveText('old second')
178
+ done()
179
+
180
+ describe 'document title', ->
181
+
182
+ it "sets the document title to a 'title' tag in the response", ->
183
+ affix('.container').text('old container text')
184
+ up.replace('.container', '/path')
185
+ @respondWith """
186
+ <html>
187
+ <head>
188
+ <title>Title from HTML</title>
189
+ </head>
190
+ <body>
191
+ <div class='container'>
192
+ new container text
193
+ </div>
194
+ </body>
195
+ </html>
196
+ """
197
+ expect($('.container')).toHaveText('new container text')
198
+ expect(document.title).toBe('Title from HTML')
199
+
200
+ it "sets the document title to an 'X-Up-Title' header in the response", ->
201
+ affix('.container').text('old container text')
202
+ up.replace('.container', '/path')
203
+ @respondWith
204
+ responseHeaders:
205
+ 'X-Up-Title': 'Title from header'
206
+ responseText: """
207
+ <div class='container'>
208
+ new container text
209
+ </div>
210
+ """
211
+ expect($('.container')).toHaveText('new container text')
212
+ expect(document.title).toBe('Title from header')
213
+
214
+ describe 'selector processing', ->
215
+
216
+ it 'replaces multiple selectors separated with a comma', (done) ->
217
+ promise = up.replace('.middle, .after', '/path')
218
+ @respond()
219
+ promise.then ->
220
+ expect($('.before')).toHaveText('old-before')
221
+ expect($('.middle')).toHaveText('new-middle')
222
+ expect($('.after')).toHaveText('new-after')
223
+ done()
224
+
225
+ it 'replaces the body if asked to replace the "html" selector'
226
+
227
+ it 'prepends instead of replacing when the target has a :before pseudo-selector', (done) ->
228
+ promise = up.replace('.middle:before', '/path')
229
+ @respond()
230
+ promise.then ->
231
+ expect($('.before')).toHaveText('old-before')
232
+ expect($('.middle')).toHaveText('new-middleold-middle')
233
+ expect($('.after')).toHaveText('old-after')
234
+ done()
235
+
236
+ it 'appends instead of replacing when the target has a :after pseudo-selector', (done) ->
237
+ promise = up.replace('.middle:after', '/path')
238
+ @respond()
239
+ promise.then ->
240
+ expect($('.before')).toHaveText('old-before')
241
+ expect($('.middle')).toHaveText('old-middlenew-middle')
242
+ expect($('.after')).toHaveText('old-after')
243
+ done()
244
+
245
+ it "lets the developer choose between replacing/prepending/appending for each selector", (done) ->
246
+ promise = up.replace('.before:before, .middle, .after:after', '/path')
247
+ @respond()
248
+ promise.then ->
249
+ expect($('.before')).toHaveText('new-beforeold-before')
250
+ expect($('.middle')).toHaveText('new-middle')
251
+ expect($('.after')).toHaveText('old-afternew-after')
252
+ done()
253
+
254
+ it 'executes only those script-tags in the response that get inserted into the DOM', (done) ->
255
+ window.scriptTagExecuted = jasmine.createSpy('scriptTagExecuted')
256
+
257
+ @responseText =
258
+ """
259
+ <div class="before">
260
+ new-before
261
+ <script type="text/javascript">
262
+ window.scriptTagExecuted('before')
263
+ </script>
264
+ </div>
265
+ <div class="middle">
266
+ new-middle
267
+ <script type="text/javascript">
268
+ window.scriptTagExecuted('middle')
269
+ </script>
270
+ </div>
271
+ """
272
+
273
+ promise = up.replace('.middle', '/path')
274
+ @respond()
275
+
276
+ promise.then ->
277
+ expect(window.scriptTagExecuted).not.toHaveBeenCalledWith('before')
278
+ expect(window.scriptTagExecuted).toHaveBeenCalledWith('middle')
279
+ done()
280
+
281
+ describe 'with { restoreScroll: true } option', ->
282
+
283
+ it 'restores the scroll positions of all viewports around the target', ->
284
+
285
+ $viewport = affix('div[up-viewport] .element').css
286
+ 'height': '100px'
287
+ 'width': '100px'
288
+ 'overflow-y': 'scroll'
289
+
290
+ respond = =>
291
+ @lastRequest().respondWith
292
+ status: 200
293
+ contentType: 'text/html'
294
+ responseText: '<div class="element" style="height: 300px"></div>'
295
+
296
+ up.replace('.element', '/foo')
297
+ respond()
298
+
299
+ $viewport.scrollTop(65)
300
+
301
+ up.replace('.element', '/bar')
302
+ respond()
303
+
304
+ $viewport.scrollTop(0)
305
+
306
+ up.replace('.element', '/foo', restoreScroll: true)
307
+ # No need to respond because /foo has been cached before
308
+
309
+ expect($viewport.scrollTop()).toEqual(65)
310
+
311
+
312
+ describe 'with { reveal: true } option', ->
313
+
314
+ beforeEach ->
315
+ @revealedHTML = ''
316
+
317
+ @revealMock = up.layout.knife.mock('reveal').and.callFake ($revealedElement) =>
318
+ @revealedHTML = $revealedElement.get(0).outerHTML
319
+ u.resolvedDeferred()
320
+
321
+ it 'reveals a new element before it is being replaced', (done) ->
322
+ promise = up.replace('.middle', '/path', reveal: true)
323
+ @respond()
324
+ promise.then =>
325
+ expect(@revealMock).not.toHaveBeenCalledWith(@oldMiddle)
326
+ expect(@revealedHTML).toContain('new-middle')
327
+ done()
328
+
329
+ describe 'when there is an anchor #hash in the URL', ->
330
+
331
+ it 'reveals a child with the ID of that #hash', (done) ->
332
+ promise = up.replace('.middle', '/path#three', reveal: true)
333
+ @responseText =
334
+ """
335
+ <div class="middle">
336
+ <div id="one">one</div>
337
+ <div id="two">two</div>
338
+ <div id="three">three</div>
339
+ </div>
340
+ """
341
+ @respond()
342
+ promise.then =>
343
+ expect(@revealedHTML).toEqual('<div id="three">three</div>')
344
+ done()
345
+
346
+ it "reveals the entire element if it has no child with the ID of that #hash", (done) ->
347
+ promise = up.replace('.middle', '/path#four', reveal: true)
348
+ @responseText =
349
+ """
350
+ <div class="middle">
351
+ new-middle
352
+ </div>
353
+ """
354
+ @respond()
355
+ promise.then =>
356
+ expect(@revealedHTML).toContain('new-middle')
357
+ done()
358
+
359
+ it 'reveals a new element that is being appended', (done) ->
360
+ promise = up.replace('.middle:after', '/path', reveal: true)
361
+ @respond()
362
+ promise.then =>
363
+ expect(@revealMock).not.toHaveBeenCalledWith(@oldMiddle)
364
+ # Text nodes are wrapped in a .up-insertion container so we can
365
+ # animate them and measure their position/size for scrolling.
366
+ # This is not possible for container-less text nodes.
367
+ expect(@revealedHTML).toEqual('<span class="up-insertion">new-middle</span>')
368
+ # Show that the wrapper is done after the insertion.
369
+ expect($('.up-insertion')).not.toExist()
370
+ done()
371
+
372
+ it 'reveals a new element that is being prepended', (done) ->
373
+ promise = up.replace('.middle:before', '/path', reveal: true)
374
+ @respond()
375
+ promise.then =>
376
+ expect(@revealMock).not.toHaveBeenCalledWith(@oldMiddle)
377
+ # Text nodes are wrapped in a .up-insertion container so we can
378
+ # animate them and measure their position/size for scrolling.
379
+ # This is not possible for container-less text nodes.
380
+ expect(@revealedHTML).toEqual('<span class="up-insertion">new-middle</span>')
381
+ # Show that the wrapper is done after the insertion.
382
+ expect($('.up-insertion')).not.toExist()
383
+ done()
384
+
385
+ it 'uses a { failTransition } option if the request failed'
386
+
387
+ describeFallback 'canPushState', ->
388
+
389
+ it 'makes a full page load', ->
390
+ spyOn(up.browser, 'loadPage')
391
+ up.replace('.selector', '/path')
392
+ expect(up.browser.loadPage).toHaveBeenCalledWith('/path', jasmine.anything())
393
+
394
+ describe 'up.extract', ->
395
+
396
+ it 'Updates a selector on the current page with the same selector from the given HTML string', ->
397
+
398
+ affix('.before').text('old-before')
399
+ affix('.middle').text('old-middle')
400
+ affix('.after').text('old-after')
401
+
402
+ html =
403
+ """
404
+ <div class="before">new-before</div>
405
+ <div class="middle">new-middle</div>
406
+ <div class="after">new-after</div>
407
+ """
408
+
409
+ up.extract('.middle', html)
410
+
411
+ expect($('.before')).toHaveText('old-before')
412
+ expect($('.middle')).toHaveText('new-middle')
413
+ expect($('.after')).toHaveText('old-after')
414
+
415
+ it "throws an error if the selector can't be found on the current page", ->
416
+ html = '<div class="foo-bar">text</div>'
417
+ extract = -> up.extract('.foo-bar', html)
418
+ expect(extract).toThrowError(/Could not find selector ".foo-bar" in current body/i)
419
+
420
+ it "throws an error if the selector can't be found in the given HTML string", ->
421
+ affix('.foo-bar')
422
+ extract = -> up.extract('.foo-bar', '')
423
+ expect(extract).toThrowError(/Could not find selector ".foo-bar" in response/i)
424
+
425
+ it "ignores an element that matches the selector but also matches .up-destroying", ->
426
+ html = '<div class="foo-bar">text</div>'
427
+ affix('.foo-bar.up-destroying')
428
+ extract = -> up.extract('.foo-bar', html)
429
+ expect(extract).toThrowError(/Could not find selector/i)
430
+
431
+ it "ignores an element that matches the selector but also matches .up-ghost", ->
432
+ html = '<div class="foo-bar">text</div>'
433
+ affix('.foo-bar.up-ghost')
434
+ extract = -> up.extract('.foo-bar', html)
435
+ expect(extract).toThrowError(/Could not find selector/i)
436
+
437
+ it "ignores an element that matches the selector but also has a parent matching .up-destroying", ->
438
+ html = '<div class="foo-bar">text</div>'
439
+ $parent = affix('.up-destroying')
440
+ $child = affix('.foo-bar').appendTo($parent)
441
+ extract = -> up.extract('.foo-bar', html)
442
+ expect(extract).toThrowError(/Could not find selector/i)
443
+
444
+ it "ignores an element that matches the selector but also has a parent matching .up-ghost", ->
445
+ html = '<div class="foo-bar">text</div>'
446
+ $parent = affix('.up-ghost')
447
+ $child = affix('.foo-bar').appendTo($parent)
448
+ extract = -> up.extract('.foo-bar', html)
449
+ expect(extract).toThrowError(/Could not find selector/i)
450
+
451
+ it 'only replaces the first element matching the selector', ->
452
+ html = '<div class="foo-bar">text</div>'
453
+ affix('.foo-bar')
454
+ affix('.foo-bar')
455
+ up.extract('.foo-bar', html)
456
+ elements = $('.foo-bar')
457
+ expect($(elements.get(0)).text()).toEqual('text')
458
+ expect($(elements.get(1)).text()).toEqual('')
459
+
460
+ describe 'handling of [up-keep] elements', ->
461
+
462
+ squish = (string) ->
463
+ if u.isString(string)
464
+ string = string.replace(/^\s+/g, '')
465
+ string = string.replace(/\s+$/g, '')
466
+ string = string.replace(/\s+/g, ' ')
467
+ string
468
+
469
+ beforeEach ->
470
+ # Need to refactor this spec file so examples don't all share one example
471
+ $('.before, .middle, .after').remove()
472
+
473
+ it 'keeps an [up-keep] element, but does replace other elements around it', ->
474
+ $container = affix('.container')
475
+ $container.affix('.before').text('old-before')
476
+ $container.affix('.middle[up-keep]').text('old-middle')
477
+ $container.affix('.after').text('old-after')
478
+ up.extract '.container', """
479
+ <div class='container'>
480
+ <div class='before'>new-before</div>
481
+ <div class='middle' up-keep>new-middle</div>
482
+ <div class='after'>new-after</div>
483
+ </div>
484
+ """
485
+ expect($('.before')).toHaveText('new-before')
486
+ expect($('.middle')).toHaveText('old-middle')
487
+ expect($('.after')).toHaveText('new-after')
488
+
489
+ it 'keeps an [up-keep] element, but does replace text nodes around it', ->
490
+ $container = affix('.container')
491
+ $container.html """
492
+ old-before
493
+ <div class='element' up-keep>old-inside</div>
494
+ old-after
495
+ """
496
+ up.extract '.container', """
497
+ <div class='container'>
498
+ new-before
499
+ <div class='element' up-keep>new-inside</div>
500
+ new-after
501
+ </div>
502
+ """
503
+ expect(squish($('.container').text())).toEqual('new-before old-inside new-after')
504
+
505
+ describe 'if an [up-keep] element is itself a direct replacement target', ->
506
+
507
+ it "keeps that element", ->
508
+ affix('.keeper[up-keep]').text('old-inside')
509
+ up.extract '.keeper', "<div class='keeper' up-keep>new-inside</div>"
510
+ expect($('.keeper')).toHaveText('old-inside')
511
+
512
+ it "does not compile the kept element a second time"
513
+
514
+ it "only emits an event up:fragment:kept, but not an event up:fragment:inserted", ->
515
+ insertedListener = jasmine.createSpy('subscriber to up:fragment:inserted')
516
+ up.on('up:fragment:inserted', insertedListener)
517
+ keptListener = jasmine.createSpy('subscriber to up:fragment:kept')
518
+ up.on('up:fragment:kept', keptListener)
519
+ up.on 'up:fragment:inserted', insertedListener
520
+ $keeper = affix('.keeper[up-keep]').text('old-inside')
521
+ up.extract '.keeper', "<div class='keeper' up-keep>new-inside</div>"
522
+ expect(insertedListener).not.toHaveBeenCalled()
523
+ expect(keptListener).toHaveBeenCalledWith(jasmine.anything(), $('.keeper'), jasmine.anything())
524
+
525
+ it "removes an [up-keep] element if no matching element is found in the response", ->
526
+ $container = affix('.container')
527
+ $container.html """
528
+ <div class='foo'>old-foo</div>
529
+ <div class='bar' up-keep>old-bar</div>
530
+ """
531
+ up.extract '.container', """
532
+ <div class='container'>
533
+ <div class='foo'>new-foo</div>
534
+ </div>
535
+ """
536
+ expect($('.container .foo')).toExist()
537
+ expect($('.container .bar')).not.toExist()
538
+
539
+ it "updates an element if a matching element is found in the response, but that other element is no longer [up-keep]", ->
540
+ $container = affix('.container')
541
+ $container.html """
542
+ <div class='foo'>old-foo</div>
543
+ <div class='bar' up-keep>old-bar</div>
544
+ """
545
+ up.extract '.container', """
546
+ <div class='container'>
547
+ <div class='foo'>new-foo</div>
548
+ <div class='bar'>new-bar</div>
549
+ </div>
550
+ """
551
+ expect($('.container .foo')).toHaveText('new-foo')
552
+ expect($('.container .bar')).toHaveText('new-bar')
553
+
554
+ it 'moves a kept element to the ancestry position of the matching element in the response', ->
555
+ $container = affix('.container')
556
+ $container.html """
557
+ <div class="parent1">
558
+ <div class="keeper" up-keep>old-inside</div>
559
+ </div>
560
+ <div class="parent2">
561
+ </div>
562
+ """
563
+ up.extract '.container', """
564
+ <div class='container'>
565
+ <div class="parent1">
566
+ </div>
567
+ <div class="parent2">
568
+ <div class="keeper" up-keep>old-inside</div>
569
+ </div>
570
+ </div>
571
+ """
572
+ expect($('.keeper')).toHaveText('old-inside')
573
+ expect($('.keeper').parent()).toEqual($('.parent2'))
574
+
575
+ it 'lets developers choose a selector to match against as the value of the up-keep attribute', ->
576
+ $container = affix('.container')
577
+ $container.html """
578
+ <div class="keeper" up-keep=".stayer"></div>
579
+ """
580
+ up.extract '.container', """
581
+ <div class='container'>
582
+ <div up-keep class="stayer"></div>
583
+ </div>
584
+ """
585
+ expect('.keeper').toExist()
586
+
587
+ it 'does not compile a kept element a second time', ->
588
+ compiler = jasmine.createSpy('compiler')
589
+ up.compiler('.keeper', compiler)
590
+ $container = affix('.container')
591
+ $container.html """
592
+ <div class="keeper" up-keep>old-text</div>
593
+ """
594
+
595
+ console.log '*** before hello ***'
596
+ up.hello($container)
597
+ console.log '*** after hello ***'
598
+ expect(compiler.calls.count()).toEqual(1)
599
+
600
+ up.extract '.container', """
601
+ <div class='container'>
602
+ <div class="keeper" up-keep>new-text</div>
603
+ </div>
604
+ """
605
+ expect(compiler.calls.count()).toEqual(1)
606
+ expect('.keeper').toExist()
607
+
608
+ it 'lets listeners cancel the keeping by preventing default on an up:fragment:keep event', ->
609
+ $keeper = affix('.keeper[up-keep]').text('old-inside')
610
+ $keeper.on 'up:fragment:keep', (event) -> event.preventDefault()
611
+ up.extract '.keeper', "<div class='keeper' up-keep>new-inside</div>"
612
+ expect($('.keeper')).toHaveText('new-inside')
613
+
614
+ it 'lets listeners prevent up:fragment:keep event if the element was kept before (bugfix)', ->
615
+ $keeper = affix('.keeper[up-keep]').text('version 1')
616
+ $keeper.on 'up:fragment:keep', (event) ->
617
+ event.preventDefault() if event.$newElement.text() == 'version 3'
618
+ up.extract '.keeper', "<div class='keeper' up-keep>version 2</div>"
619
+ expect($('.keeper')).toHaveText('version 1')
620
+ up.extract '.keeper', "<div class='keeper' up-keep>version 3</div>"
621
+ expect($('.keeper')).toHaveText('version 3')
622
+
623
+ it 'emits an up:fragment:kept event on a kept element and up:fragment:inserted on an updated parent', ->
624
+ insertedListener = jasmine.createSpy()
625
+ up.on('up:fragment:inserted', insertedListener)
626
+ keptListener = jasmine.createSpy()
627
+ up.on('up:fragment:kept', keptListener)
628
+
629
+ $container = affix('.container')
630
+ $container.html """
631
+ <div class="keeper" up-keep></div>
632
+ """
633
+ up.extract '.container', """
634
+ <div class='container'>
635
+ <div class="keeper" up-keep></div>
636
+ </div>
637
+ """
638
+ expect(insertedListener).toHaveBeenCalledWith(jasmine.anything(), $('.container'), jasmine.anything())
639
+ expect(keptListener).toHaveBeenCalledWith(jasmine.anything(), $('.container .keeper'), jasmine.anything())
640
+
641
+ it 'emits an up:fragment:kept event on a kept element with a newData property corresponding to the up-data attribute value of the discarded element', ->
642
+ keptListener = jasmine.createSpy()
643
+ up.on 'up:fragment:kept', (event) -> keptListener(event.$element, event.newData)
644
+ $container = affix('.container')
645
+ $keeper = $container.affix('.keeper[up-keep]').text('old-inside')
646
+ up.extract '.container', """
647
+ <div class='container'>
648
+ <div class='keeper' up-keep up-data='{ "foo": "bar" }'>new-inside</div>
649
+ </div>
650
+ """
651
+ expect($('.keeper')).toHaveText('old-inside')
652
+ expect(keptListener).toHaveBeenCalledWith($keeper, { 'foo': 'bar' })
653
+
654
+ it 'emits an up:fragment:kept with { newData: {} } if the discarded element had no up-data value', ->
655
+ keptListener = jasmine.createSpy()
656
+ up.on('up:fragment:kept', keptListener)
657
+ $container = affix('.container')
658
+ $keeper = $container.affix('.keeper[up-keep]').text('old-inside')
659
+ up.extract '.keeper', """
660
+ <div class='container'>
661
+ <div class='keeper' up-keep>new-inside</div>
662
+ </div>
663
+ """
664
+ expect($('.keeper')).toHaveText('old-inside')
665
+ expect(keptListener).toEqual(jasmine.anything(), $('.keeper'), {})
666
+
667
+ it 'reuses the same element and emits up:fragment:kept during multiple extractions', ->
668
+ keptListener = jasmine.createSpy()
669
+ up.on 'up:fragment:kept', (event) -> keptListener(event.$element, event.newData)
670
+ $container = affix('.container')
671
+ $keeper = $container.affix('.keeper[up-keep]').text('old-inside')
672
+ up.extract '.keeper', """
673
+ <div class='container'>
674
+ <div class='keeper' up-keep up-data='{ \"key\": \"value1\" }'>new-inside</div>
675
+ </div>
676
+ """
677
+ up.extract '.keeper', """
678
+ <div class='container'>
679
+ <div class='keeper' up-keep up-data='{ \"key\": \"value2\" }'>new-inside</div>
680
+ """
681
+ $keeper = $('.keeper')
682
+ expect($keeper).toHaveText('old-inside')
683
+ expect(keptListener).toHaveBeenCalledWith($keeper, { key: 'value1' })
684
+ expect(keptListener).toHaveBeenCalledWith($keeper, { key: 'value2' })
685
+
686
+ it "doesn't let the discarded element appear in a transition", (done) ->
687
+ oldTextDuringTransition = undefined
688
+ newTextDuringTransition = undefined
689
+ transition = ($old, $new) ->
690
+ oldTextDuringTransition = squish($old.text())
691
+ newTextDuringTransition = squish($new.text())
692
+ u.resolvedDeferred()
693
+ $container = affix('.container')
694
+ $container.html """
695
+ <div class='foo'>old-foo</div>
696
+ <div class='bar' up-keep>old-bar</div>
697
+ """
698
+ newHtml = """
699
+ <div class='container'>
700
+ <div class='foo'>new-foo</div>
701
+ <div class='bar' up-keep>new-bar</div>
702
+ </div>
703
+ """
704
+ promise = up.extract('.container', newHtml, transition: transition)
705
+ promise.then ->
706
+ expect(oldTextDuringTransition).toEqual('old-foo old-bar')
707
+ expect(newTextDuringTransition).toEqual('new-foo old-bar')
708
+ done()
709
+
710
+ describe 'up.destroy', ->
711
+
712
+ it 'removes the element with the given selector', ->
713
+ affix('.element')
714
+ up.destroy('.element')
715
+ expect($('.element')).not.toExist()
716
+
717
+ it 'calls destructors for custom elements', ->
718
+ up.compiler('.element', ($element) -> destructor)
719
+ destructor = jasmine.createSpy('destructor')
720
+ up.hello(affix('.element'))
721
+ up.destroy('.element')
722
+ expect(destructor).toHaveBeenCalled()
723
+
724
+ describe 'up.reload', ->
725
+
726
+ describeCapability 'canPushState', ->
727
+
728
+ it 'reloads the given selector from the closest known source URL', (done) ->
729
+ affix('.container[up-source="/source"] .element').find('.element').text('old text')
730
+
731
+ up.reload('.element').then ->
732
+ expect($('.element')).toHaveText('new text')
733
+ done()
734
+
735
+ expect(@lastRequest().url).toMatch(/\/source$/)
736
+
737
+ @respondWith """
738
+ <div class="container">
739
+ <div class="element">new text</div>
740
+ </div>
741
+ """
742
+
743
+ describeFallback 'canPushState', ->
744
+
745
+ it 'makes a page load from the closest known source URL', ->
746
+ affix('.container[up-source="/source"] .element').find('.element').text('old text')
747
+ spyOn(up.browser, 'loadPage')
748
+ up.reload('.element')
749
+ expect(up.browser.loadPage).toHaveBeenCalledWith('/source', jasmine.anything())
750
+
751
+
752
+ describe 'up.reset', ->
753
+
754
+ it 'should have tests'
755
+