yousty-activeadmin 1.0.4.pre → 1.0.5.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (467) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +261 -211
  3. data/CONTRIBUTING.md +73 -39
  4. data/Gemfile +38 -20
  5. data/Guardfile +1 -0
  6. data/LICENSE +1 -1
  7. data/README.md +48 -24
  8. data/Rakefile +12 -4
  9. data/activeadmin.gemspec +21 -26
  10. data/app/assets/javascripts/active_admin/application.js.coffee +34 -5
  11. data/app/assets/javascripts/active_admin/base.js.coffee +11 -2
  12. data/app/assets/javascripts/active_admin/ext/jquery-ui.js.coffee +6 -0
  13. data/app/assets/javascripts/active_admin/ext/jquery.js.coffee +7 -0
  14. data/app/assets/javascripts/active_admin/lib/batch_actions.js.coffee +39 -0
  15. data/app/assets/javascripts/active_admin/lib/checkbox-toggler.js.coffee +3 -4
  16. data/app/assets/javascripts/active_admin/lib/dropdown-menu.js.coffee +51 -55
  17. data/app/assets/javascripts/active_admin/lib/flash.js.coffee +19 -0
  18. data/app/assets/javascripts/active_admin/lib/has_many.js.coffee +79 -0
  19. data/app/assets/javascripts/active_admin/lib/modal_dialog.js.coffee +37 -0
  20. data/app/assets/javascripts/active_admin/lib/per_page.js.coffee +27 -0
  21. data/app/assets/javascripts/active_admin/lib/popover.js.coffee +29 -58
  22. data/app/assets/javascripts/active_admin/lib/table-checkbox-toggler.js.coffee +2 -3
  23. data/app/assets/stylesheets/active_admin/{_base.css.scss → _base.scss} +3 -0
  24. data/app/assets/stylesheets/active_admin/{_forms.css.scss → _forms.scss} +51 -15
  25. data/app/assets/stylesheets/active_admin/{_header.css.scss → _header.scss} +9 -5
  26. data/app/assets/stylesheets/active_admin/{_mixins.css.scss → _mixins.scss} +0 -0
  27. data/app/assets/stylesheets/active_admin/{_typography.css.scss → _typography.scss} +0 -0
  28. data/app/assets/stylesheets/active_admin/components/_batch_actions.scss +11 -0
  29. data/app/assets/stylesheets/active_admin/components/_buttons.scss +1 -1
  30. data/app/assets/stylesheets/active_admin/components/{_comments.css.scss → _comments.scss} +0 -0
  31. data/app/assets/stylesheets/active_admin/components/{_date_picker.css.scss → _date_picker.scss} +40 -12
  32. data/app/assets/stylesheets/active_admin/components/_dropdown_menu.scss +3 -1
  33. data/app/assets/stylesheets/active_admin/components/_flash_messages.scss +37 -0
  34. data/app/assets/stylesheets/active_admin/components/_modal_dialog.scss +34 -0
  35. data/app/assets/stylesheets/active_admin/components/_pagination.scss +10 -0
  36. data/app/assets/stylesheets/active_admin/components/{_popovers.css.scss → _popovers.scss} +0 -0
  37. data/app/assets/stylesheets/active_admin/components/_status_tags.scss +4 -0
  38. data/app/assets/stylesheets/active_admin/components/_table_tools.scss +67 -0
  39. data/app/assets/stylesheets/active_admin/components/{_tables.css.scss → _tables.scss} +1 -0
  40. data/app/assets/stylesheets/active_admin/components/_tabs.scss +65 -0
  41. data/app/assets/stylesheets/active_admin/components/_unsupported_browser.scss +16 -0
  42. data/app/assets/stylesheets/active_admin/mixins/{_all.css.scss → _all.scss} +0 -0
  43. data/app/assets/stylesheets/active_admin/mixins/{_buttons.css.scss → _buttons.scss} +0 -0
  44. data/app/assets/stylesheets/active_admin/mixins/{_gradients.css.scss → _gradients.scss} +1 -1
  45. data/app/assets/stylesheets/active_admin/mixins/{_icons.css.scss → _icons.scss} +1 -2
  46. data/app/assets/stylesheets/active_admin/mixins/{_reset.css.scss → _reset.scss} +0 -0
  47. data/app/assets/stylesheets/active_admin/mixins/{_rounded.css.scss → _rounded.scss} +0 -0
  48. data/app/assets/stylesheets/active_admin/mixins/{_sections.css.scss → _sections.scss} +7 -1
  49. data/app/assets/stylesheets/active_admin/mixins/{_shadows.css.scss → _shadows.scss} +0 -0
  50. data/app/assets/stylesheets/active_admin/mixins/{_variables.css.scss → _variables.scss} +10 -8
  51. data/app/assets/stylesheets/active_admin/{print.css.scss → print.scss} +4 -0
  52. data/app/assets/stylesheets/active_admin/structure/_title_bar.scss +10 -7
  53. data/app/views/active_admin/devise/confirmations/new.html.erb +15 -0
  54. data/app/views/active_admin/devise/mailer/reset_password_instructions.html.erb +1 -1
  55. data/app/views/active_admin/devise/mailer/unlock_instructions.html.erb +1 -1
  56. data/app/views/active_admin/devise/passwords/edit.html.erb +9 -10
  57. data/app/views/active_admin/devise/passwords/new.html.erb +5 -4
  58. data/app/views/active_admin/devise/registrations/new.html.erb +22 -0
  59. data/app/views/active_admin/devise/sessions/new.html.erb +8 -8
  60. data/app/views/active_admin/devise/shared/_links.erb +1 -1
  61. data/app/views/active_admin/devise/unlocks/new.html.erb +5 -4
  62. data/app/views/layouts/active_admin_logged_out.html.erb +3 -5
  63. data/config/locales/ar.yml +120 -0
  64. data/config/locales/bg.yml +26 -6
  65. data/config/locales/bs.yml +122 -0
  66. data/config/locales/ca.yml +10 -1
  67. data/config/locales/cs.yml +7 -2
  68. data/config/locales/da.yml +7 -3
  69. data/config/locales/de-CH.yml +14 -31
  70. data/config/locales/de.yml +33 -33
  71. data/config/locales/el.yml +127 -0
  72. data/config/locales/en-GB.yml +11 -4
  73. data/config/locales/en.yml +21 -4
  74. data/config/locales/{es_MX.yml → es-MX.yml} +14 -24
  75. data/config/locales/es.yml +32 -25
  76. data/config/locales/fa.yml +120 -0
  77. data/config/locales/fi.yml +9 -5
  78. data/config/locales/fr.yml +28 -12
  79. data/config/locales/he.yml +7 -3
  80. data/config/locales/hr.yml +42 -11
  81. data/config/locales/hu.yml +10 -3
  82. data/config/locales/it.yml +31 -3
  83. data/config/locales/ja.yml +17 -4
  84. data/config/locales/ko.yml +7 -1
  85. data/config/locales/lt.yml +42 -11
  86. data/config/locales/lv.yml +7 -3
  87. data/config/locales/{no-NB.yml → nb.yml} +46 -15
  88. data/config/locales/nl.yml +36 -5
  89. data/config/locales/pl.yml +13 -8
  90. data/config/locales/pt-BR.yml +36 -5
  91. data/config/locales/pt-PT.yml +8 -4
  92. data/config/locales/ro.yml +7 -3
  93. data/config/locales/ru.yml +26 -5
  94. data/config/locales/sv-SE.yml +9 -5
  95. data/config/locales/tr.yml +10 -3
  96. data/config/locales/uk.yml +36 -12
  97. data/config/locales/vi.yml +7 -3
  98. data/config/locales/zh-CN.yml +26 -10
  99. data/config/locales/zh-TW.yml +19 -13
  100. data/docs/0-installation.md +14 -6
  101. data/docs/1-general-configuration.md +8 -5
  102. data/docs/10-custom-pages.md +68 -70
  103. data/docs/11-decorators.md +48 -59
  104. data/docs/12-arbre-components.md +79 -73
  105. data/docs/13-authorization-adapter.md +128 -107
  106. data/docs/14-gotchas.md +90 -0
  107. data/docs/2-resource-customization.md +82 -15
  108. data/docs/3-index-pages.md +71 -12
  109. data/docs/3-index-pages/custom-index.md +31 -0
  110. data/docs/3-index-pages/index-as-table.md +45 -2
  111. data/docs/4-csv-format.md +1 -1
  112. data/docs/5-forms.md +78 -29
  113. data/docs/6-show-pages.md +31 -3
  114. data/docs/7-sidebars.md +46 -25
  115. data/docs/8-custom-actions.md +98 -77
  116. data/docs/9-batch-actions.md +211 -133
  117. data/docs/README.md +24 -0
  118. data/features/action_item.feature +3 -3
  119. data/features/authorization_pundit.feature +37 -0
  120. data/features/belongs_to.feature +3 -0
  121. data/features/breadcrumb.feature +48 -0
  122. data/features/comments/commenting.feature +44 -13
  123. data/features/development_reloading.feature +3 -4
  124. data/features/edit_page.feature +9 -19
  125. data/features/favicon.feature +3 -3
  126. data/features/i18n.feature +5 -0
  127. data/features/index/batch_actions.feature +41 -0
  128. data/features/index/filters.feature +23 -0
  129. data/features/index/format_as_csv.feature +90 -4
  130. data/features/index/index_as_blog.feature +4 -4
  131. data/features/index/index_as_table.feature +102 -6
  132. data/features/index/index_blank_slate.feature +22 -0
  133. data/features/index/index_scope_to.feature +16 -16
  134. data/features/index/page_title.feature +11 -0
  135. data/features/index/pagination.feature +1 -1
  136. data/features/index/switch_index_view.feature +14 -14
  137. data/features/new_page.feature +10 -20
  138. data/features/registering_pages.feature +1 -1
  139. data/features/renamed_resource.feature +32 -0
  140. data/features/show/page_title.feature +11 -0
  141. data/features/show/tabs.feature +27 -0
  142. data/features/sidebar_sections.feature +12 -0
  143. data/features/specifying_actions.feature +3 -3
  144. data/features/step_definitions/action_item_steps.rb +2 -2
  145. data/features/step_definitions/action_link_steps.rb +14 -1
  146. data/features/step_definitions/additional_web_steps.rb +17 -18
  147. data/features/step_definitions/asset_steps.rb +3 -3
  148. data/features/step_definitions/attribute_steps.rb +8 -3
  149. data/features/step_definitions/batch_action_steps.rb +26 -9
  150. data/features/step_definitions/blog_steps.rb +3 -0
  151. data/features/step_definitions/breadcrumb_steps.rb +1 -1
  152. data/features/step_definitions/comment_steps.rb +1 -1
  153. data/features/step_definitions/configuration_steps.rb +1 -1
  154. data/features/step_definitions/dashboard_steps.rb +2 -2
  155. data/features/step_definitions/factory_steps.rb +6 -6
  156. data/features/step_definitions/filter_steps.rb +25 -3
  157. data/features/step_definitions/flash_steps.rb +3 -3
  158. data/features/step_definitions/format_steps.rb +17 -10
  159. data/features/step_definitions/index_scope_steps.rb +5 -5
  160. data/features/step_definitions/layout_steps.rb +1 -1
  161. data/features/step_definitions/member_link_steps.rb +2 -2
  162. data/features/step_definitions/menu_steps.rb +3 -3
  163. data/features/step_definitions/pagination_steps.rb +2 -3
  164. data/features/step_definitions/sidebar_steps.rb +8 -3
  165. data/features/step_definitions/site_title_steps.rb +6 -4
  166. data/features/step_definitions/symbol_leak_steps.rb +1 -1
  167. data/features/step_definitions/tab_steps.rb +5 -0
  168. data/features/step_definitions/table_steps.rb +4 -4
  169. data/features/step_definitions/user_steps.rb +15 -9
  170. data/features/step_definitions/web_steps.rb +10 -11
  171. data/features/sti_resource.feature +2 -10
  172. data/features/strong_parameters.feature +73 -0
  173. data/features/support/env.rb +35 -2
  174. data/features/support/paths.rb +2 -2
  175. data/features/support/selectors.rb +1 -1
  176. data/features/users/resetting_password.feature +7 -7
  177. data/lib/active_admin.rb +18 -13
  178. data/lib/active_admin/abstract_view_factory.rb +7 -17
  179. data/lib/active_admin/application.rb +50 -25
  180. data/lib/active_admin/asset_registration.rb +2 -2
  181. data/lib/active_admin/authorization_adapter.rb +2 -2
  182. data/lib/active_admin/base_controller.rb +2 -3
  183. data/lib/active_admin/base_controller/authorization.rb +13 -31
  184. data/lib/active_admin/batch_actions.rb +1 -1
  185. data/lib/active_admin/batch_actions/controller.rb +13 -7
  186. data/lib/active_admin/batch_actions/resource_extension.rb +43 -17
  187. data/lib/active_admin/batch_actions/views/batch_action_form.rb +7 -4
  188. data/lib/active_admin/batch_actions/views/batch_action_popover.rb +3 -3
  189. data/lib/active_admin/batch_actions/views/batch_action_selector.rb +8 -17
  190. data/lib/active_admin/batch_actions/views/selection_cells.rb +4 -4
  191. data/lib/active_admin/callbacks.rb +25 -24
  192. data/lib/active_admin/cancan_adapter.rb +7 -11
  193. data/lib/active_admin/csv_builder.rb +92 -15
  194. data/lib/active_admin/dependency.rb +93 -0
  195. data/lib/active_admin/deprecation.rb +6 -7
  196. data/lib/active_admin/devise.rb +26 -14
  197. data/lib/active_admin/dsl.rb +18 -11
  198. data/lib/active_admin/engine.rb +7 -2
  199. data/lib/active_admin/error.rb +59 -0
  200. data/lib/active_admin/filters/dsl.rb +2 -2
  201. data/lib/active_admin/filters/forms.rb +19 -30
  202. data/lib/active_admin/filters/formtastic_addons.rb +20 -11
  203. data/lib/active_admin/filters/resource_extension.rb +16 -9
  204. data/lib/active_admin/form_builder.rb +94 -105
  205. data/lib/active_admin/helpers/collection.rb +7 -13
  206. data/lib/active_admin/helpers/i18n.rb +7 -0
  207. data/lib/active_admin/helpers/optional_display.rb +5 -5
  208. data/lib/active_admin/helpers/scope_chain.rb +1 -1
  209. data/lib/active_admin/helpers/settings.rb +16 -9
  210. data/lib/active_admin/iconic.rb +17 -15
  211. data/lib/active_admin/iconic/icons.rb +136 -136
  212. data/lib/active_admin/inputs.rb +11 -7
  213. data/lib/active_admin/inputs/datepicker_input.rb +1 -1
  214. data/lib/active_admin/inputs/filters/base.rb +42 -0
  215. data/lib/active_admin/inputs/filters/base/search_method_select.rb +75 -0
  216. data/lib/active_admin/inputs/filters/boolean_input.rb +24 -0
  217. data/lib/active_admin/inputs/filters/check_boxes_input.rb +50 -0
  218. data/lib/active_admin/inputs/filters/date_range_input.rb +36 -0
  219. data/lib/active_admin/inputs/filters/numeric_input.rb +12 -0
  220. data/lib/active_admin/inputs/filters/select_input.rb +54 -0
  221. data/lib/active_admin/inputs/filters/string_input.rb +26 -0
  222. data/lib/active_admin/menu.rb +3 -3
  223. data/lib/active_admin/menu_collection.rb +1 -4
  224. data/lib/active_admin/namespace.rb +52 -29
  225. data/lib/active_admin/order_clause.rb +26 -0
  226. data/lib/active_admin/orm/active_record.rb +2 -0
  227. data/lib/active_admin/orm/active_record/comments.rb +48 -51
  228. data/lib/active_admin/orm/active_record/comments/comment.rb +16 -10
  229. data/lib/active_admin/orm/active_record/comments/namespace_helper.rb +1 -1
  230. data/lib/active_admin/orm/active_record/comments/resource_helper.rb +1 -1
  231. data/lib/active_admin/orm/active_record/comments/views/active_admin_comments.rb +15 -13
  232. data/lib/active_admin/page.rb +5 -1
  233. data/lib/active_admin/page_dsl.rb +1 -1
  234. data/lib/active_admin/page_presenter.rb +2 -2
  235. data/lib/active_admin/pundit_adapter.rb +68 -0
  236. data/lib/active_admin/resource.rb +12 -3
  237. data/lib/active_admin/resource/action_items.rb +15 -8
  238. data/lib/active_admin/resource/belongs_to.rb +7 -3
  239. data/lib/active_admin/resource/controllers.rb +1 -0
  240. data/lib/active_admin/resource/includes.rb +12 -0
  241. data/lib/active_admin/resource/menu.rb +5 -5
  242. data/lib/active_admin/resource/naming.rb +25 -47
  243. data/lib/active_admin/resource/page_presenters.rb +1 -1
  244. data/lib/active_admin/resource/routes.rb +26 -10
  245. data/lib/active_admin/resource/scope_to.rb +7 -7
  246. data/lib/active_admin/resource/sidebars.rb +1 -0
  247. data/lib/active_admin/resource_collection.rb +44 -16
  248. data/lib/active_admin/resource_controller.rb +6 -5
  249. data/lib/active_admin/resource_controller/data_access.rb +87 -82
  250. data/lib/active_admin/resource_controller/decorators.rb +91 -9
  251. data/lib/active_admin/resource_controller/streaming.rb +37 -0
  252. data/lib/active_admin/resource_dsl.rb +54 -10
  253. data/lib/active_admin/router.rb +7 -7
  254. data/lib/active_admin/scope.rb +6 -6
  255. data/lib/active_admin/sidebar_section.rb +10 -2
  256. data/lib/active_admin/version.rb +1 -1
  257. data/lib/active_admin/view_factory.rb +17 -16
  258. data/lib/active_admin/view_helpers.rb +0 -1
  259. data/lib/active_admin/view_helpers/auto_link_helper.rb +23 -12
  260. data/lib/active_admin/view_helpers/breadcrumb_helper.rb +13 -6
  261. data/lib/active_admin/view_helpers/display_helper.rb +30 -17
  262. data/lib/active_admin/view_helpers/download_format_links_helper.rb +21 -24
  263. data/lib/active_admin/view_helpers/fields_for.rb +2 -2
  264. data/lib/active_admin/view_helpers/flash_helper.rb +4 -3
  265. data/lib/active_admin/view_helpers/form_helper.rb +5 -9
  266. data/lib/active_admin/view_helpers/method_or_proc_helper.rb +6 -6
  267. data/lib/active_admin/views/action_items.rb +2 -2
  268. data/lib/active_admin/views/components/action_list_popover.rb +1 -1
  269. data/lib/active_admin/views/components/active_admin_form.rb +123 -0
  270. data/lib/active_admin/views/components/attributes_table.rb +22 -13
  271. data/lib/active_admin/views/components/blank_slate.rb +1 -1
  272. data/lib/active_admin/views/components/columns.rb +13 -7
  273. data/lib/active_admin/views/components/dropdown_menu.rb +6 -6
  274. data/lib/active_admin/views/components/index_list.rb +7 -7
  275. data/lib/active_admin/views/components/paginated_collection.rb +33 -17
  276. data/lib/active_admin/views/components/panel.rb +8 -2
  277. data/lib/active_admin/views/components/popover.rb +1 -1
  278. data/lib/active_admin/views/components/scopes.rb +1 -1
  279. data/lib/active_admin/views/components/sidebar_section.rb +3 -2
  280. data/lib/active_admin/views/components/site_title.rb +2 -2
  281. data/lib/active_admin/views/components/status_tag.rb +34 -11
  282. data/lib/active_admin/views/components/table_for.rb +67 -22
  283. data/lib/active_admin/views/components/tabs.rb +28 -0
  284. data/lib/active_admin/views/components/unsupported_browser.rb +11 -0
  285. data/lib/active_admin/views/footer.rb +3 -3
  286. data/lib/active_admin/views/header.rb +3 -3
  287. data/lib/active_admin/views/index_as_blog.rb +6 -6
  288. data/lib/active_admin/views/index_as_grid.rb +2 -2
  289. data/lib/active_admin/views/index_as_table.rb +127 -40
  290. data/lib/active_admin/views/pages/base.rb +22 -18
  291. data/lib/active_admin/views/pages/form.rb +16 -6
  292. data/lib/active_admin/views/pages/index.rb +36 -20
  293. data/lib/active_admin/views/pages/layout.rb +1 -1
  294. data/lib/active_admin/views/pages/show.rb +4 -4
  295. data/lib/active_admin/views/tabbed_navigation.rb +7 -3
  296. data/lib/active_admin/views/title_bar.rb +10 -8
  297. data/lib/generators/active_admin/assets/assets_generator.rb +1 -3
  298. data/lib/generators/active_admin/devise/devise_generator.rb +20 -28
  299. data/lib/generators/active_admin/install/install_generator.rb +8 -9
  300. data/lib/generators/active_admin/install/templates/active_admin.rb.erb +20 -22
  301. data/lib/generators/active_admin/install/templates/admin_user.rb.erb +12 -9
  302. data/lib/generators/active_admin/install/templates/dashboard.rb +4 -4
  303. data/lib/generators/active_admin/install/templates/migrations/create_active_admin_comments.rb +3 -3
  304. data/lib/generators/active_admin/page/USAGE +8 -0
  305. data/lib/generators/active_admin/page/page_generator.rb +12 -0
  306. data/lib/generators/active_admin/page/templates/page.rb +5 -0
  307. data/lib/generators/active_admin/resource/resource_generator.rb +2 -4
  308. data/lib/generators/active_admin/resource/templates/admin.rb +15 -0
  309. data/lib/ransack_ext.rb +4 -4
  310. data/script/local +2 -2
  311. data/script/travis_cache +107 -0
  312. data/spec/javascripts/coffeescripts/jquery.aa.flash.js.coffee +25 -0
  313. data/spec/javascripts/fixtures/flashes.html +2 -0
  314. data/spec/rails_helper.rb +154 -0
  315. data/spec/{integration → requests}/default_namespace_spec.rb +6 -6
  316. data/spec/{integration → requests}/javascript_spec.rb +5 -5
  317. data/spec/requests/memory_spec.rb +23 -0
  318. data/spec/requests/stylesheets_spec.rb +18 -0
  319. data/spec/spec_helper.rb +12 -170
  320. data/spec/support/detect_rails_version.rb +31 -39
  321. data/spec/support/rails_template.rb +61 -34
  322. data/spec/support/rails_template_with_data.rb +14 -14
  323. data/spec/support/templates/admin/stores.rb +3 -5
  324. data/spec/support/templates/policies/active_admin/comment_policy.rb +9 -0
  325. data/spec/support/templates/policies/active_admin/page_policy.rb +18 -0
  326. data/spec/support/templates/policies/admin_user_policy.rb +11 -0
  327. data/spec/support/templates/policies/application_policy.rb +45 -0
  328. data/spec/support/templates/policies/category_policy.rb +7 -0
  329. data/spec/support/templates/policies/post_policy.rb +15 -0
  330. data/spec/support/templates/policies/store_policy.rb +11 -0
  331. data/spec/support/templates/policies/user_policy.rb +11 -0
  332. data/spec/support/templates/post_decorator.rb +4 -46
  333. data/spec/unit/abstract_view_factory_spec.rb +11 -11
  334. data/spec/unit/action_builder_spec.rb +24 -18
  335. data/spec/unit/active_admin_spec.rb +2 -2
  336. data/spec/unit/application_spec.rb +30 -31
  337. data/spec/unit/asset_registration_spec.rb +11 -11
  338. data/spec/unit/authorization/authorization_adapter_spec.rb +7 -7
  339. data/spec/unit/authorization/controller_authorization_spec.rb +11 -11
  340. data/spec/unit/authorization/index_overriding_spec.rb +22 -0
  341. data/spec/unit/auto_link_spec.rb +42 -5
  342. data/spec/unit/batch_actions/resource_spec.rb +15 -14
  343. data/spec/unit/batch_actions/settings_spec.rb +18 -18
  344. data/spec/unit/belongs_to_spec.rb +26 -17
  345. data/spec/unit/cancan_adapter_spec.rb +4 -4
  346. data/spec/unit/comments_spec.rb +99 -39
  347. data/spec/unit/component_spec.rb +3 -3
  348. data/spec/unit/config_shared_examples.rb +8 -8
  349. data/spec/unit/controller_filters_spec.rb +26 -14
  350. data/spec/unit/csv_builder_spec.rb +152 -24
  351. data/spec/unit/dependency_spec.rb +135 -0
  352. data/spec/unit/devise_spec.rb +17 -37
  353. data/spec/unit/dsl_spec.rb +70 -9
  354. data/spec/unit/event_spec.rb +9 -9
  355. data/spec/unit/filters/filter_form_builder_spec.rb +167 -157
  356. data/spec/unit/filters/resource_spec.rb +35 -33
  357. data/spec/unit/form_builder_spec.rb +383 -145
  358. data/spec/unit/generators/install_spec.rb +5 -5
  359. data/spec/unit/helpers/collection_spec.rb +18 -18
  360. data/spec/unit/helpers/scope_chain_spec.rb +5 -5
  361. data/spec/unit/helpers/settings_spec.rb +4 -4
  362. data/spec/unit/i18n_spec.rb +12 -0
  363. data/spec/unit/menu_collection_spec.rb +14 -14
  364. data/spec/unit/menu_item_spec.rb +42 -42
  365. data/spec/unit/menu_spec.rb +20 -20
  366. data/spec/unit/namespace/authorization_spec.rb +5 -5
  367. data/spec/unit/namespace/register_page_spec.rb +9 -9
  368. data/spec/unit/namespace/register_resource_spec.rb +26 -28
  369. data/spec/unit/namespace_spec.rb +20 -20
  370. data/spec/unit/order_clause_spec.rb +81 -0
  371. data/spec/unit/page_controller_spec.rb +1 -1
  372. data/spec/unit/page_spec.rb +18 -12
  373. data/spec/unit/pretty_format_spec.rb +42 -14
  374. data/spec/unit/pundit_adapter_spec.rb +98 -0
  375. data/spec/unit/resource/action_items_spec.rb +13 -10
  376. data/spec/unit/resource/includes_spec.rb +21 -0
  377. data/spec/unit/resource/menu_spec.rb +1 -1
  378. data/spec/unit/resource/naming_spec.rb +23 -23
  379. data/spec/unit/resource/page_presenters_spec.rb +8 -8
  380. data/spec/unit/resource/pagination_spec.rb +6 -6
  381. data/spec/unit/resource/routes_spec.rb +10 -10
  382. data/spec/unit/resource/scopes_spec.rb +14 -7
  383. data/spec/unit/resource/sidebars_spec.rb +6 -6
  384. data/spec/unit/resource_collection_spec.rb +66 -68
  385. data/spec/unit/resource_controller/data_access_spec.rb +39 -21
  386. data/spec/unit/resource_controller/decorators_spec.rb +83 -0
  387. data/spec/unit/resource_controller/sidebars_spec.rb +7 -8
  388. data/spec/unit/resource_controller_spec.rb +66 -62
  389. data/spec/unit/resource_registration_spec.rb +12 -12
  390. data/spec/unit/resource_spec.rb +75 -40
  391. data/spec/unit/routing_spec.rb +39 -31
  392. data/spec/unit/scope_spec.rb +112 -30
  393. data/spec/unit/settings_spec.rb +51 -21
  394. data/spec/unit/view_factory_spec.rb +2 -2
  395. data/spec/unit/view_helpers/breadcrumbs_spec.rb +137 -69
  396. data/spec/unit/view_helpers/display_name_spec.rb +49 -21
  397. data/spec/unit/view_helpers/download_format_links_helper_spec.rb +5 -5
  398. data/spec/unit/view_helpers/fields_for_spec.rb +18 -18
  399. data/spec/unit/view_helpers/flash_helper_spec.rb +25 -0
  400. data/spec/unit/view_helpers/form_helper_spec.rb +9 -22
  401. data/spec/unit/view_helpers/method_or_proc_helper_spec.rb +59 -21
  402. data/spec/unit/views/components/action_list_popover_spec.rb +16 -6
  403. data/spec/unit/views/components/attributes_table_spec.rb +94 -52
  404. data/spec/unit/views/components/batch_action_popover_spec.rb +20 -6
  405. data/spec/unit/views/components/blank_slate_spec.rb +14 -4
  406. data/spec/unit/views/components/columns_spec.rb +52 -22
  407. data/spec/unit/views/components/index_list_spec.rb +11 -8
  408. data/spec/unit/views/components/index_table_for_spec.rb +46 -0
  409. data/spec/unit/views/components/paginated_collection_spec.rb +68 -59
  410. data/spec/unit/views/components/panel_spec.rb +32 -21
  411. data/spec/unit/views/components/popover_spec.rb +7 -7
  412. data/spec/unit/views/components/sidebar_section_spec.rb +18 -8
  413. data/spec/unit/views/components/site_title_spec.rb +8 -8
  414. data/spec/unit/views/components/status_tag_spec.rb +178 -38
  415. data/spec/unit/views/components/table_for_spec.rb +227 -44
  416. data/spec/unit/views/components/tabs_spec.rb +39 -0
  417. data/spec/unit/views/components/unsupported_browser_spec.rb +47 -0
  418. data/spec/unit/views/pages/form_spec.rb +17 -10
  419. data/spec/unit/views/pages/index_spec.rb +60 -0
  420. data/spec/unit/views/pages/layout_spec.rb +17 -21
  421. data/spec/unit/views/pages/show_spec.rb +16 -3
  422. data/spec/unit/views/tabbed_navigation_spec.rb +61 -52
  423. data/tasks/docs.rake +1 -1
  424. data/tasks/parallel_tests.rake +8 -2
  425. data/tasks/test.rake +8 -4
  426. data/tasks/yard.rake +7 -5
  427. metadata +180 -101
  428. data/app/assets/images/active_admin/admin_notes_icon.png +0 -0
  429. data/app/assets/images/active_admin/datepicker/datepicker-header-bg.png +0 -0
  430. data/app/assets/images/active_admin/datepicker/datepicker-next-link-icon.png +0 -0
  431. data/app/assets/images/active_admin/datepicker/datepicker-nipple.png +0 -0
  432. data/app/assets/images/active_admin/datepicker/datepicker-prev-link-icon.png +0 -0
  433. data/app/assets/images/active_admin/index_list_icons/block_icon.svg +0 -10
  434. data/app/assets/images/active_admin/index_list_icons/blog_icon.svg +0 -4
  435. data/app/assets/images/active_admin/index_list_icons/grid_icon.svg +0 -13
  436. data/app/assets/images/active_admin/index_list_icons/table_icon.svg +0 -3
  437. data/app/assets/images/active_admin/loading.gif +0 -0
  438. data/app/assets/javascripts/active_admin/components/application.js.coffee +0 -23
  439. data/app/assets/javascripts/active_admin/components/batch_actions.js.coffee +0 -26
  440. data/app/assets/javascripts/active_admin/components/has_many.js.coffee +0 -41
  441. data/app/assets/stylesheets/active_admin/components/_batch_actions.css.scss +0 -11
  442. data/app/assets/stylesheets/active_admin/components/_flash_messages.css.scss +0 -39
  443. data/app/assets/stylesheets/active_admin/components/_table_tools.css.scss +0 -95
  444. data/app/views/active_admin/dashboard/index.html.arb +0 -1
  445. data/app/views/active_admin/resource/index.csv.erb +0 -17
  446. data/docs/3-index-pages/create-an-index.md +0 -29
  447. data/lib/active_admin/inputs/filter_base.rb +0 -33
  448. data/lib/active_admin/inputs/filter_base/search_method_select.rb +0 -73
  449. data/lib/active_admin/inputs/filter_boolean_input.rb +0 -32
  450. data/lib/active_admin/inputs/filter_check_boxes_input.rb +0 -51
  451. data/lib/active_admin/inputs/filter_date_range_input.rb +0 -34
  452. data/lib/active_admin/inputs/filter_numeric_input.rb +0 -10
  453. data/lib/active_admin/inputs/filter_select_input.rb +0 -61
  454. data/lib/active_admin/inputs/filter_string_input.rb +0 -24
  455. data/lib/active_admin/view_helpers/assigns_with_indifferent_access_helper.rb +0 -7
  456. data/spec/integration/memory_spec.rb +0 -29
  457. data/spec/integration/stylesheets_spec.rb +0 -41
  458. data/spec/javascripts/compiled/jquery.aa.checkbox-toggler-spec.js +0 -60
  459. data/spec/javascripts/compiled/jquery.aa.popover-spec.js +0 -106
  460. data/spec/javascripts/compiled/jquery.aa.table-checkbox-toggler-spec.js +0 -37
  461. data/spec/javascripts/helpers/vendor/jasmine-fixture-0.0.5.js +0 -108
  462. data/spec/javascripts/helpers/vendor/jasmine-jquery.js +0 -288
  463. data/spec/javascripts/helpers/vendor/sinon-1.2.0.js +0 -2915
  464. data/spec/javascripts/support/jquery-ui-1.8.16.custom.min.js +0 -34
  465. data/spec/javascripts/support/jquery.min.js +0 -4
  466. data/spec/spec_helper_without_rails.rb +0 -16
  467. data/tasks/js.rake +0 -32
@@ -1,37 +0,0 @@
1
- (function() {
2
-
3
- describe("ActiveAdmin.TableCheckboxToggler", function() {
4
- beforeEach(function() {
5
- loadFixtures('table_checkboxes.html');
6
- this.collection = $("#collection");
7
- this.toggle_all = this.collection.find(".toggle_all");
8
- this.checkboxes = this.collection.find(":checkbox").not(this.toggle_all);
9
- return new ActiveAdmin.TableCheckboxToggler({}, this.collection);
10
- });
11
- describe("'selected' class for table row", function() {
12
- it("should add the class 'selected' to rows when their checkbox is checked ", function() {
13
- var checkbox;
14
- checkbox = $("#item_1");
15
- checkbox.attr("checked", "checked");
16
- checkbox.trigger("change");
17
- return expect(checkbox.parents("tr")).toHaveAttr("class", "selected");
18
- });
19
- return it("should remove the class 'selected' from rows when their checkbox is unchecked ", function() {
20
- var checkbox;
21
- checkbox = $("#item_1");
22
- checkbox.trigger("change");
23
- return expect(checkbox.parents("tr")).not.toHaveAttr("class", "selected");
24
- });
25
- });
26
- return describe("clicking a cell", function() {
27
- return it("should toggle the checkbox when a cell is clicked", function() {
28
- var checkbox, row;
29
- checkbox = $("#item_1");
30
- row = checkbox.parents("td");
31
- $(row).trigger("click");
32
- return expect(checkbox).toHaveAttr("checked", "checked");
33
- });
34
- });
35
- });
36
-
37
- }).call(this);
@@ -1,108 +0,0 @@
1
- /* jasmine-fixture Makes injecting HTML snippets into the DOM easy & clean!
2
- * site: https://github.com/searls/jasmine-fixture */
3
- (function($){
4
- var originalJasmineFixture = window.jasmineFixture,
5
- defaultConfiguration = {
6
- el:'div',
7
- cssClass:'',
8
- id:'',
9
- text: '',
10
- html: '',
11
- defaultAttribute: 'class',
12
- attrs: {}
13
- };
14
-
15
- window.jasmineFixture = function($) {
16
- var isReady = false,
17
- rootId = 'specContainer',
18
- defaults = $.extend({},defaultConfiguration);
19
-
20
- $.jasmine = {
21
- inject: function(arg,context) {
22
- if(isReady !== true) init();
23
- var parent = context ? context : $('#'+rootId),
24
- $toInject;
25
- if(itLooksLikeHtml(arg)) {
26
- $toInject = $(arg);
27
- } else {
28
- var config = $.extend({},defaults,arg,{ userString: arg });
29
- $toInject = $('<'+config.el+'></'+config.el+'>');
30
- applyAttributes($toInject,config);
31
- injectContents($toInject,config);
32
- }
33
- return $toInject.appendTo(parent);
34
- },
35
- configure: function(config) {
36
- $.extend(defaults,config);
37
- },
38
- restoreDefaults: function(){
39
- defaults = $.extend({},defaultConfiguration);
40
- },
41
- noConflict: function() {
42
- window.jasmineFixture = originalJasmineFixture;
43
- return this;
44
- }
45
- };
46
-
47
- $.fn.inject = function(html){
48
- return $.jasmine.inject(html,$(this));
49
- };
50
-
51
- var applyAttributes = function($html,config) {
52
- var attrs = $.extend({},{
53
- id: config.id,
54
- 'class': config['class'] || config.cssClass
55
- }, config.attrs);
56
- if(isString(config.userString)) {
57
- attrs[config.defaultAttribute] = config.userString;
58
- }
59
- for(var key in attrs) {
60
- if(attrs[key]) {
61
- $html.attr(key,attrs[key]);
62
- }
63
- }
64
- };
65
-
66
- var injectContents = function($el,config){
67
- if(config.text && config.html) {
68
- throw "Error: because they conflict, you may only configure inject() to set `html` or `text`, not both! \n\nHTML was: "+config.html+" \n\n Text was: "+config.text
69
- } else if(config.text) {
70
- $el.text(config.text);
71
- } else if(config.html) {
72
- $el.html(config.html);
73
- }
74
- }
75
-
76
- var itLooksLikeHtml = function(arg) {
77
- return isString(arg) && arg.indexOf('<') !== -1
78
- };
79
-
80
- var isString = function(arg) {
81
- return arg && arg.constructor === String;
82
- };
83
-
84
- var init = function() {
85
- $('body').append('<div id="'+rootId+'"></div>');
86
- isReady = true;
87
- };
88
-
89
- var tidyUp = function() {
90
- $('#'+rootId).remove();
91
- isReady = false;
92
- };
93
-
94
- $(function(jQuery){
95
- init();
96
- });
97
- afterEach(function(){
98
- tidyUp();
99
- });
100
-
101
- return $.jasmine;
102
- };
103
-
104
- if(jQuery) {
105
- var jasmineFixture = window.jasmineFixture(jQuery);
106
- window.inject = window.inject || jasmineFixture.inject;
107
- }
108
- })(jQuery);
@@ -1,288 +0,0 @@
1
- var readFixtures = function() {
2
- return jasmine.getFixtures().proxyCallTo_('read', arguments);
3
- };
4
-
5
- var preloadFixtures = function() {
6
- jasmine.getFixtures().proxyCallTo_('preload', arguments);
7
- };
8
-
9
- var loadFixtures = function() {
10
- jasmine.getFixtures().proxyCallTo_('load', arguments);
11
- };
12
-
13
- var setFixtures = function(html) {
14
- jasmine.getFixtures().set(html);
15
- };
16
-
17
- var sandbox = function(attributes) {
18
- return jasmine.getFixtures().sandbox(attributes);
19
- };
20
-
21
- var spyOnEvent = function(selector, eventName) {
22
- jasmine.JQuery.events.spyOn(selector, eventName);
23
- }
24
-
25
- jasmine.getFixtures = function() {
26
- return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures();
27
- };
28
-
29
- jasmine.Fixtures = function() {
30
- this.containerId = 'jasmine-fixtures';
31
- this.fixturesCache_ = {};
32
- this.fixturesPath = 'spec/javascripts/fixtures';
33
- };
34
-
35
- jasmine.Fixtures.prototype.set = function(html) {
36
- this.cleanUp();
37
- this.createContainer_(html);
38
- };
39
-
40
- jasmine.Fixtures.prototype.preload = function() {
41
- this.read.apply(this, arguments);
42
- };
43
-
44
- jasmine.Fixtures.prototype.load = function() {
45
- this.cleanUp();
46
- this.createContainer_(this.read.apply(this, arguments));
47
- };
48
-
49
- jasmine.Fixtures.prototype.read = function() {
50
- var htmlChunks = [];
51
-
52
- var fixtureUrls = arguments;
53
- for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) {
54
- htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex]));
55
- }
56
-
57
- return htmlChunks.join('');
58
- };
59
-
60
- jasmine.Fixtures.prototype.clearCache = function() {
61
- this.fixturesCache_ = {};
62
- };
63
-
64
- jasmine.Fixtures.prototype.cleanUp = function() {
65
- jQuery('#' + this.containerId).remove();
66
- };
67
-
68
- jasmine.Fixtures.prototype.sandbox = function(attributes) {
69
- var attributesToSet = attributes || {};
70
- return jQuery('<div id="sandbox" />').attr(attributesToSet);
71
- };
72
-
73
- jasmine.Fixtures.prototype.createContainer_ = function(html) {
74
- var container;
75
- if(html instanceof jQuery) {
76
- container = jQuery('<div id="' + this.containerId + '" />');
77
- container.html(html);
78
- } else {
79
- container = '<div id="' + this.containerId + '">' + html + '</div>'
80
- }
81
- jQuery('body').append(container);
82
- };
83
-
84
- jasmine.Fixtures.prototype.getFixtureHtml_ = function(url) {
85
- if (typeof this.fixturesCache_[url] == 'undefined') {
86
- this.loadFixtureIntoCache_(url);
87
- }
88
- return this.fixturesCache_[url];
89
- };
90
-
91
- jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) {
92
- var self = this;
93
- var url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl;
94
- jQuery.ajax({
95
- async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded
96
- cache: false,
97
- dataType: 'html',
98
- url: url,
99
- success: function(data) {
100
- self.fixturesCache_[relativeUrl] = data;
101
- },
102
- error: function(jqXHR, status, errorThrown) {
103
- throw Error('Fixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + errorThrown.message + ')');
104
- }
105
- });
106
- };
107
-
108
- jasmine.Fixtures.prototype.proxyCallTo_ = function(methodName, passedArguments) {
109
- return this[methodName].apply(this, passedArguments);
110
- };
111
-
112
-
113
- jasmine.JQuery = function() {};
114
-
115
- jasmine.JQuery.browserTagCaseIndependentHtml = function(html) {
116
- return jQuery('<div/>').append(html).html();
117
- };
118
-
119
- jasmine.JQuery.elementToString = function(element) {
120
- return jQuery('<div />').append(element.clone()).html();
121
- };
122
-
123
- jasmine.JQuery.matchersClass = {};
124
-
125
- (function(namespace) {
126
- var data = {
127
- spiedEvents: {},
128
- handlers: []
129
- };
130
-
131
- namespace.events = {
132
- spyOn: function(selector, eventName) {
133
- var handler = function(e) {
134
- data.spiedEvents[[selector, eventName]] = e;
135
- };
136
- jQuery(selector).bind(eventName, handler);
137
- data.handlers.push(handler);
138
- },
139
-
140
- wasTriggered: function(selector, eventName) {
141
- return !!(data.spiedEvents[[selector, eventName]]);
142
- },
143
-
144
- cleanUp: function() {
145
- data.spiedEvents = {};
146
- data.handlers = [];
147
- }
148
- }
149
- })(jasmine.JQuery);
150
-
151
- (function(){
152
- var jQueryMatchers = {
153
- toHaveClass: function(className) {
154
- return this.actual.hasClass(className);
155
- },
156
-
157
- toBeVisible: function() {
158
- return this.actual.is(':visible');
159
- },
160
-
161
- toBeHidden: function() {
162
- return this.actual.is(':hidden');
163
- },
164
-
165
- toBeSelected: function() {
166
- return this.actual.is(':selected');
167
- },
168
-
169
- toBeChecked: function() {
170
- return this.actual.is(':checked');
171
- },
172
-
173
- toBeEmpty: function() {
174
- return this.actual.is(':empty');
175
- },
176
-
177
- toExist: function() {
178
- return this.actual.size() > 0;
179
- },
180
-
181
- toHaveAttr: function(attributeName, expectedAttributeValue) {
182
- return hasProperty(this.actual.attr(attributeName), expectedAttributeValue);
183
- },
184
-
185
- toHaveId: function(id) {
186
- return this.actual.attr('id') == id;
187
- },
188
-
189
- toHaveHtml: function(html) {
190
- return this.actual.html() == jasmine.JQuery.browserTagCaseIndependentHtml(html);
191
- },
192
-
193
- toHaveText: function(text) {
194
- if (text && jQuery.isFunction(text.test)) {
195
- return text.test(this.actual.text());
196
- } else {
197
- return this.actual.text() == text;
198
- }
199
- },
200
-
201
- toHaveValue: function(value) {
202
- return this.actual.val() == value;
203
- },
204
-
205
- toHaveData: function(key, expectedValue) {
206
- return hasProperty(this.actual.data(key), expectedValue);
207
- },
208
-
209
- toBe: function(selector) {
210
- return this.actual.is(selector);
211
- },
212
-
213
- toContain: function(selector) {
214
- return this.actual.find(selector).size() > 0;
215
- },
216
-
217
- toBeDisabled: function(selector){
218
- return this.actual.is(':disabled');
219
- },
220
-
221
- // tests the existence of a specific event binding
222
- toHandle: function(eventName) {
223
- var events = this.actual.data("events");
224
- return events && events[eventName].length > 0;
225
- },
226
-
227
- // tests the existence of a specific event binding + handler
228
- toHandleWith: function(eventName, eventHandler) {
229
- var stack = this.actual.data("events")[eventName];
230
- var i;
231
- for (i = 0; i < stack.length; i++) {
232
- if (stack[i].handler == eventHandler) {
233
- return true;
234
- }
235
- }
236
- return false;
237
- }
238
- };
239
-
240
- var hasProperty = function(actualValue, expectedValue) {
241
- if (expectedValue === undefined) {
242
- return actualValue !== undefined;
243
- }
244
- return actualValue == expectedValue;
245
- };
246
-
247
- var bindMatcher = function(methodName) {
248
- var builtInMatcher = jasmine.Matchers.prototype[methodName];
249
-
250
- jasmine.JQuery.matchersClass[methodName] = function() {
251
- if (this.actual instanceof jQuery) {
252
- var result = jQueryMatchers[methodName].apply(this, arguments);
253
- this.actual = jasmine.JQuery.elementToString(this.actual);
254
- return result;
255
- }
256
-
257
- if (builtInMatcher) {
258
- return builtInMatcher.apply(this, arguments);
259
- }
260
-
261
- return false;
262
- };
263
- };
264
-
265
- for(var methodName in jQueryMatchers) {
266
- bindMatcher(methodName);
267
- }
268
- })();
269
-
270
- beforeEach(function() {
271
- this.addMatchers(jasmine.JQuery.matchersClass);
272
- this.addMatchers({
273
- toHaveBeenTriggeredOn: function(selector) {
274
- this.message = function() {
275
- return [
276
- "Expected event " + this.actual + " to have been triggered on" + selector,
277
- "Expected event " + this.actual + " not to have been triggered on" + selector
278
- ];
279
- };
280
- return jasmine.JQuery.events.wasTriggered(selector, this.actual);
281
- }
282
- })
283
- });
284
-
285
- afterEach(function() {
286
- jasmine.getFixtures().cleanUp();
287
- jasmine.JQuery.events.cleanUp();
288
- });
@@ -1,2915 +0,0 @@
1
- /**
2
- * Sinon.JS 1.2.0, 2011/09/27
3
- *
4
- * @author Christian Johansen (christian@cjohansen.no)
5
- *
6
- * (The BSD License)
7
- *
8
- * Copyright (c) 2010-2011, Christian Johansen, christian@cjohansen.no
9
- * All rights reserved.
10
- *
11
- * Redistribution and use in source and binary forms, with or without modification,
12
- * are permitted provided that the following conditions are met:
13
- *
14
- * * Redistributions of source code must retain the above copyright notice,
15
- * this list of conditions and the following disclaimer.
16
- * * Redistributions in binary form must reproduce the above copyright notice,
17
- * this list of conditions and the following disclaimer in the documentation
18
- * and/or other materials provided with the distribution.
19
- * * Neither the name of Christian Johansen nor the names of his contributors
20
- * may be used to endorse or promote products derived from this software
21
- * without specific prior written permission.
22
- *
23
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
27
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
- */
34
-
35
- "use strict";
36
- /*jslint eqeqeq: false, onevar: false, forin: true, nomen: false, regexp: false, plusplus: false*/
37
- /*global module, require, __dirname, document*/
38
- /**
39
- * Sinon core utilities. For internal use only.
40
- *
41
- * @author Christian Johansen (christian@cjohansen.no)
42
- * @license BSD
43
- *
44
- * Copyright (c) 2010-2011 Christian Johansen
45
- */
46
-
47
- var sinon = (function () {
48
- var div = typeof document != "undefined" && document.createElement("div");
49
-
50
- function isNode(obj) {
51
- var success = false;
52
-
53
- try {
54
- obj.appendChild(div);
55
- success = div.parentNode == obj;
56
- } catch (e) {
57
- return false;
58
- } finally {
59
- try {
60
- obj.removeChild(div);
61
- } catch (e) {}
62
- }
63
-
64
- return success;
65
- }
66
-
67
- function isElement(obj) {
68
- return div && obj && obj.nodeType === 1 && isNode(obj);
69
- }
70
-
71
- return {
72
- wrapMethod: function wrapMethod(object, property, method) {
73
- if (!object) {
74
- throw new TypeError("Should wrap property of object");
75
- }
76
-
77
- if (typeof method != "function") {
78
- throw new TypeError("Method wrapper should be function");
79
- }
80
-
81
- var wrappedMethod = object[property];
82
- var type = typeof wrappedMethod;
83
-
84
- if (type != "function") {
85
- throw new TypeError("Attempted to wrap " + type + " property " + property +
86
- " as function");
87
- }
88
-
89
- if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
90
- throw new TypeError("Attempted to wrap " + property + " which is already wrapped");
91
- }
92
-
93
- if (wrappedMethod.calledBefore) {
94
- var verb = !!wrappedMethod.returns ? "stubbed" : "spied on";
95
- throw new TypeError("Attempted to wrap " + property + " which is already " + verb);
96
- }
97
-
98
- var owned = object.hasOwnProperty(property);
99
- object[property] = method;
100
- method.displayName = property;
101
-
102
- method.restore = function () {
103
- if(owned) {
104
- object[property] = wrappedMethod;
105
- } else {
106
- delete object[property];
107
- }
108
- };
109
-
110
- method.restore.sinon = true;
111
-
112
- return method;
113
- },
114
-
115
- extend: function extend(target) {
116
- for (var i = 1, l = arguments.length; i < l; i += 1) {
117
- for (var prop in arguments[i]) {
118
- if (arguments[i].hasOwnProperty(prop)) {
119
- target[prop] = arguments[i][prop];
120
- }
121
-
122
- // DONT ENUM bug, only care about toString
123
- if (arguments[i].hasOwnProperty("toString") &&
124
- arguments[i].toString != target.toString) {
125
- target.toString = arguments[i].toString;
126
- }
127
- }
128
- }
129
-
130
- return target;
131
- },
132
-
133
- create: function create(proto) {
134
- var F = function () {};
135
- F.prototype = proto;
136
- return new F();
137
- },
138
-
139
- deepEqual: function deepEqual(a, b) {
140
- if (typeof a != "object" || typeof b != "object") {
141
- return a === b;
142
- }
143
-
144
- if (isElement(a) || isElement(b)) {
145
- return a === b;
146
- }
147
-
148
- if (a === b) {
149
- return true;
150
- }
151
-
152
- if (Object.prototype.toString.call(a) == "[object Array]") {
153
- if (a.length !== b.length) {
154
- return false;
155
- }
156
-
157
- for (var i = 0, l = a.length; i < l; i += 1) {
158
- if (!deepEqual(a[i], b[i])) {
159
- return false;
160
- }
161
- }
162
-
163
- return true;
164
- }
165
-
166
- var prop, aLength = 0, bLength = 0;
167
-
168
- for (prop in a) {
169
- aLength += 1;
170
-
171
- if (!deepEqual(a[prop], b[prop])) {
172
- return false;
173
- }
174
- }
175
-
176
- for (prop in b) {
177
- bLength += 1;
178
- }
179
-
180
- if (aLength != bLength) {
181
- return false;
182
- }
183
-
184
- return true;
185
- },
186
-
187
- functionName: function functionName(func) {
188
- var name = func.displayName || func.name;
189
-
190
- // Use function decomposition as a last resort to get function
191
- // name. Does not rely on function decomposition to work - if it
192
- // doesn't debugging will be slightly less informative
193
- // (i.e. toString will say 'spy' rather than 'myFunc').
194
- if (!name) {
195
- var matches = func.toString().match(/function ([^\s\(]+)/);
196
- name = matches && matches[1];
197
- }
198
-
199
- return name;
200
- },
201
-
202
- functionToString: function toString() {
203
- if (this.getCall && this.callCount) {
204
- var thisValue, prop, i = this.callCount;
205
-
206
- while (i--) {
207
- thisValue = this.getCall(i).thisValue;
208
-
209
- for (prop in thisValue) {
210
- if (thisValue[prop] === this) {
211
- return prop;
212
- }
213
- }
214
- }
215
- }
216
-
217
- return this.displayName || "sinon fake";
218
- },
219
-
220
- getConfig: function (custom) {
221
- var config = {};
222
- custom = custom || {};
223
- var defaults = sinon.defaultConfig;
224
-
225
- for (var prop in defaults) {
226
- if (defaults.hasOwnProperty(prop)) {
227
- config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
228
- }
229
- }
230
-
231
- return config;
232
- },
233
-
234
- format: function (val) {
235
- return "" + val;
236
- },
237
-
238
- defaultConfig: {
239
- injectIntoThis: true,
240
- injectInto: null,
241
- properties: ["spy", "stub", "mock", "clock", "server", "requests"],
242
- useFakeTimers: true,
243
- useFakeServer: true
244
- },
245
-
246
- timesInWords: function timesInWords(count) {
247
- return count == 1 && "once" ||
248
- count == 2 && "twice" ||
249
- count == 3 && "thrice" ||
250
- (count || 0) + " times";
251
- },
252
-
253
- calledInOrder: function (spies) {
254
- for (var i = 1, l = spies.length; i < l; i++) {
255
- if (!spies[i - 1].calledBefore(spies[i])) {
256
- return false;
257
- }
258
- }
259
-
260
- return true;
261
- },
262
-
263
- orderByFirstCall: function (spies) {
264
- return spies.sort(function (a, b) {
265
- // uuid, won't ever be equal
266
- return a.getCall(0).callId < b.getCall(0).callId ? -1 : 1;
267
- });
268
- }
269
- };
270
- }());
271
-
272
- if (typeof module == "object" && typeof require == "function") {
273
- module.exports = sinon;
274
- module.exports.spy = require("./sinon/spy");
275
- module.exports.stub = require("./sinon/stub");
276
- module.exports.mock = require("./sinon/mock");
277
- module.exports.collection = require("./sinon/collection");
278
- module.exports.assert = require("./sinon/assert");
279
- module.exports.sandbox = require("./sinon/sandbox");
280
- module.exports.test = require("./sinon/test");
281
- module.exports.testCase = require("./sinon/test_case");
282
- module.exports.assert = require("./sinon/assert");
283
- }
284
-
285
- /* @depend ../sinon.js */
286
- /*jslint eqeqeq: false, onevar: false, plusplus: false*/
287
- /*global module, require, sinon*/
288
- /**
289
- * Spy functions
290
- *
291
- * @author Christian Johansen (christian@cjohansen.no)
292
- * @license BSD
293
- *
294
- * Copyright (c) 2010-2011 Christian Johansen
295
- */
296
-
297
- (function (sinon) {
298
- var commonJSModule = typeof module == "object" && typeof require == "function";
299
- var spyCall;
300
- var callId = 0;
301
- var push = [].push;
302
-
303
- if (!sinon && commonJSModule) {
304
- sinon = require("../sinon");
305
- }
306
-
307
- if (!sinon) {
308
- return;
309
- }
310
-
311
- function spy(object, property) {
312
- if (!property && typeof object == "function") {
313
- return spy.create(object);
314
- }
315
-
316
- if (!object || !property) {
317
- return spy.create(function () {});
318
- }
319
-
320
- var method = object[property];
321
- return sinon.wrapMethod(object, property, spy.create(method));
322
- }
323
-
324
- sinon.extend(spy, (function () {
325
- var slice = Array.prototype.slice;
326
-
327
- function delegateToCalls(api, method, matchAny, actual, notCalled) {
328
- api[method] = function () {
329
- if (!this.called) {
330
- return !!notCalled;
331
- }
332
-
333
- var currentCall;
334
- var matches = 0;
335
-
336
- for (var i = 0, l = this.callCount; i < l; i += 1) {
337
- currentCall = this.getCall(i);
338
-
339
- if (currentCall[actual || method].apply(currentCall, arguments)) {
340
- matches += 1;
341
-
342
- if (matchAny) {
343
- return true;
344
- }
345
- }
346
- }
347
-
348
- return matches === this.callCount;
349
- };
350
- }
351
-
352
- function matchingFake(fakes, args, strict) {
353
- if (!fakes) {
354
- return;
355
- }
356
-
357
- var alen = args.length;
358
-
359
- for (var i = 0, l = fakes.length; i < l; i++) {
360
- if (fakes[i].matches(args, strict)) {
361
- return fakes[i];
362
- }
363
- }
364
- }
365
-
366
- var uuid = 0;
367
-
368
- // Public API
369
- var spyApi = {
370
- reset: function () {
371
- this.called = false;
372
- this.calledOnce = false;
373
- this.calledTwice = false;
374
- this.calledThrice = false;
375
- this.callCount = 0;
376
- this.args = [];
377
- this.returnValues = [];
378
- this.thisValues = [];
379
- this.exceptions = [];
380
- this.callIds = [];
381
- },
382
-
383
- create: function create(func) {
384
- var name;
385
-
386
- if (typeof func != "function") {
387
- func = function () {};
388
- } else {
389
- name = sinon.functionName(func);
390
- }
391
-
392
- function proxy() {
393
- return proxy.invoke(func, this, slice.call(arguments));
394
- }
395
-
396
- sinon.extend(proxy, spy);
397
- delete proxy.create;
398
- sinon.extend(proxy, func);
399
-
400
- proxy.reset();
401
- proxy.prototype = func.prototype;
402
- proxy.displayName = name || "spy";
403
- proxy.toString = sinon.functionToString;
404
- proxy._create = sinon.spy.create;
405
- proxy.id = "spy#" + uuid++;
406
-
407
- return proxy;
408
- },
409
-
410
- invoke: function invoke(func, thisValue, args) {
411
- var matching = matchingFake(this.fakes, args);
412
- var exception, returnValue;
413
- this.called = true;
414
- this.callCount += 1;
415
- this.calledOnce = this.callCount == 1;
416
- this.calledTwice = this.callCount == 2;
417
- this.calledThrice = this.callCount == 3;
418
- push.call(this.thisValues, thisValue);
419
- push.call(this.args, args);
420
- push.call(this.callIds, callId++);
421
-
422
- try {
423
- if (matching) {
424
- returnValue = matching.invoke(func, thisValue, args);
425
- } else {
426
- returnValue = (this.func || func).apply(thisValue, args);
427
- }
428
- } catch (e) {
429
- push.call(this.returnValues, undefined);
430
- exception = e;
431
- throw e;
432
- } finally {
433
- push.call(this.exceptions, exception);
434
- }
435
-
436
- push.call(this.returnValues, returnValue);
437
-
438
- return returnValue;
439
- },
440
-
441
- getCall: function getCall(i) {
442
- if (i < 0 || i >= this.callCount) {
443
- return null;
444
- }
445
-
446
- return spyCall.create(this, this.thisValues[i], this.args[i],
447
- this.returnValues[i], this.exceptions[i],
448
- this.callIds[i]);
449
- },
450
-
451
- calledBefore: function calledBefore(spyFn) {
452
- if (!this.called) {
453
- return false;
454
- }
455
-
456
- if (!spyFn.called) {
457
- return true;
458
- }
459
-
460
- return this.callIds[0] < spyFn.callIds[0];
461
- },
462
-
463
- calledAfter: function calledAfter(spyFn) {
464
- if (!this.called || !spyFn.called) {
465
- return false;
466
- }
467
-
468
- return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
469
- },
470
-
471
- withArgs: function () {
472
- var args = slice.call(arguments);
473
-
474
- if (this.fakes) {
475
- var match = matchingFake(this.fakes, args, true);
476
-
477
- if (match) {
478
- return match;
479
- }
480
- } else {
481
- this.fakes = [];
482
- }
483
-
484
- var original = this;
485
- var fake = this._create();
486
- fake.matchingAguments = args;
487
- push.call(this.fakes, fake);
488
-
489
- fake.withArgs = function () {
490
- return original.withArgs.apply(original, arguments);
491
- };
492
-
493
- return fake;
494
- },
495
-
496
- matches: function (args, strict) {
497
- var margs = this.matchingAguments;
498
-
499
- if (margs.length <= args.length &&
500
- sinon.deepEqual(margs, args.slice(0, margs.length))) {
501
- return !strict || margs.length == args.length;
502
- }
503
- },
504
-
505
- printf: function (format) {
506
- var spy = this;
507
- var args = [].slice.call(arguments, 1);
508
- var formatter;
509
-
510
- return (format || "").replace(/%(.)/g, function (match, specifyer) {
511
- formatter = spyApi.formatters[specifyer];
512
-
513
- if (typeof formatter == "function") {
514
- return formatter.call(null, spy, args);
515
- } else if (!isNaN(parseInt(specifyer), 10)) {
516
- return sinon.format(args[specifyer - 1]);
517
- }
518
-
519
- return "%" + specifyer;
520
- });
521
- }
522
- };
523
-
524
- delegateToCalls(spyApi, "calledOn", true);
525
- delegateToCalls(spyApi, "alwaysCalledOn", false, "calledOn");
526
- delegateToCalls(spyApi, "calledWith", true);
527
- delegateToCalls(spyApi, "alwaysCalledWith", false, "calledWith");
528
- delegateToCalls(spyApi, "calledWithExactly", true);
529
- delegateToCalls(spyApi, "alwaysCalledWithExactly", false, "calledWithExactly");
530
- delegateToCalls(spyApi, "neverCalledWith", false, "notCalledWith", true);
531
- delegateToCalls(spyApi, "threw", true);
532
- delegateToCalls(spyApi, "alwaysThrew", false, "threw");
533
- delegateToCalls(spyApi, "returned", true);
534
- delegateToCalls(spyApi, "alwaysReturned", false, "returned");
535
- delegateToCalls(spyApi, "calledWithNew", true);
536
- delegateToCalls(spyApi, "alwaysCalledWithNew", false, "calledWithNew");
537
-
538
- spyApi.formatters = {
539
- "c": function (spy) {
540
- return sinon.timesInWords(spy.callCount);
541
- },
542
-
543
- "n": function (spy) {
544
- return spy.toString();
545
- },
546
-
547
- "C": function (spy) {
548
- var calls = [];
549
-
550
- for (var i = 0, l = spy.callCount; i < l; ++i) {
551
- push.call(calls, " " + spy.getCall(i).toString());
552
- }
553
-
554
- return calls.length > 0 ? "\n" + calls.join("\n") : "";
555
- },
556
-
557
- "t": function (spy) {
558
- var objects = [];
559
-
560
- for (var i = 0, l = spy.callCount; i < l; ++i) {
561
- push.call(objects, sinon.format(spy.thisValues[i]));
562
- }
563
-
564
- return objects.join(", ");
565
- },
566
-
567
- "*": function (spy, args) {
568
- return args.join(", ");
569
- }
570
- };
571
-
572
- return spyApi;
573
- }()));
574
-
575
- spyCall = (function () {
576
- return {
577
- create: function create(spy, thisValue, args, returnValue, exception, id) {
578
- var proxyCall = sinon.create(spyCall);
579
- delete proxyCall.create;
580
- proxyCall.proxy = spy;
581
- proxyCall.thisValue = thisValue;
582
- proxyCall.args = args;
583
- proxyCall.returnValue = returnValue;
584
- proxyCall.exception = exception;
585
- proxyCall.callId = typeof id == "number" && id || callId++;
586
-
587
- return proxyCall;
588
- },
589
-
590
- calledOn: function calledOn(thisValue) {
591
- return this.thisValue === thisValue;
592
- },
593
-
594
- calledWith: function calledWith() {
595
- for (var i = 0, l = arguments.length; i < l; i += 1) {
596
- if (!sinon.deepEqual(arguments[i], this.args[i])) {
597
- return false;
598
- }
599
- }
600
-
601
- return true;
602
- },
603
-
604
- calledWithExactly: function calledWithExactly() {
605
- return arguments.length == this.args.length &&
606
- this.calledWith.apply(this, arguments);
607
- },
608
-
609
- notCalledWith: function notCalledWith() {
610
- for (var i = 0, l = arguments.length; i < l; i += 1) {
611
- if (!sinon.deepEqual(arguments[i], this.args[i])) {
612
- return true;
613
- }
614
- }
615
- return false;
616
- },
617
-
618
- returned: function returned(value) {
619
- return this.returnValue === value;
620
- },
621
-
622
- threw: function threw(error) {
623
- if (typeof error == "undefined" || !this.exception) {
624
- return !!this.exception;
625
- }
626
-
627
- if (typeof error == "string") {
628
- return this.exception.name == error;
629
- }
630
-
631
- return this.exception === error;
632
- },
633
-
634
- calledWithNew: function calledWithNew(thisValue) {
635
- return this.thisValue instanceof this.proxy;
636
- },
637
-
638
- calledBefore: function (other) {
639
- return this.callId < other.callId;
640
- },
641
-
642
- calledAfter: function (other) {
643
- return this.callId > other.callId;
644
- },
645
-
646
- toString: function () {
647
- var callStr = this.proxy.toString() + "(";
648
- var args = [];
649
-
650
- for (var i = 0, l = this.args.length; i < l; ++i) {
651
- push.call(args, sinon.format(this.args[i]));
652
- }
653
-
654
- callStr = callStr + args.join(", ") + ")";
655
-
656
- if (typeof this.returnValue != "undefined") {
657
- callStr += " => " + sinon.format(this.returnValue);
658
- }
659
-
660
- if (this.exception) {
661
- callStr += " !" + this.exception.name;
662
-
663
- if (this.exception.message) {
664
- callStr += "(" + this.exception.message + ")";
665
- }
666
- }
667
-
668
- return callStr;
669
- }
670
- };
671
- }());
672
-
673
- spy.spyCall = spyCall;
674
-
675
- // This steps outside the module sandbox and will be removed
676
- sinon.spyCall = spyCall;
677
-
678
- if (commonJSModule) {
679
- module.exports = spy;
680
- } else {
681
- sinon.spy = spy;
682
- }
683
- }(typeof sinon == "object" && sinon || null));
684
-
685
- /**
686
- * @depend ../sinon.js
687
- * @depend spy.js
688
- */
689
- /*jslint eqeqeq: false, onevar: false*/
690
- /*global module, require, sinon*/
691
- /**
692
- * Stub functions
693
- *
694
- * @author Christian Johansen (christian@cjohansen.no)
695
- * @license BSD
696
- *
697
- * Copyright (c) 2010-2011 Christian Johansen
698
- */
699
-
700
- (function (sinon) {
701
- var commonJSModule = typeof module == "object" && typeof require == "function";
702
-
703
- if (!sinon && commonJSModule) {
704
- sinon = require("../sinon");
705
- }
706
-
707
- if (!sinon) {
708
- return;
709
- }
710
-
711
- function stub(object, property, func) {
712
- if (!!func && typeof func != "function") {
713
- throw new TypeError("Custom stub should be function");
714
- }
715
-
716
- var wrapper;
717
-
718
- if (func) {
719
- wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
720
- } else {
721
- wrapper = stub.create();
722
- }
723
-
724
- if (!object && !property) {
725
- return sinon.stub.create();
726
- }
727
-
728
- if (!property && !!object && typeof object == "object") {
729
- for (var prop in object) {
730
- if (object.hasOwnProperty(prop) && typeof object[prop] == "function") {
731
- stub(object, prop);
732
- }
733
- }
734
-
735
- return object;
736
- }
737
-
738
- return sinon.wrapMethod(object, property, wrapper);
739
- }
740
-
741
- function getCallback(stub, args) {
742
- if (stub.callArgAt < 0) {
743
- for (var i = 0, l = args.length; i < l; ++i) {
744
- if (!stub.callArgProp && typeof args[i] == "function") {
745
- return args[i];
746
- }
747
-
748
- if (stub.callArgProp && args[i] &&
749
- typeof args[i][stub.callArgProp] == "function") {
750
- return args[i][stub.callArgProp];
751
- }
752
- }
753
-
754
- return null;
755
- }
756
-
757
- return args[stub.callArgAt];
758
- }
759
-
760
- var join = Array.prototype.join;
761
-
762
- function getCallbackError(stub, func, args) {
763
- if (stub.callArgAt < 0) {
764
- var msg;
765
-
766
- if (stub.callArgProp) {
767
- msg = sinon.functionName(stub) +
768
- " expected to yield to '" + stub.callArgProp +
769
- "', but no object with such a property was passed."
770
- } else {
771
- msg = sinon.functionName(stub) +
772
- " expected to yield, but no callback was passed."
773
- }
774
-
775
- if (args.length > 0) {
776
- msg += " Received [" + join.call(args, ", ") + "]";
777
- }
778
-
779
- return msg;
780
- }
781
-
782
- return "argument at index " + stub.callArgAt + " is not a function: " + func;
783
- }
784
-
785
- function callCallback(stub, args) {
786
- if (typeof stub.callArgAt == "number") {
787
- var func = getCallback(stub, args);
788
-
789
- if (typeof func != "function") {
790
- throw new TypeError(getCallbackError(stub, func, args));
791
- }
792
-
793
- func.apply(null, stub.callbackArguments);
794
- }
795
- }
796
-
797
- var uuid = 0;
798
-
799
- sinon.extend(stub, (function () {
800
- var slice = Array.prototype.slice;
801
-
802
- function throwsException(error, message) {
803
- if (typeof error == "string") {
804
- this.exception = new Error(message || "");
805
- this.exception.name = error;
806
- } else if (!error) {
807
- this.exception = new Error("Error");
808
- } else {
809
- this.exception = error;
810
- }
811
-
812
- return this;
813
- }
814
-
815
- return {
816
- create: function create() {
817
- var functionStub = function () {
818
- if (functionStub.exception) {
819
- throw functionStub.exception;
820
- }
821
-
822
- callCallback(functionStub, arguments);
823
-
824
- return functionStub.returnValue;
825
- };
826
-
827
- functionStub.id = "stub#" + uuid++;
828
- var orig = functionStub;
829
- functionStub = sinon.spy.create(functionStub);
830
- functionStub.func = orig;
831
-
832
- sinon.extend(functionStub, stub);
833
- functionStub._create = sinon.stub.create;
834
- functionStub.displayName = "stub";
835
- functionStub.toString = sinon.functionToString;
836
-
837
- return functionStub;
838
- },
839
-
840
- returns: function returns(value) {
841
- this.returnValue = value;
842
-
843
- return this;
844
- },
845
-
846
- "throws": throwsException,
847
- throwsException: throwsException,
848
-
849
- callsArg: function callsArg(pos) {
850
- if (typeof pos != "number") {
851
- throw new TypeError("argument index is not number");
852
- }
853
-
854
- this.callArgAt = pos;
855
- this.callbackArguments = [];
856
-
857
- return this;
858
- },
859
-
860
- callsArgWith: function callsArgWith(pos) {
861
- if (typeof pos != "number") {
862
- throw new TypeError("argument index is not number");
863
- }
864
-
865
- this.callArgAt = pos;
866
- this.callbackArguments = slice.call(arguments, 1);
867
-
868
- return this;
869
- },
870
-
871
- yields: function () {
872
- this.callArgAt = -1;
873
- this.callbackArguments = slice.call(arguments, 0);
874
-
875
- return this;
876
- },
877
-
878
- yieldsTo: function (prop) {
879
- this.callArgAt = -1;
880
- this.callArgProp = prop;
881
- this.callbackArguments = slice.call(arguments, 1);
882
-
883
- return this;
884
- }
885
- };
886
- }()));
887
-
888
- if (commonJSModule) {
889
- module.exports = stub;
890
- } else {
891
- sinon.stub = stub;
892
- }
893
- }(typeof sinon == "object" && sinon || null));
894
-
895
- /**
896
- * @depend ../sinon.js
897
- * @depend stub.js
898
- */
899
- /*jslint eqeqeq: false, onevar: false, nomen: false*/
900
- /*global module, require, sinon*/
901
- /**
902
- * Mock functions.
903
- *
904
- * @author Christian Johansen (christian@cjohansen.no)
905
- * @license BSD
906
- *
907
- * Copyright (c) 2010-2011 Christian Johansen
908
- */
909
-
910
- (function (sinon) {
911
- var commonJSModule = typeof module == "object" && typeof require == "function";
912
- var push = [].push;
913
-
914
- if (!sinon && commonJSModule) {
915
- sinon = require("../sinon");
916
- }
917
-
918
- if (!sinon) {
919
- return;
920
- }
921
-
922
- function mock(object) {
923
- if (!object) {
924
- return sinon.expectation.create("Anonymous mock");
925
- }
926
-
927
- return mock.create(object);
928
- }
929
-
930
- sinon.mock = mock;
931
-
932
- sinon.extend(mock, (function () {
933
- function each(collection, callback) {
934
- if (!collection) {
935
- return;
936
- }
937
-
938
- for (var i = 0, l = collection.length; i < l; i += 1) {
939
- callback(collection[i]);
940
- }
941
- }
942
-
943
- return {
944
- create: function create(object) {
945
- if (!object) {
946
- throw new TypeError("object is null");
947
- }
948
-
949
- var mockObject = sinon.extend({}, mock);
950
- mockObject.object = object;
951
- delete mockObject.create;
952
-
953
- return mockObject;
954
- },
955
-
956
- expects: function expects(method) {
957
- if (!method) {
958
- throw new TypeError("method is falsy");
959
- }
960
-
961
- if (!this.expectations) {
962
- this.expectations = {};
963
- this.proxies = [];
964
- }
965
-
966
- if (!this.expectations[method]) {
967
- this.expectations[method] = [];
968
- var mockObject = this;
969
-
970
- sinon.wrapMethod(this.object, method, function () {
971
- return mockObject.invokeMethod(method, this, arguments);
972
- });
973
-
974
- push.call(this.proxies, method);
975
- }
976
-
977
- var expectation = sinon.expectation.create(method);
978
- push.call(this.expectations[method], expectation);
979
-
980
- return expectation;
981
- },
982
-
983
- restore: function restore() {
984
- var object = this.object;
985
-
986
- each(this.proxies, function (proxy) {
987
- if (typeof object[proxy].restore == "function") {
988
- object[proxy].restore();
989
- }
990
- });
991
- },
992
-
993
- verify: function verify() {
994
- var expectations = this.expectations || {};
995
- var messages = [], met = [];
996
-
997
- each(this.proxies, function (proxy) {
998
- each(expectations[proxy], function (expectation) {
999
- if (!expectation.met()) {
1000
- push.call(messages, expectation.toString());
1001
- } else {
1002
- push.call(met, expectation.toString());
1003
- }
1004
- });
1005
- });
1006
-
1007
- this.restore();
1008
-
1009
- if (messages.length > 0) {
1010
- sinon.expectation.fail(messages.concat(met).join("\n"));
1011
- }
1012
-
1013
- return true;
1014
- },
1015
-
1016
- invokeMethod: function invokeMethod(method, thisValue, args) {
1017
- var expectations = this.expectations && this.expectations[method];
1018
- var length = expectations && expectations.length || 0;
1019
-
1020
- for (var i = 0; i < length; i += 1) {
1021
- if (!expectations[i].met() &&
1022
- expectations[i].allowsCall(thisValue, args)) {
1023
- return expectations[i].apply(thisValue, args);
1024
- }
1025
- }
1026
-
1027
- var messages = [];
1028
-
1029
- for (i = 0; i < length; i += 1) {
1030
- push.call(messages, " " + expectations[i].toString());
1031
- }
1032
-
1033
- messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({
1034
- proxy: method,
1035
- args: args
1036
- }));
1037
-
1038
- sinon.expectation.fail(messages.join("\n"));
1039
- }
1040
- };
1041
- }()));
1042
-
1043
- var times = sinon.timesInWords;
1044
-
1045
- sinon.expectation = (function () {
1046
- var slice = Array.prototype.slice;
1047
- var _invoke = sinon.spy.invoke;
1048
-
1049
- function callCountInWords(callCount) {
1050
- if (callCount == 0) {
1051
- return "never called";
1052
- } else {
1053
- return "called " + times(callCount);
1054
- }
1055
- }
1056
-
1057
- function expectedCallCountInWords(expectation) {
1058
- var min = expectation.minCalls;
1059
- var max = expectation.maxCalls;
1060
-
1061
- if (typeof min == "number" && typeof max == "number") {
1062
- var str = times(min);
1063
-
1064
- if (min != max) {
1065
- str = "at least " + str + " and at most " + times(max);
1066
- }
1067
-
1068
- return str;
1069
- }
1070
-
1071
- if (typeof min == "number") {
1072
- return "at least " + times(min);
1073
- }
1074
-
1075
- return "at most " + times(max);
1076
- }
1077
-
1078
- function receivedMinCalls(expectation) {
1079
- var hasMinLimit = typeof expectation.minCalls == "number";
1080
- return !hasMinLimit || expectation.callCount >= expectation.minCalls;
1081
- }
1082
-
1083
- function receivedMaxCalls(expectation) {
1084
- if (typeof expectation.maxCalls != "number") {
1085
- return false;
1086
- }
1087
-
1088
- return expectation.callCount == expectation.maxCalls;
1089
- }
1090
-
1091
- return {
1092
- minCalls: 1,
1093
- maxCalls: 1,
1094
-
1095
- create: function create(methodName) {
1096
- var expectation = sinon.extend(sinon.stub.create(), sinon.expectation);
1097
- delete expectation.create;
1098
- expectation.method = methodName;
1099
-
1100
- return expectation;
1101
- },
1102
-
1103
- invoke: function invoke(func, thisValue, args) {
1104
- this.verifyCallAllowed(thisValue, args);
1105
-
1106
- return _invoke.apply(this, arguments);
1107
- },
1108
-
1109
- atLeast: function atLeast(num) {
1110
- if (typeof num != "number") {
1111
- throw new TypeError("'" + num + "' is not number");
1112
- }
1113
-
1114
- if (!this.limitsSet) {
1115
- this.maxCalls = null;
1116
- this.limitsSet = true;
1117
- }
1118
-
1119
- this.minCalls = num;
1120
-
1121
- return this;
1122
- },
1123
-
1124
- atMost: function atMost(num) {
1125
- if (typeof num != "number") {
1126
- throw new TypeError("'" + num + "' is not number");
1127
- }
1128
-
1129
- if (!this.limitsSet) {
1130
- this.minCalls = null;
1131
- this.limitsSet = true;
1132
- }
1133
-
1134
- this.maxCalls = num;
1135
-
1136
- return this;
1137
- },
1138
-
1139
- never: function never() {
1140
- return this.exactly(0);
1141
- },
1142
-
1143
- once: function once() {
1144
- return this.exactly(1);
1145
- },
1146
-
1147
- twice: function twice() {
1148
- return this.exactly(2);
1149
- },
1150
-
1151
- thrice: function thrice() {
1152
- return this.exactly(3);
1153
- },
1154
-
1155
- exactly: function exactly(num) {
1156
- if (typeof num != "number") {
1157
- throw new TypeError("'" + num + "' is not a number");
1158
- }
1159
-
1160
- this.atLeast(num);
1161
- return this.atMost(num);
1162
- },
1163
-
1164
- met: function met() {
1165
- return !this.failed && receivedMinCalls(this);
1166
- },
1167
-
1168
- verifyCallAllowed: function verifyCallAllowed(thisValue, args) {
1169
- if (receivedMaxCalls(this)) {
1170
- this.failed = true;
1171
- sinon.expectation.fail(this.method + " already called " + times(this.maxCalls));
1172
- }
1173
-
1174
- if ("expectedThis" in this && this.expectedThis !== thisValue) {
1175
- sinon.expectation.fail(this.method + " called with " + thisValue + " as thisValue, expected " +
1176
- this.expectedThis);
1177
- }
1178
-
1179
- if (!("expectedArguments" in this)) {
1180
- return;
1181
- }
1182
-
1183
- if (!args || args.length === 0) {
1184
- sinon.expectation.fail(this.method + " received no arguments, expected " +
1185
- this.expectedArguments.join());
1186
- }
1187
-
1188
- if (args.length < this.expectedArguments.length) {
1189
- sinon.expectation.fail(this.method + " received too few arguments (" + args.join() +
1190
- "), expected " + this.expectedArguments.join());
1191
- }
1192
-
1193
- if (this.expectsExactArgCount &&
1194
- args.length != this.expectedArguments.length) {
1195
- sinon.expectation.fail(this.method + " received too many arguments (" + args.join() +
1196
- "), expected " + this.expectedArguments.join());
1197
- }
1198
-
1199
- for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
1200
- if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
1201
- sinon.expectation.fail(this.method + " received wrong arguments (" + args.join() +
1202
- "), expected " + this.expectedArguments.join());
1203
- }
1204
- }
1205
- },
1206
-
1207
- allowsCall: function allowsCall(thisValue, args) {
1208
- if (this.met()) {
1209
- return false;
1210
- }
1211
-
1212
- if ("expectedThis" in this && this.expectedThis !== thisValue) {
1213
- return false;
1214
- }
1215
-
1216
- if (!("expectedArguments" in this)) {
1217
- return true;
1218
- }
1219
-
1220
- args = args || [];
1221
-
1222
- if (args.length < this.expectedArguments.length) {
1223
- return false;
1224
- }
1225
-
1226
- if (this.expectsExactArgCount &&
1227
- args.length != this.expectedArguments.length) {
1228
- return false;
1229
- }
1230
-
1231
- for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
1232
- if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
1233
- return false;
1234
- }
1235
- }
1236
-
1237
- return true;
1238
- },
1239
-
1240
- withArgs: function withArgs() {
1241
- this.expectedArguments = slice.call(arguments);
1242
- return this;
1243
- },
1244
-
1245
- withExactArgs: function withExactArgs() {
1246
- this.withArgs.apply(this, arguments);
1247
- this.expectsExactArgCount = true;
1248
- return this;
1249
- },
1250
-
1251
- on: function on(thisValue) {
1252
- this.expectedThis = thisValue;
1253
- return this;
1254
- },
1255
-
1256
- toString: function () {
1257
- var args = (this.expectedArguments || []).slice();
1258
-
1259
- if (!this.expectsExactArgCount) {
1260
- push.call(args, "[...]");
1261
- }
1262
-
1263
- var callStr = sinon.spyCall.toString.call({
1264
- proxy: this.method, args: args
1265
- });
1266
-
1267
- var message = callStr.replace(", [...", "[, ...") + " " +
1268
- expectedCallCountInWords(this);
1269
-
1270
- if (this.met()) {
1271
- return "Expectation met: " + message;
1272
- }
1273
-
1274
- return "Expected " + message + " (" +
1275
- callCountInWords(this.callCount) + ")";
1276
- },
1277
-
1278
- verify: function verify() {
1279
- if (!this.met()) {
1280
- sinon.expectation.fail(this.toString());
1281
- }
1282
-
1283
- return true;
1284
- },
1285
-
1286
- fail: function (message) {
1287
- var exception = new Error(message);
1288
- exception.name = "ExpectationError";
1289
-
1290
- throw exception;
1291
- }
1292
- };
1293
- }());
1294
-
1295
- if (commonJSModule) {
1296
- module.exports = mock;
1297
- } else {
1298
- sinon.mock = mock;
1299
- }
1300
- }(typeof sinon == "object" && sinon || null));
1301
-
1302
- /**
1303
- * @depend ../sinon.js
1304
- * @depend stub.js
1305
- * @depend mock.js
1306
- */
1307
- /*jslint eqeqeq: false, onevar: false, forin: true*/
1308
- /*global module, require, sinon*/
1309
- /**
1310
- * Collections of stubs, spies and mocks.
1311
- *
1312
- * @author Christian Johansen (christian@cjohansen.no)
1313
- * @license BSD
1314
- *
1315
- * Copyright (c) 2010-2011 Christian Johansen
1316
- */
1317
-
1318
- (function (sinon) {
1319
- var commonJSModule = typeof module == "object" && typeof require == "function";
1320
- var push = [].push;
1321
-
1322
- if (!sinon && commonJSModule) {
1323
- sinon = require("../sinon");
1324
- }
1325
-
1326
- if (!sinon) {
1327
- return;
1328
- }
1329
-
1330
- function getFakes(fakeCollection) {
1331
- if (!fakeCollection.fakes) {
1332
- fakeCollection.fakes = [];
1333
- }
1334
-
1335
- return fakeCollection.fakes;
1336
- }
1337
-
1338
- function each(fakeCollection, method) {
1339
- var fakes = getFakes(fakeCollection);
1340
-
1341
- for (var i = 0, l = fakes.length; i < l; i += 1) {
1342
- if (typeof fakes[i][method] == "function") {
1343
- fakes[i][method]();
1344
- }
1345
- }
1346
- }
1347
-
1348
- function compact(fakeCollection) {
1349
- var fakes = getFakes(fakeCollection);
1350
- var i = 0;
1351
- while (i < fakes.length) {
1352
- fakes.splice(i, 1);
1353
- }
1354
- }
1355
-
1356
- var collection = {
1357
- verify: function resolve() {
1358
- each(this, "verify");
1359
- },
1360
-
1361
- restore: function restore() {
1362
- each(this, "restore");
1363
- compact(this);
1364
- },
1365
-
1366
- verifyAndRestore: function verifyAndRestore() {
1367
- var exception;
1368
-
1369
- try {
1370
- this.verify();
1371
- } catch (e) {
1372
- exception = e;
1373
- }
1374
-
1375
- this.restore();
1376
-
1377
- if (exception) {
1378
- throw exception;
1379
- }
1380
- },
1381
-
1382
- add: function add(fake) {
1383
- push.call(getFakes(this), fake);
1384
- return fake;
1385
- },
1386
-
1387
- spy: function spy() {
1388
- return this.add(sinon.spy.apply(sinon, arguments));
1389
- },
1390
-
1391
- stub: function stub(object, property, value) {
1392
- if (property) {
1393
- var original = object[property];
1394
-
1395
- if (typeof original != "function") {
1396
- if (!object.hasOwnProperty(property)) {
1397
- throw new TypeError("Cannot stub non-existent own property " + property);
1398
- }
1399
-
1400
- object[property] = value;
1401
-
1402
- return this.add({
1403
- restore: function () {
1404
- object[property] = original;
1405
- }
1406
- });
1407
- }
1408
- }
1409
-
1410
- return this.add(sinon.stub.apply(sinon, arguments));
1411
- },
1412
-
1413
- mock: function mock() {
1414
- return this.add(sinon.mock.apply(sinon, arguments));
1415
- },
1416
-
1417
- inject: function inject(obj) {
1418
- var col = this;
1419
-
1420
- obj.spy = function () {
1421
- return col.spy.apply(col, arguments);
1422
- };
1423
-
1424
- obj.stub = function () {
1425
- return col.stub.apply(col, arguments);
1426
- };
1427
-
1428
- obj.mock = function () {
1429
- return col.mock.apply(col, arguments);
1430
- };
1431
-
1432
- return obj;
1433
- }
1434
- };
1435
-
1436
- if (commonJSModule) {
1437
- module.exports = collection;
1438
- } else {
1439
- sinon.collection = collection;
1440
- }
1441
- }(typeof sinon == "object" && sinon || null));
1442
-
1443
- /*jslint eqeqeq: false, plusplus: false, evil: true, onevar: false, browser: true, forin: false*/
1444
- /*global module, require, window*/
1445
- /**
1446
- * Fake timer API
1447
- * setTimeout
1448
- * setInterval
1449
- * clearTimeout
1450
- * clearInterval
1451
- * tick
1452
- * reset
1453
- * Date
1454
- *
1455
- * Inspired by jsUnitMockTimeOut from JsUnit
1456
- *
1457
- * @author Christian Johansen (christian@cjohansen.no)
1458
- * @license BSD
1459
- *
1460
- * Copyright (c) 2010-2011 Christian Johansen
1461
- */
1462
-
1463
- if (typeof sinon == "undefined") {
1464
- var sinon = {};
1465
- }
1466
-
1467
- sinon.clock = (function () {
1468
- var id = 0;
1469
-
1470
- function addTimer(args, recurring) {
1471
- if (args.length === 0) {
1472
- throw new Error("Function requires at least 1 parameter");
1473
- }
1474
-
1475
- var toId = id++;
1476
- var delay = args[1] || 0;
1477
-
1478
- if (!this.timeouts) {
1479
- this.timeouts = {};
1480
- }
1481
-
1482
- this.timeouts[toId] = {
1483
- id: toId,
1484
- func: args[0],
1485
- callAt: this.now + delay
1486
- };
1487
-
1488
- if (recurring === true) {
1489
- this.timeouts[toId].interval = delay;
1490
- }
1491
-
1492
- return toId;
1493
- }
1494
-
1495
- function parseTime(str) {
1496
- if (!str) {
1497
- return 0;
1498
- }
1499
-
1500
- var strings = str.split(":");
1501
- var l = strings.length, i = l;
1502
- var ms = 0, parsed;
1503
-
1504
- if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
1505
- throw new Error("tick only understands numbers and 'h:m:s'");
1506
- }
1507
-
1508
- while (i--) {
1509
- parsed = parseInt(strings[i], 10);
1510
-
1511
- if (parsed >= 60) {
1512
- throw new Error("Invalid time " + str);
1513
- }
1514
-
1515
- ms += parsed * Math.pow(60, (l - i - 1));
1516
- }
1517
-
1518
- return ms * 1000;
1519
- }
1520
-
1521
- function createObject(object) {
1522
- var newObject;
1523
-
1524
- if (Object.create) {
1525
- newObject = Object.create(object);
1526
- } else {
1527
- var F = function () {};
1528
- F.prototype = object;
1529
- newObject = new F();
1530
- }
1531
-
1532
- newObject.Date.clock = newObject;
1533
- return newObject;
1534
- }
1535
-
1536
- return {
1537
- now: 0,
1538
-
1539
- create: function create(now) {
1540
- var clock = createObject(this);
1541
-
1542
- if (typeof now == "number") {
1543
- this.now = now;
1544
- }
1545
-
1546
- return clock;
1547
- },
1548
-
1549
- setTimeout: function setTimeout(callback, timeout) {
1550
- return addTimer.call(this, arguments, false);
1551
- },
1552
-
1553
- clearTimeout: function clearTimeout(timerId) {
1554
- if (!this.timeouts) {
1555
- this.timeouts = [];
1556
- }
1557
-
1558
- delete this.timeouts[timerId];
1559
- },
1560
-
1561
- setInterval: function setInterval(callback, timeout) {
1562
- return addTimer.call(this, arguments, true);
1563
- },
1564
-
1565
- clearInterval: function clearInterval(timerId) {
1566
- this.clearTimeout(timerId);
1567
- },
1568
-
1569
- tick: function tick(ms) {
1570
- ms = typeof ms == "number" ? ms : parseTime(ms);
1571
- var tickFrom = this.now, tickTo = this.now + ms, previous = this.now;
1572
- var timer = this.firstTimerInRange(tickFrom, tickTo);
1573
-
1574
- while (timer && tickFrom <= tickTo) {
1575
- if (this.timeouts[timer.id]) {
1576
- tickFrom = this.now = timer.callAt;
1577
- this.callTimer(timer);
1578
- }
1579
-
1580
- timer = this.firstTimerInRange(previous, tickTo);
1581
- previous = tickFrom;
1582
- }
1583
-
1584
- this.now = tickTo;
1585
- },
1586
-
1587
- firstTimerInRange: function (from, to) {
1588
- var timer, smallest, originalTimer;
1589
-
1590
- for (var id in this.timeouts) {
1591
- if (this.timeouts.hasOwnProperty(id)) {
1592
- if (this.timeouts[id].callAt < from || this.timeouts[id].callAt > to) {
1593
- continue;
1594
- }
1595
-
1596
- if (!smallest || this.timeouts[id].callAt < smallest) {
1597
- originalTimer = this.timeouts[id];
1598
- smallest = this.timeouts[id].callAt;
1599
-
1600
- timer = {
1601
- func: this.timeouts[id].func,
1602
- callAt: this.timeouts[id].callAt,
1603
- interval: this.timeouts[id].interval,
1604
- id: this.timeouts[id].id
1605
- };
1606
- }
1607
- }
1608
- }
1609
-
1610
- return timer || null;
1611
- },
1612
-
1613
- callTimer: function (timer) {
1614
- try {
1615
- if (typeof timer.func == "function") {
1616
- timer.func.call(null);
1617
- } else {
1618
- eval(timer.func);
1619
- }
1620
- } catch (e) {}
1621
-
1622
- if (!this.timeouts[timer.id]) {
1623
- return;
1624
- }
1625
-
1626
- if (typeof timer.interval == "number") {
1627
- this.timeouts[timer.id].callAt += timer.interval;
1628
- } else {
1629
- delete this.timeouts[timer.id];
1630
- }
1631
- },
1632
-
1633
- reset: function reset() {
1634
- this.timeouts = {};
1635
- },
1636
-
1637
- Date: (function () {
1638
- var NativeDate = Date;
1639
-
1640
- function ClockDate(year, month, date, hour, minute, second, ms) {
1641
- // Defensive and verbose to avoid potential harm in passing
1642
- // explicit undefined when user does not pass argument
1643
- switch (arguments.length) {
1644
- case 0:
1645
- return new NativeDate(ClockDate.clock.now);
1646
- case 1:
1647
- return new NativeDate(year);
1648
- case 2:
1649
- return new NativeDate(year, month);
1650
- case 3:
1651
- return new NativeDate(year, month, date);
1652
- case 4:
1653
- return new NativeDate(year, month, date, hour);
1654
- case 5:
1655
- return new NativeDate(year, month, date, hour, minute);
1656
- case 6:
1657
- return new NativeDate(year, month, date, hour, minute, second);
1658
- default:
1659
- return new NativeDate(year, month, date, hour, minute, second, ms);
1660
- }
1661
- }
1662
-
1663
- if (NativeDate.now) {
1664
- ClockDate.now = function now() {
1665
- return ClockDate.clock.now;
1666
- };
1667
- }
1668
-
1669
- if (NativeDate.toSource) {
1670
- ClockDate.toSource = function toSource() {
1671
- return NativeDate.toSource();
1672
- };
1673
- }
1674
-
1675
- ClockDate.toString = function toString() {
1676
- return NativeDate.toString();
1677
- };
1678
-
1679
- ClockDate.prototype = NativeDate.prototype;
1680
- ClockDate.parse = NativeDate.parse;
1681
- ClockDate.UTC = NativeDate.UTC;
1682
-
1683
- return ClockDate;
1684
- }())
1685
- };
1686
- }());
1687
-
1688
- sinon.timers = {
1689
- setTimeout: setTimeout,
1690
- clearTimeout: clearTimeout,
1691
- setInterval: setInterval,
1692
- clearInterval: clearInterval,
1693
- Date: Date
1694
- };
1695
-
1696
- sinon.useFakeTimers = (function (global) {
1697
- var methods = ["Date", "setTimeout", "setInterval", "clearTimeout", "clearInterval"];
1698
-
1699
- function restore() {
1700
- var method;
1701
-
1702
- for (var i = 0, l = this.methods.length; i < l; i++) {
1703
- method = this.methods[i];
1704
- global[method] = this["_" + method];
1705
- }
1706
- }
1707
-
1708
- function stubGlobal(method, clock) {
1709
- clock["_" + method] = global[method];
1710
-
1711
- global[method] = function () {
1712
- return clock[method].apply(clock, arguments);
1713
- };
1714
-
1715
- for (var prop in clock[method]) {
1716
- if (clock[method].hasOwnProperty(prop)) {
1717
- global[method][prop] = clock[method][prop];
1718
- }
1719
- }
1720
-
1721
- global[method].clock = clock;
1722
- }
1723
-
1724
- return function useFakeTimers(now) {
1725
- var clock = sinon.clock.create(now);
1726
- clock.restore = restore;
1727
- clock.methods = Array.prototype.slice.call(arguments,
1728
- typeof now == "number" ? 1 : 0);
1729
-
1730
- if (clock.methods.length === 0) {
1731
- clock.methods = methods;
1732
- }
1733
-
1734
- for (var i = 0, l = clock.methods.length; i < l; i++) {
1735
- stubGlobal(clock.methods[i], clock);
1736
- }
1737
-
1738
- return clock;
1739
- };
1740
- }(typeof global != "undefined" ? global : this));
1741
-
1742
- if (typeof module == "object" && typeof require == "function") {
1743
- module.exports = sinon;
1744
- }
1745
-
1746
- /*jslint eqeqeq: false, onevar: false*/
1747
- /*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
1748
- /**
1749
- * Minimal Event interface implementation
1750
- *
1751
- * Original implementation by Sven Fuchs: https://gist.github.com/995028
1752
- * Modifications and tests by Christian Johansen.
1753
- *
1754
- * @author Sven Fuchs (svenfuchs@artweb-design.de)
1755
- * @author Christian Johansen (christian@cjohansen.no)
1756
- * @license BSD
1757
- *
1758
- * Copyright (c) 2011 Sven Fuchs, Christian Johansen
1759
- */
1760
-
1761
- if (typeof sinon == "undefined") {
1762
- this.sinon = {};
1763
- }
1764
-
1765
- (function () {
1766
- var push = [].push;
1767
-
1768
- sinon.Event = function Event(type, bubbles, cancelable) {
1769
- this.initEvent(type, bubbles, cancelable);
1770
- };
1771
-
1772
- sinon.Event.prototype = {
1773
- initEvent: function(type, bubbles, cancelable) {
1774
- this.type = type;
1775
- this.bubbles = bubbles;
1776
- this.cancelable = cancelable;
1777
- },
1778
-
1779
- stopPropagation: function () {},
1780
-
1781
- preventDefault: function () {
1782
- this.defaultPrevented = true;
1783
- }
1784
- };
1785
-
1786
- sinon.EventTarget = {
1787
- addEventListener: function addEventListener(event, listener, useCapture) {
1788
- this.eventListeners = this.eventListeners || {};
1789
- this.eventListeners[event] = this.eventListeners[event] || [];
1790
- push.call(this.eventListeners[event], listener);
1791
- },
1792
-
1793
- removeEventListener: function removeEventListener(event, listener, useCapture) {
1794
- var listeners = this.eventListeners && this.eventListeners[event] || [];
1795
-
1796
- for (var i = 0, l = listeners.length; i < l; ++i) {
1797
- if (listeners[i] == listener) {
1798
- return listeners.splice(i, 1);
1799
- }
1800
- }
1801
- },
1802
-
1803
- dispatchEvent: function dispatchEvent(event) {
1804
- var type = event.type;
1805
- var listeners = this.eventListeners && this.eventListeners[type] || [];
1806
-
1807
- for (var i = 0; i < listeners.length; i++) {
1808
- if (typeof listeners[i] == "function") {
1809
- listeners[i].call(this, event);
1810
- } else {
1811
- listeners[i].handleEvent(event);
1812
- }
1813
- }
1814
-
1815
- return !!event.defaultPrevented;
1816
- }
1817
- };
1818
- }());
1819
-
1820
- /**
1821
- * @depend event.js
1822
- */
1823
- /*jslint eqeqeq: false, onevar: false*/
1824
- /*global sinon, module, require, ActiveXObject, XMLHttpRequest, DOMParser*/
1825
- /**
1826
- * Fake XMLHttpRequest object
1827
- *
1828
- * @author Christian Johansen (christian@cjohansen.no)
1829
- * @license BSD
1830
- *
1831
- * Copyright (c) 2010-2011 Christian Johansen
1832
- */
1833
-
1834
- if (typeof sinon == "undefined") {
1835
- this.sinon = {};
1836
- }
1837
-
1838
- sinon.xhr = { XMLHttpRequest: this.XMLHttpRequest };
1839
-
1840
- sinon.FakeXMLHttpRequest = (function () {
1841
- /*jsl:ignore*/
1842
- var unsafeHeaders = {
1843
- "Accept-Charset": true,
1844
- "Accept-Encoding": true,
1845
- "Connection": true,
1846
- "Content-Length": true,
1847
- "Cookie": true,
1848
- "Cookie2": true,
1849
- "Content-Transfer-Encoding": true,
1850
- "Date": true,
1851
- "Expect": true,
1852
- "Host": true,
1853
- "Keep-Alive": true,
1854
- "Referer": true,
1855
- "TE": true,
1856
- "Trailer": true,
1857
- "Transfer-Encoding": true,
1858
- "Upgrade": true,
1859
- "User-Agent": true,
1860
- "Via": true
1861
- };
1862
- /*jsl:end*/
1863
-
1864
- function FakeXMLHttpRequest() {
1865
- this.readyState = FakeXMLHttpRequest.UNSENT;
1866
- this.requestHeaders = {};
1867
- this.requestBody = null;
1868
- this.status = 0;
1869
- this.statusText = "";
1870
-
1871
- if (typeof FakeXMLHttpRequest.onCreate == "function") {
1872
- FakeXMLHttpRequest.onCreate(this);
1873
- }
1874
- }
1875
-
1876
- function verifyState(xhr) {
1877
- if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
1878
- throw new Error("INVALID_STATE_ERR");
1879
- }
1880
-
1881
- if (xhr.sendFlag) {
1882
- throw new Error("INVALID_STATE_ERR");
1883
- }
1884
- }
1885
-
1886
- sinon.extend(FakeXMLHttpRequest.prototype, sinon.EventTarget, {
1887
- async: true,
1888
-
1889
- open: function open(method, url, async, username, password) {
1890
- this.method = method;
1891
- this.url = url;
1892
- this.async = typeof async == "boolean" ? async : true;
1893
- this.username = username;
1894
- this.password = password;
1895
- this.responseText = null;
1896
- this.responseXML = null;
1897
- this.requestHeaders = {};
1898
- this.sendFlag = false;
1899
- this.readyStateChange(FakeXMLHttpRequest.OPENED);
1900
- },
1901
-
1902
- readyStateChange: function readyStateChange(state) {
1903
- this.readyState = state;
1904
-
1905
- if (typeof this.onreadystatechange == "function") {
1906
- this.onreadystatechange();
1907
- }
1908
-
1909
- this.dispatchEvent(new sinon.Event("readystatechange"));
1910
- },
1911
-
1912
- setRequestHeader: function setRequestHeader(header, value) {
1913
- verifyState(this);
1914
-
1915
- if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) {
1916
- throw new Error("Refused to set unsafe header \"" + header + "\"");
1917
- }
1918
-
1919
- if (this.requestHeaders[header]) {
1920
- this.requestHeaders[header] += "," + value;
1921
- } else {
1922
- this.requestHeaders[header] = value;
1923
- }
1924
- },
1925
-
1926
- // Helps testing
1927
- setResponseHeaders: function setResponseHeaders(headers) {
1928
- this.responseHeaders = {};
1929
-
1930
- for (var header in headers) {
1931
- if (headers.hasOwnProperty(header)) {
1932
- this.responseHeaders[header] = headers[header];
1933
- }
1934
- }
1935
-
1936
- if (this.async) {
1937
- this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
1938
- }
1939
- },
1940
-
1941
- // Currently treats ALL data as a DOMString (i.e. no Document)
1942
- send: function send(data) {
1943
- verifyState(this);
1944
-
1945
- if (!/^(get|head)$/i.test(this.method)) {
1946
- if (this.requestHeaders["Content-Type"]) {
1947
- var value = this.requestHeaders["Content-Type"].split(";");
1948
- this.requestHeaders["Content-Type"] = value[0] + ";charset=utf-8";
1949
- } else {
1950
- this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
1951
- }
1952
-
1953
- this.requestBody = data;
1954
- }
1955
-
1956
- this.errorFlag = false;
1957
- this.sendFlag = this.async;
1958
- this.readyStateChange(FakeXMLHttpRequest.OPENED);
1959
-
1960
- if (typeof this.onSend == "function") {
1961
- this.onSend(this);
1962
- }
1963
- },
1964
-
1965
- abort: function abort() {
1966
- this.aborted = true;
1967
- this.responseText = null;
1968
- this.errorFlag = true;
1969
- this.requestHeaders = {};
1970
-
1971
- if (this.readyState > sinon.FakeXMLHttpRequest.UNSENT && this.sendFlag) {
1972
- this.readyStateChange(sinon.FakeXMLHttpRequest.DONE);
1973
- this.sendFlag = false;
1974
- }
1975
-
1976
- this.readyState = sinon.FakeXMLHttpRequest.UNSENT;
1977
- },
1978
-
1979
- getResponseHeader: function getResponseHeader(header) {
1980
- if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
1981
- return null;
1982
- }
1983
-
1984
- if (/^Set-Cookie2?$/i.test(header)) {
1985
- return null;
1986
- }
1987
-
1988
- header = header.toLowerCase();
1989
-
1990
- for (var h in this.responseHeaders) {
1991
- if (h.toLowerCase() == header) {
1992
- return this.responseHeaders[h];
1993
- }
1994
- }
1995
-
1996
- return null;
1997
- },
1998
-
1999
- getAllResponseHeaders: function getAllResponseHeaders() {
2000
- if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
2001
- return "";
2002
- }
2003
-
2004
- var headers = "";
2005
-
2006
- for (var header in this.responseHeaders) {
2007
- if (this.responseHeaders.hasOwnProperty(header) &&
2008
- !/^Set-Cookie2?$/i.test(header)) {
2009
- headers += header + ": " + this.responseHeaders[header] + "\r\n";
2010
- }
2011
- }
2012
-
2013
- return headers;
2014
- },
2015
-
2016
- setResponseBody: function setResponseBody(body) {
2017
- if (this.readyState == FakeXMLHttpRequest.DONE) {
2018
- throw new Error("Request done");
2019
- }
2020
-
2021
- if (this.async && this.readyState != FakeXMLHttpRequest.HEADERS_RECEIVED) {
2022
- throw new Error("No headers received");
2023
- }
2024
-
2025
- var chunkSize = this.chunkSize || 10;
2026
- var index = 0;
2027
- this.responseText = "";
2028
-
2029
- do {
2030
- if (this.async) {
2031
- this.readyStateChange(FakeXMLHttpRequest.LOADING);
2032
- }
2033
-
2034
- this.responseText += body.substring(index, index + chunkSize);
2035
- index += chunkSize;
2036
- } while (index < body.length);
2037
-
2038
- var type = this.getResponseHeader("Content-Type");
2039
-
2040
- if (this.responseText &&
2041
- (!type || /(text\/xml)|(application\/xml)|(\+xml)/.test(type))) {
2042
- try {
2043
- this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText);
2044
- } catch (e) {}
2045
- }
2046
-
2047
- if (this.async) {
2048
- this.readyStateChange(FakeXMLHttpRequest.DONE);
2049
- } else {
2050
- this.readyState = FakeXMLHttpRequest.DONE;
2051
- }
2052
- },
2053
-
2054
- respond: function respond(status, headers, body) {
2055
- this.setResponseHeaders(headers || {});
2056
- this.status = typeof status == "number" ? status : 200;
2057
- this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
2058
- this.setResponseBody(body || "");
2059
- }
2060
- });
2061
-
2062
- sinon.extend(FakeXMLHttpRequest, {
2063
- UNSENT: 0,
2064
- OPENED: 1,
2065
- HEADERS_RECEIVED: 2,
2066
- LOADING: 3,
2067
- DONE: 4
2068
- });
2069
-
2070
- // Borrowed from JSpec
2071
- FakeXMLHttpRequest.parseXML = function parseXML(text) {
2072
- var xmlDoc;
2073
-
2074
- if (typeof DOMParser != "undefined") {
2075
- var parser = new DOMParser();
2076
- xmlDoc = parser.parseFromString(text, "text/xml");
2077
- } else {
2078
- xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
2079
- xmlDoc.async = "false";
2080
- xmlDoc.loadXML(text);
2081
- }
2082
-
2083
- return xmlDoc;
2084
- };
2085
-
2086
- FakeXMLHttpRequest.statusCodes = {
2087
- 100: "Continue",
2088
- 101: "Switching Protocols",
2089
- 200: "OK",
2090
- 201: "Created",
2091
- 202: "Accepted",
2092
- 203: "Non-Authoritative Information",
2093
- 204: "No Content",
2094
- 205: "Reset Content",
2095
- 206: "Partial Content",
2096
- 300: "Multiple Choice",
2097
- 301: "Moved Permanently",
2098
- 302: "Found",
2099
- 303: "See Other",
2100
- 304: "Not Modified",
2101
- 305: "Use Proxy",
2102
- 307: "Temporary Redirect",
2103
- 400: "Bad Request",
2104
- 401: "Unauthorized",
2105
- 402: "Payment Required",
2106
- 403: "Forbidden",
2107
- 404: "Not Found",
2108
- 405: "Method Not Allowed",
2109
- 406: "Not Acceptable",
2110
- 407: "Proxy Authentication Required",
2111
- 408: "Request Timeout",
2112
- 409: "Conflict",
2113
- 410: "Gone",
2114
- 411: "Length Required",
2115
- 412: "Precondition Failed",
2116
- 413: "Request Entity Too Large",
2117
- 414: "Request-URI Too Long",
2118
- 415: "Unsupported Media Type",
2119
- 416: "Requested Range Not Satisfiable",
2120
- 417: "Expectation Failed",
2121
- 422: "Unprocessable Entity",
2122
- 500: "Internal Server Error",
2123
- 501: "Not Implemented",
2124
- 502: "Bad Gateway",
2125
- 503: "Service Unavailable",
2126
- 504: "Gateway Timeout",
2127
- 505: "HTTP Version Not Supported"
2128
- };
2129
-
2130
- return FakeXMLHttpRequest;
2131
- }());
2132
-
2133
- (function (global) {
2134
- var GlobalXMLHttpRequest = global.XMLHttpRequest;
2135
- var GlobalActiveXObject = global.ActiveXObject;
2136
- var supportsActiveX = typeof ActiveXObject != "undefined";
2137
- var supportsXHR = typeof XMLHttpRequest != "undefined";
2138
-
2139
- sinon.useFakeXMLHttpRequest = function () {
2140
- sinon.FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
2141
- if (supportsXHR) {
2142
- global.XMLHttpRequest = GlobalXMLHttpRequest;
2143
- }
2144
-
2145
- if (supportsActiveX) {
2146
- global.ActiveXObject = GlobalActiveXObject;
2147
- }
2148
-
2149
- delete sinon.FakeXMLHttpRequest.restore;
2150
-
2151
- if (keepOnCreate !== true) {
2152
- delete sinon.FakeXMLHttpRequest.onCreate;
2153
- }
2154
- };
2155
-
2156
- if (supportsXHR) {
2157
- global.XMLHttpRequest = sinon.FakeXMLHttpRequest;
2158
- }
2159
-
2160
- if (supportsActiveX) {
2161
- global.ActiveXObject = function ActiveXObject(objId) {
2162
- if (objId == "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
2163
- return new sinon.FakeXMLHttpRequest();
2164
- }
2165
-
2166
- return new GlobalActiveXObject(objId);
2167
- };
2168
- }
2169
-
2170
- return sinon.FakeXMLHttpRequest;
2171
- };
2172
- }(this));
2173
-
2174
- if (typeof module == "object" && typeof require == "function") {
2175
- module.exports = sinon;
2176
- }
2177
-
2178
- /**
2179
- * @depend fake_xml_http_request.js
2180
- */
2181
- /*jslint eqeqeq: false, onevar: false, regexp: false, plusplus: false*/
2182
- /*global module, require, window*/
2183
- /**
2184
- * The Sinon "server" mimics a web server that receives requests from
2185
- * sinon.FakeXMLHttpRequest and provides an API to respond to those requests,
2186
- * both synchronously and asynchronously. To respond synchronuously, canned
2187
- * answers have to be provided upfront.
2188
- *
2189
- * @author Christian Johansen (christian@cjohansen.no)
2190
- * @license BSD
2191
- *
2192
- * Copyright (c) 2010-2011 Christian Johansen
2193
- */
2194
-
2195
- if (typeof sinon == "undefined") {
2196
- var sinon = {};
2197
- }
2198
-
2199
- sinon.fakeServer = (function () {
2200
- var push = [].push;
2201
- function F() {}
2202
-
2203
- function create(proto) {
2204
- F.prototype = proto;
2205
- return new F();
2206
- }
2207
-
2208
- function responseArray(handler) {
2209
- var response = handler;
2210
-
2211
- if (Object.prototype.toString.call(handler) != "[object Array]") {
2212
- response = [200, {}, handler];
2213
- }
2214
-
2215
- if (typeof response[2] != "string") {
2216
- throw new TypeError("Fake server response body should be string, but was " +
2217
- typeof response[2]);
2218
- }
2219
-
2220
- return response;
2221
- }
2222
-
2223
- var wloc = window.location;
2224
- var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host);
2225
-
2226
- function matchOne(response, reqMethod, reqUrl) {
2227
- var rmeth = response.method;
2228
- var matchMethod = !rmeth || rmeth.toLowerCase() == reqMethod.toLowerCase();
2229
- var url = response.url;
2230
- var matchUrl = !url || url == reqUrl || (typeof url.test == "function" && url.test(reqUrl));
2231
-
2232
- return matchMethod && matchUrl;
2233
- }
2234
-
2235
- function match(response, request) {
2236
- var requestMethod = this.getHTTPMethod(request);
2237
- var requestUrl = request.url;
2238
-
2239
- if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) {
2240
- requestUrl = requestUrl.replace(rCurrLoc, "");
2241
- }
2242
-
2243
- if (matchOne(response, this.getHTTPMethod(request), requestUrl)) {
2244
- if (typeof response.response == "function") {
2245
- var args = [request].concat(requestUrl.match(response.url).slice(1));
2246
- return response.response.apply(response, args);
2247
- }
2248
-
2249
- return true;
2250
- }
2251
-
2252
- return false;
2253
- }
2254
-
2255
- return {
2256
- create: function () {
2257
- var server = create(this);
2258
- this.xhr = sinon.useFakeXMLHttpRequest();
2259
- server.requests = [];
2260
-
2261
- this.xhr.onCreate = function (xhrObj) {
2262
- server.addRequest(xhrObj);
2263
- };
2264
-
2265
- return server;
2266
- },
2267
-
2268
- addRequest: function addRequest(xhrObj) {
2269
- var server = this;
2270
- push.call(this.requests, xhrObj);
2271
-
2272
- xhrObj.onSend = function () {
2273
- server.handleRequest(this);
2274
- };
2275
-
2276
- if (this.autoRespond && !this.responding) {
2277
- setTimeout(function () {
2278
- server.responding = false;
2279
- server.respond();
2280
- }, this.autoRespondAfter || 10);
2281
-
2282
- this.responding = true;
2283
- }
2284
- },
2285
-
2286
- getHTTPMethod: function getHTTPMethod(request) {
2287
- if (this.fakeHTTPMethods && /post/i.test(request.method)) {
2288
- var matches = (request.requestBody || "").match(/_method=([^\b;]+)/);
2289
- return !!matches ? matches[1] : request.method;
2290
- }
2291
-
2292
- return request.method;
2293
- },
2294
-
2295
- handleRequest: function handleRequest(xhr) {
2296
- if (xhr.async) {
2297
- if (!this.queue) {
2298
- this.queue = [];
2299
- }
2300
-
2301
- push.call(this.queue, xhr);
2302
- } else {
2303
- this.processRequest(xhr);
2304
- }
2305
- },
2306
-
2307
- respondWith: function respondWith(method, url, body) {
2308
- if (arguments.length == 1) {
2309
- this.response = responseArray(method);
2310
- } else {
2311
- if (!this.responses) {
2312
- this.responses = [];
2313
- }
2314
-
2315
- if (arguments.length == 2) {
2316
- body = url;
2317
- url = method;
2318
- method = null;
2319
- }
2320
-
2321
- push.call(this.responses, {
2322
- method: method,
2323
- url: url,
2324
- response: typeof body == "function" ? body : responseArray(body)
2325
- });
2326
- }
2327
- },
2328
-
2329
- respond: function respond() {
2330
- var queue = this.queue || [];
2331
- var request;
2332
-
2333
- while(request = queue.shift()) {
2334
- this.processRequest(request);
2335
- }
2336
- },
2337
-
2338
- processRequest: function processRequest(request) {
2339
- try {
2340
- if (request.aborted) {
2341
- return;
2342
- }
2343
-
2344
- var response = this.response || [404, {}, ""];
2345
-
2346
- if (this.responses) {
2347
- for (var i = 0, l = this.responses.length; i < l; i++) {
2348
- if (match.call(this, this.responses[i], request)) {
2349
- response = this.responses[i].response;
2350
- break;
2351
- }
2352
- }
2353
- }
2354
-
2355
- if (request.readyState != 4) {
2356
- request.respond(response[0], response[1], response[2]);
2357
- }
2358
- } catch (e) {}
2359
- },
2360
-
2361
- restore: function restore() {
2362
- return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments);
2363
- }
2364
- };
2365
- }());
2366
-
2367
- if (typeof module == "object" && typeof require == "function") {
2368
- module.exports = sinon;
2369
- }
2370
-
2371
- /**
2372
- * @depend fake_server.js
2373
- * @depend fake_timers.js
2374
- */
2375
- /*jslint browser: true, eqeqeq: false, onevar: false*/
2376
- /*global sinon*/
2377
- /**
2378
- * Add-on for sinon.fakeServer that automatically handles a fake timer along with
2379
- * the FakeXMLHttpRequest. The direct inspiration for this add-on is jQuery
2380
- * 1.3.x, which does not use xhr object's onreadystatehandler at all - instead,
2381
- * it polls the object for completion with setInterval. Dispite the direct
2382
- * motivation, there is nothing jQuery-specific in this file, so it can be used
2383
- * in any environment where the ajax implementation depends on setInterval or
2384
- * setTimeout.
2385
- *
2386
- * @author Christian Johansen (christian@cjohansen.no)
2387
- * @license BSD
2388
- *
2389
- * Copyright (c) 2010-2011 Christian Johansen
2390
- */
2391
-
2392
- (function () {
2393
- function Server() {}
2394
- Server.prototype = sinon.fakeServer;
2395
-
2396
- sinon.fakeServerWithClock = new Server();
2397
-
2398
- sinon.fakeServerWithClock.addRequest = function addRequest(xhr) {
2399
- if (xhr.async) {
2400
- if (typeof setTimeout.clock == "object") {
2401
- this.clock = setTimeout.clock;
2402
- } else {
2403
- this.clock = sinon.useFakeTimers();
2404
- this.resetClock = true;
2405
- }
2406
-
2407
- if (!this.longestTimeout) {
2408
- var clockSetTimeout = this.clock.setTimeout;
2409
- var clockSetInterval = this.clock.setInterval;
2410
- var server = this;
2411
-
2412
- this.clock.setTimeout = function (fn, timeout) {
2413
- server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
2414
-
2415
- return clockSetTimeout.apply(this, arguments);
2416
- };
2417
-
2418
- this.clock.setInterval = function (fn, timeout) {
2419
- server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
2420
-
2421
- return clockSetInterval.apply(this, arguments);
2422
- };
2423
- }
2424
- }
2425
-
2426
- return sinon.fakeServer.addRequest.call(this, xhr);
2427
- };
2428
-
2429
- sinon.fakeServerWithClock.respond = function respond() {
2430
- var returnVal = sinon.fakeServer.respond.apply(this, arguments);
2431
-
2432
- if (this.clock) {
2433
- this.clock.tick(this.longestTimeout || 0);
2434
- this.longestTimeout = 0;
2435
-
2436
- if (this.resetClock) {
2437
- this.clock.restore();
2438
- this.resetClock = false;
2439
- }
2440
- }
2441
-
2442
- return returnVal;
2443
- };
2444
-
2445
- sinon.fakeServerWithClock.restore = function restore() {
2446
- if (this.clock) {
2447
- this.clock.restore();
2448
- }
2449
-
2450
- return sinon.fakeServer.restore.apply(this, arguments);
2451
- };
2452
- }());
2453
-
2454
- /**
2455
- * @depend ../sinon.js
2456
- * @depend collection.js
2457
- * @depend util/fake_timers.js
2458
- * @depend util/fake_server_with_clock.js
2459
- */
2460
- /*jslint eqeqeq: false, onevar: false, plusplus: false*/
2461
- /*global require, module*/
2462
- /**
2463
- * Manages fake collections as well as fake utilities such as Sinon's
2464
- * timers and fake XHR implementation in one convenient object.
2465
- *
2466
- * @author Christian Johansen (christian@cjohansen.no)
2467
- * @license BSD
2468
- *
2469
- * Copyright (c) 2010-2011 Christian Johansen
2470
- */
2471
-
2472
- if (typeof module == "object" && typeof require == "function") {
2473
- var sinon = require("../sinon");
2474
- sinon.extend(sinon, require("./util/fake_timers"));
2475
- }
2476
-
2477
- (function () {
2478
- var push = [].push;
2479
-
2480
- function exposeValue(sandbox, config, key, value) {
2481
- if (!value) {
2482
- return;
2483
- }
2484
-
2485
- if (config.injectInto) {
2486
- config.injectInto[key] = value;
2487
- } else {
2488
- push.call(sandbox.args, value);
2489
- }
2490
- }
2491
-
2492
- function prepareSandboxFromConfig(config) {
2493
- var sandbox = sinon.create(sinon.sandbox);
2494
-
2495
- if (config.useFakeServer) {
2496
- if (typeof config.useFakeServer == "object") {
2497
- sandbox.serverPrototype = config.useFakeServer;
2498
- }
2499
-
2500
- sandbox.useFakeServer();
2501
- }
2502
-
2503
- if (config.useFakeTimers) {
2504
- if (typeof config.useFakeTimers == "object") {
2505
- sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
2506
- } else {
2507
- sandbox.useFakeTimers();
2508
- }
2509
- }
2510
-
2511
- return sandbox;
2512
- }
2513
-
2514
- sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
2515
- useFakeTimers: function useFakeTimers() {
2516
- this.clock = sinon.useFakeTimers.apply(sinon, arguments);
2517
-
2518
- return this.add(this.clock);
2519
- },
2520
-
2521
- serverPrototype: sinon.fakeServer,
2522
-
2523
- useFakeServer: function useFakeServer() {
2524
- var proto = this.serverPrototype || sinon.fakeServer;
2525
-
2526
- if (!proto || !proto.create) {
2527
- return null;
2528
- }
2529
-
2530
- this.server = proto.create();
2531
- return this.add(this.server);
2532
- },
2533
-
2534
- inject: function (obj) {
2535
- sinon.collection.inject.call(this, obj);
2536
-
2537
- if (this.clock) {
2538
- obj.clock = this.clock;
2539
- }
2540
-
2541
- if (this.server) {
2542
- obj.server = this.server;
2543
- obj.requests = this.server.requests;
2544
- }
2545
-
2546
- return obj;
2547
- },
2548
-
2549
- create: function (config) {
2550
- if (!config) {
2551
- return sinon.create(sinon.sandbox);
2552
- }
2553
-
2554
- var sandbox = prepareSandboxFromConfig(config);
2555
- sandbox.args = sandbox.args || [];
2556
- var prop, value, exposed = sandbox.inject({});
2557
-
2558
- if (config.properties) {
2559
- for (var i = 0, l = config.properties.length; i < l; i++) {
2560
- prop = config.properties[i];
2561
- value = exposed[prop] || prop == "sandbox" && sandbox;
2562
- exposeValue(sandbox, config, prop, value);
2563
- }
2564
- } else {
2565
- exposeValue(sandbox, config, "sandbox", value);
2566
- }
2567
-
2568
- return sandbox;
2569
- }
2570
- });
2571
-
2572
- sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
2573
-
2574
- if (typeof module != "undefined") {
2575
- module.exports = sinon.sandbox;
2576
- }
2577
- }());
2578
-
2579
- /**
2580
- * @depend ../sinon.js
2581
- * @depend stub.js
2582
- * @depend mock.js
2583
- * @depend sandbox.js
2584
- */
2585
- /*jslint eqeqeq: false, onevar: false, forin: true, plusplus: false*/
2586
- /*global module, require, sinon*/
2587
- /**
2588
- * Test function, sandboxes fakes
2589
- *
2590
- * @author Christian Johansen (christian@cjohansen.no)
2591
- * @license BSD
2592
- *
2593
- * Copyright (c) 2010-2011 Christian Johansen
2594
- */
2595
-
2596
- (function (sinon) {
2597
- var commonJSModule = typeof module == "object" && typeof require == "function";
2598
-
2599
- if (!sinon && commonJSModule) {
2600
- sinon = require("../sinon");
2601
- }
2602
-
2603
- if (!sinon) {
2604
- return;
2605
- }
2606
-
2607
- function test(callback) {
2608
- var type = typeof callback;
2609
-
2610
- if (type != "function") {
2611
- throw new TypeError("sinon.test needs to wrap a test function, got " + type);
2612
- }
2613
-
2614
- return function () {
2615
- var config = sinon.getConfig(sinon.config);
2616
- config.injectInto = config.injectIntoThis && this || config.injectInto;
2617
- var sandbox = sinon.sandbox.create(config);
2618
- var exception, result;
2619
- var args = Array.prototype.slice.call(arguments).concat(sandbox.args);
2620
-
2621
- try {
2622
- result = callback.apply(this, args);
2623
- } catch (e) {
2624
- exception = e;
2625
- }
2626
-
2627
- sandbox.verifyAndRestore();
2628
-
2629
- if (exception) {
2630
- throw exception;
2631
- }
2632
-
2633
- return result;
2634
- };
2635
- }
2636
-
2637
- test.config = {
2638
- injectIntoThis: true,
2639
- injectInto: null,
2640
- properties: ["spy", "stub", "mock", "clock", "server", "requests"],
2641
- useFakeTimers: true,
2642
- useFakeServer: true
2643
- };
2644
-
2645
- if (commonJSModule) {
2646
- module.exports = test;
2647
- } else {
2648
- sinon.test = test;
2649
- }
2650
- }(typeof sinon == "object" && sinon || null));
2651
-
2652
- /**
2653
- * @depend ../sinon.js
2654
- * @depend test.js
2655
- */
2656
- /*jslint eqeqeq: false, onevar: false, eqeqeq: false*/
2657
- /*global module, require, sinon*/
2658
- /**
2659
- * Test case, sandboxes all test functions
2660
- *
2661
- * @author Christian Johansen (christian@cjohansen.no)
2662
- * @license BSD
2663
- *
2664
- * Copyright (c) 2010-2011 Christian Johansen
2665
- */
2666
-
2667
- (function (sinon) {
2668
- var commonJSModule = typeof module == "object" && typeof require == "function";
2669
-
2670
- if (!sinon && commonJSModule) {
2671
- sinon = require("../sinon");
2672
- }
2673
-
2674
- if (!sinon || !Object.prototype.hasOwnProperty) {
2675
- return;
2676
- }
2677
-
2678
- function createTest(property, setUp, tearDown) {
2679
- return function () {
2680
- if (setUp) {
2681
- setUp.apply(this, arguments);
2682
- }
2683
-
2684
- var exception, result;
2685
-
2686
- try {
2687
- result = property.apply(this, arguments);
2688
- } catch (e) {
2689
- exception = e;
2690
- }
2691
-
2692
- if (tearDown) {
2693
- tearDown.apply(this, arguments);
2694
- }
2695
-
2696
- if (exception) {
2697
- throw exception;
2698
- }
2699
-
2700
- return result;
2701
- };
2702
- }
2703
-
2704
- function testCase(tests, prefix) {
2705
- /*jsl:ignore*/
2706
- if (!tests || typeof tests != "object") {
2707
- throw new TypeError("sinon.testCase needs an object with test functions");
2708
- }
2709
- /*jsl:end*/
2710
-
2711
- prefix = prefix || "test";
2712
- var rPrefix = new RegExp("^" + prefix);
2713
- var methods = {}, testName, property, method;
2714
- var setUp = tests.setUp;
2715
- var tearDown = tests.tearDown;
2716
-
2717
- for (testName in tests) {
2718
- if (tests.hasOwnProperty(testName)) {
2719
- property = tests[testName];
2720
-
2721
- if (/^(setUp|tearDown)$/.test(testName)) {
2722
- continue;
2723
- }
2724
-
2725
- if (typeof property == "function" && rPrefix.test(testName)) {
2726
- method = property;
2727
-
2728
- if (setUp || tearDown) {
2729
- method = createTest(property, setUp, tearDown);
2730
- }
2731
-
2732
- methods[testName] = sinon.test(method);
2733
- } else {
2734
- methods[testName] = tests[testName];
2735
- }
2736
- }
2737
- }
2738
-
2739
- return methods;
2740
- }
2741
-
2742
- if (commonJSModule) {
2743
- module.exports = testCase;
2744
- } else {
2745
- sinon.testCase = testCase;
2746
- }
2747
- }(typeof sinon == "object" && sinon || null));
2748
-
2749
- /**
2750
- * @depend ../sinon.js
2751
- * @depend stub.js
2752
- */
2753
- /*jslint eqeqeq: false, onevar: false, nomen: false, plusplus: false*/
2754
- /*global module, require, sinon*/
2755
- /**
2756
- * Assertions matching the test spy retrieval interface.
2757
- *
2758
- * @author Christian Johansen (christian@cjohansen.no)
2759
- * @license BSD
2760
- *
2761
- * Copyright (c) 2010-2011 Christian Johansen
2762
- */
2763
-
2764
- (function (sinon) {
2765
- var commonJSModule = typeof module == "object" && typeof require == "function";
2766
- var slice = Array.prototype.slice;
2767
- var assert;
2768
-
2769
- if (!sinon && commonJSModule) {
2770
- sinon = require("../sinon");
2771
- }
2772
-
2773
- if (!sinon) {
2774
- return;
2775
- }
2776
-
2777
- function verifyIsStub() {
2778
- var method;
2779
-
2780
- for (var i = 0, l = arguments.length; i < l; ++i) {
2781
- method = arguments[i];
2782
-
2783
- if (!method) {
2784
- assert.fail("fake is not a spy");
2785
- }
2786
-
2787
- if (typeof method != "function") {
2788
- assert.fail(method + " is not a function");
2789
- }
2790
-
2791
- if (typeof method.getCall != "function") {
2792
- assert.fail(method + " is not stubbed");
2793
- }
2794
- }
2795
- }
2796
-
2797
- function failAssertion(object, msg) {
2798
- var failMethod = object.fail || assert.fail;
2799
- failMethod.call(object, msg);
2800
- }
2801
-
2802
- function mirrorPropAsAssertion(name, method, message) {
2803
- if (arguments.length == 2) {
2804
- message = method;
2805
- method = name;
2806
- }
2807
-
2808
- assert[name] = function (fake) {
2809
- verifyIsStub(fake);
2810
-
2811
- var args = slice.call(arguments, 1);
2812
- var failed = false;
2813
-
2814
- if (typeof method == "function") {
2815
- failed = !method(fake);
2816
- } else {
2817
- failed = typeof fake[method] == "function" ?
2818
- !fake[method].apply(fake, args) : !fake[method];
2819
- }
2820
-
2821
- if (failed) {
2822
- failAssertion(this, fake.printf.apply(fake, [message].concat(args)));
2823
- } else {
2824
- assert.pass(name);
2825
- }
2826
- };
2827
- }
2828
-
2829
- function exposedName(prefix, prop) {
2830
- return !prefix || /^fail/.test(prop) ? prop :
2831
- prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1);
2832
- };
2833
-
2834
- assert = {
2835
- failException: "AssertError",
2836
-
2837
- fail: function fail(message) {
2838
- var error = new Error(message);
2839
- error.name = this.failException || assert.failException;
2840
-
2841
- throw error;
2842
- },
2843
-
2844
- pass: function pass(assertion) {},
2845
-
2846
- callOrder: function assertCallOrder() {
2847
- verifyIsStub.apply(null, arguments);
2848
- var expected = "", actual = "";
2849
-
2850
- if (!sinon.calledInOrder(arguments)) {
2851
- try {
2852
- expected = [].join.call(arguments, ", ");
2853
- actual = sinon.orderByFirstCall(slice.call(arguments)).join(", ");
2854
- } catch (e) {}
2855
-
2856
- failAssertion(this, "expected " + expected + " to be " +
2857
- "called in order but were called as " + actual);
2858
- } else {
2859
- assert.pass("callOrder");
2860
- }
2861
- },
2862
-
2863
- callCount: function assertCallCount(method, count) {
2864
- verifyIsStub(method);
2865
-
2866
- if (method.callCount != count) {
2867
- var msg = "expected %n to be called " + sinon.timesInWords(count) +
2868
- " but was called %c%C";
2869
- failAssertion(this, method.printf(msg));
2870
- } else {
2871
- assert.pass("callCount");
2872
- }
2873
- },
2874
-
2875
- expose: function expose(target, options) {
2876
- if (!target) {
2877
- throw new TypeError("target is null or undefined");
2878
- }
2879
-
2880
- var o = options || {};
2881
- var prefix = typeof o.prefix == "undefined" && "assert" || o.prefix;
2882
- var includeFail = typeof o.includeFail == "undefined" || !!o.includeFail;
2883
-
2884
- for (var method in this) {
2885
- if (method != "export" && (includeFail || !/^(fail)/.test(method))) {
2886
- target[exposedName(prefix, method)] = this[method];
2887
- }
2888
- }
2889
-
2890
- return target;
2891
- }
2892
- };
2893
-
2894
- mirrorPropAsAssertion("called", "expected %n to have been called at least once but was never called");
2895
- mirrorPropAsAssertion("notCalled", function (spy) { return !spy.called; },
2896
- "expected %n to not have been called but was called %c%C");
2897
- mirrorPropAsAssertion("calledOnce", "expected %n to be called once but was called %c%C");
2898
- mirrorPropAsAssertion("calledTwice", "expected %n to be called twice but was called %c%C");
2899
- mirrorPropAsAssertion("calledThrice", "expected %n to be called thrice but was called %c%C");
2900
- mirrorPropAsAssertion("calledOn", "expected %n to be called with %1 as this but was called with %t");
2901
- mirrorPropAsAssertion("alwaysCalledOn", "expected %n to always be called with %1 as this but was called with %t");
2902
- mirrorPropAsAssertion("calledWith", "expected %n to be called with arguments %*%C");
2903
- mirrorPropAsAssertion("alwaysCalledWith", "expected %n to always be called with arguments %*%C");
2904
- mirrorPropAsAssertion("calledWithExactly", "expected %n to be called with exact arguments %*%C");
2905
- mirrorPropAsAssertion("alwaysCalledWithExactly", "expected %n to always be called with exact arguments %*%C");
2906
- mirrorPropAsAssertion("neverCalledWith", "expected %n to never be called with arguments %*%C");
2907
- mirrorPropAsAssertion("threw", "%n did not throw exception%C");
2908
- mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C");
2909
-
2910
- if (commonJSModule) {
2911
- module.exports = assert;
2912
- } else {
2913
- sinon.assert = assert;
2914
- }
2915
- }(typeof sinon == "object" && sinon || null));