releaf-core 0.2.1 → 1.0.3

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 (256) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +19 -21
  3. data/app/assets/javascripts/releaf/application.js +1 -2
  4. data/app/assets/javascripts/releaf/include/field.type_date_or_datetime_or_time.js +19 -21
  5. data/app/assets/javascripts/releaf/include/field.type_richtext.js +31 -9
  6. data/app/assets/javascripts/releaf/include/localization.js +3 -8
  7. data/app/assets/javascripts/releaf/include/nested_fields.js +1 -1
  8. data/app/assets/javascripts/releaf/include/remote_validator.js +7 -4
  9. data/app/assets/javascripts/releaf/include/sortable.js +1 -1
  10. data/app/assets/javascripts/releaf/include/{profile_settings.js → store_settings.js} +4 -10
  11. data/app/assets/javascripts/releaf/include/toolbox.js +7 -11
  12. data/app/assets/stylesheets/releaf/layout/fields.scss +1 -0
  13. data/app/assets/stylesheets/releaf/layout/header.scss +1 -0
  14. data/app/assets/stylesheets/releaf/layout/search.scss +15 -0
  15. data/app/builders/releaf/builders/base.rb +11 -9
  16. data/app/builders/releaf/builders/confirm_destroy_dialog_builder.rb +2 -2
  17. data/app/builders/releaf/builders/confirm_dialog_builder.rb +3 -3
  18. data/app/builders/releaf/builders/edit_builder.rb +51 -6
  19. data/app/builders/releaf/builders/form_builder/associated_set_field.rb +37 -0
  20. data/app/builders/releaf/builders/form_builder/associations.rb +153 -0
  21. data/app/builders/releaf/builders/form_builder/boolean_fields.rb +12 -0
  22. data/app/builders/releaf/builders/form_builder/date_fields.rb +30 -0
  23. data/app/builders/releaf/builders/form_builder/fields.rb +10 -0
  24. data/app/builders/releaf/builders/form_builder/file_fields.rb +47 -0
  25. data/app/builders/releaf/builders/form_builder/i18n_fields.rb +75 -0
  26. data/app/builders/releaf/builders/form_builder/label.rb +34 -0
  27. data/app/builders/releaf/builders/form_builder/number_fields.rb +13 -0
  28. data/app/builders/releaf/builders/form_builder/richtext_fields.rb +28 -0
  29. data/app/builders/releaf/builders/form_builder/text_fields.rb +43 -0
  30. data/app/builders/releaf/builders/form_builder.rb +8 -489
  31. data/app/builders/releaf/builders/index_builder.rb +10 -3
  32. data/app/builders/releaf/builders/page/header_builder.rb +23 -59
  33. data/app/builders/releaf/builders/page/layout_builder.rb +125 -115
  34. data/app/builders/releaf/builders/page/menu_builder.rb +96 -106
  35. data/app/builders/releaf/builders/refused_destroy_dialog_builder.rb +7 -12
  36. data/app/builders/releaf/builders/resource_view.rb +4 -4
  37. data/app/builders/releaf/builders/table_builder.rb +20 -30
  38. data/app/builders/releaf/builders/toolbox_builder.rb +1 -1
  39. data/app/builders/releaf/builders/utilities/date_fields.rb +100 -0
  40. data/app/builders/releaf/builders/utilities/resolve_attribute_field_method_name.rb +80 -0
  41. data/app/builders/releaf/builders/view.rb +5 -2
  42. data/app/builders/releaf/settings/form_builder.rb +18 -0
  43. data/app/builders/releaf/settings/table_builder.rb +9 -0
  44. data/app/controllers/releaf/action_controller.rb +174 -0
  45. data/app/controllers/releaf/{core/errors_controller.rb → errors_controller.rb} +1 -1
  46. data/app/controllers/releaf/root_controller.rb +23 -0
  47. data/app/controllers/releaf/settings_controller.rb +22 -0
  48. data/app/helpers/releaf/application_helper.rb +1 -1
  49. data/app/lib/releaf/action_controller/ajax.rb +24 -0
  50. data/app/lib/releaf/action_controller/breadcrumbs.rb +26 -0
  51. data/app/lib/releaf/action_controller/builders.rb +34 -0
  52. data/app/lib/releaf/action_controller/features.rb +47 -0
  53. data/app/lib/releaf/action_controller/notifications.rb +28 -0
  54. data/app/lib/releaf/action_controller/resources.rb +59 -0
  55. data/app/{controllers/concerns/releaf → lib/releaf/action_controller}/richtext_attachments.rb +1 -1
  56. data/app/lib/releaf/action_controller/search.rb +22 -0
  57. data/app/lib/releaf/action_controller/urls.rb +49 -0
  58. data/app/lib/releaf/action_controller/views.rb +29 -0
  59. data/app/lib/releaf/assets_resolver.rb +51 -0
  60. data/app/lib/releaf/build_errors_hash.rb +81 -0
  61. data/app/lib/releaf/controller_definition.rb +22 -0
  62. data/app/lib/releaf/controller_group_definition.rb +12 -0
  63. data/app/lib/releaf/{core/default_searchable_fields.rb → default_searchable_fields.rb} +1 -1
  64. data/app/lib/releaf/{core/resource_base.rb → resource_base.rb} +14 -6
  65. data/app/lib/releaf/{core/resource_fields.rb → resource_fields.rb} +1 -1
  66. data/app/lib/releaf/{core/resource_params.rb → resource_params.rb} +3 -3
  67. data/app/lib/releaf/resource_table_fields.rb +10 -0
  68. data/app/lib/releaf/{core/resource_utilities.rb → resource_utilities.rb} +2 -2
  69. data/app/lib/releaf/{core/responders → responders}/access_denied_responder.rb +2 -2
  70. data/app/lib/releaf/{core/responders → responders}/after_save_responder.rb +3 -3
  71. data/app/lib/releaf/{core/responders → responders}/confirm_destroy_responder.rb +1 -1
  72. data/app/lib/releaf/{core/responders → responders}/destroy_responder.rb +1 -1
  73. data/app/lib/releaf/{core/responders → responders}/error_responder.rb +1 -1
  74. data/app/lib/releaf/{core/responders → responders}/feature_disabled_responder.rb +2 -2
  75. data/app/lib/releaf/{core/responders → responders}/page_not_found_responder.rb +2 -2
  76. data/app/lib/releaf/responders.rb +31 -0
  77. data/app/lib/releaf/{core/search.rb → search.rb} +1 -1
  78. data/app/lib/releaf/settings/normalize_value.rb +45 -0
  79. data/app/lib/releaf/settings/register.rb +45 -0
  80. data/app/models/releaf/settings.rb +25 -13
  81. data/app/services/array/reorder.rb +82 -0
  82. data/app/views/releaf/{base → action}/confirm_destroy.ruby +0 -0
  83. data/app/views/releaf/{base → action}/create_releaf_richtext_attachment.haml +0 -0
  84. data/app/views/releaf/{base → action}/edit.ruby +0 -0
  85. data/app/views/releaf/{base → action}/index.ruby +0 -0
  86. data/app/views/releaf/{base → action}/new.ruby +0 -0
  87. data/app/views/releaf/{base → action}/refused_destroy.ruby +0 -0
  88. data/app/views/releaf/{base → action}/show.ruby +0 -0
  89. data/app/views/releaf/{base → action}/toolbox.ruby +0 -0
  90. data/lib/generators/dummy/install_generator.rb +5 -0
  91. data/lib/generators/dummy/templates/assets/javascripts/controllers/admin/books.js +23 -0
  92. data/lib/generators/dummy/templates/assets/javascripts/controllers/admin/nodes.js +1 -0
  93. data/lib/generators/dummy/templates/assets/javascripts/controllers/admin/other_site/other_nodes.js +1 -0
  94. data/lib/generators/dummy/templates/assets/stylesheets/controllers/admin/nodes.scss +1 -0
  95. data/lib/generators/dummy/templates/assets/stylesheets/controllers/admin/other_site/other_nodes.scss +1 -0
  96. data/lib/generators/dummy/templates/builders/admin/books/form_builder.rb +11 -1
  97. data/lib/generators/dummy/templates/config/routes.rb +31 -7
  98. data/lib/generators/dummy/templates/controllers/admin/authors_controller.rb +3 -6
  99. data/lib/generators/dummy/templates/controllers/admin/books_controller.rb +1 -1
  100. data/lib/generators/dummy/templates/controllers/admin/chapters_controller.rb +1 -1
  101. data/lib/generators/dummy/templates/controllers/admin/nodes_controller.rb +3 -0
  102. data/lib/generators/dummy/templates/controllers/admin/other_site/other_nodes_controller.rb +3 -0
  103. data/lib/generators/dummy/templates/controllers/admin/publishers_controller.rb +1 -1
  104. data/lib/generators/dummy/templates/controllers/application_controller.rb +27 -5
  105. data/lib/generators/dummy/templates/controllers/concerns/node_controller.rb +13 -3
  106. data/lib/generators/dummy/templates/controllers/contacts_controller.rb +3 -1
  107. data/lib/generators/dummy/templates/initializers/releaf.rb +31 -25
  108. data/lib/generators/dummy/templates/migrations/create_home_pages.rb +1 -0
  109. data/lib/generators/dummy/templates/migrations/create_other_nodes.rb +29 -0
  110. data/lib/generators/dummy/templates/models/author.rb +2 -2
  111. data/lib/generators/dummy/templates/models/book.rb +0 -2
  112. data/lib/generators/dummy/templates/models/chapter.rb +0 -2
  113. data/lib/generators/dummy/templates/models/home_page.rb +1 -0
  114. data/lib/generators/dummy/templates/models/other_site/other_node.rb +7 -0
  115. data/lib/generators/dummy/templates/models/publisher.rb +0 -5
  116. data/lib/generators/dummy/templates/models/text_page.rb +0 -1
  117. data/lib/generators/dummy/templates/views/contacts/show.html.haml +1 -1
  118. data/lib/generators/dummy/templates/views/layouts/application.html.haml +9 -1
  119. data/lib/generators/dummy/templates/views/text_pages/show.haml +1 -1
  120. data/lib/generators/releaf/templates/initializers/releaf.rb +6 -17
  121. data/lib/generators/releaf/templates/migrations/create_releaf_translations.rb +13 -14
  122. data/lib/generators/releaf/templates/seeds/seeds.rb +28 -32
  123. data/lib/releaf/{core/application.rb → application.rb} +5 -4
  124. data/lib/releaf/{core/component.rb → component.rb} +6 -2
  125. data/lib/releaf/configuration.rb +95 -0
  126. data/lib/releaf/core_ext/array/reorder.rb +5 -0
  127. data/lib/releaf/engine.rb +12 -0
  128. data/lib/releaf/exceptions.rb +5 -0
  129. data/lib/releaf/instance_cache.rb +72 -0
  130. data/lib/releaf/{core → rails_ext}/validation_error_codes.rb +1 -1
  131. data/lib/releaf/root/configuration.rb +6 -0
  132. data/lib/releaf/root/default_controller_resolver.rb +37 -0
  133. data/lib/releaf/root/settings_manager.rb +12 -0
  134. data/lib/releaf/root.rb +17 -0
  135. data/lib/releaf/{core/route_mapper.rb → route_mapper.rb} +6 -6
  136. data/lib/releaf/service.rb +11 -0
  137. data/lib/releaf/settings_ui.rb +7 -0
  138. data/lib/releaf/version.rb +1 -1
  139. data/lib/releaf-core.rb +38 -9
  140. data/spec/builders/{builders → releaf/builders}/association_reflector_spec.rb +0 -0
  141. data/spec/builders/{builders → releaf/builders}/base_spec.rb +17 -21
  142. data/spec/builders/{builders → releaf/builders}/collection_spec.rb +0 -0
  143. data/spec/builders/{builders → releaf/builders}/confirm_destroy_dialog_builder_spec.rb +5 -5
  144. data/spec/builders/{builders → releaf/builders}/confirm_dialog_builder_spec.rb +9 -7
  145. data/spec/builders/{builders → releaf/builders}/edit_builder_spec.rb +127 -20
  146. data/spec/builders/releaf/builders/form_builder/associations_spec.rb +129 -0
  147. data/spec/builders/releaf/builders/form_builder/date_fields_spec.rb +86 -0
  148. data/spec/builders/releaf/builders/form_builder/i18n_fields_spec.rb +48 -0
  149. data/spec/builders/releaf/builders/form_builder/label_spec.rb +106 -0
  150. data/spec/builders/releaf/builders/form_builder/number_fields_spec.rb +37 -0
  151. data/spec/builders/releaf/builders/form_builder_spec.rb +228 -0
  152. data/spec/builders/{builders → releaf/builders}/index_builder_spec.rb +29 -10
  153. data/spec/builders/releaf/builders/page/header_builder_spec.rb +65 -0
  154. data/spec/builders/releaf/builders/page/layout_builder_spec.rb +170 -0
  155. data/spec/builders/releaf/builders/page/menu_builder_spec.rb +345 -0
  156. data/spec/builders/{builders → releaf/builders}/pagination_builder_spec.rb +0 -0
  157. data/spec/builders/{builders → releaf/builders}/resource_dialog_spec.rb +0 -0
  158. data/spec/builders/{builders → releaf/builders}/resource_view_spec.rb +8 -8
  159. data/spec/builders/{builders → releaf/builders}/show_builder_spec.rb +0 -0
  160. data/spec/builders/{builders → releaf/builders}/table_builder_spec.rb +31 -75
  161. data/spec/builders/{builders → releaf/builders}/template_spec.rb +0 -0
  162. data/spec/builders/{builders → releaf/builders}/toolbox_builder_spec.rb +4 -4
  163. data/spec/builders/{builders → releaf/builders}/toolbox_spec.rb +0 -0
  164. data/spec/builders/releaf/builders/utilities/date_fields_spec.rb +125 -0
  165. data/spec/builders/releaf/builders/utilities/resolve_attribute_field_method_name_spec.rb +318 -0
  166. data/spec/builders/{builders → releaf/builders}/view_spec.rb +1 -1
  167. data/spec/builders/{builders_spec.rb → releaf/builders_spec.rb} +0 -0
  168. data/spec/builders/releaf/settings/form_builder_spec.rb +48 -0
  169. data/spec/builders/{core → releaf}/settings/table_builder_spec.rb +6 -4
  170. data/spec/controllers/concerns/releaf/richtext_attachments_spec.rb +1 -1
  171. data/spec/controllers/releaf/{base_controller_spec.rb → action_controller_spec.rb} +132 -161
  172. data/spec/controllers/releaf/root_controller_spec.rb +40 -0
  173. data/spec/controllers/releaf/settings_controller_spec.rb +52 -0
  174. data/spec/error_hash_builder_spec.rb +83 -0
  175. data/spec/ext/array_reorder_spec.rb +12 -0
  176. data/spec/features/ajaxbox_spec.rb +6 -6
  177. data/spec/features/errors_spec.rb +2 -1
  178. data/spec/features/index_table_spec.rb +6 -3
  179. data/spec/features/richtext_attachments_spec.rb +2 -2
  180. data/spec/features/richtext_custom_config_spec.rb +28 -0
  181. data/spec/features/richtext_embed_spec.rb +1 -1
  182. data/spec/features/richtext_spec.rb +10 -1
  183. data/spec/features/search_spec.rb +1 -1
  184. data/spec/features/settings_spec.rb +10 -5
  185. data/spec/helpers/application_helper_spec.rb +4 -6
  186. data/spec/lib/releaf/action_controller/features_spec.rb +171 -0
  187. data/spec/lib/releaf/action_controller/search_spec.rb +84 -0
  188. data/spec/lib/releaf/{core/application_spec.rb → application_spec.rb} +7 -6
  189. data/spec/lib/releaf/assets_resolver_spec.rb +130 -0
  190. data/spec/lib/releaf/build_errors_hash_spec.rb +141 -0
  191. data/spec/lib/releaf/configuration_spec.rb +205 -0
  192. data/spec/lib/releaf/controller_definition_spec.rb +49 -0
  193. data/spec/lib/releaf/controller_group_definition_spec.rb +27 -0
  194. data/spec/lib/releaf/{core/default_searchable_fields_spec.rb → default_searchable_fields_spec.rb} +1 -1
  195. data/spec/lib/releaf/instance_cache_spec.rb +98 -0
  196. data/spec/lib/releaf/{core/resource_base_spec.rb → resource_base_spec.rb} +59 -21
  197. data/spec/lib/releaf/{core/resource_fields_spec.rb → resource_fields_spec.rb} +1 -1
  198. data/spec/lib/releaf/{core/resource_params_spec.rb → resource_params_spec.rb} +3 -5
  199. data/spec/lib/releaf/resource_table_fields_spec.rb +20 -0
  200. data/spec/lib/releaf/{core/resource_utilities_spec.rb → resource_utilities_spec.rb} +1 -1
  201. data/spec/lib/releaf/{core/responders → responders}/access_denied_responder_spec.rb +1 -1
  202. data/spec/lib/releaf/{core/responders → responders}/after_save_responder_spec.rb +9 -8
  203. data/spec/lib/releaf/{core/responders → responders}/confirm_destroy_responder_spec.rb +2 -2
  204. data/spec/lib/releaf/{core/responders → responders}/destroy_responder_spec.rb +2 -2
  205. data/spec/lib/releaf/{core/responders → responders}/error_responder_spec.rb +4 -4
  206. data/spec/lib/releaf/{core/responders → responders}/feature_disabled_responder_spec.rb +1 -1
  207. data/spec/lib/releaf/{core/responders → responders}/page_not_found_responder_spec.rb +1 -1
  208. data/spec/lib/releaf/{core/responders_spec.rb → responders_spec.rb} +14 -14
  209. data/spec/lib/releaf/root/configuration_spec.rb +9 -0
  210. data/spec/lib/releaf/root/default_controller_resolver_spec.rb +108 -0
  211. data/spec/lib/releaf/root_spec.rb +13 -0
  212. data/spec/lib/releaf/service_spec.rb +20 -0
  213. data/spec/lib/releaf/settings/normalize_value_spec.rb +103 -0
  214. data/spec/lib/releaf/settings/register_spec.rb +135 -0
  215. data/spec/lib/releaf/settings_manager_spec.rb +22 -0
  216. data/spec/lib/validation_error_codes_spec.rb +1 -1
  217. data/spec/misc/factories_spec.rb +0 -12
  218. data/spec/models/settings_spec.rb +74 -32
  219. data/spec/routing/route_mapper_spec.rb +5 -5
  220. data/spec/rspec_helpers/test_helpers_spec.rb +1 -1
  221. data/spec/rspec_helpers/test_spec.rb +14 -0
  222. data/spec/{lib/releaf/core/item_orderer_spec.rb → services/array/reorder_spec.rb} +32 -53
  223. metadata +299 -224
  224. data/app/builders/releaf/builders/orderer.rb +0 -5
  225. data/app/builders/releaf/builders/tags/releaf_associated_set_field.rb +0 -40
  226. data/app/builders/releaf/core/settings/form_builder.rb +0 -21
  227. data/app/builders/releaf/core/settings/table_builder.rb +0 -11
  228. data/app/controllers/concerns/releaf/breadcrumbs.rb +0 -42
  229. data/app/controllers/releaf/base_controller.rb +0 -458
  230. data/app/controllers/releaf/core/settings_controller.rb +0 -50
  231. data/app/helpers/releaf/javascript_helper.rb +0 -75
  232. data/app/lib/releaf/core/assets_resolver.rb +0 -58
  233. data/app/lib/releaf/core/error_formatter.rb +0 -103
  234. data/app/lib/releaf/core/item_orderer.rb +0 -102
  235. data/app/lib/releaf/core/resource_table_fields.rb +0 -10
  236. data/app/lib/releaf/core/responders.rb +0 -31
  237. data/app/lib/releaf/core/template_field_type_mapper.rb +0 -127
  238. data/lib/generators/dummy/templates/controllers/concerns/.keep +0 -0
  239. data/lib/releaf/core/builders_autoload.rb +0 -27
  240. data/lib/releaf/core/configuration.rb +0 -101
  241. data/lib/releaf/core/engine.rb +0 -35
  242. data/lib/releaf/core/exceptions.rb +0 -38
  243. data/lib/releaf/core/settings_ui_component.rb +0 -7
  244. data/releaf-core.gemspec +0 -35
  245. data/spec/builders/builders/form_builder_spec.rb +0 -562
  246. data/spec/builders/builders/orderer_spec.rb +0 -22
  247. data/spec/builders/builders/page/header_builder_spec.rb +0 -143
  248. data/spec/builders/builders/page/layout_builder_spec.rb +0 -73
  249. data/spec/builders/builders/page/menu_builder_spec.rb +0 -160
  250. data/spec/builders/core/settings/form_builder_spec.rb +0 -69
  251. data/spec/controllers/releaf/core/settings_controller_spec.rb +0 -31
  252. data/spec/lib/releaf/core/assets_resolver_spec.rb +0 -113
  253. data/spec/lib/releaf/core/configuration_spec.rb +0 -230
  254. data/spec/lib/releaf/core/error_formatter_spec.rb +0 -242
  255. data/spec/lib/releaf/core/resource_table_fields_spec.rb +0 -18
  256. data/spec/lib/releaf/core/template_field_type_mapper_spec.rb +0 -311
@@ -0,0 +1,106 @@
1
+ require "rails_helper"
2
+
3
+ describe Releaf::Builders::FormBuilder::Label, type: :class do
4
+ class FormBuilderTestHelper < ActionView::Base
5
+ include Releaf::ApplicationHelper
6
+ include Releaf::ButtonHelper
7
+ include FontAwesome::Rails::IconHelper
8
+ end
9
+
10
+ let(:template){ FormBuilderTestHelper.new }
11
+ let(:object){ Book.new }
12
+ let(:subject){ Releaf::Builders::FormBuilder.new(:book, object, template, {}) }
13
+
14
+ describe "#releaf_label" do
15
+ it "passes options :label value to #label_text and use returned value for label text content" do
16
+ allow(subject).to receive(:label_text).with(:color, a: "b").and_return("xx")
17
+ result = '<div class="label-wrap"><label for="book_color">xx</label></div>'
18
+
19
+ expect(subject.releaf_label(:color, {}, label: {a: "b"})).to eq(result)
20
+ end
21
+
22
+ it "uses #label_attributes for label attributes" do
23
+ allow(subject).to receive(:label_attributes).with(:color, {class: "red"}, {a: "b"}).and_return(class: "red blue")
24
+ result = '<div class="label-wrap"><label class="red blue" for="book_color">Color</label></div>'
25
+
26
+ expect(subject.releaf_label(:color, {class: "red"}, {a: "b"})).to eq(result)
27
+ end
28
+
29
+ context "when options[:label][:description] is not blank" do
30
+ context "when label has full version" do
31
+ it "includes description" do
32
+ result = '<div class="label-wrap"><label for="book_color">Color</label><div class="description">xxx</div></div>'
33
+ expect(subject.releaf_label(:color, {}, label: {description: "xxx"})).to eq(result)
34
+ end
35
+ end
36
+
37
+ context "when label has minimal version" do
38
+ it "does not include description" do
39
+ result = '<label for="book_color">Color</label>'
40
+ expect(subject.releaf_label(:color, {}, label: {minimal: true})).to eq(result)
41
+ end
42
+ end
43
+ end
44
+
45
+ context "when options[:label][:minimal] is true" do
46
+ it "returns label tag without wrap element" do
47
+ result = '<label for="book_color">Color</label>'
48
+ expect(subject).to_not receive(:wrapper)
49
+ expect(subject.releaf_label(:color, {}, label: {minimal: true})).to eq(result)
50
+ end
51
+ end
52
+
53
+ context "when options[:label][:minimal] is not true" do
54
+ it "returns label tag with wrap element" do
55
+ allow(subject).to receive(:wrapper).with('<label for="book_color">Color</label>', class: "label-wrap").and_return("x")
56
+ expect(subject.releaf_label(:color, {}, label: {minimal: false})).to eq("x")
57
+ expect(subject.releaf_label(:color, {}, label: {minimal: nil})).to eq("x")
58
+ expect(subject.releaf_label(:color, {}, label: {adasd: "xx"})).to eq("x")
59
+ end
60
+ end
61
+ end
62
+
63
+ describe "#label_attributes" do
64
+ it "returns unmodified attributes (allow further override by other builders)" do
65
+ expect(subject.label_attributes(:color, {data: "x"}, {})).to eq(data: "x")
66
+ end
67
+ end
68
+
69
+ describe "#label_text" do
70
+ it "returns model attributes scoped translated value" do
71
+ allow(subject).to receive(:translate_attribute).with("color").and_return("x")
72
+ expect(subject.label_text(:color)).to eq("x")
73
+ end
74
+
75
+ context "when :label_text option exists" do
76
+ context "when :label_text is not blank" do
77
+ it "returns :label_text option" do
78
+ expect(subject.label_text(:color, label_text: "krāsa")).to eq("krāsa")
79
+ end
80
+ end
81
+
82
+ context "when :label_text is blank" do
83
+ it "returns translated value" do
84
+ expect(subject.label_text(:color, label_text: nil)).to eq("Color")
85
+ expect(subject.label_text(:color, label_text: "")).to eq("Color")
86
+ end
87
+ end
88
+ end
89
+
90
+ context "when :translation_key option exists" do
91
+ context "when :translation_key is not blank" do
92
+ it "passes :translation_key option to translation and return translated value" do
93
+ allow(subject).to receive(:translate_attribute).with("true_color").and_return("x")
94
+ expect(subject.label_text(:color, translation_key: "true_color")).to eq("x")
95
+ end
96
+ end
97
+
98
+ context "when :translation_key is blank" do
99
+ it "returns translated value" do
100
+ expect(subject.label_text(:color, translation_key: nil)).to eq("Color")
101
+ expect(subject.label_text(:color, translation_key: "")).to eq("Color")
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,37 @@
1
+ require "rails_helper"
2
+
3
+ describe Releaf::Builders::FormBuilder::NumberFields, type: :class do
4
+ class FormBuilderTestHelper < ActionView::Base
5
+ include Releaf::ApplicationHelper
6
+ include Releaf::ButtonHelper
7
+ include FontAwesome::Rails::IconHelper
8
+ end
9
+
10
+ let(:template){ FormBuilderTestHelper.new }
11
+ let(:object){ Book.new }
12
+ let(:subject){ Releaf::Builders::FormBuilder.new(:book, object, template, {}) }
13
+
14
+ describe "#releaf_number_field" do
15
+ it "returns input with type 'number'" do
16
+ expect(subject).to receive(:number_field).with("title", { value: nil, step: "any", class: "text" }).and_return("x")
17
+ expect(subject).to receive(:input_wrapper_with_label).with("title", "x", { label: {}, field: {}, options: { field: { type: "number" }}}).and_return("y")
18
+ expect(subject.releaf_number_field("title")).to eq("y")
19
+ end
20
+
21
+ context "aliases" do
22
+ let(:releaf_number_field_method) { subject.method(:releaf_number_field) }
23
+
24
+ it "is aliased by #releaf_integer_field" do
25
+ expect(subject.method(:releaf_integer_field)).to eq(releaf_number_field_method)
26
+ end
27
+
28
+ it "is aliased by #releaf_float_field" do
29
+ expect(subject.method(:releaf_float_field)).to eq(releaf_number_field_method)
30
+ end
31
+
32
+ it "is aliased by #releaf_decimal_field" do
33
+ expect(subject.method(:releaf_decimal_field)).to eq(releaf_number_field_method)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,228 @@
1
+ require "rails_helper"
2
+
3
+ describe Releaf::Builders::FormBuilder, type: :class do
4
+ class FormBuilderTestHelper < ActionView::Base
5
+ include Releaf::ApplicationHelper
6
+ include Releaf::ButtonHelper
7
+ include FontAwesome::Rails::IconHelper
8
+ end
9
+
10
+ let(:template){ FormBuilderTestHelper.new }
11
+ let(:object){ Book.new }
12
+ let(:subject){ described_class.new(:book, object, template, {}) }
13
+ let(:normalized_fields){
14
+ [
15
+ {
16
+ render_method: "render_title",
17
+ field: "title",
18
+ subfields: nil
19
+ },
20
+ {
21
+ render_method: "render_author_id",
22
+ field: "author_id",
23
+ subfields: nil
24
+ },
25
+ {
26
+ render_method: "render_chapters",
27
+ field: :chapters,
28
+ subfields: ["title", "text", "sample_html"]
29
+ },
30
+ {
31
+ render_method: "render_book_sequels",
32
+ field: :book_sequels,
33
+ subfields: ["sequel_id"]
34
+ }
35
+ ]
36
+ }
37
+
38
+ it "includes Releaf::Builders::Base" do
39
+ expect(described_class.ancestors).to include(Releaf::Builders::Base)
40
+ end
41
+
42
+ describe "#field_names" do
43
+ it "returns field names for object class" do
44
+ allow(Releaf::ResourceFields).to receive(:new).with(object.class).and_call_original
45
+ allow_any_instance_of(Releaf::ResourceFields).to receive(:values).and_return(["a", "b"])
46
+ expect(subject.field_names).to eq(["a", "b"])
47
+ end
48
+ end
49
+
50
+ describe "#field_type_method" do
51
+ it "returns field type method resolved with ``" do
52
+ allow(Releaf::Builders::Utilities::ResolveAttributeFieldMethodName).to receive(:call)
53
+ .with(object: object, attribute_name: "color").and_return("some_method")
54
+ expect(subject.field_type_method(:color)).to eq("some_method")
55
+ end
56
+ end
57
+
58
+ describe "#field_render_method_name" do
59
+ it "returns method name for given field" do
60
+ expect(subject.field_render_method_name(:title)).to eq("render_title")
61
+ end
62
+
63
+ context "when builder has parent builder(-s)" do
64
+ it "traverses through all builders and add relation name option to field name" do
65
+ root_builder = described_class.new(:author, Author.new, template, {})
66
+ middle_builder = described_class.new(:author, Author.new, template, {relation_name: :pages, parent_builder: root_builder})
67
+ subject.options[:parent_builder] = middle_builder
68
+ subject.options[:relation_name] = :chapters
69
+
70
+ expect(subject.field_render_method_name(:title)).to eq("render_pages_chapters_title")
71
+ end
72
+ end
73
+ end
74
+
75
+ describe "#normalize_fields" do
76
+ it "returns normalized fields for use with #releaf_fields method" do
77
+ fields = [
78
+ "title",
79
+ "author_id",
80
+ {chapters: ["title", "text", "sample_html"]},
81
+ {book_sequels: ["sequel_id"]}
82
+ ]
83
+ expect(subject.normalize_fields(fields)).to eq(normalized_fields)
84
+ end
85
+
86
+ it "handles multi-key hashes" do
87
+ fields = [
88
+ "title",
89
+ "author_id",
90
+ {
91
+ chapters: ["title", "text", "sample_html"],
92
+ book_sequels: ["sequel_id"]
93
+ }
94
+ ]
95
+ expect(subject.normalize_fields(fields)).to eq(normalized_fields)
96
+ end
97
+ end
98
+
99
+ describe "#releaf_fields" do
100
+ it "normalizes given fields with #normalize_fields" do
101
+ allow(subject).to receive(:render_field_by_options)
102
+ expect(subject).to receive(:normalize_fields).with([:a, :b]).and_return([:x, :y])
103
+ subject.releaf_fields(:a, :b)
104
+ end
105
+
106
+ it "passes all normalized field options to #render_field" do
107
+ allow(subject).to receive(:normalize_fields).and_return([:x, :y])
108
+ expect(subject).to receive(:render_field_by_options).with(:x)
109
+ expect(subject).to receive(:render_field_by_options).with(:y)
110
+ subject.releaf_fields(:a, :b)
111
+ end
112
+
113
+ it "concatenates and return all #render_field_by_options outputs with #safe_join" do
114
+ allow(subject).to receive(:render_field_by_options).and_return('_a_', '_b_')
115
+ allow(subject).to receive(:normalize_fields).and_return([:x, :y])
116
+ expect(subject).to receive(:safe_join).with(no_args){|&block|
117
+ expect(block.call).to eq(['_a_', '_b_'])
118
+ }.and_return("xxx")
119
+ expect(subject.releaf_fields(:a, :b)).to eq("xxx")
120
+ end
121
+ end
122
+
123
+ describe "#render_field_by_options" do
124
+ let(:options){ {
125
+ render_method: "sortable_column_name", # just random method here
126
+ field: "title",
127
+ subfields: [:a, :b],
128
+ } }
129
+
130
+ before do
131
+ allow(subject).to receive(:reflect_on_association).with("title").and_return(:x)
132
+ allow(subject).to receive(:sortable_column_name)
133
+ .with(no_args).and_return("_render_method_content_")
134
+ allow(subject).to receive(:releaf_association_fields)
135
+ .with(:x, [:a, :b]).and_return("_association_method_content_")
136
+ allow(subject).to receive(:releaf_field)
137
+ .with("title").and_return("_releaf_field_content_")
138
+ end
139
+
140
+ context "when method defined in options[:render_method] exists" do
141
+ it "returns this method output" do
142
+ expect(subject.render_field_by_options(options)).to eq("_render_method_content_")
143
+ end
144
+ end
145
+
146
+ context "when custom method does not exist" do
147
+ before do
148
+ options[:render_method] = "something_unexisting"
149
+ end
150
+
151
+ context "when reflection exists for given field" do
152
+ it "returns #releaf_association_fields by passing options[:field] and options[:subfields]" do
153
+ expect(subject.render_field_by_options(options)).to eq("_association_method_content_")
154
+ end
155
+ end
156
+
157
+ context "when reflection does not exist for given field" do
158
+ it "returns #releaf_field with options[:field] as argument" do
159
+ allow(subject).to receive(:reflect_on_association).with("title").and_return(nil)
160
+ expect(subject.render_field_by_options(options)).to eq("_releaf_field_content_")
161
+ end
162
+ end
163
+ end
164
+ end
165
+
166
+ describe "#input_wrapper_with_label" do
167
+ before do
168
+ allow(subject).to receive(:wrapper).with("input_content", class: "value").and_return("input_content")
169
+ allow(subject).to receive(:releaf_label).with(:color, "label_attributes", "options").and_return("label_content")
170
+ allow(subject).to receive(:field).with(:color, "field_attributes", "options"){ |name, field, options, &block|
171
+ expect(block.call).to eq("label_contentinput_content")
172
+ }.and_return("content")
173
+ end
174
+
175
+ it "returns wrapped label and input content" do
176
+ expect(subject.input_wrapper_with_label(:color, "input_content", label: "label_attributes", field: "field_attributes", options: "options"))
177
+ .to eq("content")
178
+ end
179
+
180
+ context "when block given" do
181
+ it "safely concatinate block output to content" do
182
+ content = 'input_content<input type="hidden" name="book[id]" id="book_id" />'
183
+ allow(subject).to receive(:wrapper).with(content, class: "value").and_return("input_content")
184
+ expect(subject.input_wrapper_with_label(:color, "input_content", label: "label_attributes", field: "field_attributes", options: "options"){ subject.hidden_field(:id) })
185
+ .to eq("content")
186
+ end
187
+
188
+ it "correctly handles block nil output" do
189
+ expect(subject.input_wrapper_with_label(:color, "input_content", label: "label_attributes", field: "field_attributes", options: "options"){ })
190
+ .to eq("content")
191
+ end
192
+ end
193
+ end
194
+
195
+ describe "#field_attributes" do
196
+ it "adds field data and class attributes and cast name to string within data attributes" do
197
+ expect(subject.field_attributes(:color, {}, {field: {type: "text"}})).to eq(data: {name: "color"}, class: ["field", "type-text"])
198
+ end
199
+
200
+ it "merges attributes over build-in data hash" do
201
+ expect(subject.field_attributes(:color, {data: {other: "x"}}, {})[:data]).to eq(name: "color", other: "x")
202
+ expect(subject.field_attributes(:color, {data: {other: "x", name: :lll}}, {})[:data]).to eq(name: :lll, other: "x")
203
+ end
204
+
205
+ it "supports class attributes merging" do
206
+ expect(subject.field_attributes(:color, {class: ["a", "b"]}, {})[:class]).to eq(["field", "type-", "a", "b"])
207
+ end
208
+ end
209
+
210
+ describe "#input_attributes" do
211
+ it "returns unmodified attributes (allow further override by other builders)" do
212
+ expect(subject.input_attributes(:color, {data: "x"}, {})).to eq(data: "x")
213
+ end
214
+ end
215
+
216
+ describe "#sortable_column_name" do
217
+ it "returns 'item_position'" do
218
+ expect( subject.sortable_column_name ).to eq 'item_position'
219
+ end
220
+ end
221
+
222
+ describe "#translate_attribute" do
223
+ it "translates given attribute within object translation scope" do
224
+ allow(object.class).to receive(:human_attribute_name).with("x").and_return("z")
225
+ expect(subject.translate_attribute("x")).to eq("z")
226
+ end
227
+ end
228
+ end
@@ -6,11 +6,7 @@ describe Releaf::Builders::IndexBuilder, type: :class do
6
6
  delegate :resource_class, :table_options, to: :controller
7
7
 
8
8
  def controller
9
- @controller ||= begin
10
- c = Admin::BooksController.new
11
- c.setup
12
- c
13
- end
9
+ @controller ||= Admin::BooksController.new
14
10
  end
15
11
  end
16
12
 
@@ -85,9 +81,22 @@ describe Releaf::Builders::IndexBuilder, type: :class do
85
81
  end
86
82
 
87
83
  describe "#header_extras" do
88
- it "returns search block" do
84
+ before do
89
85
  allow(subject).to receive(:search_block).and_return("x")
90
- expect(subject.header_extras).to eq("x")
86
+ end
87
+
88
+ context "when search feature is enabled" do
89
+ it "returns search block" do
90
+ allow(subject).to receive(:feature_available?).with(:search).and_return(true)
91
+ expect(subject.header_extras).to eq("x")
92
+ end
93
+ end
94
+
95
+ context "when search feature is disabled" do
96
+ it "returns nil" do
97
+ allow(subject).to receive(:feature_available?).with(:search).and_return(false)
98
+ expect(subject.header_extras).to be nil
99
+ end
91
100
  end
92
101
  end
93
102
 
@@ -318,11 +327,8 @@ describe Releaf::Builders::IndexBuilder, type: :class do
318
327
  expect(subject).to receive(:pagination_builder_class).and_return(dummy)
319
328
  expect( subject.pagination_block).to eq :ok
320
329
  end
321
-
322
330
  end
323
331
 
324
-
325
-
326
332
  describe "#resource_creation_button" do
327
333
  it "returns resource creation button" do
328
334
  allow(subject.template).to receive(:url_for).with(controller: "_controller_name_", action: "new").and_return("x")
@@ -342,4 +348,17 @@ describe Releaf::Builders::IndexBuilder, type: :class do
342
348
  expect(subject.section_body).to eq('<div class="body">xx</div>')
343
349
  end
344
350
  end
351
+
352
+ describe "#table_options" do
353
+ it "returns table options" do
354
+ allow(subject).to receive(:builder_class).with(:table).and_return("CustomTableBuilderClassHere")
355
+ allow(subject).to receive(:feature_available?).with(:toolbox).and_return("boolean_value_here")
356
+
357
+ options = {
358
+ builder: "CustomTableBuilderClassHere",
359
+ toolbox: "boolean_value_here"
360
+ }
361
+ expect(subject.table_options).to eq(options)
362
+ end
363
+ end
345
364
  end
@@ -0,0 +1,65 @@
1
+ require "rails_helper"
2
+
3
+ describe Releaf::Builders::Page::HeaderBuilder, type: :class do
4
+ class PageHeaderBuilderTestHelper < ActionView::Base
5
+ include Rails.application.routes.url_helpers
6
+ include FontAwesome::Rails::IconHelper
7
+
8
+ def protect_against_forgery?
9
+ true
10
+ end
11
+
12
+ def form_authenticity_token
13
+ "xxx"
14
+ end
15
+
16
+ def request_forgery_protection_token
17
+ "yyy"
18
+ end
19
+ end
20
+
21
+ subject { described_class.new(template) }
22
+ let(:template){ PageHeaderBuilderTestHelper.new }
23
+
24
+ describe "#output" do
25
+ it "returns safely joined items" do
26
+ allow(subject).to receive(:items).and_return([ '<', ActiveSupport::SafeBuffer.new(">")])
27
+ expect(subject.output).to eq("&lt;>")
28
+ end
29
+ end
30
+
31
+ describe "#items" do
32
+ it "returns array of home link, profile block and logout form content" do
33
+ allow(subject).to receive(:home_link).and_return("a")
34
+ expect(subject.items).to eq(["a"])
35
+ end
36
+ end
37
+
38
+ describe "#home_link" do
39
+ it "returns home link with a logo" do
40
+ allow(subject).to receive(:home_url).and_return("www.xxx")
41
+ allow(subject).to receive(:home_text).and_return("Rrr")
42
+ allow(subject).to receive(:home_image_path).and_return("releaf/foo.png")
43
+ content = '<a class="home" href="www.xxx"><img alt="Rrr" src="/images/releaf/foo.png" /></a>'
44
+ expect(subject.home_link).to eq(content)
45
+ end
46
+ end
47
+
48
+ describe "#home_url" do
49
+ it "returns home url" do
50
+ expect(subject.home_url).to eq("/admin")
51
+ end
52
+ end
53
+
54
+ describe "#home_image_path" do
55
+ it "returns image to the logo image asset" do
56
+ expect(subject.home_image_path).to eq("releaf/logo.png")
57
+ end
58
+ end
59
+
60
+ describe "#home_text" do
61
+ it "returns releaf home link text" do
62
+ expect(subject.home_text).to eq("Releaf")
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,170 @@
1
+ require "rails_helper"
2
+
3
+ describe Releaf::Builders::Page::LayoutBuilder, type: :class do
4
+ class DummyBuilder
5
+ include Releaf::Builders::Base
6
+ include Releaf::Builders::Template
7
+ def output; end
8
+ end
9
+
10
+ class DummyAssetsResolver
11
+ def self.controller_assets(_a, _b); end
12
+ end
13
+
14
+ class PageHeaderBuilderTestHelper < ActionView::Base
15
+ include Rails.application.routes.url_helpers
16
+ include FontAwesome::Rails::IconHelper
17
+
18
+ def protect_against_forgery?
19
+ true
20
+ end
21
+
22
+ def form_authenticity_token
23
+ "xxx"
24
+ end
25
+
26
+ def request_forgery_protection_token
27
+ "yyy"
28
+ end
29
+ end
30
+
31
+ class NewRolesController < Releaf::Permissions::RolesController
32
+ end
33
+
34
+ subject { described_class.new(template) }
35
+ let(:template){ PageHeaderBuilderTestHelper.new }
36
+
37
+ describe "#controller_classes" do
38
+ it "returns array of ignorable ancester classes" do
39
+ allow(subject).to receive(:controller).and_return(NewRolesController.new)
40
+ expect(subject.controller_classes).to eq([Releaf::Permissions::RolesController, NewRolesController])
41
+
42
+ allow(subject).to receive(:controller).and_return(Releaf::Permissions::RolesController.new)
43
+ expect(subject.controller_classes).to eq([Releaf::Permissions::RolesController])
44
+
45
+ allow(subject).to receive(:controller).and_return(Releaf::Permissions::SessionsController.new)
46
+ expect(subject.controller_classes).to eq([Releaf::Permissions::SessionsController])
47
+ end
48
+ end
49
+
50
+ describe "#header_builder" do
51
+ it "returns `Releaf::Builders::Page::HeaderBuilder` class" do
52
+ expect(subject.header_builder).to eq(Releaf::Builders::Page::HeaderBuilder)
53
+ end
54
+ end
55
+
56
+ describe "#assets_resolver" do
57
+ it "returns `Releaf::AssetsResolver` class" do
58
+ expect(subject.assets_resolver).to eq(Releaf::AssetsResolver)
59
+ end
60
+ end
61
+
62
+ describe "#stylesheets" do
63
+ it "returns stylesheets from assets resolver for given controller" do
64
+ allow(subject).to receive(:assets_resolver).and_return(DummyAssetsResolver)
65
+ allow(subject).to receive(:controller_name).and_return("_controller")
66
+ allow(DummyAssetsResolver).to receive(:controller_assets).with("_controller", :stylesheets)
67
+ .and_return("x")
68
+ expect(subject.stylesheets).to eq("x")
69
+ end
70
+ end
71
+
72
+ describe "#javascripts" do
73
+ it "returns javascripts from assets resolver for given controller" do
74
+ allow(subject).to receive(:assets_resolver).and_return(DummyAssetsResolver)
75
+ allow(subject).to receive(:controller_name).and_return("_controller")
76
+ allow(DummyAssetsResolver).to receive(:controller_assets).with("_controller", :javascripts)
77
+ .and_return("y")
78
+ expect(subject.javascripts).to eq("y")
79
+ end
80
+ end
81
+
82
+ describe "#header" do
83
+ it "returns menu builder output wrapped within `aside` tag" do
84
+ menu_builder = DummyBuilder.new(template)
85
+ allow(menu_builder).to receive(:output).and_return("_header")
86
+ allow(DummyBuilder).to receive(:new).with(template).and_return(menu_builder)
87
+ allow(subject).to receive(:header_builder).and_return(DummyBuilder)
88
+ allow(subject).to receive(:tag).with(:header, "_header").and_return("<_header>")
89
+
90
+ expect(subject.header).to eq("<_header>")
91
+ end
92
+ end
93
+
94
+ describe "#menu" do
95
+ it "returns menu builder output wrapped within `aside` tag" do
96
+ menu_builder = DummyBuilder.new(template)
97
+ allow(menu_builder).to receive(:output).and_return("_menu")
98
+ allow(DummyBuilder).to receive(:new).with(template).and_return(menu_builder)
99
+ allow(subject).to receive(:menu_builder).and_return(DummyBuilder)
100
+ allow(subject).to receive(:tag).with(:aside, "_menu").and_return("<_menu>")
101
+
102
+ expect(subject.menu).to eq("<_menu>")
103
+ end
104
+ end
105
+
106
+ describe "#menu_builder" do
107
+ it "returns `Releaf::Builders::Page::MenuBuilder` class" do
108
+ expect(subject.menu_builder).to eq(Releaf::Builders::Page::MenuBuilder)
109
+ end
110
+ end
111
+
112
+ describe "#body" do
113
+ it "returns body with body attributes and" do
114
+ allow(subject).to receive(:assets).with(:javascripts, :javascript_include_tag).and_return("_assets_")
115
+ allow(subject).to receive(:body_atttributes).and_return(class: ["xx", "y"], id: "121212")
116
+ allow(subject).to receive(:body_content){|*args, &block| expect(block.call).to eq("x") }.and_return("body content")
117
+ expect(subject.body{ "x" }).to eq("<body class=\"xx y\" id=\"121212\">body content_assets_</body>")
118
+ end
119
+ end
120
+
121
+ describe "#controller_body_classes" do
122
+ it "returns normalized html classes from controller classes" do
123
+ allow(subject).to receive(:controller_classes).and_return([Releaf::ActionController, Releaf::Permissions::RolesController])
124
+ expect(subject.controller_body_classes).to eq(["controller-releaf-action", "controller-releaf-permissions-roles"])
125
+ end
126
+ end
127
+
128
+ describe "#settings_path" do
129
+ it "returns root controller settings path" do
130
+ allow(subject).to receive(:url_for).with(action: "store_settings", controller: "/releaf/root", only_path: true)
131
+ .and_return("asdasdasd")
132
+ expect(subject.settings_path).to eq("asdasdasd")
133
+ end
134
+ end
135
+
136
+ describe "#body_atttributes" do
137
+ it "returns hash with classes and data-settings-path" do
138
+ allow(subject).to receive(:controller_body_classes).and_return(["a", "b"])
139
+ allow(subject).to receive(:settings_path).and_return("/xxx/sett")
140
+ expect(subject.body_atttributes).to eq(class: ["application-dummy", "a", "b"], "data-settings-path" => "/xxx/sett")
141
+ end
142
+ end
143
+
144
+ describe "#head_blocks" do
145
+ it "returns array" do
146
+ {
147
+ title: :title_sym,
148
+ meta: :meta_sym,
149
+ favicons: :favicon_sym,
150
+ ms_tile: :ms_tile_sym,
151
+ assets: :assets_sym,
152
+ csrf: :csrf_sym,
153
+ }.each_pair do |method, stub_answer|
154
+ allow(subject).to receive(method).and_return stub_answer
155
+ end
156
+
157
+ expect(subject.head_blocks).to match_array(
158
+ [
159
+ :title_sym,
160
+ :meta_sym,
161
+ :favicon_sym,
162
+ :ms_tile_sym,
163
+ :assets_sym,
164
+ :csrf_sym,
165
+ ]
166
+ )
167
+ end
168
+ end
169
+ end
170
+