releaf-core 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +24 -0
  3. data/app/assets/fonts/releaf/RobotoRegular_normal_400.ttf +0 -0
  4. data/app/assets/fonts/releaf/RobotoRegular_normal_400.woff +0 -0
  5. data/app/assets/fonts/releaf/RobotoRegular_normal_400.woff2 +0 -0
  6. data/app/assets/images/releaf/icons/apple-touch-icon-114x114-precomposed.png +0 -0
  7. data/app/assets/images/releaf/icons/apple-touch-icon-152x152-precomposed.png +0 -0
  8. data/app/assets/images/releaf/icons/apple-touch-icon-72x72-precomposed.png +0 -0
  9. data/app/assets/images/releaf/icons/favicon.ico +0 -0
  10. data/app/assets/images/releaf/icons/favicon.png +0 -0
  11. data/app/assets/images/releaf/icons/msapplication-tile-144x144.png +0 -0
  12. data/app/assets/images/releaf/logo-login.png +0 -0
  13. data/app/assets/images/releaf/logo.png +0 -0
  14. data/app/assets/javascripts/ckeditor/plugins/mediaembed/icons/hidpi/mediaembed.png +0 -0
  15. data/app/assets/javascripts/ckeditor/plugins/mediaembed/icons/mediaembed.png +0 -0
  16. data/app/assets/javascripts/ckeditor/plugins/mediaembed/lang/en.js +12 -0
  17. data/app/assets/javascripts/ckeditor/plugins/mediaembed/lang/es.js +12 -0
  18. data/app/assets/javascripts/ckeditor/plugins/mediaembed/plugin.js +63 -0
  19. data/app/assets/javascripts/releaf/3rd_party/jquery-ui-timepicker-addon.js +1882 -0
  20. data/app/assets/javascripts/releaf/3rd_party/jquery.magnific-popup.min.js +4 -0
  21. data/app/assets/javascripts/releaf/application.js +13 -0
  22. data/app/assets/javascripts/releaf/include/ajax.js +66 -0
  23. data/app/assets/javascripts/releaf/include/ajaxbox.js +179 -0
  24. data/app/assets/javascripts/releaf/include/dialogs.js +13 -0
  25. data/app/assets/javascripts/releaf/include/field.type_associated_set.js +32 -0
  26. data/app/assets/javascripts/releaf/include/field.type_date_or_datetime_or_time.js +73 -0
  27. data/app/assets/javascripts/releaf/include/field.type_richtext.js +188 -0
  28. data/app/assets/javascripts/releaf/include/loader.js +45 -0
  29. data/app/assets/javascripts/releaf/include/localization.js +213 -0
  30. data/app/assets/javascripts/releaf/include/nested_fields.js +295 -0
  31. data/app/assets/javascripts/releaf/include/notifications.js +267 -0
  32. data/app/assets/javascripts/releaf/include/pagination.js +19 -0
  33. data/app/assets/javascripts/releaf/include/profile_settings.js +28 -0
  34. data/app/assets/javascripts/releaf/include/remote_validator.js +437 -0
  35. data/app/assets/javascripts/releaf/include/search.js +140 -0
  36. data/app/assets/javascripts/releaf/include/sidebar.js +149 -0
  37. data/app/assets/javascripts/releaf/include/sortable.js +69 -0
  38. data/app/assets/javascripts/releaf/include/toolbox.js +221 -0
  39. data/app/assets/javascripts/releaf/include/url_builder.js +193 -0
  40. data/app/assets/stylesheets/releaf/application.scss +9 -0
  41. data/app/assets/stylesheets/releaf/environment/extras.scss +11 -0
  42. data/app/assets/stylesheets/releaf/environment/functions/units.scss +12 -0
  43. data/app/assets/stylesheets/releaf/environment/functions.scss +1 -0
  44. data/app/assets/stylesheets/releaf/environment/mixins/blocks.scss +133 -0
  45. data/app/assets/stylesheets/releaf/environment/mixins/elements.scss +64 -0
  46. data/app/assets/stylesheets/releaf/environment/mixins/text.scss +61 -0
  47. data/app/assets/stylesheets/releaf/environment/mixins.scss +3 -0
  48. data/app/assets/stylesheets/releaf/environment/variables/colors.scss +93 -0
  49. data/app/assets/stylesheets/releaf/environment/variables/dimensions.scss +0 -0
  50. data/app/assets/stylesheets/releaf/environment/variables/magnific-popup.scss +6 -0
  51. data/app/assets/stylesheets/releaf/environment/variables.scss +5 -0
  52. data/app/assets/stylesheets/releaf/environment.scss +4 -0
  53. data/app/assets/stylesheets/releaf/layout/base.scss +32 -0
  54. data/app/assets/stylesheets/releaf/layout/breadcrumbs.scss +47 -0
  55. data/app/assets/stylesheets/releaf/layout/buttons.scss +107 -0
  56. data/app/assets/stylesheets/releaf/layout/deprecated.scss +29 -0
  57. data/app/assets/stylesheets/releaf/layout/dialogs.scss +138 -0
  58. data/app/assets/stylesheets/releaf/layout/errors.scss +28 -0
  59. data/app/assets/stylesheets/releaf/layout/extras.scss +10 -0
  60. data/app/assets/stylesheets/releaf/layout/fields.scss +305 -0
  61. data/app/assets/stylesheets/releaf/layout/fonts.scss +16 -0
  62. data/app/assets/stylesheets/releaf/layout/footer.scss +80 -0
  63. data/app/assets/stylesheets/releaf/layout/forms.scss +23 -0
  64. data/app/assets/stylesheets/releaf/layout/header.scss +55 -0
  65. data/app/assets/stylesheets/releaf/layout/icons.scss +4 -0
  66. data/app/assets/stylesheets/releaf/layout/images.scss +4 -0
  67. data/app/assets/stylesheets/releaf/layout/links.scss +7 -0
  68. data/app/assets/stylesheets/releaf/layout/localization.scss +79 -0
  69. data/app/assets/stylesheets/releaf/layout/main.scss +43 -0
  70. data/app/assets/stylesheets/releaf/layout/notifications.scss +67 -0
  71. data/app/assets/stylesheets/releaf/layout/pagination.scss +18 -0
  72. data/app/assets/stylesheets/releaf/layout/search.scss +70 -0
  73. data/app/assets/stylesheets/releaf/layout/sections.scss +138 -0
  74. data/app/assets/stylesheets/releaf/layout/sidebar.scss +306 -0
  75. data/app/assets/stylesheets/releaf/layout/tables.scss +99 -0
  76. data/app/assets/stylesheets/releaf/layout/text.scss +31 -0
  77. data/app/assets/stylesheets/releaf/layout/toolboxes.scss +69 -0
  78. data/app/assets/stylesheets/releaf/layout.scss +35 -0
  79. data/app/assets/stylesheets/releaf/vendor/magnific-popup/main.scss +596 -0
  80. data/app/assets/stylesheets/releaf/vendor/magnific-popup/settings.scss +45 -0
  81. data/app/builders/releaf/builders/association_reflector.rb +58 -0
  82. data/app/builders/releaf/builders/base.rb +80 -0
  83. data/app/builders/releaf/builders/collection.rb +8 -0
  84. data/app/builders/releaf/builders/confirm_destroy_dialog_builder.rb +25 -0
  85. data/app/builders/releaf/builders/confirm_dialog_builder.rb +54 -0
  86. data/app/builders/releaf/builders/edit_builder.rb +66 -0
  87. data/app/builders/releaf/builders/form_builder.rb +594 -0
  88. data/app/builders/releaf/builders/index_builder.rb +118 -0
  89. data/app/builders/releaf/builders/orderer.rb +5 -0
  90. data/app/builders/releaf/builders/page/header_builder.rb +70 -0
  91. data/app/builders/releaf/builders/page/layout_builder.rb +155 -0
  92. data/app/builders/releaf/builders/page/menu_builder.rb +140 -0
  93. data/app/builders/releaf/builders/pagination_builder.rb +107 -0
  94. data/app/builders/releaf/builders/refused_destroy_dialog_builder.rb +68 -0
  95. data/app/builders/releaf/builders/resource.rb +9 -0
  96. data/app/builders/releaf/builders/resource_dialog.rb +8 -0
  97. data/app/builders/releaf/builders/resource_view.rb +54 -0
  98. data/app/builders/releaf/builders/show_builder.rb +3 -0
  99. data/app/builders/releaf/builders/table_builder.rb +280 -0
  100. data/app/builders/releaf/builders/tags/releaf_associated_set_field.rb +40 -0
  101. data/app/builders/releaf/builders/template.rb +8 -0
  102. data/app/builders/releaf/builders/toolbox.rb +23 -0
  103. data/app/builders/releaf/builders/toolbox_builder.rb +27 -0
  104. data/app/builders/releaf/builders/view.rb +132 -0
  105. data/app/builders/releaf/builders.rb +38 -0
  106. data/app/builders/releaf/core/settings/form_builder.rb +21 -0
  107. data/app/builders/releaf/core/settings/table_builder.rb +11 -0
  108. data/app/controllers/concerns/releaf/breadcrumbs.rb +42 -0
  109. data/app/controllers/concerns/releaf/richtext_attachments.rb +20 -0
  110. data/app/controllers/releaf/base_controller.rb +458 -0
  111. data/app/controllers/releaf/core/errors_controller.rb +5 -0
  112. data/app/controllers/releaf/core/settings_controller.rb +50 -0
  113. data/app/helpers/releaf/application_helper.rb +53 -0
  114. data/app/helpers/releaf/button_helper.rb +50 -0
  115. data/app/helpers/releaf/javascript_helper.rb +75 -0
  116. data/app/lib/releaf/core/assets_resolver.rb +58 -0
  117. data/app/lib/releaf/core/default_searchable_fields.rb +43 -0
  118. data/app/lib/releaf/core/error_formatter.rb +103 -0
  119. data/app/lib/releaf/core/item_orderer.rb +102 -0
  120. data/app/lib/releaf/core/resource_base.rb +66 -0
  121. data/app/lib/releaf/core/resource_fields.rb +6 -0
  122. data/app/lib/releaf/core/resource_params.rb +47 -0
  123. data/app/lib/releaf/core/resource_table_fields.rb +10 -0
  124. data/app/lib/releaf/core/resource_utilities.rb +36 -0
  125. data/app/lib/releaf/core/responders/access_denied_responder.rb +9 -0
  126. data/app/lib/releaf/core/responders/after_save_responder.rb +28 -0
  127. data/app/lib/releaf/core/responders/confirm_destroy_responder.rb +13 -0
  128. data/app/lib/releaf/core/responders/destroy_responder.rb +10 -0
  129. data/app/lib/releaf/core/responders/error_responder.rb +9 -0
  130. data/app/lib/releaf/core/responders/feature_disabled_responder.rb +9 -0
  131. data/app/lib/releaf/core/responders/page_not_found_responder.rb +9 -0
  132. data/app/lib/releaf/core/responders.rb +31 -0
  133. data/app/lib/releaf/core/search.rb +147 -0
  134. data/app/lib/releaf/core/template_field_type_mapper.rb +127 -0
  135. data/app/models/releaf/richtext_attachment.rb +6 -0
  136. data/app/models/releaf/settings.rb +27 -0
  137. data/app/views/layouts/releaf/admin.html.erb +1 -0
  138. data/app/views/releaf/base/confirm_destroy.ruby +1 -0
  139. data/app/views/releaf/base/create_releaf_richtext_attachment.haml +1 -0
  140. data/app/views/releaf/base/edit.ruby +1 -0
  141. data/app/views/releaf/base/index.ruby +1 -0
  142. data/app/views/releaf/base/new.ruby +1 -0
  143. data/app/views/releaf/base/refused_destroy.ruby +1 -0
  144. data/app/views/releaf/base/show.ruby +1 -0
  145. data/app/views/releaf/base/toolbox.ruby +1 -0
  146. data/app/views/releaf/error_pages/_error.html.haml +10 -0
  147. data/app/views/releaf/error_pages/access_denied.html.haml +1 -0
  148. data/app/views/releaf/error_pages/feature_disabled.html.haml +1 -0
  149. data/app/views/releaf/error_pages/page_not_found.html.haml +2 -0
  150. data/lib/generators/dummy/install_generator.rb +18 -0
  151. data/lib/generators/dummy/templates/builders/admin/books/form_builder.rb +13 -0
  152. data/lib/generators/dummy/templates/builders/admin/books/index_builder.rb +30 -0
  153. data/lib/generators/dummy/templates/builders/admin/books/table_builder.rb +7 -0
  154. data/lib/generators/dummy/templates/builders/admin/nodes/form_builder.rb +7 -0
  155. data/lib/generators/dummy/templates/config/routes.rb +19 -0
  156. data/lib/generators/dummy/templates/controllers/admin/authors_controller.rb +12 -0
  157. data/lib/generators/dummy/templates/controllers/admin/books_controller.rb +17 -0
  158. data/lib/generators/dummy/templates/controllers/admin/chapters_controller.rb +3 -0
  159. data/lib/generators/dummy/templates/controllers/admin/publishers_controller.rb +3 -0
  160. data/lib/generators/dummy/templates/controllers/application_controller.rb +39 -0
  161. data/lib/generators/dummy/templates/controllers/concerns/.keep +0 -0
  162. data/lib/generators/dummy/templates/controllers/concerns/node_controller.rb +37 -0
  163. data/lib/generators/dummy/templates/controllers/contacts_controller.rb +3 -0
  164. data/lib/generators/dummy/templates/controllers/home_pages_controller.rb +3 -0
  165. data/lib/generators/dummy/templates/controllers/text_pages_controller.rb +3 -0
  166. data/lib/generators/dummy/templates/initializers/releaf.rb +35 -0
  167. data/lib/generators/dummy/templates/migrations/create_authors.rb +14 -0
  168. data/lib/generators/dummy/templates/migrations/create_banners.rb +11 -0
  169. data/lib/generators/dummy/templates/migrations/create_book_sequels.rb +14 -0
  170. data/lib/generators/dummy/templates/migrations/create_books.rb +27 -0
  171. data/lib/generators/dummy/templates/migrations/create_bundles.rb +7 -0
  172. data/lib/generators/dummy/templates/migrations/create_chapters.rb +13 -0
  173. data/lib/generators/dummy/templates/migrations/create_home_pages.rb +9 -0
  174. data/lib/generators/dummy/templates/migrations/create_node_extra_fields.rb +5 -0
  175. data/lib/generators/dummy/templates/migrations/create_publishers.rb +8 -0
  176. data/lib/generators/dummy/templates/migrations/create_text_pages.rb +9 -0
  177. data/lib/generators/dummy/templates/models/author.rb +10 -0
  178. data/lib/generators/dummy/templates/models/banner.rb +5 -0
  179. data/lib/generators/dummy/templates/models/book.rb +19 -0
  180. data/lib/generators/dummy/templates/models/book_sequel.rb +4 -0
  181. data/lib/generators/dummy/templates/models/bundle.rb +17 -0
  182. data/lib/generators/dummy/templates/models/chapter.rb +7 -0
  183. data/lib/generators/dummy/templates/models/home_page.rb +5 -0
  184. data/lib/generators/dummy/templates/models/node.rb +10 -0
  185. data/lib/generators/dummy/templates/models/publisher.rb +9 -0
  186. data/lib/generators/dummy/templates/models/text_page.rb +5 -0
  187. data/lib/generators/dummy/templates/views/contacts/show.html.haml +1 -0
  188. data/lib/generators/dummy/templates/views/home_pages/show.haml +1 -0
  189. data/lib/generators/dummy/templates/views/layouts/application.html.haml +22 -0
  190. data/lib/generators/dummy/templates/views/text_pages/show.haml +1 -0
  191. data/lib/generators/releaf/install_generator.rb +93 -0
  192. data/lib/generators/releaf/templates/initializers/haml.rb +1 -0
  193. data/lib/generators/releaf/templates/initializers/releaf.rb +30 -0
  194. data/lib/generators/releaf/templates/migrations/create_releaf_nodes.rb +28 -0
  195. data/lib/generators/releaf/templates/migrations/create_releaf_permissions.rb +12 -0
  196. data/lib/generators/releaf/templates/migrations/create_releaf_richtext_attachments.rb +12 -0
  197. data/lib/generators/releaf/templates/migrations/create_releaf_roles.rb +9 -0
  198. data/lib/generators/releaf/templates/migrations/create_releaf_settings.rb +17 -0
  199. data/lib/generators/releaf/templates/migrations/create_releaf_translations.rb +21 -0
  200. data/lib/generators/releaf/templates/migrations/create_releaf_users.rb +52 -0
  201. data/lib/generators/releaf/templates/models/node.rb +3 -0
  202. data/lib/generators/releaf/templates/seeds/seeds.rb +54 -0
  203. data/lib/releaf/core/application.rb +17 -0
  204. data/lib/releaf/core/builders_autoload.rb +27 -0
  205. data/lib/releaf/core/component.rb +9 -0
  206. data/lib/releaf/core/configuration.rb +101 -0
  207. data/lib/releaf/core/engine.rb +35 -0
  208. data/lib/releaf/core/exceptions.rb +38 -0
  209. data/lib/releaf/core/route_mapper.rb +59 -0
  210. data/lib/releaf/core/settings_ui_component.rb +7 -0
  211. data/lib/releaf/core/validation_error_codes.rb +36 -0
  212. data/lib/releaf/version.rb +3 -0
  213. data/lib/releaf-core.rb +14 -0
  214. data/lib/tasks/releaf_tasks.rake +4 -0
  215. data/releaf-core.gemspec +35 -0
  216. data/spec/builders/builders/association_reflector_spec.rb +138 -0
  217. data/spec/builders/builders/base_spec.rb +276 -0
  218. data/spec/builders/builders/collection_spec.rb +18 -0
  219. data/spec/builders/builders/confirm_destroy_dialog_builder_spec.rb +71 -0
  220. data/spec/builders/builders/confirm_dialog_builder_spec.rb +105 -0
  221. data/spec/builders/builders/edit_builder_spec.rb +215 -0
  222. data/spec/builders/builders/form_builder_spec.rb +562 -0
  223. data/spec/builders/builders/index_builder_spec.rb +345 -0
  224. data/spec/builders/builders/orderer_spec.rb +22 -0
  225. data/spec/builders/builders/page/header_builder_spec.rb +143 -0
  226. data/spec/builders/builders/page/layout_builder_spec.rb +73 -0
  227. data/spec/builders/builders/page/menu_builder_spec.rb +160 -0
  228. data/spec/builders/builders/pagination_builder_spec.rb +330 -0
  229. data/spec/builders/builders/resource_dialog_spec.rb +21 -0
  230. data/spec/builders/builders/resource_view_spec.rb +158 -0
  231. data/spec/builders/builders/show_builder_spec.rb +7 -0
  232. data/spec/builders/builders/table_builder_spec.rb +638 -0
  233. data/spec/builders/builders/template_spec.rb +12 -0
  234. data/spec/builders/builders/toolbox_builder_spec.rb +67 -0
  235. data/spec/builders/builders/toolbox_spec.rb +48 -0
  236. data/spec/builders/builders/view_spec.rb +281 -0
  237. data/spec/builders/builders_spec.rb +134 -0
  238. data/spec/builders/core/settings/form_builder_spec.rb +69 -0
  239. data/spec/builders/core/settings/table_builder_spec.rb +21 -0
  240. data/spec/controllers/concerns/releaf/richtext_attachments_spec.rb +51 -0
  241. data/spec/controllers/releaf/base_controller_spec.rb +447 -0
  242. data/spec/controllers/releaf/core/settings_controller_spec.rb +31 -0
  243. data/spec/features/ajaxbox_spec.rb +111 -0
  244. data/spec/features/authorization_spec.rb +50 -0
  245. data/spec/features/dragonfly_integration_spec.rb +24 -0
  246. data/spec/features/edit_actions_spec.rb +142 -0
  247. data/spec/features/errors_spec.rb +29 -0
  248. data/spec/features/index_actions_spec.rb +85 -0
  249. data/spec/features/index_table_spec.rb +32 -0
  250. data/spec/features/menu_spec.rb +71 -0
  251. data/spec/features/richtext_attachments_spec.rb +64 -0
  252. data/spec/features/richtext_embed_spec.rb +29 -0
  253. data/spec/features/richtext_spec.rb +19 -0
  254. data/spec/features/search_spec.rb +825 -0
  255. data/spec/features/settings_spec.rb +38 -0
  256. data/spec/features/title_spec.rb +13 -0
  257. data/spec/fixtures/common_fields.yml +17 -0
  258. data/spec/fixtures/cs.png +0 -0
  259. data/spec/fixtures/time.formats.xlsx +0 -0
  260. data/spec/fixtures/unicorn.jpg +0 -0
  261. data/spec/helpers/application_helper_spec.rb +75 -0
  262. data/spec/helpers/button_helper_spec.rb +146 -0
  263. data/spec/lib/releaf/core/application_spec.rb +42 -0
  264. data/spec/lib/releaf/core/assets_resolver_spec.rb +113 -0
  265. data/spec/lib/releaf/core/configuration_spec.rb +230 -0
  266. data/spec/lib/releaf/core/default_searchable_fields_spec.rb +161 -0
  267. data/spec/lib/releaf/core/error_formatter_spec.rb +242 -0
  268. data/spec/lib/releaf/core/item_orderer_spec.rb +142 -0
  269. data/spec/lib/releaf/core/resource_base_spec.rb +174 -0
  270. data/spec/lib/releaf/core/resource_fields_spec.rb +12 -0
  271. data/spec/lib/releaf/core/resource_params_spec.rb +117 -0
  272. data/spec/lib/releaf/core/resource_table_fields_spec.rb +18 -0
  273. data/spec/lib/releaf/core/resource_utilities_spec.rb +87 -0
  274. data/spec/lib/releaf/core/responders/access_denied_responder_spec.rb +12 -0
  275. data/spec/lib/releaf/core/responders/after_save_responder_spec.rb +102 -0
  276. data/spec/lib/releaf/core/responders/confirm_destroy_responder_spec.rb +26 -0
  277. data/spec/lib/releaf/core/responders/destroy_responder_spec.rb +30 -0
  278. data/spec/lib/releaf/core/responders/error_responder_spec.rb +26 -0
  279. data/spec/lib/releaf/core/responders/feature_disabled_responder_spec.rb +12 -0
  280. data/spec/lib/releaf/core/responders/page_not_found_responder_spec.rb +12 -0
  281. data/spec/lib/releaf/core/responders_spec.rb +60 -0
  282. data/spec/lib/releaf/core/template_field_type_mapper_spec.rb +311 -0
  283. data/spec/lib/validation_error_codes_spec.rb +56 -0
  284. data/spec/misc/factories_spec.rb +43 -0
  285. data/spec/models/settings_spec.rb +58 -0
  286. data/spec/routing/route_mapper_spec.rb +185 -0
  287. data/spec/rspec_helpers/test_helpers_spec.rb +20 -0
  288. metadata +657 -0
@@ -0,0 +1,230 @@
1
+ require "rails_helper"
2
+
3
+ describe Releaf::Core::Configuration do
4
+ describe "#configure" do
5
+ it "calls all initializators" do
6
+ expect(subject).to receive(:initialize_defaults).ordered
7
+ expect(subject).to receive(:initialize_locales).ordered
8
+ expect(subject).to receive(:initialize_controllers).ordered
9
+ expect(subject).to receive(:initialize_components).ordered
10
+ subject.configure
11
+ end
12
+ end
13
+
14
+ describe "#assets_resolver" do
15
+ it "returns assets resolver class" do
16
+ allow(subject).to receive(:assets_resolver_class_name).and_return("Book")
17
+ expect(subject.assets_resolver).to eq(Book)
18
+ end
19
+ end
20
+
21
+ describe "#access_control_module" do
22
+ it "returns access control module class" do
23
+ allow(subject).to receive(:access_control_module_name).and_return("Book")
24
+ expect(subject.access_control_module).to eq(Book)
25
+ end
26
+ end
27
+
28
+ describe "#initialize_defaults" do
29
+ it "ovewrites only nil values with default ones" do
30
+ allow(subject).to receive(:default_values).and_return(menu: "aa", components: "lk")
31
+ subject.menu = "x"
32
+ subject.components = nil
33
+ expect{ subject.initialize_defaults }.to change{ [subject.menu, subject.components] }.to(["x", "lk"])
34
+ end
35
+ end
36
+
37
+ describe "#initialize_locales" do
38
+ before do
39
+ subject.available_locales = [:a, :b]
40
+ subject.available_admin_locales = [:b, :c]
41
+ allow(::I18n).to receive(:available_locales=)
42
+ end
43
+
44
+ it "assigns available locales to `I18n.available_locales`" do
45
+ expect(::I18n).to receive(:available_locales=).with([:a, :b])
46
+ subject.initialize_locales
47
+ end
48
+
49
+ context "when no `available_admin_locales` defined" do
50
+ it "overwrites it with available locales" do
51
+ expect{ subject.initialize_locales }.to_not change{ subject.available_admin_locales }
52
+
53
+ subject.available_admin_locales = nil
54
+ expect{ subject.initialize_locales }.to change{ subject.available_admin_locales }.to eq([:a, :b])
55
+ end
56
+ end
57
+
58
+ it "merges unique locales form admin and available locales, casts it to strings and assign to `all_locales`" do
59
+ expect{ subject.initialize_locales }.to change{ subject.all_locales }.to eq(["a", "b", "c"])
60
+ end
61
+ end
62
+
63
+ describe "#initialize_components" do
64
+ before do
65
+ class DummyComponentA; end
66
+ class DummyComponentB
67
+ def self.initialize_component; end
68
+ end
69
+ allow(subject).to receive(:flatten_components).with(["x", "s"])
70
+ .and_return([DummyComponentA, DummyComponentB])
71
+ subject.components = ["x", "s"]
72
+ end
73
+
74
+ it "reassign normalized components" do
75
+ expect{ subject.initialize_components }.to change{ subject.components }.to([DummyComponentA, DummyComponentB])
76
+ end
77
+
78
+ it "calls component initializing method if available" do
79
+ expect(DummyComponentB).to receive(:initialize_component)
80
+ subject.initialize_components
81
+ end
82
+ end
83
+
84
+ describe "#flatten_components" do
85
+ it "returns recursively flattened component list" do
86
+ class DummyComponentA; end
87
+ class DummyComponentB
88
+ def self.components
89
+ ["o", "p"]
90
+ end
91
+ end
92
+
93
+ allow(subject).to receive(:flatten_components).and_call_original
94
+ allow(subject).to receive(:flatten_components).with(["o", "p"]).and_return(["x", "y"])
95
+ expect(subject.flatten_components([DummyComponentA, DummyComponentB])).to eq([DummyComponentA, "x", "y", DummyComponentB])
96
+ end
97
+ end
98
+
99
+ describe "#initialize_controllers" do
100
+ before do
101
+ subject.menu = ["a"]
102
+ subject.additional_controllers = ["b"]
103
+ allow(subject).to receive(:normalize_controllers).with(["a"]).and_return(["aa"])
104
+ allow(subject).to receive(:normalize_controllers).with(["b"]).and_return(["bb"])
105
+ allow(subject).to receive(:extract_controllers).with(["aa", "bb"]).and_return({"c" => "d"})
106
+ end
107
+
108
+ it "normalizes menu" do
109
+ expect{ subject.initialize_controllers }.to change{ subject.menu }.from(["a"]).to(["aa"])
110
+ end
111
+
112
+ it "normalizes additional controllers" do
113
+ expect{ subject.initialize_controllers }.to change{ subject.additional_controllers }.from(["b"]).to(["bb"])
114
+ end
115
+
116
+ it "extract controller items from menu and additional controllers and assign then to controllers" do
117
+ expect{ subject.initialize_controllers }.to change{ subject.controllers }.from(nil).to("c" => "d")
118
+ end
119
+
120
+ it "extract controller names and assign to available controllers" do
121
+ expect{ subject.initialize_controllers }.to change{ subject.available_controllers }.from(nil).to(["c"])
122
+ end
123
+ end
124
+
125
+ describe "#extract_controllers" do
126
+ it "returns recursively built hash with controllers from given array" do
127
+ list = [{controller: "a"}, {items: [{controller: "b"}, {controller: "c"}, {xx: "x"}]}, {controller: "d"}, {asd: "xx"}]
128
+ result = {"a"=>{controller: "a"}, "b"=>{controller: "b"}, "c"=>{controller: "c"}, "d" => {controller: "d"}}
129
+ expect(subject.extract_controllers(list)).to eq(result)
130
+ end
131
+ end
132
+
133
+ describe "#normalize_controllers" do
134
+ it "returns list of normalized controllers" do
135
+ allow(subject).to receive(:normalize_controller_item).with(:a).and_return("ab")
136
+ allow(subject).to receive(:normalize_controller_item).with(:b).and_return("bc")
137
+ expect(subject.normalize_controllers([:a, :b])).to eq(["ab", "bc"])
138
+ end
139
+ end
140
+
141
+ describe "#normalize_controller_item" do
142
+ describe ":controller" do
143
+ context "when given value is instance of `String`" do
144
+ it "use value as controller name" do
145
+ expect(subject.normalize_controller_item("a")[:controller]).to eq("a")
146
+ end
147
+ end
148
+
149
+ context "when given value is hash" do
150
+ it "does not add controller value" do
151
+ expect(subject.normalize_controller_item(a: "x")[:controller]).to be nil
152
+ end
153
+
154
+ it "does not modify controller value" do
155
+ expect(subject.normalize_controller_item(controller: "x")[:controller]).to eq("x")
156
+ end
157
+ end
158
+ end
159
+
160
+ describe ":name" do
161
+ context "when controller hash does not have name value" do
162
+ it "assigns controller value as name" do
163
+ expect(subject.normalize_controller_item(controller: "x")[:name]).to eq("x")
164
+ end
165
+ end
166
+
167
+ context "when controller hash has name value" do
168
+ it "does not change existing name value" do
169
+ expect(subject.normalize_controller_item(controller: "x", name: "b")[:name]).to eq("b")
170
+ end
171
+ end
172
+ end
173
+
174
+ describe ":url_helper" do
175
+ context "when controller hash does not have neither helper or controller values" do
176
+ it "does not add url helper value" do
177
+ expect(subject.normalize_controller_item(x: "x")[:url_helper]).to be nil
178
+ end
179
+ end
180
+
181
+ context "when controller hash has helper value" do
182
+ it "assigns symbolized helper value" do
183
+ expect(subject.normalize_controller_item(controller: "x", helper: "b")[:url_helper]).to eq(:b)
184
+ end
185
+ end
186
+
187
+ context "when controller hash has controller value" do
188
+ it "assigns convert controller name to url helper" do
189
+ expect(subject.normalize_controller_item(controller: "a/b")[:url_helper]).to eq(:a_b)
190
+ end
191
+ end
192
+ end
193
+
194
+ describe ":items" do
195
+ before do
196
+ allow(subject).to receive(:normalize_controllers).with(["a", "b"]).and_return(["c", "d"])
197
+ end
198
+
199
+ context "when controller hash does not have items value" do
200
+ it "does not add items value" do
201
+ expect(subject.normalize_controller_item(x: "x")[:items]).to be nil
202
+ end
203
+ end
204
+
205
+ context "when controller hash has items value" do
206
+ it "does normalizes items" do
207
+ expect(subject.normalize_controller_item(x: "x", items: ["a", "b"])[:items]).to eq(["c", "d"])
208
+ end
209
+ end
210
+ end
211
+ end
212
+
213
+ describe "#default_values" do
214
+ it "returns default configuration key, value hash" do
215
+ result = {
216
+ menu: [],
217
+ devise_for: 'releaf/permissions/user',
218
+ additional_controllers: [],
219
+ controllers: {},
220
+ components: [],
221
+ assets_resolver_class_name: 'Releaf::Core::AssetsResolver',
222
+ layout_builder_class_name: 'Releaf::Builders::Page::LayoutBuilder',
223
+ access_control_module_name: 'Releaf::Permissions'
224
+ }
225
+ expect(subject.default_values).to eq(result)
226
+ end
227
+ end
228
+ end
229
+
230
+
@@ -0,0 +1,161 @@
1
+ require "rails_helper"
2
+
3
+ describe Releaf::Core::DefaultSearchableFields do
4
+ # emulate klass::Translations
5
+ with_model :SearchableObjectTranslations, scope: :all do
6
+ table do |t|
7
+ t.string :name
8
+ end
9
+ end
10
+
11
+ with_model :SearchableObject, scope: :all do
12
+ table do |t|
13
+ t.string :email
14
+ t.string :first_name
15
+ t.string :forename
16
+ t.string :last_name
17
+ t.string :login
18
+ t.string :middle_name
19
+ t.string :name
20
+ t.string :surname
21
+ t.string :title
22
+ t.string :username
23
+ t.string :non_searchable
24
+ t.string :password
25
+ t.integer :size
26
+ t.boolean :bool
27
+ t.text :text
28
+ end
29
+
30
+ model do
31
+ # emulate globalize accessors
32
+ def self.translates?
33
+ true
34
+ end
35
+ end
36
+ end
37
+
38
+ with_model :NonSearchableObject, scope: :all do
39
+ table do |t|
40
+ t.integer :email
41
+ t.integer :first_name
42
+ t.integer :forename
43
+ t.integer :last_name
44
+ t.integer :login
45
+ t.integer :middle_name
46
+ t.integer :name
47
+ t.integer :surname
48
+ t.integer :title
49
+ t.integer :username
50
+ end
51
+ end
52
+
53
+ before(:all) do
54
+ # emulate globalize accessors
55
+ SearchableObject.const_set('Translation', SearchableObjectTranslations)
56
+ end
57
+
58
+ subject { described_class.new(SearchableObject) }
59
+
60
+ describe "#possible_field_names" do
61
+ it "returns array of possible field names to search" do
62
+ expect( subject.possible_field_names ).to match_array %w[
63
+ email
64
+ first_name
65
+ forename
66
+ last_name
67
+ login
68
+ middle_name
69
+ name
70
+ surname
71
+ title
72
+ username
73
+ ]
74
+ end
75
+ end
76
+
77
+ describe "#find" do
78
+ context "when searchable fields exist" do
79
+ it "returns array of searchable string columns" do
80
+ expect( described_class.new(SearchableObject).find ).to match_array %w[
81
+ email
82
+ first_name
83
+ forename
84
+ last_name
85
+ login
86
+ middle_name
87
+ name
88
+ surname
89
+ title
90
+ username
91
+ ] + [translations: %w[name]]
92
+ end
93
+ end
94
+
95
+ context "when searchable fields doesn't exist" do
96
+ it "returns array of searchable string columns" do
97
+ expect( described_class.new(NonSearchableObject).find ).to be_blank
98
+ end
99
+ end
100
+ end
101
+
102
+ describe "#string_columns" do
103
+ it "returns string columsn of model" do
104
+ expect( subject.string_columns ).to match_array %w[
105
+ email
106
+ first_name
107
+ forename
108
+ last_name
109
+ login
110
+ middle_name
111
+ name
112
+ surname
113
+ title
114
+ username
115
+ non_searchable
116
+ password
117
+ ]
118
+ end
119
+ end
120
+
121
+ describe "#has_searchable_translated_string_columns?" do
122
+ context "when #klass isn't translated" do
123
+ it "returns false" do
124
+ allow(SearchableObject).to receive(:translates?).and_return(false)
125
+ expect( subject.has_searchable_translated_string_columns? ).to eq false
126
+ end
127
+ end
128
+
129
+ context "when #klass is translated and has translated searchable columns" do
130
+ it "returns true" do
131
+ expect( subject.has_searchable_translated_string_columns? ).to eq true
132
+ end
133
+ end
134
+
135
+ context "when #klass is translated but has no translated searchable columns" do
136
+ it "returns false" do
137
+ allow( subject ).to receive(:searchable_translated_string_columns).and_return([])
138
+ expect( subject.has_searchable_translated_string_columns? ).to eq false
139
+ end
140
+ end
141
+
142
+ end
143
+
144
+ describe "#searchable_translated_string_columns" do
145
+ it "returns translated string columns of klass::Translation" do
146
+ expect( subject.searchable_translated_string_columns ).to match_array %w[name]
147
+ end
148
+
149
+ it "caches result" do
150
+ searchable_fields = double(described_class)
151
+ expect( searchable_fields ).to receive(:find).once.and_return []
152
+
153
+ subject # init subject
154
+
155
+ allow( described_class ).to receive(:new).with(SearchableObject::Translation).and_return(searchable_fields)
156
+
157
+ subject.searchable_translated_string_columns
158
+ subject.searchable_translated_string_columns
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,242 @@
1
+ require 'rails_helper'
2
+
3
+ describe Releaf::Core::ErrorFormatter do
4
+
5
+ class DummyResourceValidatorAuthor < Author
6
+ self.table_name = 'authors'
7
+ has_many :books, inverse_of: :author, class_name: :DummyResourceValidatorBook, foreign_key: :author_id
8
+ end
9
+
10
+ class DummyResourceValidatorBook < Book
11
+ self.table_name = 'books'
12
+ belongs_to :author, inverse_of: :books, class_name: :DummyResourceValidatorAuthor
13
+
14
+ validates_presence_of :author
15
+ validate :base_validation
16
+ accepts_nested_attributes_for :author
17
+
18
+ attr_accessor :add_error_on_base
19
+
20
+ def base_validation
21
+ return unless add_error_on_base
22
+ self.errors.add(:base, 'error on base')
23
+ end
24
+ end
25
+
26
+ let(:book) {
27
+ b = Book.new
28
+ b.valid?
29
+ b
30
+ }
31
+
32
+ subject do
33
+ described_class.new(book, 'resource')
34
+ end
35
+
36
+ describe "#errors" do
37
+ it "is a hash" do
38
+ allow_any_instance_of(described_class).to receive(:format_errors)
39
+ expect( subject.errors ).to be_an_instance_of Hash
40
+ end
41
+ end
42
+
43
+ describe "#format_errors" do
44
+ let(:book) {
45
+ b = DummyResourceValidatorBook.new
46
+ b.valid?
47
+ b
48
+ }
49
+
50
+ def blank_error(attribute, class_name='DummyResourceValidatorBook', id='null')
51
+ {
52
+ error_code: :blank,
53
+ message: "Blank",
54
+ full_message: "#{class_name} with id #{id} has error \"Blank\" on attribute \"#{attribute}\""
55
+ }
56
+ end
57
+
58
+ it "is called after initialization" do
59
+ expect_any_instance_of( described_class ).to receive(:format_errors)
60
+ described_class.new(Book.new, 'resource')
61
+ end
62
+
63
+ it "doesn't validates resource" do
64
+ expect( book ).to_not receive(:valid?)
65
+ expect( book ).to_not receive(:invalid?)
66
+ subject
67
+ end
68
+
69
+ it "correctly adds errors for fields resource fields" do
70
+ expect( subject.errors["resource[title]"] ).to eq [blank_error('title')]
71
+ end
72
+
73
+ it "correclty adds errors for missing associated object (belongs_to)" do
74
+ expect( subject.errors["resource[author_id]"] ).to eq [blank_error('author')]
75
+ end
76
+
77
+ it "correctly adds error for missing associated object attributes (belongs_to)" do
78
+ book.build_author
79
+ book.valid?
80
+ expect( subject.errors["resource[author_attributes][name]"] ).to eq [blank_error('name', 'DummyResourceValidatorAuthor')]
81
+ end
82
+
83
+ it "correctly adds error for missing associated object attributes (has_many)" do
84
+ book.chapters.new(id: 12)
85
+ book.chapters.new(:title => 'test')
86
+ book.valid?
87
+ expect( subject.errors["resource[chapters_attributes][0][title]"] ).to eq [blank_error('title', 'Chapter', '12')]
88
+ expect( subject.errors["resource[chapters_attributes][1][title]"] ).to be_nil
89
+
90
+ expect( subject.errors["resource[chapters_attributes][0][text]"] ).to eq [blank_error('text', 'Chapter', '12')]
91
+ expect( subject.errors["resource[chapters_attributes][1][text]"] ).to eq [blank_error('text', 'Chapter')]
92
+ end
93
+
94
+ it "handles errors on base" do
95
+ book.add_error_on_base = true
96
+ book.valid?
97
+ expect( subject.errors["resource"] ).to eq [{
98
+ error_code: :invalid,
99
+ message: "Error on base",
100
+ full_message: 'DummyResourceValidatorBook with id null has error "error on base"'
101
+ }]
102
+ end
103
+ end
104
+
105
+ describe "#association" do
106
+ it "returns active record reflection of association" do
107
+ expect( subject.send(:association, 'author') ).to eq Book.reflect_on_association(:author)
108
+ end
109
+ end
110
+
111
+ describe "#association_type" do
112
+ it "returns active record reflection macro" do
113
+ expect( subject.send(:association_type, 'author') ).to eq :belongs_to
114
+ end
115
+ end
116
+
117
+ describe "#single_association?" do
118
+ context "for :belongs_to association" do
119
+ it "returns true" do
120
+ expect( subject.send(:single_association?, 'author') ).to be true
121
+ end
122
+ end
123
+
124
+ context "for :has_many association" do
125
+ it "returns false" do
126
+ expect( subject.send(:single_association?, 'chapters') ).to be false
127
+ end
128
+ end
129
+
130
+ context "for :has_one association" do
131
+ it "returns true" do
132
+ allow(subject).to receive(:association_type).with('author').and_return(:has_one)
133
+ expect( subject.send(:single_association?, 'author') ).to be true
134
+ end
135
+ end
136
+ end
137
+
138
+ describe "#models_attribute?" do
139
+ context "when attribute name contains dot" do
140
+ it "returns false" do
141
+ expect( subject.send(:models_attribute?, 'test.attribute') ).to be false
142
+ end
143
+ end
144
+
145
+ context "when attribute name doesn't contain dot" do
146
+ it "returns true" do
147
+ expect( subject.send(:models_attribute?, 'test') ).to be true
148
+ end
149
+ end
150
+ end
151
+
152
+ describe "#field_id" do
153
+ context "when error is on base" do
154
+ it "returns resource field_id" do
155
+ expect( subject.send(:field_id, 'base') ).to eq 'resource'
156
+ end
157
+ end
158
+
159
+ context "when attribute is association" do
160
+ it "returns field_id for associations foreign key" do
161
+ expect( subject.send(:field_id, 'author') ).to eq 'resource[author_id]'
162
+ end
163
+ end
164
+
165
+ context "when attribute is not association" do
166
+ it "returns field_id for field" do
167
+ expect( subject.send(:field_id, 'title') ).to eq 'resource[title]'
168
+ end
169
+ end
170
+ end
171
+
172
+ describe "#add_error" do
173
+ before do
174
+ # prevent formatting errors when class is initialized
175
+ allow_any_instance_of(described_class).to receive(:format_errors)
176
+ end
177
+
178
+ it "adds error to errors" do
179
+ expected_result = {
180
+ 'resource[title]' => [
181
+ {
182
+ error_code: 'test error',
183
+ message: 'Error message',
184
+ full_message: 'Book with id null has error "error message" on attribute "title"'
185
+ },
186
+ {
187
+ error_code: 'test error',
188
+ message: 'Jet another error message',
189
+ full_message: 'Book with id null has error "jet another error message" on attribute "title"'
190
+ }
191
+ ],
192
+ 'resource[author_id]' => [
193
+ {
194
+ error_code: 'invalid',
195
+ message: 'Invalid author',
196
+ full_message: 'Book with id null has error "invalid author" on attribute "author"',
197
+ data: {foo: :bar}
198
+ }
199
+ ]
200
+ }
201
+
202
+ message = ActiveModel::ErrorMessage.new("error message")
203
+ allow(message).to receive(:error_code).and_return('test error')
204
+ allow(message).to receive(:data).and_return(nil)
205
+
206
+ other_message = ActiveModel::ErrorMessage.new("invalid author")
207
+ allow(other_message).to receive(:error_code).and_return('invalid')
208
+ allow(other_message).to receive(:data).and_return({foo: :bar})
209
+
210
+ jet_another_message = ActiveModel::ErrorMessage.new("jet another error message")
211
+ allow(jet_another_message).to receive(:error_code).and_return('test error')
212
+ allow(jet_another_message).to receive(:data).and_return(nil)
213
+
214
+ expect do
215
+ subject.send(:add_error, 'title', message)
216
+ subject.send(:add_error, 'author', other_message)
217
+ subject.send(:add_error, 'title', jet_another_message)
218
+ end.to change { subject.errors }.from({}).to(expected_result)
219
+ end
220
+
221
+ it "localizes error messages" do
222
+ message = ActiveModel::ErrorMessage.new("error message")
223
+ allow(message).to receive(:error_code).and_return('test error')
224
+ allow(message).to receive(:data).and_return(nil)
225
+
226
+ expect( I18n ).to receive(:t).with(message, scope: "activerecord.errors.messages.book").and_call_original
227
+
228
+ template = "%{class} with id %{id} has error \"error message\" on attribute \"%{attribute}\""
229
+ expect( I18n ).to receive(:t).with(template, {
230
+ default: template,
231
+ attribute: 'title',
232
+ class: 'Book',
233
+ id: 'null',
234
+ scope: "activerecord.errors.messages.book"
235
+ }).and_call_original
236
+
237
+ subject.send(:add_error, 'title', message)
238
+ end
239
+ end
240
+
241
+
242
+ end