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,4 +1,4 @@
1
- require 'spec_helper'
1
+ require 'rails_helper'
2
2
 
3
3
  describe ActiveAdmin::Filters::ResourceExtension do
4
4
 
@@ -7,48 +7,52 @@ 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.keys.sort.should == [
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
35
  describe "removing a filter" do
32
36
  it "should work" do
33
- resource.filters.keys.should include :author
37
+ expect(resource.filters.keys).to include :author
34
38
  resource.remove_filter :author
35
- resource.filters.keys.should_not include :author
39
+ expect(resource.filters.keys).to_not include :author
36
40
  end
37
41
 
38
42
  it "should work as a string" do
39
- resource.filters.keys.should include :author
43
+ expect(resource.filters.keys).to include :author
40
44
  resource.remove_filter 'author'
41
- resource.filters.keys.should_not include :author
45
+ expect(resource.filters.keys).to_not include :author
42
46
  end
43
47
 
44
48
  it "should be lazy" do
45
- resource.should_not_receive :default_filters # this hits the DB
49
+ expect(resource).to_not receive :default_filters # this hits the DB
46
50
  resource.remove_filter :author
47
51
  end
48
52
 
49
53
  it "should not prevent the default filters from being added" do
50
54
  resource.remove_filter :author
51
- resource.filters.should_not be_empty
55
+ expect(resource.filters).to_not be_empty
52
56
  end
53
57
 
54
58
  it "should raise an exception when filters are disabled" do
@@ -57,46 +61,44 @@ describe ActiveAdmin::Filters::ResourceExtension do
57
61
  end
58
62
  end
59
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
69
+ end
70
+ end
71
+
60
72
  describe "adding a filter" do
61
73
  it "should work" do
62
74
  resource.add_filter :title
63
- resource.filters.should eq title: {}
75
+ expect(resource.filters).to eq title: {}
64
76
  end
65
77
 
66
78
  it "should work as a string" do
67
79
  resource.add_filter 'title'
68
- resource.filters.should eq title: {}
80
+ expect(resource.filters).to eq title: {}
69
81
  end
70
82
 
71
83
  it "should work with specified options" do
72
84
  resource.add_filter :title, as: :string
73
- resource.filters.should eq title: {as: :string}
85
+ expect(resource.filters).to eq title: {as: :string}
74
86
  end
75
87
 
76
88
  it "should override an existing filter" do
77
89
  resource.add_filter :title, one: :two
78
90
  resource.add_filter :title, three: :four
79
91
 
80
- resource.filters.should eq title: {three: :four}
81
- end
82
-
83
- it "should keep specified options" do
84
- resource.add_filter :title, one: :two
85
-
86
- resource.filters.each do |attribute, opts|
87
- opts.delete(:one)
88
- end
89
-
90
- resource.filters.should eq title: {one: :two}
92
+ expect(resource.filters).to eq title: {three: :four}
91
93
  end
92
94
 
93
95
  it "should preserve default filters" do
94
96
  resource.preserve_default_filters!
95
97
  resource.add_filter :count, as: :string
96
98
 
97
- resource.filters.keys.sort.should == [
98
- :author, :body, :category, :count, :created_at, :published_at, :starred, :title, :updated_at
99
- ]
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
+ ])
100
102
  end
101
103
 
102
104
  it "should raise an exception when filters are disabled" do
@@ -107,13 +109,13 @@ describe ActiveAdmin::Filters::ResourceExtension do
107
109
 
108
110
  it "should reset filters" do
109
111
  resource.add_filter :title
110
- resource.filters.size.should == 1
112
+ expect(resource.filters.size).to eq 1
111
113
  resource.reset_filters!
112
- resource.filters.size.should > 1
114
+ expect(resource.filters.size).to be > 1
113
115
  end
114
116
 
115
117
  it "should add a sidebar section for the filters" do
116
- resource.sidebar_sections.first.name.should == :filters
118
+ expect(resource.sidebar_sections.first.name).to eq :filters
117
119
  end
118
120
 
119
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,27 +80,24 @@ 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
 
@@ -73,7 +105,7 @@ describe ActiveAdmin::FormBuilder do
73
105
  it "should raise error" do
74
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
111
  }.to raise_error(Formtastic::PolymorphicInputWithoutCollectionError)
@@ -82,29 +114,30 @@ describe ActiveAdmin::FormBuilder do
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,159 +280,222 @@ 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" }
331
+ end
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
259
347
  end
260
- body.should have_tag("li", :attributes => {:class => "important string input optional stringish"})
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 > a', href: '#',
316
- content: 'Remove', class: 'button has_many_remove', data: {placeholder: 'NEW_POST_RECORD'}
407
+ expect(body).to have_selector(".has_many_container > fieldset > ol > li > a.button.has_many_remove[href='#']", text: "Remove")
317
408
  end
318
409
 
319
410
  it "should add a link to add new nested records" do
320
- Capybara.string(body).should have_css(".has_many > fieldset > ol > li > a", :class => "button", :href => "#", :content => "Add New Post")
411
+ expect(body).to have_selector(".has_many_container > a.button.has_many_add[href='#']", text: "Add New Post")
412
+ end
413
+
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
417
+ end
418
+
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
321
425
  end
322
426
  end
323
427
 
324
428
  describe "with complex block" do
325
429
  let :body do
326
- build_form({:url => '/categories'}, Category.new) do |f|
430
+ build_form({url: '/categories'}, Category.new) do |f|
327
431
  f.object.posts.build
328
432
  f.has_many :posts do |p,i|
329
- p.input :title, :label => "Title #{i}"
433
+ p.input :title, label: "Title #{i}"
330
434
  end
331
435
  end
332
436
  end
333
437
 
334
438
  it "should accept a block with a second argument" do
335
- body.should have_tag("label", "Title 1")
439
+ expect(body).to have_selector("label", text: "Title 1")
336
440
  end
337
441
 
338
442
  it "should add a custom header" do
339
- body.should have_tag('h3', 'Post')
443
+ expect(body).to have_selector("h3", text: "Post")
340
444
  end
341
445
 
342
446
  end
343
447
 
344
448
  describe "without heading and new record link" do
345
449
  let :body do
346
- build_form({:url => '/categories'}, Category.new) do |f|
450
+ build_form({url: '/categories'}, Category.new) do |f|
347
451
  f.object.posts.build
348
- f.has_many :posts, :heading => false, :new_record => false do |p|
452
+ f.has_many :posts, heading: false, new_record: false do |p|
349
453
  p.input :title
350
454
  end
351
455
  end
352
456
  end
353
457
 
354
458
  it "should not add a header" do
355
- body.should_not have_tag('h3', 'Post')
459
+ expect(body).not_to have_selector("h3", text: "Post")
356
460
  end
357
461
 
358
462
  it "should not add link to new nested records" do
359
- body.should_not have_tag('a', 'Add New Post')
463
+ expect(body).not_to have_selector("a", text: "Add New Post")
360
464
  end
361
465
 
466
+ it "should render the nested form" do
467
+ expect(body).to have_selector("input[name='category[posts_attributes][0][title]']")
468
+ end
362
469
  end
363
470
 
364
471
  describe "with custom heading" do
365
472
  let :body do
366
- build_form({:url => '/categories'}, Category.new) do |f|
473
+ build_form({url: '/categories'}, Category.new) do |f|
367
474
  f.object.posts.build
368
- f.has_many :posts, :heading => "Test heading" do |p|
475
+ f.has_many :posts, heading: "Test heading" do |p|
369
476
  p.input :title
370
477
  end
371
478
  end
372
479
  end
373
480
 
374
481
  it "should add a custom header" do
375
- body.should have_tag('h3', 'Test heading')
482
+ expect(body).to have_selector("h3", "Test heading")
376
483
  end
377
484
 
378
485
  end
379
486
 
380
487
  describe "with custom new record link" do
381
488
  let :body do
382
- build_form({:url => '/categories'}, Category.new) do |f|
489
+ build_form({url: '/categories'}, Category.new) do |f|
383
490
  f.object.posts.build
384
- f.has_many :posts, :new_record => 'My Custom New Post' do |p|
491
+ f.has_many :posts, new_record: 'My Custom New Post' do |p|
385
492
  p.input :title
386
493
  end
387
494
  end
388
495
  end
389
496
 
390
497
  it "should add a custom new record link" do
391
- body.should have_tag('a', 'My Custom New Post')
498
+ expect(body).to have_selector("a", text: "My Custom New Post")
392
499
  end
393
500
 
394
501
  end
@@ -396,49 +503,185 @@ describe ActiveAdmin::FormBuilder do
396
503
  describe "with allow destroy" do
397
504
  context "with an existing post" do
398
505
  let :body do
399
- build_form({:url => '/categories'}, Category.new) do |f|
400
- f.object.posts.build.stub(:new_record? => false)
401
- 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|
402
509
  p.input :title
403
510
  end
404
511
  end
405
512
  end
406
513
 
407
514
  it "should include a boolean field for _destroy" do
408
- 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]']")
409
516
  end
410
517
 
411
518
  it "should have a check box with 'Remove' as its label" do
412
- body.should have_tag("label", :attributes => {:for => "category_posts_attributes_0__destroy"}, :content => "Delete")
519
+ expect(body).to have_selector("label[for=category_posts_attributes_0__destroy]", text: "Delete")
413
520
  end
414
521
 
415
522
  it "should wrap the destroy field in an li with class 'has_many_delete'" do
416
- Capybara.string(body).should have_css(".has_many > fieldset > ol > li.has_many_delete > input")
523
+ expect(body).to have_selector(".has_many_container > fieldset > ol > li.has_many_delete > input", count: 1)
417
524
  end
418
525
  end
419
526
 
420
527
  context "with a new post" do
421
528
  let :body do
422
- build_form({:url => '/categories'}, Category.new) do |f|
529
+ build_form({url: '/categories'}, Category.new) do |f|
423
530
  f.object.posts.build
424
- f.has_many :posts, :allow_destroy => true do |p|
531
+ f.has_many :posts, allow_destroy: true do |p|
425
532
  p.input :title
426
533
  end
427
534
  end
428
535
  end
429
536
 
430
537
  it "should not have a boolean field for _destroy" do
431
- 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]']")
432
539
  end
433
540
 
434
541
  it "should not have a check box with 'Remove' as its label" do
435
- 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")
436
543
  end
437
544
  end
438
545
  end
439
546
 
440
- pending "should render the block if it returns nil" do
441
- body = build_form({:url => '/categories'}, Category.new) do |f|
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']")
630
+ end
631
+ end
632
+ end
633
+
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|
442
685
  f.object.posts.build
443
686
  f.has_many :posts do |p|
444
687
  p.input :title
@@ -446,22 +689,22 @@ describe ActiveAdmin::FormBuilder do
446
689
  end
447
690
  end
448
691
 
449
- 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]']")
450
693
  end
451
694
  end
452
695
 
453
696
  { # Testing that the same input can be used multiple times
454
- "f.input :title, :as => :string" => /id="post_title"/,
455
- "f.input :title, :as => :text" => /id="post_title"/,
456
- "f.input :created_at, :as => :time_select" => /id="post_created_at_2i"/,
457
- "f.input :created_at, :as => :datetime_select" => /id="post_created_at_2i"/,
458
- "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",
459
702
  # Testing that return values don't screw up the form
460
- "f.input :title; nil" => /id="post_title"/,
461
- "f.input :title; []" => /id="post_title"/,
462
- "[:title].each{ |r| f.input r }" => /id="post_title"/,
463
- "[:title].map { |r| f.input r }" => /id="post_title"/,
464
- }.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|
465
708
  it "should properly buffer `#{source}`" do
466
709
  body = build_form do |f|
467
710
  f.inputs do
@@ -469,7 +712,7 @@ describe ActiveAdmin::FormBuilder do
469
712
  eval source
470
713
  end
471
714
  end
472
- body.scan(regex).size.should == 2
715
+ expect(body).to have_selector("[id=#{selector}]", count: 2)
473
716
  end
474
717
  end
475
718
 
@@ -478,14 +721,12 @@ describe ActiveAdmin::FormBuilder do
478
721
  let :body do
479
722
  build_form do |f|
480
723
  f.inputs do
481
- f.input :created_at, :as => :datepicker
724
+ f.input :created_at, as: :datepicker
482
725
  end
483
726
  end
484
727
  end
485
728
  it "should generate a text input with the class of datepicker" do
486
- body.should have_tag("input", :attributes => { :type => "text",
487
- :class => "datepicker",
488
- :name => "post[created_at]" })
729
+ expect(body).to have_selector("input.datepicker[type=text][name='post[created_at]']")
489
730
  end
490
731
  end
491
732
 
@@ -493,22 +734,19 @@ describe ActiveAdmin::FormBuilder do
493
734
  let :body do
494
735
  build_form do |f|
495
736
  f.inputs do
496
- f.input :created_at, :as => :datepicker,
497
- :datepicker_options => {
498
- :min_date => Date.new(2013, 10, 18),
499
- :max_date => "2013-12-31" }
737
+ f.input :created_at, as: :datepicker,
738
+ datepicker_options: {
739
+ min_date: Date.new(2013, 10, 18),
740
+ max_date: "2013-12-31" }
500
741
  end
501
742
  end
502
- it 'should generate a datepicker text input with data min and max dates' do
503
- body.should have_tag("input", :attributes => { :type => "text",
504
- :class => "datepicker",
505
- :name => "post[created_at]",
506
- :data => { :datepicker_options => {
507
- :minDate => "2013-10-18",
508
- :maxDate => "2013-12-31" }.to_json }})
509
- 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)
510
749
  end
511
750
  end
512
751
  end
513
-
514
752
  end