activeadmin 0.6.6 → 1.0.0.pre1

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

Potentially problematic release.


This version of activeadmin might be problematic. Click here for more details.

Files changed (512) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +11 -8
  3. data/.hound.yml +11 -0
  4. data/.travis.yml +36 -10
  5. data/.yardopts +2 -1
  6. data/CHANGELOG.md +118 -67
  7. data/CONTRIBUTING.md +96 -73
  8. data/Gemfile +35 -35
  9. data/Guardfile +1 -0
  10. data/LICENSE +1 -1
  11. data/README.md +98 -0
  12. data/Rakefile +12 -4
  13. data/activeadmin.gemspec +21 -24
  14. data/app/assets/javascripts/active_admin/application.js.coffee +32 -0
  15. data/app/assets/javascripts/active_admin/base.js.coffee +14 -0
  16. data/app/assets/javascripts/active_admin/ext/jquery-ui.js.coffee +6 -0
  17. data/app/assets/javascripts/active_admin/ext/jquery.js.coffee +7 -0
  18. data/app/assets/javascripts/active_admin/lib/batch_actions.js.coffee +39 -0
  19. data/app/assets/javascripts/active_admin/{components/jquery.aa.checkbox-toggler.js.coffee → lib/checkbox-toggler.js.coffee} +3 -4
  20. data/app/assets/javascripts/active_admin/lib/dropdown-menu.js.coffee +101 -0
  21. data/app/assets/javascripts/active_admin/lib/flash.js.coffee +19 -0
  22. data/app/assets/javascripts/active_admin/lib/has_many.js.coffee +79 -0
  23. data/app/assets/javascripts/active_admin/lib/modal_dialog.js.coffee +37 -0
  24. data/app/assets/javascripts/active_admin/lib/per_page.js.coffee +27 -0
  25. data/app/assets/javascripts/active_admin/lib/popover.js.coffee +68 -0
  26. data/app/assets/javascripts/active_admin/{components/jquery.aa.table-checkbox-toggler.js.coffee → lib/table-checkbox-toggler.js.coffee} +2 -3
  27. data/app/assets/stylesheets/active_admin/{_base.css.scss → _base.scss} +3 -0
  28. data/app/assets/stylesheets/active_admin/{_forms.css.scss → _forms.scss} +61 -17
  29. data/app/assets/stylesheets/active_admin/{_header.css.scss → _header.scss} +9 -5
  30. data/app/assets/stylesheets/active_admin/{_mixins.css.scss → _mixins.scss} +0 -0
  31. data/app/assets/stylesheets/active_admin/{_typography.css.scss → _typography.scss} +0 -0
  32. data/app/assets/stylesheets/active_admin/components/_batch_actions.scss +11 -0
  33. data/app/assets/stylesheets/active_admin/components/_blank_slates.scss +0 -1
  34. data/app/assets/stylesheets/active_admin/components/_buttons.scss +1 -1
  35. data/app/assets/stylesheets/active_admin/components/{_comments.css.scss → _comments.scss} +0 -0
  36. data/app/assets/stylesheets/active_admin/components/{_date_picker.css.scss → _date_picker.scss} +40 -14
  37. data/app/assets/stylesheets/active_admin/components/_dropdown_menu.scss +5 -4
  38. data/app/assets/stylesheets/active_admin/components/_flash_messages.scss +37 -0
  39. data/app/assets/stylesheets/active_admin/components/_modal_dialog.scss +34 -0
  40. data/app/assets/stylesheets/active_admin/components/_pagination.scss +10 -0
  41. data/app/assets/stylesheets/active_admin/components/{_popovers.css.scss → _popovers.scss} +2 -3
  42. data/app/assets/stylesheets/active_admin/components/_status_tags.scss +4 -0
  43. data/app/assets/stylesheets/active_admin/components/_table_tools.scss +67 -0
  44. data/app/assets/stylesheets/active_admin/components/{_tables.css.scss → _tables.scss} +4 -2
  45. data/app/assets/stylesheets/active_admin/components/_tabs.scss +65 -0
  46. data/app/assets/stylesheets/active_admin/components/_unsupported_browser.scss +16 -0
  47. data/app/assets/stylesheets/active_admin/mixins/{_all.css.scss → _all.scss} +0 -0
  48. data/app/assets/stylesheets/active_admin/mixins/{_buttons.css.scss → _buttons.scss} +0 -1
  49. data/app/assets/stylesheets/active_admin/mixins/_gradients.scss +28 -0
  50. data/app/assets/stylesheets/active_admin/mixins/{_icons.css.scss → _icons.scss} +1 -2
  51. data/app/assets/stylesheets/active_admin/mixins/{_reset.css.scss → _reset.scss} +0 -0
  52. data/app/assets/stylesheets/active_admin/mixins/_rounded.scss +22 -0
  53. data/app/assets/stylesheets/active_admin/mixins/{_sections.css.scss → _sections.scss} +8 -2
  54. data/app/assets/stylesheets/active_admin/mixins/{_shadows.css.scss → _shadows.scss} +0 -7
  55. data/app/assets/stylesheets/active_admin/mixins/_utilities.scss +0 -9
  56. data/app/assets/stylesheets/active_admin/mixins/{_variables.css.scss → _variables.scss} +10 -8
  57. data/app/assets/stylesheets/active_admin/{print.css.scss → print.scss} +4 -0
  58. data/app/assets/stylesheets/active_admin/structure/_main_structure.scss +5 -2
  59. data/app/assets/stylesheets/active_admin/structure/_title_bar.scss +11 -9
  60. data/app/views/active_admin/devise/confirmations/new.html.erb +15 -0
  61. data/app/views/active_admin/devise/mailer/reset_password_instructions.html.erb +1 -1
  62. data/app/views/active_admin/devise/mailer/unlock_instructions.html.erb +1 -1
  63. data/app/views/active_admin/devise/passwords/edit.html.erb +9 -10
  64. data/app/views/active_admin/devise/passwords/new.html.erb +5 -4
  65. data/app/views/active_admin/devise/registrations/new.html.erb +22 -0
  66. data/app/views/active_admin/devise/sessions/new.html.erb +9 -7
  67. data/app/views/active_admin/devise/shared/_links.erb +1 -1
  68. data/app/views/active_admin/devise/unlocks/new.html.erb +5 -4
  69. data/app/views/layouts/active_admin_logged_out.html.erb +3 -5
  70. data/config/locales/ar.yml +120 -0
  71. data/config/locales/bg.yml +26 -6
  72. data/config/locales/bs.yml +122 -0
  73. data/config/locales/ca.yml +10 -1
  74. data/config/locales/cs.yml +7 -2
  75. data/config/locales/da.yml +7 -3
  76. data/config/locales/de-CH.yml +14 -31
  77. data/config/locales/de.yml +33 -33
  78. data/config/locales/el.yml +28 -2
  79. data/config/locales/en-GB.yml +12 -4
  80. data/config/locales/en.yml +29 -3
  81. data/config/locales/{es_MX.yml → es-MX.yml} +9 -24
  82. data/config/locales/es.yml +32 -25
  83. data/config/locales/fa.yml +120 -0
  84. data/config/locales/fi.yml +113 -0
  85. data/config/locales/fr.yml +21 -11
  86. data/config/locales/he.yml +7 -3
  87. data/config/locales/hr.yml +42 -11
  88. data/config/locales/hu.yml +10 -3
  89. data/config/locales/it.yml +31 -3
  90. data/config/locales/ja.yml +8 -3
  91. data/config/locales/ko.yml +7 -1
  92. data/config/locales/lt.yml +42 -11
  93. data/config/locales/lv.yml +7 -3
  94. data/config/locales/{no-NB.yml → nb.yml} +46 -15
  95. data/config/locales/nl.yml +36 -5
  96. data/config/locales/pl.yml +13 -8
  97. data/config/locales/pt-BR.yml +37 -5
  98. data/config/locales/pt-PT.yml +8 -4
  99. data/config/locales/ro.yml +7 -3
  100. data/config/locales/ru.yml +26 -5
  101. data/config/locales/sv-SE.yml +9 -5
  102. data/config/locales/tr.yml +10 -3
  103. data/config/locales/uk.yml +36 -12
  104. data/config/locales/vi.yml +7 -3
  105. data/config/locales/zh-CN.yml +26 -10
  106. data/config/locales/zh-TW.yml +19 -13
  107. data/docs/0-installation.md +65 -29
  108. data/docs/1-general-configuration.md +92 -81
  109. data/docs/10-custom-pages.md +68 -68
  110. data/docs/11-decorators.md +48 -59
  111. data/docs/12-arbre-components.md +80 -74
  112. data/docs/13-authorization-adapter.md +128 -107
  113. data/docs/14-gotchas.md +92 -0
  114. data/docs/2-resource-customization.md +293 -178
  115. data/docs/3-index-pages.md +160 -86
  116. data/docs/3-index-pages/custom-index.md +31 -0
  117. data/docs/3-index-pages/index-as-block.md +14 -9
  118. data/docs/3-index-pages/index-as-blog.md +41 -31
  119. data/docs/3-index-pages/index-as-grid.md +16 -8
  120. data/docs/3-index-pages/index-as-table.md +129 -52
  121. data/docs/4-csv-format.md +31 -24
  122. data/docs/5-forms.md +133 -56
  123. data/docs/6-show-pages.md +89 -27
  124. data/docs/7-sidebars.md +48 -27
  125. data/docs/8-custom-actions.md +98 -77
  126. data/docs/9-batch-actions.md +210 -146
  127. data/docs/README.md +24 -0
  128. data/features/action_item.feature +3 -3
  129. data/features/authorization_pundit.feature +37 -0
  130. data/features/breadcrumb.feature +48 -0
  131. data/features/comments/commenting.feature +56 -13
  132. data/features/development_reloading.feature +17 -30
  133. data/features/edit_page.feature +12 -1
  134. data/features/favicon.feature +3 -3
  135. data/features/i18n.feature +5 -4
  136. data/features/index/batch_actions.feature +41 -0
  137. data/features/index/filters.feature +67 -0
  138. data/features/index/format_as_csv.feature +90 -4
  139. data/features/index/formats.feature +27 -0
  140. data/features/index/index_as_blog.feature +4 -4
  141. data/features/index/index_as_table.feature +102 -6
  142. data/features/index/index_blank_slate.feature +22 -0
  143. data/features/index/index_scope_to.feature +16 -16
  144. data/features/index/page_title.feature +11 -0
  145. data/features/index/pagination.feature +1 -1
  146. data/features/index/switch_index_view.feature +14 -14
  147. data/features/new_page.feature +13 -2
  148. data/features/registering_pages.feature +1 -1
  149. data/features/renamed_resource.feature +32 -0
  150. data/features/show/page_title.feature +11 -0
  151. data/features/show/tabs.feature +27 -0
  152. data/features/sidebar_sections.feature +12 -0
  153. data/features/site_title.feature +2 -2
  154. data/features/specifying_actions.feature +3 -3
  155. data/features/step_definitions/action_item_steps.rb +2 -2
  156. data/features/step_definitions/action_link_steps.rb +14 -1
  157. data/features/step_definitions/additional_web_steps.rb +19 -20
  158. data/features/step_definitions/asset_steps.rb +3 -3
  159. data/features/step_definitions/attribute_steps.rb +8 -3
  160. data/features/step_definitions/batch_action_steps.rb +26 -9
  161. data/features/step_definitions/blog_steps.rb +3 -0
  162. data/features/step_definitions/breadcrumb_steps.rb +1 -1
  163. data/features/step_definitions/comment_steps.rb +1 -1
  164. data/features/step_definitions/configuration_steps.rb +9 -2
  165. data/features/step_definitions/dashboard_steps.rb +2 -2
  166. data/features/step_definitions/factory_steps.rb +9 -8
  167. data/features/step_definitions/filter_steps.rb +25 -3
  168. data/features/step_definitions/flash_steps.rb +3 -3
  169. data/features/step_definitions/format_steps.rb +18 -18
  170. data/features/step_definitions/index_scope_steps.rb +5 -5
  171. data/features/step_definitions/layout_steps.rb +1 -1
  172. data/features/step_definitions/member_link_steps.rb +2 -2
  173. data/features/step_definitions/menu_steps.rb +3 -3
  174. data/features/step_definitions/pagination_steps.rb +2 -3
  175. data/features/step_definitions/sidebar_steps.rb +8 -3
  176. data/features/step_definitions/site_title_steps.rb +6 -4
  177. data/features/step_definitions/symbol_leak_steps.rb +3 -0
  178. data/features/step_definitions/tab_steps.rb +5 -0
  179. data/features/step_definitions/table_steps.rb +4 -4
  180. data/features/step_definitions/user_steps.rb +10 -7
  181. data/features/step_definitions/web_steps.rb +14 -11
  182. data/features/sti_resource.feature +6 -2
  183. data/features/strong_parameters.feature +73 -0
  184. data/features/support/env.rb +34 -9
  185. data/features/support/paths.rb +14 -6
  186. data/features/support/selectors.rb +1 -1
  187. data/features/symbol_leak.feature +35 -0
  188. data/features/users/resetting_password.feature +5 -6
  189. data/lib/active_admin.rb +26 -25
  190. data/lib/active_admin/abstract_view_factory.rb +7 -17
  191. data/lib/active_admin/application.rb +72 -59
  192. data/lib/active_admin/asset_registration.rb +2 -2
  193. data/lib/active_admin/authorization_adapter.rb +2 -2
  194. data/lib/active_admin/base_controller.rb +2 -3
  195. data/lib/active_admin/base_controller/authorization.rb +13 -31
  196. data/lib/active_admin/batch_actions.rb +1 -1
  197. data/lib/active_admin/batch_actions/controller.rb +24 -8
  198. data/lib/active_admin/batch_actions/resource_extension.rb +47 -18
  199. data/lib/active_admin/batch_actions/views/batch_action_form.rb +7 -4
  200. data/lib/active_admin/batch_actions/views/batch_action_popover.rb +3 -3
  201. data/lib/active_admin/batch_actions/views/batch_action_selector.rb +8 -17
  202. data/lib/active_admin/batch_actions/views/selection_cells.rb +4 -4
  203. data/lib/active_admin/callbacks.rb +25 -24
  204. data/lib/active_admin/cancan_adapter.rb +7 -11
  205. data/lib/active_admin/csv_builder.rb +92 -15
  206. data/lib/active_admin/dependency.rb +93 -0
  207. data/lib/active_admin/deprecation.rb +6 -7
  208. data/lib/active_admin/devise.rb +28 -18
  209. data/lib/active_admin/dsl.rb +18 -11
  210. data/lib/active_admin/engine.rb +10 -8
  211. data/lib/active_admin/error.rb +62 -0
  212. data/lib/active_admin/filters/dsl.rb +2 -2
  213. data/lib/active_admin/filters/forms.rb +17 -27
  214. data/lib/active_admin/filters/formtastic_addons.rb +49 -15
  215. data/lib/active_admin/filters/resource_extension.rb +43 -34
  216. data/lib/active_admin/form_builder.rb +93 -154
  217. data/lib/active_admin/helpers/collection.rb +7 -13
  218. data/lib/active_admin/helpers/i18n.rb +7 -0
  219. data/lib/active_admin/helpers/optional_display.rb +5 -5
  220. data/lib/active_admin/helpers/routes/url_helpers.rb +15 -0
  221. data/lib/active_admin/helpers/scope_chain.rb +1 -1
  222. data/lib/active_admin/helpers/settings.rb +16 -9
  223. data/lib/active_admin/iconic.rb +17 -15
  224. data/lib/active_admin/iconic/icons.rb +136 -136
  225. data/lib/active_admin/inputs.rb +11 -7
  226. data/lib/active_admin/inputs/datepicker_input.rb +12 -3
  227. data/lib/active_admin/inputs/filters/base.rb +42 -0
  228. data/lib/active_admin/inputs/filters/base/search_method_select.rb +75 -0
  229. data/lib/active_admin/inputs/filters/boolean_input.rb +24 -0
  230. data/lib/active_admin/inputs/filters/check_boxes_input.rb +50 -0
  231. data/lib/active_admin/inputs/filters/date_range_input.rb +36 -0
  232. data/lib/active_admin/inputs/filters/numeric_input.rb +12 -0
  233. data/lib/active_admin/inputs/filters/select_input.rb +54 -0
  234. data/lib/active_admin/inputs/filters/string_input.rb +26 -0
  235. data/lib/active_admin/menu.rb +6 -4
  236. data/lib/active_admin/menu_collection.rb +1 -4
  237. data/lib/active_admin/namespace.rb +55 -29
  238. data/lib/active_admin/order_clause.rb +26 -0
  239. data/lib/active_admin/orm/active_record.rb +5 -0
  240. data/lib/active_admin/orm/active_record/comments.rb +81 -0
  241. data/lib/active_admin/orm/active_record/comments/comment.rb +45 -0
  242. data/lib/active_admin/{comments → orm/active_record/comments}/namespace_helper.rb +2 -2
  243. data/lib/active_admin/{comments → orm/active_record/comments}/resource_helper.rb +1 -1
  244. data/lib/active_admin/{comments → orm/active_record/comments}/show_page_helper.rb +0 -0
  245. data/lib/active_admin/orm/active_record/comments/views.rb +2 -0
  246. data/lib/active_admin/{comments → orm/active_record/comments}/views/active_admin_comments.rb +16 -14
  247. data/lib/active_admin/orm/mongoid.rb +1 -0
  248. data/lib/active_admin/orm/mongoid/.gitkeep +0 -0
  249. data/lib/active_admin/page.rb +7 -3
  250. data/lib/active_admin/page_dsl.rb +1 -1
  251. data/lib/active_admin/page_presenter.rb +2 -2
  252. data/lib/active_admin/pundit_adapter.rb +68 -0
  253. data/lib/active_admin/resource.rb +16 -17
  254. data/lib/active_admin/resource/action_items.rb +23 -18
  255. data/lib/active_admin/resource/belongs_to.rb +7 -3
  256. data/lib/active_admin/resource/controllers.rb +1 -0
  257. data/lib/active_admin/resource/includes.rb +12 -0
  258. data/lib/active_admin/resource/menu.rb +5 -5
  259. data/lib/active_admin/resource/naming.rb +27 -43
  260. data/lib/active_admin/resource/page_presenters.rb +1 -1
  261. data/lib/active_admin/resource/routes.rb +27 -11
  262. data/lib/active_admin/resource/scope_to.rb +7 -7
  263. data/lib/active_admin/resource/sidebars.rb +1 -0
  264. data/lib/active_admin/resource_controller.rb +6 -7
  265. data/lib/active_admin/resource_controller/data_access.rb +101 -93
  266. data/lib/active_admin/resource_controller/decorators.rb +91 -9
  267. data/lib/active_admin/resource_controller/streaming.rb +37 -0
  268. data/lib/active_admin/resource_dsl.rb +53 -10
  269. data/lib/active_admin/router.rb +7 -7
  270. data/lib/active_admin/scope.rb +6 -6
  271. data/lib/active_admin/sidebar_section.rb +10 -2
  272. data/lib/active_admin/version.rb +1 -1
  273. data/lib/active_admin/view_factory.rb +17 -17
  274. data/lib/active_admin/view_helpers.rb +0 -1
  275. data/lib/active_admin/view_helpers/auto_link_helper.rb +23 -12
  276. data/lib/active_admin/view_helpers/breadcrumb_helper.rb +4 -3
  277. data/lib/active_admin/view_helpers/display_helper.rb +30 -15
  278. data/lib/active_admin/view_helpers/download_format_links_helper.rb +21 -25
  279. data/lib/active_admin/view_helpers/fields_for.rb +4 -4
  280. data/lib/active_admin/view_helpers/flash_helper.rb +4 -3
  281. data/lib/active_admin/view_helpers/form_helper.rb +5 -9
  282. data/lib/active_admin/view_helpers/method_or_proc_helper.rb +6 -6
  283. data/lib/active_admin/views/action_items.rb +2 -2
  284. data/lib/active_admin/views/components/action_list_popover.rb +1 -1
  285. data/lib/active_admin/views/components/active_admin_form.rb +123 -0
  286. data/lib/active_admin/views/components/attributes_table.rb +63 -21
  287. data/lib/active_admin/views/components/blank_slate.rb +1 -1
  288. data/lib/active_admin/views/components/columns.rb +13 -7
  289. data/lib/active_admin/views/components/dropdown_menu.rb +6 -6
  290. data/lib/active_admin/views/components/index_list.rb +7 -7
  291. data/lib/active_admin/views/components/paginated_collection.rb +38 -20
  292. data/lib/active_admin/views/components/panel.rb +8 -2
  293. data/lib/active_admin/views/components/popover.rb +1 -1
  294. data/lib/active_admin/views/components/scopes.rb +5 -4
  295. data/lib/active_admin/views/components/sidebar_section.rb +3 -2
  296. data/lib/active_admin/views/components/site_title.rb +2 -2
  297. data/lib/active_admin/views/components/status_tag.rb +34 -11
  298. data/lib/active_admin/views/components/table_for.rb +90 -45
  299. data/lib/active_admin/views/components/tabs.rb +28 -0
  300. data/lib/active_admin/views/components/unsupported_browser.rb +11 -0
  301. data/lib/active_admin/views/footer.rb +3 -3
  302. data/lib/active_admin/views/header.rb +3 -3
  303. data/lib/active_admin/views/index_as_block.rb +10 -10
  304. data/lib/active_admin/views/index_as_blog.rb +45 -39
  305. data/lib/active_admin/views/index_as_grid.rb +14 -10
  306. data/lib/active_admin/views/index_as_table.rb +242 -129
  307. data/lib/active_admin/views/pages/base.rb +22 -18
  308. data/lib/active_admin/views/pages/form.rb +21 -11
  309. data/lib/active_admin/views/pages/index.rb +40 -35
  310. data/lib/active_admin/views/pages/layout.rb +1 -1
  311. data/lib/active_admin/views/pages/show.rb +4 -4
  312. data/lib/active_admin/views/tabbed_navigation.rb +7 -3
  313. data/lib/active_admin/views/title_bar.rb +10 -8
  314. data/lib/generators/active_admin/assets/assets_generator.rb +3 -28
  315. data/lib/generators/active_admin/assets/templates/{3.1/active_admin.css.scss → active_admin.css.scss} +0 -0
  316. data/lib/generators/active_admin/assets/templates/active_admin.js.coffee +1 -0
  317. data/lib/generators/active_admin/devise/devise_generator.rb +24 -26
  318. data/lib/generators/active_admin/install/install_generator.rb +8 -9
  319. data/lib/generators/active_admin/install/templates/active_admin.rb.erb +28 -26
  320. data/lib/generators/active_admin/install/templates/admin_user.rb.erb +12 -2
  321. data/lib/generators/active_admin/install/templates/dashboard.rb +4 -4
  322. data/lib/generators/active_admin/install/templates/migrations/create_active_admin_comments.rb +3 -3
  323. data/lib/generators/active_admin/page/USAGE +8 -0
  324. data/lib/generators/active_admin/page/page_generator.rb +12 -0
  325. data/lib/generators/active_admin/page/templates/page.rb +5 -0
  326. data/lib/generators/active_admin/resource/resource_generator.rb +3 -5
  327. data/lib/generators/active_admin/resource/templates/admin.rb +15 -0
  328. data/lib/ransack_ext.rb +12 -0
  329. data/script/local +2 -2
  330. data/script/travis_cache +107 -0
  331. data/spec/javascripts/coffeescripts/jquery.aa.flash.js.coffee +25 -0
  332. data/spec/javascripts/fixtures/flashes.html +2 -0
  333. data/spec/rails_helper.rb +154 -0
  334. data/spec/{integration → requests}/default_namespace_spec.rb +6 -6
  335. data/spec/{integration → requests}/javascript_spec.rb +5 -5
  336. data/spec/requests/memory_spec.rb +23 -0
  337. data/spec/requests/stylesheets_spec.rb +18 -0
  338. data/spec/spec_helper.rb +12 -173
  339. data/spec/support/detect_rails_version.rb +9 -17
  340. data/spec/support/rails_template.rb +64 -35
  341. data/spec/support/rails_template_with_data.rb +14 -14
  342. data/spec/support/templates/admin/stores.rb +5 -1
  343. data/spec/support/templates/policies/active_admin/comment_policy.rb +9 -0
  344. data/spec/support/templates/policies/active_admin/page_policy.rb +18 -0
  345. data/spec/support/templates/policies/admin_user_policy.rb +11 -0
  346. data/spec/support/templates/policies/application_policy.rb +45 -0
  347. data/spec/support/templates/policies/category_policy.rb +7 -0
  348. data/spec/support/templates/policies/post_policy.rb +15 -0
  349. data/spec/support/templates/policies/store_policy.rb +11 -0
  350. data/spec/support/templates/policies/user_policy.rb +11 -0
  351. data/spec/support/templates/post_decorator.rb +4 -46
  352. data/spec/unit/abstract_view_factory_spec.rb +16 -16
  353. data/spec/unit/action_builder_spec.rb +24 -18
  354. data/spec/unit/active_admin_spec.rb +2 -2
  355. data/spec/unit/application_spec.rb +33 -34
  356. data/spec/unit/asset_registration_spec.rb +25 -29
  357. data/spec/unit/authorization/authorization_adapter_spec.rb +10 -10
  358. data/spec/unit/authorization/controller_authorization_spec.rb +11 -11
  359. data/spec/unit/authorization/index_overriding_spec.rb +22 -0
  360. data/spec/unit/auto_link_spec.rb +43 -13
  361. data/spec/unit/batch_actions/resource_spec.rb +15 -14
  362. data/spec/unit/batch_actions/settings_spec.rb +18 -18
  363. data/spec/unit/belongs_to_spec.rb +28 -19
  364. data/spec/unit/cancan_adapter_spec.rb +8 -8
  365. data/spec/unit/comments_spec.rb +99 -39
  366. data/spec/unit/component_spec.rb +3 -3
  367. data/spec/unit/config_shared_examples.rb +10 -10
  368. data/spec/unit/controller_filters_spec.rb +23 -16
  369. data/spec/unit/csv_builder_spec.rb +165 -24
  370. data/spec/unit/dependency_spec.rb +135 -0
  371. data/spec/unit/devise_spec.rb +17 -37
  372. data/spec/unit/dsl_spec.rb +70 -9
  373. data/spec/unit/event_spec.rb +11 -11
  374. data/spec/unit/filters/filter_form_builder_spec.rb +207 -148
  375. data/spec/unit/filters/resource_spec.rb +60 -26
  376. data/spec/unit/form_builder_spec.rb +419 -145
  377. data/spec/unit/generators/install_spec.rb +23 -0
  378. data/spec/unit/helpers/collection_spec.rb +18 -18
  379. data/spec/unit/helpers/scope_chain_spec.rb +6 -6
  380. data/spec/unit/helpers/settings_spec.rb +4 -4
  381. data/spec/unit/i18n_spec.rb +12 -0
  382. data/spec/unit/menu_collection_spec.rb +14 -14
  383. data/spec/unit/menu_item_spec.rb +42 -42
  384. data/spec/unit/menu_spec.rb +20 -20
  385. data/spec/unit/namespace/authorization_spec.rb +8 -8
  386. data/spec/unit/namespace/register_page_spec.rb +11 -11
  387. data/spec/unit/namespace/register_resource_spec.rb +28 -30
  388. data/spec/unit/namespace_spec.rb +20 -20
  389. data/spec/unit/order_clause_spec.rb +81 -0
  390. data/spec/unit/page_controller_spec.rb +1 -1
  391. data/spec/unit/page_spec.rb +18 -12
  392. data/spec/unit/pretty_format_spec.rb +42 -14
  393. data/spec/unit/pundit_adapter_spec.rb +98 -0
  394. data/spec/unit/resource/action_items_spec.rb +15 -12
  395. data/spec/unit/resource/includes_spec.rb +21 -0
  396. data/spec/unit/resource/menu_spec.rb +1 -1
  397. data/spec/unit/resource/naming_spec.rb +35 -21
  398. data/spec/unit/resource/page_presenters_spec.rb +8 -8
  399. data/spec/unit/resource/pagination_spec.rb +6 -6
  400. data/spec/unit/resource/routes_spec.rb +10 -10
  401. data/spec/unit/resource/scopes_spec.rb +14 -7
  402. data/spec/unit/resource/sidebars_spec.rb +6 -6
  403. data/spec/unit/resource_collection_spec.rb +31 -38
  404. data/spec/unit/resource_controller/data_access_spec.rb +96 -30
  405. data/spec/unit/resource_controller/decorators_spec.rb +83 -0
  406. data/spec/unit/resource_controller/sidebars_spec.rb +7 -8
  407. data/spec/unit/resource_controller_spec.rb +73 -70
  408. data/spec/unit/resource_registration_spec.rb +12 -12
  409. data/spec/unit/resource_spec.rb +77 -42
  410. data/spec/unit/routing_spec.rb +39 -31
  411. data/spec/unit/scope_spec.rb +112 -30
  412. data/spec/unit/settings_spec.rb +51 -21
  413. data/spec/unit/view_factory_spec.rb +2 -3
  414. data/spec/unit/view_helpers/breadcrumbs_spec.rb +71 -60
  415. data/spec/unit/view_helpers/display_name_spec.rb +49 -21
  416. data/spec/unit/view_helpers/download_format_links_helper_spec.rb +5 -5
  417. data/spec/unit/view_helpers/fields_for_spec.rb +18 -18
  418. data/spec/unit/view_helpers/flash_helper_spec.rb +25 -0
  419. data/spec/unit/view_helpers/form_helper_spec.rb +10 -23
  420. data/spec/unit/view_helpers/method_or_proc_helper_spec.rb +64 -22
  421. data/spec/unit/views/components/action_list_popover_spec.rb +16 -6
  422. data/spec/unit/views/components/attributes_table_spec.rb +171 -30
  423. data/spec/unit/views/components/batch_action_popover_spec.rb +20 -6
  424. data/spec/unit/views/components/blank_slate_spec.rb +14 -4
  425. data/spec/unit/views/components/columns_spec.rb +52 -22
  426. data/spec/unit/views/components/index_list_spec.rb +11 -8
  427. data/spec/unit/views/components/index_table_for_spec.rb +46 -0
  428. data/spec/unit/views/components/paginated_collection_spec.rb +79 -90
  429. data/spec/unit/views/components/panel_spec.rb +32 -21
  430. data/spec/unit/views/components/popover_spec.rb +7 -7
  431. data/spec/unit/views/components/sidebar_section_spec.rb +18 -8
  432. data/spec/unit/views/components/site_title_spec.rb +26 -26
  433. data/spec/unit/views/components/status_tag_spec.rb +178 -38
  434. data/spec/unit/views/components/table_for_spec.rb +237 -35
  435. data/spec/unit/views/components/tabs_spec.rb +39 -0
  436. data/spec/unit/views/components/unsupported_browser_spec.rb +47 -0
  437. data/spec/unit/views/pages/form_spec.rb +17 -10
  438. data/spec/unit/views/pages/index_spec.rb +60 -0
  439. data/spec/unit/views/pages/layout_spec.rb +17 -21
  440. data/spec/unit/views/pages/show_spec.rb +18 -6
  441. data/spec/unit/views/tabbed_navigation_spec.rb +61 -52
  442. data/tasks/docs.rake +9 -11
  443. data/tasks/parallel_tests.rake +8 -2
  444. data/tasks/test.rake +13 -9
  445. data/tasks/yard.rake +7 -4
  446. metadata +219 -163
  447. data/.document +0 -5
  448. data/README.rdoc +0 -88
  449. data/app/assets/images/active_admin/admin_notes_icon.png +0 -0
  450. data/app/assets/images/active_admin/datepicker/datepicker-header-bg.png +0 -0
  451. data/app/assets/images/active_admin/datepicker/datepicker-next-link-icon.png +0 -0
  452. data/app/assets/images/active_admin/datepicker/datepicker-nipple.png +0 -0
  453. data/app/assets/images/active_admin/datepicker/datepicker-prev-link-icon.png +0 -0
  454. data/app/assets/images/active_admin/index_list_icons/block_icon.svg +0 -10
  455. data/app/assets/images/active_admin/index_list_icons/blog_icon.svg +0 -4
  456. data/app/assets/images/active_admin/index_list_icons/grid_icon.svg +0 -13
  457. data/app/assets/images/active_admin/index_list_icons/table_icon.svg +0 -3
  458. data/app/assets/images/active_admin/loading.gif +0 -0
  459. data/app/assets/javascripts/active_admin/application.js +0 -3
  460. data/app/assets/javascripts/active_admin/base.js +0 -5
  461. data/app/assets/javascripts/active_admin/components/jquery.aa.dropdown-menu.js.coffee +0 -105
  462. data/app/assets/javascripts/active_admin/components/jquery.aa.popover.js.coffee +0 -97
  463. data/app/assets/javascripts/active_admin/lib/namespace.js.coffee +0 -4
  464. data/app/assets/javascripts/active_admin/pages/application.js.coffee +0 -21
  465. data/app/assets/javascripts/active_admin/pages/batch_actions.js.coffee +0 -26
  466. data/app/assets/stylesheets/active_admin/components/_batch_actions.css.scss +0 -11
  467. data/app/assets/stylesheets/active_admin/components/_flash_messages.css.scss +0 -41
  468. data/app/assets/stylesheets/active_admin/components/_table_tools.css.scss +0 -95
  469. data/app/assets/stylesheets/active_admin/mixins/_gradients.css.scss +0 -38
  470. data/app/assets/stylesheets/active_admin/mixins/_rounded.css.scss +0 -43
  471. data/app/views/active_admin/dashboard/index.html.arb +0 -1
  472. data/app/views/active_admin/resource/index.csv.erb +0 -23
  473. data/docs/3-index-pages/create-an-index.md +0 -29
  474. data/lib/active_admin/comments.rb +0 -83
  475. data/lib/active_admin/comments/comment.rb +0 -42
  476. data/lib/active_admin/comments/views.rb +0 -2
  477. data/lib/active_admin/dependency_checker.rb +0 -46
  478. data/lib/active_admin/inputs/filter_base.rb +0 -33
  479. data/lib/active_admin/inputs/filter_base/search_method_select.rb +0 -73
  480. data/lib/active_admin/inputs/filter_boolean_input.rb +0 -36
  481. data/lib/active_admin/inputs/filter_check_boxes_input.rb +0 -40
  482. data/lib/active_admin/inputs/filter_date_range_input.rb +0 -34
  483. data/lib/active_admin/inputs/filter_numeric_input.rb +0 -10
  484. data/lib/active_admin/inputs/filter_select_input.rb +0 -49
  485. data/lib/active_admin/inputs/filter_string_input.rb +0 -24
  486. data/lib/active_admin/reloader.rb +0 -130
  487. data/lib/active_admin/resource_controller/actions.rb +0 -81
  488. data/lib/active_admin/sass/active_admin.scss +0 -3
  489. data/lib/active_admin/sass/css_loader.rb +0 -16
  490. data/lib/active_admin/sass/helpers.rb +0 -45
  491. data/lib/active_admin/view_helpers/assigns_with_indifferent_access_helper.rb +0 -7
  492. data/lib/active_admin/views/dashboard_section_renderer.rb +0 -19
  493. data/lib/active_admin/views/pages/dashboard.rb +0 -62
  494. data/lib/generators/active_admin/assets/templates/3.0/active_admin.js +0 -1
  495. data/lib/generators/active_admin/assets/templates/3.1/active_admin.js +0 -1
  496. data/lib/meta_search_ext.rb +0 -10
  497. data/spec/integration/memory_spec.rb +0 -29
  498. data/spec/integration/stylesheets_spec.rb +0 -41
  499. data/spec/javascripts/compiled/jquery.aa.checkbox-toggler-spec.js +0 -60
  500. data/spec/javascripts/compiled/jquery.aa.popover-spec.js +0 -106
  501. data/spec/javascripts/compiled/jquery.aa.table-checkbox-toggler-spec.js +0 -37
  502. data/spec/javascripts/helpers/vendor/jasmine-fixture-0.0.5.js +0 -108
  503. data/spec/javascripts/helpers/vendor/jasmine-jquery.js +0 -288
  504. data/spec/javascripts/helpers/vendor/sinon-1.2.0.js +0 -2915
  505. data/spec/javascripts/support/jquery-ui-1.8.16.custom.min.js +0 -34
  506. data/spec/javascripts/support/jquery.min.js +0 -4
  507. data/spec/spec_helper_without_rails.rb +0 -11
  508. data/spec/unit/generators/install_rails_3_1_spec.rb +0 -16
  509. data/spec/unit/rails_spec.rb +0 -43
  510. data/spec/unit/reloader_spec.rb +0 -124
  511. data/spec/unit/sass/helpers_spec.rb +0 -47
  512. data/tasks/js.rake +0 -32
@@ -1,4 +1,4 @@
1
- require 'spec_helper'
1
+ require 'rails_helper'
2
2
 
3
3
  describe ActiveAdmin::Filters::ResourceExtension do
4
4
 
@@ -7,81 +7,115 @@ describe ActiveAdmin::Filters::ResourceExtension do
7
7
  namespace.register(Post)
8
8
  end
9
9
 
10
+ it "should return a Hash" do
11
+ expect(resource.filters).to be_a Hash
12
+ end
13
+
10
14
  it "should return the defaults if no filters are set" do
11
- resource.filters.map{|f| f[:attribute].to_s }.sort.should == %w{
12
- author body category created_at published_at starred title updated_at
13
- }
15
+ expect(resource.filters.keys).to match_array([
16
+ :author, :body, :category, :created_at, :custom_searcher, :position, :published_at, :starred, :taggings, :title, :updated_at
17
+ ])
14
18
  end
15
19
 
16
20
  it "should not have defaults when filters are disabled on the resource" do
17
21
  resource.filters = false
18
- resource.filters.should be_empty
22
+ expect(resource.filters).to be_empty
19
23
  end
20
24
 
21
25
  it "should not have defaults when the filters are disabled on the namespace" do
22
26
  resource.namespace.filters = false
23
- resource.filters.should be_empty
27
+ expect(resource.filters).to be_empty
24
28
  end
25
29
 
26
30
  it "should not have defaults when the filters are disabled on the application" do
27
31
  resource.namespace.application.filters = false
28
- resource.filters.should be_empty
32
+ expect(resource.filters).to be_empty
29
33
  end
30
34
 
31
- context "filter removal" do
35
+ describe "removing a filter" do
32
36
  it "should work" do
33
- resource.filters.should include :attribute => :author
37
+ expect(resource.filters.keys).to include :author
34
38
  resource.remove_filter :author
35
- resource.filters.should_not include :attribute => :author
39
+ expect(resource.filters.keys).to_not include :author
40
+ end
41
+
42
+ it "should work as a string" do
43
+ expect(resource.filters.keys).to include :author
44
+ resource.remove_filter 'author'
45
+ expect(resource.filters.keys).to_not include :author
36
46
  end
37
47
 
38
48
  it "should be lazy" do
39
- resource.should_not_receive :default_filters # this hits the DB
49
+ expect(resource).to_not receive :default_filters # this hits the DB
40
50
  resource.remove_filter :author
41
51
  end
42
52
 
43
53
  it "should not prevent the default filters from being added" do
44
54
  resource.remove_filter :author
45
- resource.filters.should_not be_empty
55
+ expect(resource.filters).to_not be_empty
56
+ end
57
+
58
+ it "should raise an exception when filters are disabled" do
59
+ resource.filters = false
60
+ expect{ resource.remove_filter :author }.to raise_error ActiveAdmin::Filters::Disabled
61
+ end
62
+ end
63
+
64
+ describe "removing a multiple filters inline" do
65
+ it "should work" do
66
+ expect(resource.filters.keys).to include :author, :body
67
+ resource.remove_filter :author, :body
68
+ expect(resource.filters.keys).to_not include :author, :body
46
69
  end
47
70
  end
48
71
 
49
- context "adding a filter" do
72
+ describe "adding a filter" do
50
73
  it "should work" do
51
74
  resource.add_filter :title
52
- resource.filters.should == [{:attribute => :title}]
75
+ expect(resource.filters).to eq title: {}
76
+ end
77
+
78
+ it "should work as a string" do
79
+ resource.add_filter 'title'
80
+ expect(resource.filters).to eq title: {}
53
81
  end
54
82
 
55
83
  it "should work with specified options" do
56
- resource.add_filter :title, :as => :string
57
- resource.filters.should == [{:attribute => :title, :as => :string}]
84
+ resource.add_filter :title, as: :string
85
+ expect(resource.filters).to eq title: {as: :string}
86
+ end
87
+
88
+ it "should override an existing filter" do
89
+ resource.add_filter :title, one: :two
90
+ resource.add_filter :title, three: :four
91
+
92
+ expect(resource.filters).to eq title: {three: :four}
58
93
  end
59
94
 
60
95
  it "should preserve default filters" do
61
96
  resource.preserve_default_filters!
62
- resource.add_filter :count, :as => :string
63
- resource.filters.map { |f| f[:attribute].to_s }.sort.should == %w{
64
- author body category count created_at published_at starred title updated_at
65
- }
97
+ resource.add_filter :count, as: :string
98
+
99
+ expect(resource.filters.keys).to match_array([
100
+ :author, :body, :category, :count, :created_at, :custom_searcher, :position, :published_at, :starred, :taggings, :title, :updated_at
101
+ ])
66
102
  end
67
103
 
68
104
  it "should raise an exception when filters are disabled" do
69
105
  resource.filters = false
70
- expect {
71
- resource.add_filter :title
72
- }.should raise_error(RuntimeError)
106
+ expect{ resource.add_filter :title }.to raise_error ActiveAdmin::Filters::Disabled
73
107
  end
74
108
  end
75
109
 
76
110
  it "should reset filters" do
77
111
  resource.add_filter :title
78
- resource.filters.size.should == 1
112
+ expect(resource.filters.size).to eq 1
79
113
  resource.reset_filters!
80
- resource.filters.size.should > 1
114
+ expect(resource.filters.size).to be > 1
81
115
  end
82
116
 
83
117
  it "should add a sidebar section for the filters" do
84
- resource.sidebar_sections.first.name.should == :filters
118
+ expect(resource.sidebar_sections.first.name).to eq :filters
85
119
  end
86
120
 
87
121
  end
@@ -1,4 +1,5 @@
1
- require 'spec_helper'
1
+ require 'rails_helper'
2
+ require "rspec/mocks/standalone"
2
3
 
3
4
  describe ActiveAdmin::FormBuilder do
4
5
 
@@ -15,7 +16,7 @@ describe ActiveAdmin::FormBuilder do
15
16
  end
16
17
 
17
18
  def view.url_for(*args)
18
- if args.first == {:action => "index"}
19
+ if args.first == {action: "index"}
19
20
  posts_path
20
21
  else
21
22
  super
@@ -30,11 +31,45 @@ describe ActiveAdmin::FormBuilder do
30
31
  end
31
32
 
32
33
  def build_form(options = {}, form_object = Post.new, &block)
33
- options = {:url => helpers.posts_path}.merge(options)
34
+ options = {url: helpers.posts_path}.merge(options)
34
35
 
35
- render_arbre_component({:form_object => form_object, :form_options => options, :form_block => block}, helpers)do
36
- text_node active_admin_form_for(assigns[:form_object], assigns[:form_options], &assigns[:form_block])
36
+ form = render_arbre_component({form_object: form_object, form_options: options, form_block: block}, helpers) do
37
+ active_admin_form_for(assigns[:form_object], assigns[:form_options], &assigns[:form_block])
37
38
  end.to_s
39
+
40
+ Capybara.string(form)
41
+ end
42
+
43
+ context "in general" do
44
+ context "it without custom settings" do
45
+ let :body do
46
+ build_form do |f|
47
+ f.inputs do
48
+ f.input :title
49
+ f.input :body
50
+ end
51
+ end
52
+ end
53
+
54
+ it "should generate a fieldset with a inputs class" do
55
+ expect(body).to have_selector("fieldset.inputs")
56
+ end
57
+ end
58
+
59
+ context "it with custom settings" do
60
+ let :body do
61
+ build_form do |f|
62
+ f.inputs class: "custom_class" do
63
+ f.input :title
64
+ f.input :body
65
+ end
66
+ end
67
+ end
68
+
69
+ it "should generate a fieldset with a inputs and custom class" do
70
+ expect(body).to have_selector("fieldset.inputs.custom_class")
71
+ end
72
+ end
38
73
  end
39
74
 
40
75
  context "in general with actions" do
@@ -45,66 +80,64 @@ describe ActiveAdmin::FormBuilder do
45
80
  f.input :body
46
81
  end
47
82
  f.actions do
48
- f.action :submit, :label => "Submit Me"
49
- f.action :submit, :label => "Another Button"
83
+ f.action :submit, label: "Submit Me"
84
+ f.action :submit, label: "Another Button"
50
85
  end
51
86
  end
52
87
  end
53
88
 
54
89
  it "should generate a text input" do
55
- body.should have_tag("input", :attributes => { :type => "text",
56
- :name => "post[title]" })
90
+ expect(body).to have_selector("input[type=text][name='post[title]']")
57
91
  end
58
92
  it "should generate a textarea" do
59
- body.should have_tag("textarea", :attributes => { :name => "post[body]" })
93
+ expect(body).to have_selector("textarea[name='post[body]']")
60
94
  end
61
95
  it "should only generate the form once" do
62
- body.scan(/Title/).size.should == 1
96
+ expect(body).to have_selector("form", count: 1)
63
97
  end
64
98
  it "should generate actions" do
65
- body.should have_tag("input", :attributes => { :type => "submit",
66
- :value => "Submit Me" })
67
- body.should have_tag("input", :attributes => { :type => "submit",
68
- :value => "Another Button" })
99
+ expect(body).to have_selector("input[type=submit][value='Submit Me']")
100
+ expect(body).to have_selector("input[type=submit][value='Another Button']")
69
101
  end
70
102
  end
71
103
 
72
104
  context "when polymorphic relationship" do
73
105
  it "should raise error" do
74
- lambda {
106
+ expect {
75
107
  comment = ActiveAdmin::Comment.new
76
- build_form({:url => "admins/comments"}, comment) do |f|
108
+ build_form({url: "admins/comments"}, comment) do |f|
77
109
  f.inputs :resource
78
110
  end
79
- }.should raise_error(Formtastic::PolymorphicInputWithoutCollectionError)
111
+ }.to raise_error(Formtastic::PolymorphicInputWithoutCollectionError)
80
112
  end
81
113
  end
82
114
 
83
115
  describe "passing in options with actions" do
84
116
  let :body do
85
- build_form :html => { :multipart => true } do |f|
117
+ build_form html: { multipart: true } do |f|
86
118
  f.inputs :title
87
119
  f.actions
88
120
  end
89
121
  end
90
122
  it "should pass the options on to the form" do
91
- body.should have_tag("form", :attributes => { :enctype => "multipart/form-data" })
123
+ expect(body).to have_selector("form[enctype='multipart/form-data']")
92
124
  end
93
125
  end
94
126
 
95
- describe "passing in options with actions" do
96
- let :body do
97
- build_form :html => { :multipart => true } do |f|
98
- f.inputs :title
99
- f.actions
127
+ if Rails::VERSION::MAJOR > 3
128
+ context "file input present" do
129
+ let :body do
130
+ build_form do |f|
131
+ f.input :body, as: :file
132
+ end
133
+ end
134
+
135
+ it "adds multipart attribute automatically" do
136
+ expect(body).to have_selector("form[enctype='multipart/form-data']")
100
137
  end
101
- end
102
- it "should pass the options on to the form" do
103
- body.should have_tag("form", :attributes => { :enctype => "multipart/form-data" })
104
138
  end
105
139
  end
106
140
 
107
-
108
141
  context "with actions" do
109
142
  it "should generate the form once" do
110
143
  body = build_form do |f|
@@ -113,54 +146,66 @@ describe ActiveAdmin::FormBuilder do
113
146
  end
114
147
  f.actions
115
148
  end
116
- body.scan(/id="post_title"/).size.should == 1
149
+ expect(body).to have_selector("[id=post_title]", count: 1)
117
150
  end
118
151
  it "should generate one button and a cancel link" do
119
152
  body = build_form do |f|
120
153
  f.actions
121
154
  end
122
- body.scan(/type="submit"/).size.should == 1
123
- body.scan(/class="cancel"/).size.should == 1
155
+ expect(body).to have_selector("[type=submit]", count: 1)
156
+ expect(body).to have_selector("[class=cancel]", count: 1)
124
157
  end
125
158
  it "should generate multiple actions" do
126
159
  body = build_form do |f|
127
160
  f.actions do
128
- f.action :submit, :label => "Create & Continue"
129
- f.action :submit, :label => "Create & Edit"
161
+ f.action :submit, label: "Create & Continue"
162
+ f.action :submit, label: "Create & Edit"
130
163
  end
131
164
  end
132
- body.scan(/type="submit"/).size.should == 2
133
- body.scan(/class="cancel"/).size.should == 0
165
+ expect(body).to have_selector("[type=submit]", count: 2)
166
+ expect(body).to have_selector("[class=cancel]", count: 0)
134
167
  end
135
168
 
136
169
  end
137
170
 
138
- context "with actions" do
139
- it "should generate the form once" do
171
+ context "with Arbre inside" do
172
+ it "should render the Arbre in the expected place" do
140
173
  body = build_form do |f|
174
+ div do
175
+ h1 'Heading'
176
+ end
141
177
  f.inputs do
178
+ span 'Top note'
142
179
  f.input :title
180
+ span 'Bottom note'
143
181
  end
182
+ h3 'Footer'
144
183
  f.actions
145
184
  end
146
- body.scan(/id="post_title"/).size.should == 1
147
- end
148
- it "should generate one button and a cancel link" do
149
- body = build_form do |f|
150
- f.actions
151
- end
152
- body.scan(/type="submit"/).size.should == 1
153
- body.scan(/class="cancel"/).size.should == 1
185
+
186
+ expect(body).to have_selector("div > h1")
187
+ expect(body).to have_selector("h1", count: 1)
188
+ expect(body).to have_selector(".inputs > ol > span")
189
+ expect(body).to have_selector("span", count: 2)
154
190
  end
155
- it "should generate multiple actions" do
191
+ it "should allow a simplified syntax" do
156
192
  body = build_form do |f|
157
- f.actions do
158
- f.action :submit, :label => "Create & Continue"
159
- f.action :submit, :label => "Create & Edit"
193
+ div do
194
+ h1 'Heading'
195
+ end
196
+ inputs do
197
+ span 'Top note'
198
+ input :title
199
+ span 'Bottom note'
160
200
  end
201
+ h3 'Footer'
202
+ actions
161
203
  end
162
- body.scan(/type="submit"/).size.should == 2
163
- body.scan(/class="cancel"/).size.should == 0
204
+
205
+ expect(body).to have_selector("div > h1")
206
+ expect(body).to have_selector("h1", count: 1)
207
+ expect(body).to have_selector(".inputs > ol > span")
208
+ expect(body).to have_selector("span", count: 2)
164
209
  end
165
210
  end
166
211
 
@@ -171,11 +216,10 @@ describe ActiveAdmin::FormBuilder do
171
216
  end
172
217
  end
173
218
  it "should have a title input" do
174
- body.should have_tag("input", :attributes => { :type => "text",
175
- :name => "post[title]" })
219
+ expect(body).to have_selector("input[type=text][name='post[title]']")
176
220
  end
177
221
  it "should have a body textarea" do
178
- body.should have_tag("textarea", :attributes => { :name => "post[body]" })
222
+ expect(body).to have_selector("textarea[name='post[body]']")
179
223
  end
180
224
  end
181
225
 
@@ -186,7 +230,7 @@ describe ActiveAdmin::FormBuilder do
186
230
  f.input :title
187
231
  f.input :body
188
232
  end
189
- f.instance_eval do
233
+ f.form_builder.instance_eval do
190
234
  @object.author = User.new
191
235
  end
192
236
  f.semantic_fields_for :author do |author|
@@ -195,35 +239,35 @@ describe ActiveAdmin::FormBuilder do
195
239
  end
196
240
  end
197
241
  it "should generate a nested text input once" do
198
- body.scan("post_author_attributes_first_name_input").size.should == 1
242
+ expect(body).to have_selector("[id=post_author_attributes_first_name_input]", count: 1)
199
243
  end
200
244
  end
201
245
 
202
246
  context "with collection inputs" do
203
247
  before do
204
- User.create :first_name => "John", :last_name => "Doe"
205
- User.create :first_name => "Jane", :last_name => "Doe"
248
+ User.create first_name: "John", last_name: "Doe"
249
+ User.create first_name: "Jane", last_name: "Doe"
206
250
  end
207
251
 
208
252
  describe "as select" do
209
253
  let :body do
210
254
  build_form do |f|
211
- f.input :author
255
+ f.input :author, include_blank: false
212
256
  end
213
257
  end
214
258
  it "should create 2 options" do
215
- body.scan(/<option/).size.should == 3
259
+ expect(body).to have_selector("option", count: 2)
216
260
  end
217
261
  end
218
262
 
219
263
  describe "as radio buttons" do
220
264
  let :body do
221
265
  build_form do |f|
222
- f.input :author, :as => :radio
266
+ f.input :author, as: :radio
223
267
  end
224
268
  end
225
269
  it "should create 2 radio buttons" do
226
- body.scan(/type="radio"/).size.should == 2
270
+ expect(body).to have_selector("[type=radio]", count: 2)
227
271
  end
228
272
  end
229
273
 
@@ -236,196 +280,408 @@ describe ActiveAdmin::FormBuilder do
236
280
  f.input :title
237
281
  f.input :body
238
282
  end
239
- f.instance_eval do
283
+ f.form_builder.instance_eval do
240
284
  @object.author = User.new
241
285
  end
242
- f.inputs :name => 'Author', :for => :author do |author|
286
+ f.inputs name: 'Author', for: :author do |author|
243
287
  author.inputs :first_name, :last_name
244
288
  end
245
289
  end
246
290
  end
247
291
  it "should generate a nested text input once" do
248
- body.scan("post_author_attributes_first_name_input").size.should == 1
292
+ expect(body).to have_selector("[id=post_author_attributes_first_name_input]", count: 1)
293
+ expect(body).to have_selector("[id=post_author_attributes_last_name_input]", count: 1)
249
294
  end
250
- it "should add an author first name field" do
251
- body.should have_tag("input", :attributes => { :name => "post[author_attributes][first_name]"})
295
+ it "should add author first and last name fields" do
296
+ expect(body).to have_selector("input[name='post[author_attributes][first_name]']")
297
+ expect(body).to have_selector("input[name='post[author_attributes][last_name]']")
298
+ end
299
+ end
300
+
301
+ context "with two input fields 'for'" do
302
+ let :body do
303
+ build_form do |f|
304
+ f.inputs do
305
+ f.input :title
306
+ f.input :body
307
+ end
308
+ f.form_builder.instance_eval do
309
+ @object.author = User.new
310
+ end
311
+ f.inputs name: 'Author', for: :author do |author|
312
+ author.input :first_name
313
+ author.input :last_name
314
+ end
315
+ end
316
+ end
317
+ it "should generate a nested text input once" do
318
+ expect(body).to have_selector("[id=post_author_attributes_first_name_input]", count: 1)
319
+ expect(body).to have_selector("[id=post_author_attributes_last_name_input]", count: 1)
320
+ end
321
+ it "should add author first and last name fields" do
322
+ expect(body).to have_selector("input[name='post[author_attributes][first_name]']")
323
+ expect(body).to have_selector("input[name='post[author_attributes][last_name]']")
252
324
  end
253
325
  end
254
326
 
255
327
  context "with wrapper html" do
256
328
  it "should set a class" do
257
329
  body = build_form do |f|
258
- f.input :title, :wrapper_html => { :class => "important" }
330
+ f.input :title, wrapper_html: { class: "important" }
259
331
  end
260
- body.should have_tag("li", :attributes => {:class => "important string input optional stringish"})
332
+ expect(body).to have_selector("li[class='important string input optional stringish']")
333
+ end
334
+ end
335
+
336
+ context "with inputs twice" do
337
+ let :body do
338
+ build_form do |f|
339
+ f.inputs do
340
+ f.input :title
341
+ f.input :body
342
+ end
343
+ f.inputs do
344
+ f.input :author
345
+ f.input :published_at
346
+ end
347
+ end
348
+ end
349
+ it "should render four inputs" do
350
+ expect(body).to have_selector("input[name='post[title]']", count: 1)
351
+ expect(body).to have_selector("textarea[name='post[body]']", count: 1)
352
+ expect(body).to have_selector("select[name='post[author_id]']", count: 1)
353
+ expect(body).to have_selector("select[name='post[published_at(1i)]']", count: 1)
354
+ expect(body).to have_selector("select[name='post[published_at(2i)]']", count: 1)
355
+ expect(body).to have_selector("select[name='post[published_at(3i)]']", count: 1)
356
+ expect(body).to have_selector("select[name='post[published_at(4i)]']", count: 1)
261
357
  end
262
358
  end
263
359
 
264
360
  context "with has many inputs" do
265
361
  describe "with simple block" do
266
362
  let :body do
267
- build_form({:url => '/categories'}, Category.new) do |f|
363
+ build_form({url: '/categories'}, Category.new) do |f|
268
364
  f.object.posts.build
269
365
  f.has_many :posts do |p|
270
366
  p.input :title
367
+ p.input :body
271
368
  end
369
+ f.inputs
272
370
  end
273
371
  end
274
372
 
373
+ let(:valid_html_id) { /^[A-Za-z]+[\w\-\:\.]*$/ }
374
+
275
375
  it "should translate the association name in header" do
276
- begin
277
- I18n.backend.store_translations(:en, :activerecord => { :models => { :post => { :one => "Blog Post", :other => "Blog Posts" } } })
278
- body.should have_tag('h3', 'Blog Posts')
279
- ensure
280
- I18n.backend.reload!
376
+ with_translation activerecord: {models: {post: {one: 'Blog Post', other: 'Blog Posts'}}} do
377
+ expect(body).to have_selector("h3", text: "Blog Posts")
281
378
  end
282
379
  end
283
380
 
284
381
  it "should use model name when there is no translation for given model in header" do
285
- body.should have_tag('h3', 'Post')
382
+ expect(body).to have_selector("h3", text: "Post")
286
383
  end
287
384
 
288
385
  it "should translate the association name in has many new button" do
289
- begin
290
- I18n.backend.store_translations(:en, :activerecord => { :models => { :post => { :one => "Blog Post", :other => "Blog Posts" } } })
291
- body.should have_tag('a', 'Add New Blog Post')
292
- ensure
293
- I18n.backend.reload!
386
+ with_translation activerecord: {models: {post: {one: 'Blog Post', other: 'Blog Posts'}}} do
387
+ expect(body).to have_selector("a", text: "Add New Blog Post")
294
388
  end
295
389
  end
296
390
 
297
391
  it "should translate the attribute name" do
298
- begin
299
- I18n.backend.store_translations :en, :activerecord => { :attributes => { :post => { :title => 'A very nice title' } } }
300
- body.should have_tag 'label', 'A very nice title'
301
- ensure
302
- I18n.backend.reload!
392
+ with_translation activerecord: {attributes: {post: {title: 'A very nice title'}}} do
393
+ expect(body).to have_selector("label", text: "A very nice title")
303
394
  end
304
395
  end
305
396
 
306
397
  it "should use model name when there is no translation for given model in has many new button" do
307
- body.should have_tag('a', 'Add New Post')
398
+ expect(body).to have_selector("a", text: "Add New Post")
308
399
  end
309
400
 
310
401
  it "should render the nested form" do
311
- body.should have_tag("input", :attributes => {:name => "category[posts_attributes][0][title]"})
402
+ expect(body).to have_selector("input[name='category[posts_attributes][0][title]']")
403
+ expect(body).to have_selector("textarea[name='category[posts_attributes][0][body]']")
312
404
  end
313
405
 
314
406
  it "should add a link to remove new nested records" do
315
- Capybara.string(body).should have_css(".has_many > fieldset > ol > li.has_many_delete > a", :class => "button", :href => "#", :content => "Delete")
407
+ expect(body).to have_selector(".has_many_container > fieldset > ol > li > a.button.has_many_remove[href='#']", text: "Remove")
408
+ end
409
+
410
+ it "should add a link to add new nested records" do
411
+ expect(body).to have_selector(".has_many_container > a.button.has_many_add[href='#']", text: "Add New Post")
316
412
  end
317
413
 
318
- it "should include the nested record's class name in the js" do
319
- body.should have_tag("a", :attributes => { :onclick => /NEW_POST_RECORD/ })
414
+ it "should set an HTML-id valid placeholder" do
415
+ link = body.find('.has_many_container > a.button.has_many_add')
416
+ expect(link[:'data-placeholder']).to match valid_html_id
320
417
  end
321
418
 
322
- it "should add a link to add new nested records" do
323
- Capybara.string(body).should have_css(".has_many > fieldset > ol > li > a", :class => "button", :href => "#", :content => "Add New Post")
419
+ describe "with namespaced model" do
420
+ it "should set an HTML-id valid placeholder" do
421
+ allow(Post).to receive(:name).and_return "ActiveAdmin::Post"
422
+ link = body.find('.has_many_container > a.button.has_many_add')
423
+ expect(link[:'data-placeholder']).to match valid_html_id
424
+ end
324
425
  end
325
426
  end
326
427
 
327
428
  describe "with complex block" do
328
429
  let :body do
329
- build_form({:url => '/categories'}, Category.new) do |f|
430
+ build_form({url: '/categories'}, Category.new) do |f|
330
431
  f.object.posts.build
331
432
  f.has_many :posts do |p,i|
332
- p.input :title, :label => "Title #{i}"
433
+ p.input :title, label: "Title #{i}"
333
434
  end
334
435
  end
335
436
  end
336
437
 
337
438
  it "should accept a block with a second argument" do
338
- body.should have_tag("label", "Title 1")
439
+ expect(body).to have_selector("label", text: "Title 1")
339
440
  end
340
441
 
341
442
  it "should add a custom header" do
342
- body.should have_tag('h3', 'Post')
343
- end
443
+ expect(body).to have_selector("h3", text: "Post")
444
+ end
344
445
 
345
446
  end
346
447
 
347
448
  describe "without heading and new record link" do
348
449
  let :body do
349
- build_form({:url => '/categories'}, Category.new) do |f|
450
+ build_form({url: '/categories'}, Category.new) do |f|
350
451
  f.object.posts.build
351
- f.has_many :posts, :heading => false, :new_record => false do |p|
452
+ f.has_many :posts, heading: false, new_record: false do |p|
352
453
  p.input :title
353
454
  end
354
455
  end
355
456
  end
356
457
 
357
458
  it "should not add a header" do
358
- body.should_not have_tag('h3', 'Post')
359
- end
459
+ expect(body).not_to have_selector("h3", text: "Post")
460
+ end
360
461
 
361
462
  it "should not add link to new nested records" do
362
- body.should_not have_tag('a', 'Add New Post')
363
- end
463
+ expect(body).not_to have_selector("a", text: "Add New Post")
464
+ end
364
465
 
365
- end
466
+ it "should render the nested form" do
467
+ expect(body).to have_selector("input[name='category[posts_attributes][0][title]']")
468
+ end
469
+ end
366
470
 
367
471
  describe "with custom heading" do
368
472
  let :body do
369
- build_form({:url => '/categories'}, Category.new) do |f|
473
+ build_form({url: '/categories'}, Category.new) do |f|
370
474
  f.object.posts.build
371
- f.has_many :posts, :heading => "Test heading" do |p|
475
+ f.has_many :posts, heading: "Test heading" do |p|
372
476
  p.input :title
373
477
  end
374
478
  end
375
479
  end
376
480
 
377
481
  it "should add a custom header" do
378
- body.should have_tag('h3', 'Test heading')
379
- end
482
+ expect(body).to have_selector("h3", "Test heading")
483
+ end
484
+
485
+ end
486
+
487
+ describe "with custom new record link" do
488
+ let :body do
489
+ build_form({url: '/categories'}, Category.new) do |f|
490
+ f.object.posts.build
491
+ f.has_many :posts, new_record: 'My Custom New Post' do |p|
492
+ p.input :title
493
+ end
494
+ end
495
+ end
380
496
 
381
- end
497
+ it "should add a custom new record link" do
498
+ expect(body).to have_selector("a", text: "My Custom New Post")
499
+ end
500
+
501
+ end
382
502
 
383
503
  describe "with allow destroy" do
384
504
  context "with an existing post" do
385
505
  let :body do
386
- build_form({:url => '/categories'}, Category.new) do |f|
387
- f.object.posts.build.stub!(:new_record? => false)
388
- f.has_many :posts, :allow_destroy => true do |p|
506
+ build_form({url: '/categories'}, Category.new) do |f|
507
+ allow(f.object.posts.build).to receive(:new_record?).and_return(false)
508
+ f.has_many :posts, allow_destroy: true do |p|
389
509
  p.input :title
390
510
  end
391
511
  end
392
512
  end
393
513
 
394
514
  it "should include a boolean field for _destroy" do
395
- body.should have_tag("input", :attributes => {:name => "category[posts_attributes][0][_destroy]"})
515
+ expect(body).to have_selector("input[name='category[posts_attributes][0][_destroy]']")
396
516
  end
397
517
 
398
518
  it "should have a check box with 'Remove' as its label" do
399
- body.should have_tag("label", :attributes => {:for => "category_posts_attributes_0__destroy"}, :content => "Remove")
519
+ expect(body).to have_selector("label[for=category_posts_attributes_0__destroy]", text: "Delete")
400
520
  end
401
521
 
402
- it "should wrap the destroy field in an li with class 'has_many_remove'" do
403
- Capybara.string(body).should have_css(".has_many > fieldset > ol > li.has_many_remove > input")
522
+ it "should wrap the destroy field in an li with class 'has_many_delete'" do
523
+ expect(body).to have_selector(".has_many_container > fieldset > ol > li.has_many_delete > input", count: 1)
404
524
  end
405
525
  end
406
526
 
407
527
  context "with a new post" do
408
528
  let :body do
409
- build_form({:url => '/categories'}, Category.new) do |f|
529
+ build_form({url: '/categories'}, Category.new) do |f|
410
530
  f.object.posts.build
411
- f.has_many :posts, :allow_destroy => true do |p|
531
+ f.has_many :posts, allow_destroy: true do |p|
412
532
  p.input :title
413
533
  end
414
534
  end
415
535
  end
416
536
 
417
537
  it "should not have a boolean field for _destroy" do
418
- body.should_not have_tag("input", :attributes => {:name => "category[posts_attributes][0][_destroy]"})
538
+ expect(body).not_to have_selector("input[name='category[posts_attributes][0][_destroy]']")
419
539
  end
420
540
 
421
541
  it "should not have a check box with 'Remove' as its label" do
422
- body.should_not have_tag("label", :attributes => {:for => "category_posts_attributes_0__destroy"}, :content => "Remove")
542
+ expect(body).not_to have_selector("label[for=category_posts_attributes_0__destroy]", text: "Remove")
543
+ end
544
+ end
545
+ end
546
+
547
+ describe "sortable" do
548
+ # TODO: it doesn't make any sense to use your foreign key as something that's sortable (and therefore editable)
549
+ context "with a new post" do
550
+ let :body do
551
+ build_form({url: '/categories'}, Category.new) do |f|
552
+ f.object.posts.build
553
+ f.has_many :posts, sortable: :position do |p|
554
+ p.input :title
555
+ end
556
+ end
557
+ end
558
+
559
+ it "shows the nested fields for unsaved records" do
560
+ expect(body).to have_selector("fieldset.inputs.has_many_fields")
561
+ end
562
+
563
+ end
564
+
565
+ context "with post returning nil for the sortable attribute" do
566
+ let :body do
567
+ build_form({url: '/categories'}, Category.new) do |f|
568
+ f.object.posts.build position: 3
569
+ f.object.posts.build
570
+ f.has_many :posts, sortable: :position do |p|
571
+ p.input :title
572
+ end
573
+ end
574
+ end
575
+
576
+ it "shows the nested fields for unsaved records" do
577
+ expect(body).to have_selector("fieldset.inputs.has_many_fields")
578
+ end
579
+
580
+ end
581
+
582
+ context "with existing and new posts" do
583
+ let! :category do
584
+ Category.create name: 'Name'
585
+ end
586
+ let! :post do
587
+ category.posts.create
588
+ end
589
+ let :body do
590
+ build_form({url: '/categories'}, category) do |f|
591
+ f.object.posts.build
592
+ f.has_many :posts, sortable: :position do |p|
593
+ p.input :title
594
+ end
595
+ end
596
+ end
597
+
598
+ it "shows the nested fields for saved and unsaved records" do
599
+ expect(body).to have_selector("fieldset.inputs.has_many_fields")
600
+ end
601
+ end
602
+
603
+ context "without sortable_start set" do
604
+ let :body do
605
+ build_form({url: '/categories'}, Category.new) do |f|
606
+ f.object.posts.build
607
+ f.has_many :posts, sortable: :position do |p|
608
+ p.input :title
609
+ end
610
+ end
611
+ end
612
+
613
+ it "defaults to 0" do
614
+ expect(body).to have_selector("div.has_many_container[data-sortable-start='0']")
615
+ end
616
+ end
617
+
618
+ context "with sortable_start set" do
619
+ let :body do
620
+ build_form({url: '/categories'}, Category.new) do |f|
621
+ f.object.posts.build
622
+ f.has_many :posts, sortable: :position, sortable_start: 15 do |p|
623
+ p.input :title
624
+ end
625
+ end
626
+ end
627
+
628
+ it "sets the data attribute" do
629
+ expect(body).to have_selector("div.has_many_container[data-sortable-start='15']")
423
630
  end
424
631
  end
425
632
  end
426
633
 
427
- pending "should render the block if it returns nil" do
428
- body = build_form({:url => '/categories'}, Category.new) do |f|
634
+ describe "with nesting" do
635
+ context "in an inputs block" do
636
+ let :body do
637
+ build_form({url: '/categories'}, Category.new) do |f|
638
+ f.inputs "Field Wrapper" do
639
+ f.object.posts.build
640
+ f.has_many :posts do |p|
641
+ p.input :title
642
+ end
643
+ end
644
+ end
645
+ end
646
+
647
+ it "should wrap the has_many fieldset in an li" do
648
+ expect(body).to have_selector("ol > li.has_many_container")
649
+ end
650
+
651
+ it "should have a direct fieldset child" do
652
+ expect(body).to have_selector("li.has_many_container > fieldset")
653
+ end
654
+
655
+ it "should not contain invalid li children" do
656
+ expect(body).not_to have_selector("div.has_many_container > li")
657
+ end
658
+ end
659
+
660
+ context "in another has_many block" do
661
+ let :body do
662
+ build_form({url: '/categories'}, Category.new) do |f|
663
+ f.object.posts.build
664
+ f.has_many :posts do |p|
665
+ p.object.taggings.build
666
+ p.has_many :taggings do |t|
667
+ t.input :tag
668
+ end
669
+ end
670
+ end
671
+ end
672
+
673
+ it "should wrap the inner has_many fieldset in an ol > li" do
674
+ expect(body).to have_selector(".has_many_container ol > li.has_many_container > fieldset")
675
+ end
676
+
677
+ it "should not contain invalid li children" do
678
+ expect(body).not_to have_selector(".has_many_container div.has_many_container > li")
679
+ end
680
+ end
681
+ end
682
+
683
+ it "should render the block if it returns nil" do
684
+ body = build_form({url: '/categories'}, Category.new) do |f|
429
685
  f.object.posts.build
430
686
  f.has_many :posts do |p|
431
687
  p.input :title
@@ -433,22 +689,22 @@ describe ActiveAdmin::FormBuilder do
433
689
  end
434
690
  end
435
691
 
436
- body.should have_tag("input", :attributes => {:name => "category[posts_attributes][0][title]"})
692
+ expect(body).to have_selector("input[name='category[posts_attributes][0][title]']")
437
693
  end
438
694
  end
439
695
 
440
696
  { # Testing that the same input can be used multiple times
441
- "f.input :title, :as => :string" => /id="post_title"/,
442
- "f.input :title, :as => :text" => /id="post_title"/,
443
- "f.input :created_at, :as => :time_select" => /id="post_created_at_2i"/,
444
- "f.input :created_at, :as => :datetime_select" => /id="post_created_at_2i"/,
445
- "f.input :created_at, :as => :date_select" => /id="post_created_at_2i"/,
697
+ "f.input :title, as: :string" => "post_title",
698
+ "f.input :title, as: :text" => "post_title",
699
+ "f.input :created_at, as: :time_select" => "post_created_at_2i",
700
+ "f.input :created_at, as: :datetime_select" => "post_created_at_2i",
701
+ "f.input :created_at, as: :date_select" => "post_created_at_2i",
446
702
  # Testing that return values don't screw up the form
447
- "f.input :title; nil" => /id="post_title"/,
448
- "f.input :title; []" => /id="post_title"/,
449
- "[:title].each{ |r| f.input r }" => /id="post_title"/,
450
- "[:title].map { |r| f.input r }" => /id="post_title"/,
451
- }.each do |source, regex|
703
+ "f.input :title; nil" => "post_title",
704
+ "f.input :title; []" => "post_title",
705
+ "[:title].each{ |r| f.input r }" => "post_title",
706
+ "[:title].map { |r| f.input r }" => "post_title",
707
+ }.each do |source, selector|
452
708
  it "should properly buffer `#{source}`" do
453
709
  body = build_form do |f|
454
710
  f.inputs do
@@ -456,23 +712,41 @@ describe ActiveAdmin::FormBuilder do
456
712
  eval source
457
713
  end
458
714
  end
459
- body.scan(regex).size.should == 2
715
+ expect(body).to have_selector("[id=#{selector}]", count: 2)
460
716
  end
461
717
  end
462
718
 
463
719
  describe "datepicker input" do
464
- let :body do
465
- build_form do |f|
466
- f.inputs do
467
- f.input :created_at, :as => :datepicker
720
+ context 'with default options' do
721
+ let :body do
722
+ build_form do |f|
723
+ f.inputs do
724
+ f.input :created_at, as: :datepicker
725
+ end
468
726
  end
469
727
  end
728
+ it "should generate a text input with the class of datepicker" do
729
+ expect(body).to have_selector("input.datepicker[type=text][name='post[created_at]']")
730
+ end
470
731
  end
471
- it "should generate a text input with the class of datepicker" do
472
- body.should have_tag("input", :attributes => { :type => "text",
473
- :class => "datepicker",
474
- :name => "post[created_at]" })
732
+
733
+ context 'with date range options' do
734
+ let :body do
735
+ build_form do |f|
736
+ f.inputs do
737
+ f.input :created_at, as: :datepicker,
738
+ datepicker_options: {
739
+ min_date: Date.new(2013, 10, 18),
740
+ max_date: "2013-12-31" }
741
+ end
742
+ end
743
+ end
744
+
745
+ it 'should generate a datepicker text input with data min and max dates' do
746
+ selector = "input.datepicker[type=text][name='post[created_at]']"
747
+ expect(body).to have_selector(selector)
748
+ expect(body.find(selector)["data-datepicker-options"]).to eq({ minDate: '2013-10-18', maxDate: '2013-12-31' }.to_json)
749
+ end
475
750
  end
476
751
  end
477
-
478
752
  end