alchemy_cms 2.6.3 → 2.7.0

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 (246) hide show
  1. checksums.yaml +4 -4
  2. data/.simplecov +14 -0
  3. data/.travis.yml +1 -1
  4. data/Gemfile +7 -6
  5. data/README.md +15 -5
  6. data/alchemy_cms.gemspec +3 -2
  7. data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +9 -17
  8. data/app/assets/javascripts/alchemy/alchemy.dirty.js.coffee +70 -0
  9. data/app/assets/javascripts/alchemy/alchemy.dragndrop.js.coffee +80 -0
  10. data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +43 -19
  11. data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +3 -1
  12. data/app/assets/javascripts/alchemy/alchemy.js +4 -2
  13. data/app/assets/javascripts/alchemy/alchemy.onload.js.coffee +1 -1
  14. data/app/assets/javascripts/alchemy/alchemy.spinner.js.coffee +14 -0
  15. data/app/assets/javascripts/alchemy/alchemy.tinymce.js.coffee.erb +96 -0
  16. data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +22 -0
  17. data/app/assets/javascripts/alchemy/alchemy.windows.js.coffee +28 -17
  18. data/app/assets/stylesheets/alchemy/base.scss +6 -0
  19. data/app/assets/stylesheets/alchemy/elements.scss +2 -28
  20. data/app/assets/stylesheets/alchemy/errors.scss +1 -1
  21. data/app/assets/stylesheets/alchemy/menubar.css.scss +2 -0
  22. data/app/assets/stylesheets/alchemy/sitemap.scss +21 -34
  23. data/app/assets/stylesheets/alchemy/tables.scss +13 -3
  24. data/app/controllers/alchemy/admin/attachments_controller.rb +10 -5
  25. data/app/controllers/alchemy/admin/base_controller.rb +19 -0
  26. data/app/controllers/alchemy/admin/contents_controller.rb +1 -4
  27. data/app/controllers/alchemy/admin/dashboard_controller.rb +2 -1
  28. data/app/controllers/alchemy/admin/elements_controller.rb +1 -1
  29. data/app/controllers/alchemy/admin/essence_files_controller.rb +1 -1
  30. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +70 -56
  31. data/app/controllers/alchemy/admin/pages_controller.rb +37 -114
  32. data/app/controllers/alchemy/admin/pictures_controller.rb +5 -12
  33. data/app/controllers/alchemy/admin/resources_controller.rb +3 -1
  34. data/app/controllers/alchemy/admin/trash_controller.rb +1 -1
  35. data/app/controllers/alchemy/attachments_controller.rb +1 -1
  36. data/app/controllers/alchemy/base_controller.rb +3 -15
  37. data/app/controllers/alchemy/messages_controller.rb +4 -10
  38. data/app/controllers/alchemy/pages_controller.rb +6 -6
  39. data/app/controllers/alchemy/passwords_controller.rb +1 -1
  40. data/app/controllers/alchemy/user_sessions_controller.rb +1 -1
  41. data/app/helpers/alchemy/admin/base_helper.rb +49 -230
  42. data/app/helpers/alchemy/admin/contents_helper.rb +5 -1
  43. data/app/helpers/alchemy/admin/elements_helper.rb +19 -47
  44. data/app/helpers/alchemy/admin/essences_helper.rb +59 -17
  45. data/app/helpers/alchemy/admin/navigation_helper.rb +204 -0
  46. data/app/helpers/alchemy/admin/pages_helper.rb +22 -79
  47. data/app/helpers/alchemy/admin/pictures_helper.rb +1 -1
  48. data/app/helpers/alchemy/admin/tags_helper.rb +42 -0
  49. data/app/helpers/alchemy/base_helper.rb +0 -11
  50. data/app/helpers/alchemy/elements_helper.rb +48 -25
  51. data/app/helpers/alchemy/essences_helper.rb +0 -20
  52. data/app/helpers/alchemy/pages_helper.rb +18 -14
  53. data/app/helpers/alchemy/url_helper.rb +1 -0
  54. data/app/mailers/alchemy/messages.rb +4 -6
  55. data/app/models/alchemy/attachment.rb +3 -0
  56. data/app/models/alchemy/cell.rb +33 -35
  57. data/app/models/alchemy/content.rb +20 -111
  58. data/app/models/alchemy/content/factory.rb +188 -0
  59. data/app/models/alchemy/element.rb +51 -200
  60. data/app/models/alchemy/element/definitions.rb +52 -0
  61. data/app/models/alchemy/element/presenters.rb +87 -0
  62. data/app/models/alchemy/essence_date.rb +1 -1
  63. data/app/models/alchemy/essence_file.rb +6 -7
  64. data/app/models/alchemy/essence_picture.rb +19 -4
  65. data/app/models/alchemy/message.rb +18 -14
  66. data/app/models/alchemy/page.rb +120 -214
  67. data/app/models/alchemy/page/elements.rb +145 -36
  68. data/app/models/alchemy/page/natures.rb +90 -0
  69. data/app/models/alchemy/page/scopes.rb +93 -0
  70. data/app/models/alchemy/page/users.rb +25 -0
  71. data/app/models/alchemy/picture.rb +15 -0
  72. data/app/models/alchemy/site.rb +15 -1
  73. data/app/models/alchemy/site/layout.rb +38 -0
  74. data/app/models/alchemy/user.rb +13 -3
  75. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +7 -7
  76. data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +8 -8
  77. data/app/views/alchemy/admin/attachments/_tag_list.html.erb +1 -16
  78. data/app/views/alchemy/admin/attachments/destroy.js.erb +1 -4
  79. data/app/views/alchemy/admin/contents/create.js.erb +1 -1
  80. data/app/views/alchemy/admin/dashboard/index.html.erb +14 -13
  81. data/app/views/alchemy/admin/elements/_element_head.html.erb +7 -7
  82. data/app/views/alchemy/admin/elements/_refresh_editor.js.erb +10 -0
  83. data/app/views/alchemy/admin/elements/create.js.erb +44 -44
  84. data/app/views/alchemy/admin/elements/fold.js.erb +22 -26
  85. data/app/views/alchemy/admin/elements/trash.js.erb +1 -1
  86. data/app/views/alchemy/admin/elements/update.js.erb +22 -25
  87. data/app/views/alchemy/admin/essence_files/assign.js.erb +8 -3
  88. data/app/views/alchemy/admin/essence_pictures/crop.html.erb +14 -12
  89. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +22 -39
  90. data/app/views/alchemy/admin/pages/_page.html.erb +73 -80
  91. data/app/views/alchemy/admin/pages/destroy.js.erb +2 -2
  92. data/app/views/alchemy/admin/pages/edit.html.erb +21 -18
  93. data/app/views/alchemy/admin/pages/fold.js.erb +1 -0
  94. data/app/views/alchemy/admin/pages/info.html.erb +32 -0
  95. data/app/views/alchemy/admin/partials/_main_navigation_entry.html.erb +11 -13
  96. data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +20 -20
  97. data/app/views/alchemy/admin/partials/_sub_navigation.html.erb +8 -0
  98. data/app/views/alchemy/admin/partials/_toolbar_button.html.erb +25 -0
  99. data/app/views/alchemy/admin/partials/_upload_form.html.erb +15 -15
  100. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +39 -39
  101. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +10 -10
  102. data/app/views/alchemy/admin/pictures/_tag_list.html.erb +1 -16
  103. data/app/views/alchemy/admin/resources/destroy.js.erb +1 -1
  104. data/app/views/alchemy/base/500.html.erb +1 -1
  105. data/app/views/alchemy/base/permission_denied.js.erb +1 -1
  106. data/app/views/alchemy/base/redirect.js.erb +1 -1
  107. data/app/views/alchemy/essences/_essence_link_editor.html.erb +1 -1
  108. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +1 -1
  109. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +1 -1
  110. data/app/views/alchemy/essences/_essence_text_editor.html.erb +1 -1
  111. data/app/views/alchemy/essences/{_essence_picture_tools.html.erb → shared/_essence_picture_tools.html.erb} +5 -5
  112. data/app/views/alchemy/essences/{_linkable_essence_tools.html.erb → shared/_linkable_essence_tools.html.erb} +0 -0
  113. data/app/views/alchemy/messages/contact_form_mail.de.text.erb +12 -0
  114. data/app/views/alchemy/messages/contact_form_mail.en.text.erb +12 -0
  115. data/app/views/alchemy/notifications/reset_password_instructions.de.text.erb +1 -1
  116. data/app/views/alchemy/notifications/reset_password_instructions.en.text.erb +2 -2
  117. data/app/views/alchemy/pages/sitemap.xml.erb +3 -5
  118. data/app/views/alchemy/user_sessions/leave.html.erb +1 -1
  119. data/app/views/layouts/alchemy/admin.html.erb +4 -2
  120. data/app/views/layouts/alchemy/sitemap.xml.erb +1 -1
  121. data/bin/alchemy +7 -13
  122. data/config/alchemy/config.yml +1 -0
  123. data/config/authorization_rules.rb +2 -3
  124. data/config/initializers/dragonfly.rb +2 -0
  125. data/config/locales/alchemy.de.yml +8 -9
  126. data/config/locales/alchemy.en.yml +7 -4
  127. data/config/routes.rb +3 -0
  128. data/db/migrate/{20130214233001_alchemy_two_point_five.rb → 20130827094554_alchemy_two_point_six.rb} +29 -6
  129. data/lib/alchemy/auth/engine.rb +9 -0
  130. data/lib/alchemy/capistrano.rb +37 -12
  131. data/lib/alchemy/config.rb +48 -35
  132. data/lib/alchemy/engine.rb +35 -6
  133. data/lib/alchemy/essence.rb +25 -29
  134. data/lib/alchemy/ferret/search.rb +86 -0
  135. data/lib/alchemy/{scoped_pagination_url_helper.rb → kaminari/scoped_pagination_url_helper.rb} +0 -0
  136. data/lib/alchemy/logger.rb +3 -4
  137. data/lib/alchemy/page_layout.rb +124 -55
  138. data/lib/alchemy/resource.rb +0 -10
  139. data/lib/alchemy/resources_helper.rb +0 -5
  140. data/lib/alchemy/seeder.rb +1 -32
  141. data/lib/alchemy/shell.rb +6 -1
  142. data/lib/alchemy/tinymce.rb +41 -32
  143. data/lib/alchemy/upgrader.rb +3 -1
  144. data/lib/alchemy/upgrader/two_point_five.rb +15 -8
  145. data/lib/alchemy/upgrader/two_point_one.rb +10 -10
  146. data/lib/alchemy/upgrader/two_point_two.rb +96 -51
  147. data/lib/alchemy/version.rb +1 -1
  148. data/lib/alchemy_cms.rb +5 -46
  149. data/lib/rails/generators/alchemy/deploy_script/templates/deploy.rb.tt +1 -1
  150. data/lib/rails/generators/alchemy/devise/devise_generator.rb +9 -4
  151. data/lib/rails/generators/alchemy/essence/essence_generator.rb +7 -6
  152. data/lib/rails/generators/alchemy/essence/templates/editor.html.erb +1 -1
  153. data/lib/rails/generators/alchemy/scaffold/files/_standard.html.erb +1 -0
  154. data/lib/rails/generators/alchemy/scaffold/scaffold_generator.rb +1 -0
  155. data/lib/rails/generators/alchemy/site_layouts/site_layouts_generator.rb +23 -0
  156. data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.erb +1 -0
  157. data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.haml +1 -0
  158. data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.slim +1 -0
  159. data/lib/rails/templates/alchemy.rb +2 -2
  160. data/lib/tasks/alchemy/db.rake +3 -1
  161. data/lib/tasks/alchemy/tidy.rake +82 -0
  162. data/lib/tasks/alchemy/upgrade.rake +2 -1
  163. data/spec/controllers/admin/attachments_controller_spec.rb +124 -0
  164. data/spec/controllers/admin/base_controller_spec.rb +35 -0
  165. data/spec/controllers/admin/clipboard_controller_spec.rb +1 -1
  166. data/spec/controllers/admin/contents_controller_spec.rb +17 -26
  167. data/spec/controllers/admin/dashboard_controller_spec.rb +121 -0
  168. data/spec/controllers/admin/elements_controller_spec.rb +1 -1
  169. data/spec/controllers/admin/essence_files_controller_spec.rb +67 -0
  170. data/spec/controllers/admin/essence_pictures_controller_spec.rb +161 -0
  171. data/spec/controllers/admin/languages_controller_spec.rb +1 -1
  172. data/spec/controllers/admin/layoutpages_controller_spec.rb +28 -0
  173. data/spec/controllers/admin/pages_controller_spec.rb +164 -118
  174. data/spec/controllers/admin/pictures_controller_spec.rb +89 -0
  175. data/spec/controllers/admin/trash_controller_spec.rb +21 -31
  176. data/spec/controllers/admin/users_controller_spec.rb +114 -85
  177. data/spec/controllers/attachments_controller_spec.rb +6 -2
  178. data/spec/controllers/base_controller_spec.rb +22 -0
  179. data/spec/controllers/elements_controller_spec.rb +1 -1
  180. data/spec/controllers/messages_controller_spec.rb +200 -0
  181. data/spec/controllers/pictures_controller_spec.rb +1 -1
  182. data/spec/controllers/user_sessions_controller_spec.rb +7 -6
  183. data/spec/controllers/users_controller_spec.rb +2 -2
  184. data/spec/dummy/config/alchemy/cells.yml +2 -0
  185. data/spec/dummy/config/application.rb +19 -8
  186. data/spec/dummy/db/migrate/{20130214233001_alchemy_two_point_five.rb → 20130827094554_alchemy_two_point_six.rb} +29 -6
  187. data/spec/dummy/db/schema.rb +1 -1
  188. data/spec/fast_specs.rb +15 -0
  189. data/spec/helpers/admin/base_helper_spec.rb +53 -34
  190. data/spec/helpers/admin/contents_helper_spec.rb +15 -7
  191. data/spec/helpers/admin/elements_helper_spec.rb +79 -34
  192. data/spec/helpers/admin/essences_helper_spec.rb +45 -31
  193. data/spec/helpers/admin/navigation_helper_spec.rb +204 -0
  194. data/spec/helpers/admin/pages_helper_spec.rb +25 -15
  195. data/spec/helpers/admin/tags_helper_spec.rb +62 -2
  196. data/spec/helpers/elements_helper_spec.rb +202 -138
  197. data/spec/helpers/pages_helper_spec.rb +48 -0
  198. data/spec/helpers/url_helper_spec.rb +7 -0
  199. data/spec/libraries/config_spec.rb +110 -3
  200. data/spec/libraries/essence_spec.rb +29 -9
  201. data/spec/libraries/page_layout_spec.rb +134 -0
  202. data/spec/libraries/resource_spec.rb +3 -16
  203. data/spec/libraries/resources_helper_spec.rb +4 -8
  204. data/spec/libraries/shell_spec.rb +1 -0
  205. data/spec/libraries/tinymce_spec.rb +61 -0
  206. data/spec/mailers/messages_spec.rb +23 -0
  207. data/spec/models/attachment_spec.rb +45 -0
  208. data/spec/models/cell_spec.rb +62 -9
  209. data/spec/models/content_spec.rb +110 -28
  210. data/spec/models/element_spec.rb +275 -253
  211. data/spec/models/essence_date_spec.rb +25 -0
  212. data/spec/models/essence_file_spec.rb +23 -0
  213. data/spec/models/essence_html_spec.rb +13 -0
  214. data/spec/models/essence_picture_spec.rb +16 -0
  215. data/spec/models/essence_text_spec.rb +29 -0
  216. data/spec/models/language_spec.rb +34 -0
  217. data/spec/models/message_spec.rb +43 -0
  218. data/spec/models/page_spec.rb +726 -567
  219. data/spec/models/picture_spec.rb +98 -0
  220. data/spec/models/site_spec.rb +60 -2
  221. data/spec/models/tag_spec.rb +31 -0
  222. data/spec/models/user_spec.rb +4 -4
  223. data/spec/spec_helper.rb +49 -58
  224. data/spec/support/alchemy/controller_helpers.rb +35 -0
  225. data/spec/support/alchemy/{specs_helpers.rb → integration_helpers.rb} +4 -8
  226. data/spec/{factories.rb → support/factories.rb} +11 -1
  227. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js +2 -8
  228. metadata +166 -106
  229. data/Guardfile +0 -16
  230. data/app/assets/javascripts/alchemy/alchemy.dirty.js +0 -93
  231. data/app/assets/javascripts/alchemy/alchemy.dragndrop.js +0 -122
  232. data/app/models/alchemy/tree_node.rb +0 -4
  233. data/app/views/alchemy/admin/pages/_page_infos.html.erb +0 -3
  234. data/app/views/alchemy/admin/partials/_sub_navigation_tab.html.erb +0 -8
  235. data/app/views/alchemy/messages/contact_form_mail.text.erb +0 -12
  236. data/config/initializers/kaminari_config.rb +0 -9
  237. data/db/migrate/20130221200514_migrate_attachments_to_dragonfly.rb +0 -21
  238. data/db/migrate/20130312205327_change_alchemy_users_role_to_roles.rb +0 -11
  239. data/lib/alchemy/auth_engine.rb +0 -7
  240. data/lib/alchemy/authentication_helpers.rb +0 -9
  241. data/lib/alchemy/ferret_search.rb +0 -84
  242. data/lib/extensions/array.rb +0 -25
  243. data/lib/extensions/hash.rb +0 -34
  244. data/spec/dummy/db/migrate/20130221200514_migrate_attachments_to_dragonfly.rb +0 -21
  245. data/spec/dummy/db/migrate/20130312205327_change_alchemy_users_role_to_roles.rb +0 -11
  246. data/spec/models/page_layout_spec.rb +0 -60
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ module Alchemy
4
+ describe Tinymce do
5
+
6
+ describe '.init' do
7
+ subject { Tinymce.init }
8
+
9
+ it "returns the default config" do
10
+ should eq(Tinymce.class_variable_get('@@init'))
11
+ end
12
+ end
13
+
14
+ describe '.init=' do
15
+ let(:another_config) { {theme_advanced_buttons3: 'table'} }
16
+
17
+ it "merges the default config with given config" do
18
+ Tinymce.init = another_config
19
+ Tinymce.init.should include(another_config)
20
+ end
21
+ end
22
+
23
+ context 'Methods for contents with custom tinymce config.' do
24
+ let(:content_definition) { {'name' => 'text', 'settings' => {'tinymce' => {'foo' => 'bar'}}} }
25
+ let(:element_definition) { {'name' => 'article', 'contents' => [content_definition]} }
26
+
27
+ describe '.custom_config_contents' do
28
+ subject { Tinymce.custom_config_contents }
29
+
30
+ before do
31
+ Element.stub(:definitions).and_return([element_definition])
32
+ # Preventing memoization
33
+ Tinymce.class_variable_set('@@custom_config_contents', nil)
34
+ end
35
+
36
+ it "returns an array of content definitions that contain custom tinymce config and element name" do
37
+ should be_an(Array)
38
+ should include({'element' => element_definition['name']}.merge(content_definition))
39
+ end
40
+
41
+ context 'with no contents having custom tinymce config' do
42
+ let(:content_definition) { {'name' => 'text'} }
43
+ it { should eq([]) }
44
+ end
45
+ end
46
+
47
+ describe '.page_custom_config_contents' do
48
+ let(:page) { FactoryGirl.build_stubbed(:page) }
49
+ subject { Tinymce.page_custom_config_contents(page) }
50
+
51
+ before { page.stub(:element_definitions).and_return([element_definition]) }
52
+
53
+ it "returns an array of content definitions that contain custom tinymce config for page" do
54
+ should be_an(Array)
55
+ should include({'element' => element_definition['name']}.merge(content_definition))
56
+ end
57
+ end
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ module Alchemy
4
+ describe Messages do
5
+
6
+ let(:message) { Message.new(email: 'jon@doe.com', message: 'Lorem ipsum') }
7
+ let(:mail) { Messages.contact_form_mail(message, 'admin@page.com', 'contact@page.com', 'Subject') }
8
+
9
+ it "delivers a mail to owner" do
10
+ mail.to.should == ['admin@page.com']
11
+ mail.subject.should == 'Subject'
12
+ end
13
+
14
+ it "reply_to should be set to senders email" do
15
+ mail.reply_to.should == [message.email]
16
+ end
17
+
18
+ it "mail body includes message" do
19
+ mail.body.should match /#{message.message}/
20
+ end
21
+
22
+ end
23
+ end
@@ -73,6 +73,11 @@ module Alchemy
73
73
  its(:icon_css_class) { should == "audio" }
74
74
  end
75
75
 
76
+ context 'video file' do
77
+ subject { stub_model(Attachment, :file_mime_type => 'video/mpeg') }
78
+ its(:icon_css_class) { should == "video" }
79
+ end
80
+
76
81
  context 'png file' do
77
82
  subject { stub_model(Attachment, :file_mime_type => 'image/png') }
78
83
  its(:icon_css_class) { should == "image" }
@@ -87,6 +92,46 @@ module Alchemy
87
92
  subject { stub_model(Attachment, :file_mime_type => 'application/zip') }
88
93
  its(:icon_css_class) { should == "archive" }
89
94
  end
95
+
96
+ context 'flash file' do
97
+ subject { stub_model(Attachment, :file_mime_type => 'application/x-shockwave-flash') }
98
+ its(:icon_css_class) { should == "flash" }
99
+ end
100
+
101
+ context 'photoshop file' do
102
+ subject { stub_model(Attachment, :file_mime_type => 'image/x-psd') }
103
+ its(:icon_css_class) { should == "psd" }
104
+ end
105
+
106
+ context 'text file' do
107
+ subject { stub_model(Attachment, :file_mime_type => 'text/plain') }
108
+ its(:icon_css_class) { should == "text" }
109
+ end
110
+
111
+ context 'rtf file' do
112
+ subject { stub_model(Attachment, :file_mime_type => 'application/rtf') }
113
+ its(:icon_css_class) { should == "rtf" }
114
+ end
115
+
116
+ context 'pdf file' do
117
+ subject { stub_model(Attachment, :file_mime_type => 'application/pdf') }
118
+ its(:icon_css_class) { should == "pdf" }
119
+ end
120
+
121
+ context 'word file' do
122
+ subject { stub_model(Attachment, :file_mime_type => 'application/msword') }
123
+ its(:icon_css_class) { should == "word" }
124
+ end
125
+
126
+ context 'excel file' do
127
+ subject { stub_model(Attachment, :file_mime_type => 'application/vnd.ms-excel') }
128
+ its(:icon_css_class) { should == "excel" }
129
+ end
130
+
131
+ context 'unknown file' do
132
+ subject { stub_model(Attachment, :file_mime_type => '') }
133
+ its(:icon_css_class) { should == "file" }
134
+ end
90
135
  end
91
136
 
92
137
  end
@@ -2,43 +2,96 @@ require 'spec_helper'
2
2
 
3
3
  module Alchemy
4
4
  describe Cell do
5
-
6
5
  let(:cell) { FactoryGirl.build(:cell) }
7
6
 
8
- describe "#available_elements" do
7
+ # class methods
8
+
9
+ describe '.definitions' do
10
+ it "should return an Array" do
11
+ expect(Cell.definitions).to be_a(Array)
12
+ end
13
+ end
14
+
15
+ describe '.definition_for' do
16
+ subject { Cell.definition_for('right_column') }
17
+
18
+ it "returns a definition for given name" do
19
+ eq({'name' => 'right_column', 'elements' => %w(search)})
20
+ end
21
+ end
22
+
23
+ describe '.all_definitions_for' do
24
+ subject { Cell.all_definitions_for(%(right_column)) }
25
+
26
+ it "returns definitions for given names" do
27
+ eq([{'name' => 'right_column', 'elements' => %w(search)}])
28
+ end
29
+ end
30
+
31
+ describe ".definitions_for_element" do
32
+ before do
33
+ Cell.stub!(:definitions).and_return([
34
+ {'name' => 'cell_1', 'elements' => ['target', 'other']},
35
+ {'name' => 'cell_2', 'elements' => ['other', 'other']},
36
+ {'name' => 'cell_3', 'elements' => ['other', 'target']}
37
+ ])
38
+ end
39
+
40
+ it "should return all cell definitions that includes the given element name" do
41
+ expect(Cell.definitions_for_element('target')).to eq([
42
+ {'name' => 'cell_1', 'elements' => ['target', 'other']},
43
+ {'name' => 'cell_3', 'elements' => ['other', 'target']}
44
+ ])
45
+ end
46
+ end
47
+
48
+ describe '.translated_label_for' do
49
+ subject { Cell.translated_label_for('right_column') }
50
+
51
+ it "returns a translated label" do
52
+ eq('Right column')
53
+ end
54
+ end
55
+
56
+ # instance methods
9
57
 
58
+ describe "#available_elements" do
10
59
  context "without assigned elements" do
11
60
  it "should return an empty Array" do
12
- cell.stub!(:description).and_return({})
61
+ cell.stub!(:definition).and_return({})
13
62
  cell.available_elements.should == []
14
63
  end
15
64
  end
16
65
 
17
66
  context "with assigned elements" do
18
67
  it "should return an Array of element names" do
19
- cell.stub!(:description).and_return({'elements' => ['test_element', 'test_element_2']})
68
+ cell.stub!(:definition).and_return({'elements' => ['test_element', 'test_element_2']})
20
69
  cell.available_elements.should == ['test_element', 'test_element_2']
21
70
  end
22
71
  end
23
-
24
72
  end
25
73
 
26
- describe "#description" do
27
-
74
+ describe "#definition" do
28
75
  context "without a definition for the expected cellname" do
29
76
  it "should return an empty Hash" do
30
77
  Cell.stub!(:definition_for).and_return({})
31
- cell.description.should == {}
78
+ cell.definition.should == {}
32
79
  end
33
80
  end
34
81
 
35
82
  context "with a definition for the expected cellname found" do
36
83
  it "should return its definition Hash" do
37
84
  Cell.stub!(:definition_for).and_return({'name' => 'test_cell', 'elements' => ['test_element', 'test_element_2']})
38
- cell.description.should == {'name' => 'test_cell', 'elements' => ['test_element', 'test_element_2']}
85
+ cell.definition.should == {'name' => 'test_cell', 'elements' => ['test_element', 'test_element_2']}
39
86
  end
40
87
  end
88
+ end
41
89
 
90
+ describe "#name_for_label" do
91
+ it "should call translated_label_for" do
92
+ Cell.should_receive(:translated_label_for).with(cell.name)
93
+ cell.name_for_label
94
+ end
42
95
  end
43
96
 
44
97
  end
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
+ require 'ostruct'
2
3
 
3
4
  module Alchemy
4
5
  describe Content do
5
-
6
- let(:element) { FactoryGirl.create(:element, :name => 'headline', :create_contents_after_create => true) }
6
+ let(:element) { FactoryGirl.create(:element, name: 'headline', :create_contents_after_create => true) }
7
7
  let(:content) { element.contents.find_by_essence_type('Alchemy::EssenceText') }
8
8
 
9
9
  it "should return the ingredient from its essence" do
@@ -12,47 +12,34 @@ module Alchemy
12
12
  end
13
13
 
14
14
  describe '.normalize_essence_type' do
15
-
16
15
  context "passing namespaced essence type" do
17
-
18
16
  it "should not add alchemy namespace" do
19
17
  Content.normalize_essence_type('Alchemy::EssenceText').should == "Alchemy::EssenceText"
20
18
  end
21
-
22
19
  end
23
20
 
24
21
  context "passing not namespaced essence type" do
25
-
26
22
  it "should add alchemy namespace" do
27
23
  Content.normalize_essence_type('EssenceText').should == "Alchemy::EssenceText"
28
24
  end
29
-
30
25
  end
31
-
32
26
  end
33
27
 
34
28
  describe '#normalized_essence_type' do
35
-
36
29
  context "without namespace in essence_type column" do
37
-
38
30
  it "should return the namespaced essence type" do
39
31
  Content.new(:essence_type => 'EssenceText').normalized_essence_type.should == 'Alchemy::EssenceText'
40
32
  end
41
-
42
33
  end
43
34
 
44
35
  context "with namespace in essence_type column" do
45
-
46
36
  it "should return the namespaced essence type" do
47
37
  Content.new(:essence_type => 'Alchemy::EssenceText').normalized_essence_type.should == 'Alchemy::EssenceText'
48
38
  end
49
-
50
39
  end
51
-
52
40
  end
53
41
 
54
42
  describe '#update_essence' do
55
-
56
43
  it "should update the attributes of related essence and return true" do
57
44
  @element = FactoryGirl.create(:element, :name => 'text', :create_contents_after_create => true)
58
45
  @content = @element.contents.first
@@ -72,11 +59,9 @@ module Alchemy
72
59
  @content = @element.contents.first
73
60
  @content.update_essence
74
61
  end
75
-
76
62
  end
77
63
 
78
- describe '#copy' do
79
-
64
+ describe '.copy' do
80
65
  before(:each) do
81
66
  @element = FactoryGirl.create(:element, :name => 'text', :create_contents_after_create => true)
82
67
  @content = @element.contents.first
@@ -96,42 +81,117 @@ module Alchemy
96
81
  copy = Content.copy(@content, {:element_id => @element.id + 1})
97
82
  copy.essence.body == @content.essence.body
98
83
  end
84
+ end
99
85
 
86
+ describe '.build' do
87
+ let(:element) { FactoryGirl.build_stubbed(:element) }
88
+
89
+ it "builds a new instance from elements.yml description" do
90
+ Content.build(element, {name: 'headline'}).should be_instance_of(Content)
91
+ end
100
92
  end
101
93
 
102
- describe '.create' do
103
- let (:element) { FactoryGirl.create(:element, :name => 'headline') }
94
+ describe '.content_description' do
95
+ let(:element) { FactoryGirl.build_stubbed(:element) }
104
96
 
105
- context "with default value present" do
106
- before do
107
- element.stub(:content_description_for).and_return({'name' => 'headline', 'type' => 'EssenceText', 'default' => 'Welcome'})
97
+ context "with blank name key" do
98
+ it "returns a essence hash build from essence type" do
99
+ Content.should_receive(:content_description_from_essence_type).with(element, 'EssenceText')
100
+ Content.content_description(element, essence_type: 'EssenceText')
101
+ end
102
+ end
103
+
104
+ context "with name key present" do
105
+ it "returns a essence hash from element" do
106
+ Content.should_receive(:content_description_from_element).with(element, 'headline')
107
+ Content.content_description(element, name: 'headline')
108
+ end
109
+ end
110
+ end
111
+
112
+ describe '.content_description_from_element' do
113
+ let(:element) { FactoryGirl.build_stubbed(:element) }
114
+ let(:essence) { {name: 'headline', type: 'EssenceText'} }
115
+
116
+ it "returns the description hash from element" do
117
+ element.should_receive(:content_description_for).and_return(essence)
118
+ Content.content_description(element, name: 'headline').should == essence
119
+ end
120
+
121
+ context "with content description not found" do
122
+ before {
123
+ element.should_receive(:content_description_for).and_return(nil)
124
+ element.should_receive(:available_content_description_for).and_return(essence)
125
+ }
126
+
127
+ it "returns the description hash from available contents" do
128
+ Content.content_description(element, name: 'headline').should == essence
108
129
  end
130
+ end
131
+ end
132
+
133
+ describe '.content_description_from_essence_type' do
134
+ let(:element) { FactoryGirl.build_stubbed(:element) }
135
+
136
+ it "returns the description hash from element" do
137
+ Content.should_receive(:content_name_from_element_and_essence_type).with(element, 'EssenceText').and_return('Foo')
138
+ Content.content_description_from_essence_type(element, 'EssenceText').should == {
139
+ 'type' => 'EssenceText',
140
+ 'name' => 'Foo'
141
+ }
142
+ end
143
+ end
144
+
145
+ describe '.content_name_from_element_and_essence_type' do
146
+ let(:element) { FactoryGirl.build_stubbed(:element) }
147
+
148
+ it "returns a name from essence type and count of essences in element" do
149
+ Content.content_name_from_element_and_essence_type(element, 'EssenceText').should == "essence_text_1"
150
+ end
151
+ end
152
+
153
+ describe '.create_from_scratch' do
154
+ let(:element) { FactoryGirl.create(:element, name: 'article') }
155
+
156
+ it "builds the content" do
157
+ expect(Content.create_from_scratch(element, name: 'headline')).to be_instance_of(Alchemy::Content)
158
+ end
109
159
 
160
+ it "creates the essence from name" do
161
+ expect(Content.create_from_scratch(element, name: 'headline').essence).to_not be_nil
162
+ end
163
+
164
+ it "creates the essence from essence_type" do
165
+ expect(Content.create_from_scratch(element, essence_type: 'EssenceText').essence).to_not be_nil
166
+ end
167
+
168
+ context "with default value present" do
110
169
  it "should have the ingredient column filled with default value." do
111
- Content.create_from_scratch(element, :name => 'headline').ingredient.should == "Welcome"
170
+ Content.stub(:content_description_from_element).and_return({'name' => 'headline', 'type' => 'EssenceText', 'default' => 'Welcome'})
171
+ content = Content.create_from_scratch(element, name: 'headline')
172
+ content.ingredient.should == "Welcome"
112
173
  end
113
174
  end
114
175
  end
115
176
 
116
177
  describe '#ingredient=' do
117
178
  it "should set the given value to the ingredient column of essence" do
118
- c = Content.create_from_scratch(element, :name => 'headline')
179
+ c = Content.create_from_scratch(element, name: 'headline')
119
180
  c.ingredient = "Welcome"
120
181
  c.ingredient.should == "Welcome"
121
182
  end
122
183
 
123
184
  context "no essence associated" do
124
- let (:element) { FactoryGirl.create(:element, :name => 'headline') }
185
+ let (:element) { FactoryGirl.create(:element, name: 'headline') }
125
186
 
126
187
  it "should raise error" do
127
- c = Content.create(:element_id => element.id, :name => 'headline')
188
+ c = Content.create(:element_id => element.id, name: 'headline')
128
189
  expect { c.ingredient = "Welcome" }.to raise_error
129
190
  end
130
191
  end
131
192
  end
132
193
 
133
194
  describe "#descriptions" do
134
-
135
195
  context "without any descriptions in elements.yml file" do
136
196
  before { Element.stub(:descriptions).and_return([]) }
137
197
 
@@ -139,7 +199,29 @@ module Alchemy
139
199
  Content.descriptions.should == []
140
200
  end
141
201
  end
202
+ end
203
+
204
+ describe '#preview_text' do
205
+ let(:essence) { mock_model(EssenceText, preview_text: 'Lorem') }
206
+ let(:content) { c = Content.new; c.essence = essence; c }
207
+
208
+ it "should return the essences preview_text" do
209
+ essence.should_receive(:preview_text).with(30)
210
+ content.preview_text
211
+ end
212
+ end
142
213
 
214
+ describe '#tinymce_class_name' do
215
+ let(:element) { FactoryGirl.build_stubbed(:element, name: 'article') }
216
+ let(:content) { c = Content.new(name: 'text'); c.element = element; c }
217
+ subject { content.tinymce_class_name }
218
+
219
+ it { eq('default_tinymce') }
220
+
221
+ context 'having custom tinymce config' do
222
+ before { content.stub(:has_custom_tinymce_config?).and_return(true) }
223
+ it('returns name including element name') { eq('custom_tinymce article_text') }
224
+ end
143
225
  end
144
226
 
145
227
  end