alchemy_crm 2.0.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 (240) hide show
  1. data/.gitignore +22 -0
  2. data/.travis.yml +12 -0
  3. data/Gemfile +21 -0
  4. data/Guardfile +13 -0
  5. data/LICENSE +24 -0
  6. data/README.md +82 -0
  7. data/Rakefile +27 -0
  8. data/alchemy_crm.gemspec +31 -0
  9. data/app/assets/images/.DS_Store +0 -0
  10. data/app/assets/images/alchemy_crm/.DS_Store +0 -0
  11. data/app/assets/images/alchemy_crm/contact-icons.png +0 -0
  12. data/app/assets/images/alchemy_crm/fill_content.gif +0 -0
  13. data/app/assets/images/alchemy_crm/group-icons.png +0 -0
  14. data/app/assets/images/alchemy_crm/mailing-icons.png +0 -0
  15. data/app/assets/images/alchemy_crm/module_icon.png +0 -0
  16. data/app/assets/images/alchemy_crm/newsletter-icons.png +0 -0
  17. data/app/assets/images/alchemy_crm/statistic.png +0 -0
  18. data/app/assets/images/alchemy_crm/tag-icons.png +0 -0
  19. data/app/assets/javascripts/alchemy_crm/alchemy_crm.base.js +65 -0
  20. data/app/assets/javascripts/alchemy_crm/scripts.js +2 -0
  21. data/app/assets/stylesheets/alchemy_crm/base.css.scss +473 -0
  22. data/app/assets/stylesheets/alchemy_crm/styles.css +3 -0
  23. data/app/controllers/alchemy_crm/admin/base_controller.rb +7 -0
  24. data/app/controllers/alchemy_crm/admin/contact_groups_controller.rb +23 -0
  25. data/app/controllers/alchemy_crm/admin/contacts_controller.rb +112 -0
  26. data/app/controllers/alchemy_crm/admin/deliveries_controller.rb +80 -0
  27. data/app/controllers/alchemy_crm/admin/elements_controller_extension.rb +32 -0
  28. data/app/controllers/alchemy_crm/admin/mailings_controller.rb +47 -0
  29. data/app/controllers/alchemy_crm/admin/newsletters_controller.rb +24 -0
  30. data/app/controllers/alchemy_crm/admin/tags_controller.rb +62 -0
  31. data/app/controllers/alchemy_crm/base_controller.rb +5 -0
  32. data/app/controllers/alchemy_crm/contacts_controller.rb +103 -0
  33. data/app/controllers/alchemy_crm/mailings_controller.rb +20 -0
  34. data/app/controllers/alchemy_crm/recipients_controller.rb +35 -0
  35. data/app/controllers/alchemy_crm/subscriptions_controller.rb +57 -0
  36. data/app/helpers/alchemy/pages_helper_extension.rb +18 -0
  37. data/app/helpers/alchemy_crm/admin/base_helper.rb +12 -0
  38. data/app/helpers/alchemy_crm/mailings_helper.rb +190 -0
  39. data/app/mailers/alchemy_crm/bounce_receiver.rb +13 -0
  40. data/app/mailers/alchemy_crm/contacts_mailer.rb +26 -0
  41. data/app/mailers/alchemy_crm/mailings_mailer.rb +48 -0
  42. data/app/mailers/alchemy_crm/subscriptions_mailer.rb +17 -0
  43. data/app/models/alchemy/essence_element_teaser.rb +19 -0
  44. data/app/models/alchemy_crm/contact.rb +264 -0
  45. data/app/models/alchemy_crm/contact_group.rb +26 -0
  46. data/app/models/alchemy_crm/contact_group_filter.rb +26 -0
  47. data/app/models/alchemy_crm/delivery.rb +57 -0
  48. data/app/models/alchemy_crm/element_extension.rb +28 -0
  49. data/app/models/alchemy_crm/mailing.rb +93 -0
  50. data/app/models/alchemy_crm/newsletter.rb +48 -0
  51. data/app/models/alchemy_crm/reaction.rb +9 -0
  52. data/app/models/alchemy_crm/recipient.rb +48 -0
  53. data/app/models/alchemy_crm/subscription.rb +8 -0
  54. data/app/views/alchemy/admin/elements/_view_not_found.text.erb +0 -0
  55. data/app/views/alchemy/admin/elements/fill.js.erb +13 -0
  56. data/app/views/alchemy/admin/elements/link.js.erb +1 -0
  57. data/app/views/alchemy/elements/_newsletter_article_editor.html.erb +4 -0
  58. data/app/views/alchemy/elements/_newsletter_article_view.html.erb +16 -0
  59. data/app/views/alchemy/elements/_newsletter_article_view.text.erb +5 -0
  60. data/app/views/alchemy/elements/_newsletter_greeting_editor.html.erb +3 -0
  61. data/app/views/alchemy/elements/_newsletter_greeting_view.html.erb +11 -0
  62. data/app/views/alchemy/elements/_newsletter_greeting_view.text.erb +6 -0
  63. data/app/views/alchemy/elements/_newsletter_signout_form_editor.html.erb +3 -0
  64. data/app/views/alchemy/elements/_newsletter_signout_form_view.html.erb +32 -0
  65. data/app/views/alchemy/elements/_newsletter_signout_mail_editor.html.erb +4 -0
  66. data/app/views/alchemy/elements/_newsletter_signup_form_editor.html.erb +6 -0
  67. data/app/views/alchemy/elements/_newsletter_signup_form_view.html.erb +78 -0
  68. data/app/views/alchemy/elements/_newsletter_signup_mail_editor.html.erb +4 -0
  69. data/app/views/alchemy/essences/_essence_date_view.text.erb +3 -0
  70. data/app/views/alchemy/essences/_essence_element_teaser_editor.html.erb +31 -0
  71. data/app/views/alchemy/essences/_essence_element_teaser_view.html.erb +1 -0
  72. data/app/views/alchemy/essences/_essence_element_teaser_view.text.erb +3 -0
  73. data/app/views/alchemy/essences/_essence_richtext_view.text.erb +1 -0
  74. data/app/views/alchemy/essences/_essence_text_view.text.erb +1 -0
  75. data/app/views/alchemy/newsletter_layouts/_standard.html.erb +39 -0
  76. data/app/views/alchemy/newsletter_layouts/_standard.text.erb +5 -0
  77. data/app/views/alchemy_crm/admin/contact_groups/_contact_group.html.erb +32 -0
  78. data/app/views/alchemy_crm/admin/contact_groups/_filter.html.erb +30 -0
  79. data/app/views/alchemy_crm/admin/contact_groups/_form.html.erb +47 -0
  80. data/app/views/alchemy_crm/admin/contact_groups/_tag.html.erb +6 -0
  81. data/app/views/alchemy_crm/admin/contact_groups/add_filter.js.erb +9 -0
  82. data/app/views/alchemy_crm/admin/contact_groups/destroy.rjs +1 -0
  83. data/app/views/alchemy_crm/admin/contact_groups/edit.html.erb +1 -0
  84. data/app/views/alchemy_crm/admin/contact_groups/index.html.erb +41 -0
  85. data/app/views/alchemy_crm/admin/contact_groups/new.html.erb +1 -0
  86. data/app/views/alchemy_crm/admin/contacts/_contact.html.erb +44 -0
  87. data/app/views/alchemy_crm/admin/contacts/_form.html.erb +86 -0
  88. data/app/views/alchemy_crm/admin/contacts/destroy.rjs +1 -0
  89. data/app/views/alchemy_crm/admin/contacts/edit.html.erb +1 -0
  90. data/app/views/alchemy_crm/admin/contacts/import.html.erb +33 -0
  91. data/app/views/alchemy_crm/admin/contacts/import.js.erb +2 -0
  92. data/app/views/alchemy_crm/admin/contacts/index.html.erb +51 -0
  93. data/app/views/alchemy_crm/admin/contacts/new.html.erb +1 -0
  94. data/app/views/alchemy_crm/admin/contacts/vcf_import_result.html.erb +49 -0
  95. data/app/views/alchemy_crm/admin/deliveries/_delivery.html.erb +41 -0
  96. data/app/views/alchemy_crm/admin/deliveries/_form.html.erb +65 -0
  97. data/app/views/alchemy_crm/admin/deliveries/_recipient.html.erb +40 -0
  98. data/app/views/alchemy_crm/admin/deliveries/edit.html.erb +1 -0
  99. data/app/views/alchemy_crm/admin/deliveries/index.html.erb +29 -0
  100. data/app/views/alchemy_crm/admin/deliveries/new.html.erb +1 -0
  101. data/app/views/alchemy_crm/admin/deliveries/show.html.erb +66 -0
  102. data/app/views/alchemy_crm/admin/elements/link.rjs +4 -0
  103. data/app/views/alchemy_crm/admin/elements/teasables.html.erb +57 -0
  104. data/app/views/alchemy_crm/admin/mailings/_form.html.erb +43 -0
  105. data/app/views/alchemy_crm/admin/mailings/_mailing.html.erb +75 -0
  106. data/app/views/alchemy_crm/admin/mailings/edit.html.erb +1 -0
  107. data/app/views/alchemy_crm/admin/mailings/edit_content.html.erb +194 -0
  108. data/app/views/alchemy_crm/admin/mailings/import_result.html.erb +37 -0
  109. data/app/views/alchemy_crm/admin/mailings/index.html.erb +39 -0
  110. data/app/views/alchemy_crm/admin/mailings/new.html.erb +1 -0
  111. data/app/views/alchemy_crm/admin/mailings/show.html.erb +1 -0
  112. data/app/views/alchemy_crm/admin/mailings/show.text.erb +1 -0
  113. data/app/views/alchemy_crm/admin/newsletters/_form.html.erb +54 -0
  114. data/app/views/alchemy_crm/admin/newsletters/_newsletter.html.erb +42 -0
  115. data/app/views/alchemy_crm/admin/newsletters/_tag_with_radiobutton.html.erb +7 -0
  116. data/app/views/alchemy_crm/admin/newsletters/destroy.rjs +1 -0
  117. data/app/views/alchemy_crm/admin/newsletters/edit.html.erb +1 -0
  118. data/app/views/alchemy_crm/admin/newsletters/index.html.erb +42 -0
  119. data/app/views/alchemy_crm/admin/newsletters/new.html.erb +10 -0
  120. data/app/views/alchemy_crm/admin/tags/_radio_tag.html.erb +6 -0
  121. data/app/views/alchemy_crm/admin/tags/_tag.html.erb +32 -0
  122. data/app/views/alchemy_crm/admin/tags/edit.html.erb +40 -0
  123. data/app/views/alchemy_crm/admin/tags/index.html.erb +35 -0
  124. data/app/views/alchemy_crm/admin/tags/new.html.erb +16 -0
  125. data/app/views/alchemy_crm/contacts_mailer/signout_mail.html.erb +8 -0
  126. data/app/views/alchemy_crm/contacts_mailer/signout_mail.text.erb +4 -0
  127. data/app/views/alchemy_crm/contacts_mailer/signup_mail.html.erb +11 -0
  128. data/app/views/alchemy_crm/contacts_mailer/signup_mail.text.erb +4 -0
  129. data/app/views/alchemy_crm/mailings/show.html.erb +1 -0
  130. data/app/views/alchemy_crm/mailings_mailer/verification_mail.html.erb +11 -0
  131. data/app/views/alchemy_crm/subscriptions/index.html.erb +23 -0
  132. data/app/views/alchemy_crm/subscriptions_mailer/overview_mail.html.erb +27 -0
  133. data/app/views/alchemy_crm/subscriptions_mailer/overview_mail.text.erb +19 -0
  134. data/app/views/csv_magic/import_errors.html.erb +44 -0
  135. data/app/views/csv_magic/mapper.html.erb +62 -0
  136. data/app/views/layouts/alchemy_crm/mailings.html.erb +212 -0
  137. data/app/views/layouts/alchemy_crm/mailings.text.erb +3 -0
  138. data/config/alchemy_crm.config.yml +21 -0
  139. data/config/authorization_rules.rb +37 -0
  140. data/config/initializers/assets.rb +4 -0
  141. data/config/initializers/delayed_job.rb +6 -0
  142. data/config/locales/alchemy.de.yml +55 -0
  143. data/config/locales/alchemy.en.yml +52 -0
  144. data/config/locales/alchemy_crm.de.yml +196 -0
  145. data/config/locales/alchemy_crm.en.yml +53 -0
  146. data/config/locales/localized_country_select.de.rb +268 -0
  147. data/config/locales/localized_country_select.en.rb +282 -0
  148. data/config/module_definition.yml +30 -0
  149. data/config/routes.rb +71 -0
  150. data/db/migrate/20100708220434_create_mailings.rb +19 -0
  151. data/db/migrate/20100708220534_create_contacts.rb +27 -0
  152. data/db/migrate/20100708220812_create_contact_groups.rb +13 -0
  153. data/db/migrate/20100708221009_create_newsletters.rb +15 -0
  154. data/db/migrate/20100708221319_create_sent_mailings.rb +15 -0
  155. data/db/migrate/20100708221529_create_recipients.rb +21 -0
  156. data/db/migrate/20100708222620_acts_as_taggable_migration.rb +28 -0
  157. data/db/migrate/20100708223324_create_contact_group_filters.rb +17 -0
  158. data/db/migrate/20100708223727_create_newsletter_subscriptions.rb +14 -0
  159. data/db/migrate/20100708223922_create_essence_element_teasers.rb +15 -0
  160. data/db/migrate/20100714172207_create_contact_groups_newsletters.rb +12 -0
  161. data/db/migrate/20100927152601_create_reactions.rb +14 -0
  162. data/db/migrate/20111028091722_acts_as_taggable_on_migration.rb +15 -0
  163. data/db/migrate/20111028200710_add_counter_cache_columns_for_tags.rb +11 -0
  164. data/db/migrate/20111030204931_create_delayed_jobs.rb +21 -0
  165. data/db/migrate/20111104105854_add_deliver_at_to_sent_mailings.rb +9 -0
  166. data/db/migrate/20111104125306_remove_sent_mailing_pdf_id_from_sent_mailings.rb +9 -0
  167. data/db/migrate/20111104131912_add_delivered_at_to_sent_mailings.rb +9 -0
  168. data/db/migrate/20111124145923_namespace_alchemy_crm_models.rb +17 -0
  169. data/db/migrate/20120306115555_add_disabled_to_alchemy_crm_contacts.rb +5 -0
  170. data/db/migrate/20120307160721_rename_alchemy_crm_recipients_sent_mailing_id.rb +5 -0
  171. data/db/migrate/20120315113522_add_url_to_alchemy_crm_reactions.rb +5 -0
  172. data/db/migrate/20120316161333_add_sha1_and_salt_to_alchemy_crm_recipients.rb +6 -0
  173. data/db/migrate/20120320103412_add_indexes_to_alchemy_crm_sha1_columns.rb +7 -0
  174. data/db/migrate/20120321105455_add_queue_to_delayed_jobs.rb +9 -0
  175. data/db/migrate/20120327174301_add_more_indexes_to_alchemy_crm_tables.rb +12 -0
  176. data/lib/alchemy_crm.rb +18 -0
  177. data/lib/alchemy_crm/bounced_delivery.rb +46 -0
  178. data/lib/alchemy_crm/config.rb +28 -0
  179. data/lib/alchemy_crm/engine.rb +40 -0
  180. data/lib/alchemy_crm/i18n_helpers.rb +35 -0
  181. data/lib/alchemy_crm/newsletter_layout.rb +40 -0
  182. data/lib/alchemy_crm/seeder.rb +30 -0
  183. data/lib/alchemy_crm/version.rb +3 -0
  184. data/lib/generators/alchemy_crm/scaffold/files/_standard.html.erb +1 -0
  185. data/lib/generators/alchemy_crm/scaffold/files/_standard.text.erb +1 -0
  186. data/lib/generators/alchemy_crm/scaffold/files/elements.yml +51 -0
  187. data/lib/generators/alchemy_crm/scaffold/files/newsletter_layouts.yml +3 -0
  188. data/lib/generators/alchemy_crm/scaffold/files/newsletters.html.erb +22 -0
  189. data/lib/generators/alchemy_crm/scaffold/files/newsletters.text.erb +4 -0
  190. data/lib/generators/alchemy_crm/scaffold/files/page_layouts.yml +19 -0
  191. data/lib/generators/alchemy_crm/scaffold/scaffold_generator.rb +26 -0
  192. data/lib/tasks/alchemy_crm.rake +28 -0
  193. data/lib/tasks/routes.rake +29 -0
  194. data/rails/init.rb +1 -0
  195. data/recipes/alchemy-mailings-capistrano-tasks.rb +12 -0
  196. data/spec/alchemy_mailings_spec.rb +7 -0
  197. data/spec/config_spec.rb +28 -0
  198. data/spec/controllers/alchemy_crm/contacts_controller_spec.rb +210 -0
  199. data/spec/controllers/alchemy_crm/mailings_controller_spec.rb +89 -0
  200. data/spec/controllers/alchemy_crm/recipients_controller_spec.rb +155 -0
  201. data/spec/dummy/Rakefile +7 -0
  202. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  203. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  204. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  205. data/spec/dummy/config.ru +4 -0
  206. data/spec/dummy/config/alchemy/config.yml +142 -0
  207. data/spec/dummy/config/alchemy/elements.yml +79 -0
  208. data/spec/dummy/config/alchemy/newsletter_layouts.yml +4 -0
  209. data/spec/dummy/config/alchemy/page_layouts.yml +55 -0
  210. data/spec/dummy/config/application.rb +43 -0
  211. data/spec/dummy/config/boot.rb +10 -0
  212. data/spec/dummy/config/database.yml +22 -0
  213. data/spec/dummy/config/environment.rb +5 -0
  214. data/spec/dummy/config/environments/development.rb +30 -0
  215. data/spec/dummy/config/environments/production.rb +60 -0
  216. data/spec/dummy/config/environments/test.rb +39 -0
  217. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  218. data/spec/dummy/config/initializers/inflections.rb +10 -0
  219. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  220. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  221. data/spec/dummy/config/initializers/session_store.rb +8 -0
  222. data/spec/dummy/config/locales/en.yml +5 -0
  223. data/spec/dummy/config/routes.rb +4 -0
  224. data/spec/dummy/db/schema.rb +452 -0
  225. data/spec/dummy/public/404.html +26 -0
  226. data/spec/dummy/public/422.html +26 -0
  227. data/spec/dummy/public/500.html +26 -0
  228. data/spec/dummy/public/favicon.ico +0 -0
  229. data/spec/dummy/script/rails +6 -0
  230. data/spec/helpers/alchemy_crm/mailings_helper_spec.rb +169 -0
  231. data/spec/mailers/alchemy_crm/contacts_mailer_spec.rb +88 -0
  232. data/spec/mailers/alchemy_crm/mailings_mailer_spec.rb +42 -0
  233. data/spec/models/alchemy_crm/contact_group_spec.rb +41 -0
  234. data/spec/models/alchemy_crm/contact_spec.rb +108 -0
  235. data/spec/models/alchemy_crm/delivery_spec.rb +55 -0
  236. data/spec/models/alchemy_crm/mailing_spec.rb +63 -0
  237. data/spec/models/alchemy_crm/newsletter_spec.rb +45 -0
  238. data/spec/spec_helper.rb +58 -0
  239. data/vendor/assets/javascripts/autocomplete-rails.js +16 -0
  240. metadata +438 -0
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/404.html -->
21
+ <div class="dialog">
22
+ <h1>The page you were looking for doesn't exist.</h1>
23
+ <p>You may have mistyped the address or the page may have moved.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/422.html -->
21
+ <div class="dialog">
22
+ <h1>The change you wanted was rejected.</h1>
23
+ <p>Maybe you tried to change something you didn't have access to.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/500.html -->
21
+ <div class="dialog">
22
+ <h1>We're sorry, but something went wrong.</h1>
23
+ <p>We've been notified about this issue and we'll take a look at it shortly.</p>
24
+ </div>
25
+ </body>
26
+ </html>
File without changes
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -0,0 +1,169 @@
1
+ require 'spec_helper'
2
+
3
+ module AlchemyCrm
4
+ describe MailingsHelper do
5
+
6
+ include AlchemyCrm::Engine.routes.url_helpers
7
+
8
+ let(:recipient) { mock_model('Recipient', :email => 'foo@bar.org', :sha1 => 'kjhgfdfgh') }
9
+
10
+ describe '#render_newsletter_layout' do
11
+
12
+ before(:each) do
13
+ @page = Alchemy::Page.new(:name => 'Mailing page', :page_layout => 'newsletter_layout_standard')
14
+ language_root = Alchemy::Page.create!(:name => 'Language Root', :page_layout => 'standard', :language => Alchemy::Language.get_default, :parent_id => Alchemy::Page.root.id)
15
+ @unsubscribe_page = Alchemy::Page.create!(:name => 'Unsubscribe Page', :page_layout => 'newsletter_signout', :parent_id => language_root.id, :language => Alchemy::Language.get_default)
16
+ @mailing = mock_model('Mailing', :name => 'News 01/2012')
17
+ end
18
+
19
+ it "should render the newsletter layout" do
20
+ helper.stub!(:render_elements).and_return("")
21
+ helper.stub!(:configuration).and_return(true)
22
+ helper.stub!(:current_server).and_return('http://example.com')
23
+ helper.stub!(:current_language).and_return(mock_model('Language', :name => 'English'))
24
+ helper.render_newsletter_layout.should =~ /<h1>Newsletter/
25
+ end
26
+
27
+ it "should render the newsletter layout in plain text" do
28
+ helper.stub!(:render_elements).and_return("")
29
+ helper.stub!(:configuration).and_return(true)
30
+ helper.request.format = :text
31
+ helper.render_newsletter_layout(:format => :text).should_not =~ /<h1>Newsletter/
32
+ end
33
+
34
+ end
35
+
36
+ describe '#render_tracking_image' do
37
+ it "should render a tracking image with recipient_reads_url as source." do
38
+ helper.stub!(:current_host).and_return('example.com')
39
+ @recipient = recipient
40
+ helper.render_tracking_image.should match /<img.+src=.#{recipient_reads_url(:h => recipient.sha1, :host => 'example.com')}/
41
+ end
42
+ end
43
+
44
+ describe '#link_to_unsubscribe_page' do
45
+
46
+ before(:each) do
47
+ unsubscribe_page = mock_model('Page', {:urlname => 'unsubscribe'})
48
+ Alchemy::Page.stub!(:find_by_page_layout).and_return(unsubscribe_page)
49
+ helper.stub!(:multi_language?).and_return(false)
50
+ end
51
+
52
+ it "should render a link to the unsubscribe page." do
53
+ helper.stub!(:current_host).and_return('example.com')
54
+ helper.link_to_unsubscribe_page.should match /<a.+href=.+example.com\/unsubscribe/
55
+ end
56
+
57
+ end
58
+
59
+ describe '#read_in_browser_notice' do
60
+ it "should render a notice with a link to read the mailing in a browser." do
61
+ @recipient = recipient
62
+ @mailing = mock_model('Mailing', :sha1 => 'lkjhvghfcdfjgkh')
63
+ helper.stub!(:current_host).and_return('example.com')
64
+ helper.read_in_browser_notice.should match /If the newsletter does not displays correctly, click <a.+href=.#{show_mailing_url(:m => @mailing.sha1, :r => @recipient.sha1, :host => 'example.com')}/
65
+ end
66
+ end
67
+
68
+ describe '#image_from_server_tag' do
69
+ it "should render an image with full url to server." do
70
+ Rails.application.config.assets.prefix = 'images'
71
+ helper.stub!(:current_server).and_return('https://example.com')
72
+ helper.image_from_server_tag('logo.png').should match /<img.+src=.https:\/\/example.com\/images\/logo.png/
73
+ end
74
+ end
75
+
76
+ describe '#tracked_link_tag' do
77
+ it "should render a link with tracking url." do
78
+ @recipient = recipient
79
+ helper.stub!(:current_host).and_return('example.com')
80
+ helper.tracked_link_tag('read more', '/de/my-article', :style => 'color: black').should match /<a.+href=.#{Regexp.escape(recipient_reacts_url({:h => recipient.sha1, :r => '/de/my-article', :host => 'example.com'}))}.+style=.color: black.+read more/
81
+ end
82
+ end
83
+
84
+ describe '#current_host' do
85
+ it "should return the host from request." do
86
+ helper.stub!(:request).and_return(OpenStruct.new({:host => 'example.com'}))
87
+ helper.current_host.should match /^example.com$/
88
+ end
89
+
90
+ it "should return the host from options[:host] if no request is present." do
91
+ helper.stub!(:request).and_return(nil)
92
+ helper.instance_variable_set('@options', {:host => 'example.com'})
93
+ helper.current_host.should match /^example.com$/
94
+ end
95
+ end
96
+
97
+ describe '#current_server' do
98
+
99
+ context "if no request given" do
100
+ it "should return the full server url from options." do
101
+ helper.stub!(:request).and_return(nil)
102
+ helper.instance_variable_set('@options', {
103
+ :port => 80,
104
+ :host => 'example.com'
105
+ })
106
+ helper.current_server.should match /^http:\/\/example.com$/
107
+ end
108
+ end
109
+
110
+ context "if request given" do
111
+ it "should return the full server url from request." do
112
+ helper.current_server.should match /^http:\/\/test.host$/
113
+ end
114
+ end
115
+
116
+ context "given a port different from 80 with options present" do
117
+ it "should return the full server url with port." do
118
+ helper.stub!(:request).and_return(nil)
119
+ helper.instance_variable_set('@options', {
120
+ :port => 3000,
121
+ :host => 'localhost'
122
+ })
123
+ helper.current_server.should match /^http:\/\/localhost:3000$/
124
+ end
125
+ end
126
+
127
+ context "given port 80 with options present" do
128
+ it "should return the full server url without port." do
129
+ helper.stub!(:request).and_return(nil)
130
+ helper.instance_variable_set('@options', {
131
+ :port => 80,
132
+ :host => 'example.com'
133
+ })
134
+ helper.current_server.should match /^http:\/\/example.com$/
135
+ end
136
+ end
137
+
138
+ context "given a port different from 80 with request present" do
139
+ it "should return the full server url with port." do
140
+ helper.stub!(:request).and_return(OpenStruct.new({:host => 'localhost', :port => 3000, :protocol => 'http://'}))
141
+ helper.current_server.should match /^http:\/\/localhost:3000$/
142
+ end
143
+ end
144
+
145
+ context "given port 80 with request present" do
146
+ it "should return the full server url without port." do
147
+ helper.current_server.should match /^http:\/\/test.host$/
148
+ end
149
+ end
150
+
151
+ end
152
+
153
+ describe '#current_language' do
154
+ it "should return the language from session[:language_id]." do
155
+ helper.current_language.should be_an_instance_of(Alchemy::Language)
156
+ end
157
+
158
+ it "should return the language from options[:language_id] if no session is present." do
159
+ helper.instance_variable_set('@options', {:language_id => Alchemy::Language.get_default.id})
160
+ helper.current_language.should be_an_instance_of(Alchemy::Language)
161
+ end
162
+
163
+ it "should return the default language if no session or options[:language_id] is present." do
164
+ helper.current_language.should be_an_instance_of(Alchemy::Language)
165
+ end
166
+ end
167
+
168
+ end
169
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ module AlchemyCrm
4
+ describe ContactsMailer do
5
+
6
+ include AlchemyCrm::Engine.routes.url_helpers
7
+
8
+ before(:all) do
9
+ Alchemy::PageLayout.add({"name" => 'newsletter_mails', "elements" => ['newsletter_signup_mail'], "autogenerate" => ["newsletter_signup_mail"]})
10
+ @language_root = Alchemy::Page.create!(:name => 'Language Root', :page_layout => 'standard', :parent_id => Alchemy::Page.root.id, :language => Alchemy::Language.get_default)
11
+ @page = Alchemy::Page.create!(:name => 'Newsletter Mails', :page_layout => 'newsletter_mails', :parent_id => @language_root.id, :language => @language_root.language)
12
+ @contact = Contact.create!(:email => 'jon@doe.com', :firstname => 'Jon', :lastname => 'Doe', :salutation => 'mr')
13
+ @newsletter = Newsletter.create!(:name => 'Newsletter', :layout => 'standard')
14
+ @subscription = Subscription.create!(:contact => @contact, :newsletter => @newsletter, :verified => true, :wants => true)
15
+ end
16
+
17
+ describe '#signup_mail' do
18
+
19
+ before(:all) do
20
+ @element = @page.elements.find_by_name(:newsletter_signup_mail)
21
+ @element.content_by_name('mail_from').essence.update_attribute(:body, 'frank@dank.com')
22
+ @element.content_by_name('subject').essence.update_attribute(:body, 'Welcome, please confirm')
23
+ @element.content_by_name('text').essence.update_attribute(:body, 'Hello %{name}, please click %{link}')
24
+ @email = ContactsMailer.signup_mail(@contact, @page).deliver
25
+ end
26
+
27
+ it "should deliver to the contact's email address" do
28
+ @email.should deliver_to(@contact.email)
29
+ end
30
+
31
+ it "should have correct delivered from" do
32
+ @email.should deliver_from(@element.ingredient('mail_from'))
33
+ end
34
+
35
+ it "should contain a link to the confirmation link" do
36
+ url_regexp = Regexp.new(Regexp.escape(verify_contact_url(:token => @contact.email_sha1, :host => ActionMailer::Base.default_url_options[:host], :newsletter_ids => @contact.subscriptions.collect(&:newsletter_id))))
37
+ @email.should have_body_text(url_regexp)
38
+ end
39
+
40
+ it "should contain the correct greeting" do
41
+ @email.should have_body_text(/#{@contact.fullname}/)
42
+ end
43
+
44
+ it "should have the correct subject" do
45
+ @email.should have_subject(@element.ingredient('subject'))
46
+ end
47
+
48
+ end
49
+
50
+ describe '#signout_mail' do
51
+
52
+ before(:all) do
53
+ @element = @page.elements.find_by_name(:newsletter_signout_mail)
54
+ @element.content_by_name('mail_from').essence.update_attribute(:body, 'frank@dank.com')
55
+ @element.content_by_name('subject').essence.update_attribute(:body, 'Byebye, please confirm')
56
+ @element.content_by_name('text').essence.update_attribute(:body, 'Hello %{name}, please click %{link}')
57
+ @email = ContactsMailer.signout_mail(@contact, @page).deliver
58
+ end
59
+
60
+ it "should deliver to the contact's email address" do
61
+ @email.should deliver_to(@contact.email)
62
+ end
63
+
64
+ it "should have correct delivered from" do
65
+ @email.should deliver_from(@element.ingredient('mail_from'))
66
+ end
67
+
68
+ it "should contain a link to the confirmation link" do
69
+ @email.should have_body_text(/#{disable_contact_url(:token => @contact.email_sha1, :host => ActionMailer::Base.default_url_options[:host])}/)
70
+ end
71
+
72
+ it "should contain the correct greeting" do
73
+ @email.should have_body_text(/#{@contact.fullname}/)
74
+ end
75
+
76
+ it "should have the correct subject" do
77
+ @email.should have_subject(@element.ingredient('subject'))
78
+ end
79
+
80
+ end
81
+
82
+ after(:all) do
83
+ @language_root.destroy
84
+ @contact.destroy
85
+ end
86
+
87
+ end
88
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ module AlchemyCrm
4
+ describe MailingsMailer do
5
+
6
+ describe '#build' do
7
+
8
+ before(:all) do
9
+ @mailing = Mailing.create!(:name => 'Mailing', :subject => 'News Mailing', :additional_email_addresses => "jim@family.com, jon@doe.com, jane@family.com, \n", :newsletter => Newsletter.create!(:name => 'Newsletter', :layout => 'newsletter_layout_standard'))
10
+ @mailing.deliveries.create!
11
+ @element = @mailing.page.elements.first
12
+ @element.content_by_name('text').essence.update_attribute(:body, "<h2>Hello World</h2>")
13
+ @recipient = @mailing.recipients.first
14
+ @language_root = Alchemy::Page.create!(:name => 'Language Root', :page_layout => 'standard', :language => Alchemy::Language.get_default, :parent_id => Alchemy::Page.root.id)
15
+ @unsubscribe_page = Alchemy::Page.create!(:name => 'Unsubscribe Page', :page_layout => 'newsletter_signout', :parent_id => @language_root.id, :language => Alchemy::Language.get_default)
16
+ @email = MailingsMailer.build(@mailing, @recipient, {:host => ActionMailer::Base.default_url_options[:host], :language_id => Alchemy::Language.get_default.id}).deliver
17
+ end
18
+
19
+ it "should render the mailings body." do
20
+ @email.should have_body_text(/#{Regexp.escape(@element.ingredient('text'))}/)
21
+ end
22
+
23
+ it "should render a plain text version of mailings body." do
24
+ @email.text_part.should_not have_body_text(/<h2>/)
25
+ end
26
+
27
+ it "should deliver to recipient's email." do
28
+ @email.should deliver_to(@recipient.email)
29
+ end
30
+
31
+ it "should have mailing's subject." do
32
+ @email.should have_subject(@mailing.subject)
33
+ end
34
+
35
+ after(:all) do
36
+ @language_root.destroy
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ module AlchemyCrm
4
+ describe ContactGroup do
5
+
6
+ describe "#contacts" do
7
+
8
+ before(:each) do
9
+ @verified_contact = Contact.create!({:email => 'jon@doe.com', :firstname => 'Jon', :lastname => 'Doe', :salutation => 'mr', :tag_list => 'father', :verified => true}, :as => :admin)
10
+ @contact = Contact.create!({:email => 'jane@smith.com', :firstname => 'Jane', :lastname => 'Smith', :salutation => 'ms', :tag_list => 'mother'}, :as => :admin)
11
+ @contact_group = ContactGroup.create!(:name => 'Family', :contact_tag_list => 'father, mother, son')
12
+ end
13
+
14
+ context "with filter" do
15
+
16
+ before(:each) do
17
+ @contact_group.filters.create!(:column => 'lastname', :operator => 'IS', :value => 'Doe', :contact_group => @contact_group)
18
+ end
19
+
20
+ it "should return correct list of contacts" do
21
+ @contact_group.contacts.collect(&:email).should == ["jon@doe.com"]
22
+ end
23
+
24
+ end
25
+
26
+ context "without filter" do
27
+
28
+ before(:each) do
29
+ @contact_group.filters.delete_all
30
+ end
31
+
32
+ it "should return all contacts with tag" do
33
+ @contact_group.contacts.collect(&:email).should == ["jon@doe.com", "jane@smith.com"]
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+
3
+ module AlchemyCrm
4
+ describe Contact do
5
+
6
+ before(:all) do
7
+ @contact = Contact.create!({:email => 'jon@doe.com', :title => 'Dr.', :firstname => 'Jon', :lastname => 'Doe', :salutation => 'mr', :verified => true}, :as => :admin)
8
+ end
9
+
10
+ describe '.create' do
11
+
12
+ it "should set email_salt and email_sha1 for new records" do
13
+ @contact.email_sha1.should_not be_nil
14
+ @contact.email_salt.should_not be_nil
15
+ end
16
+
17
+ end
18
+
19
+ describe '#save' do
20
+
21
+ context "a contact with new email address" do
22
+
23
+ before(:each) do
24
+ @sha1 = @contact.email_sha1
25
+ @salt = @contact.email_salt
26
+ @contact.update_attributes!(:email => 'jane@doe.com')
27
+ end
28
+
29
+ it "should update email_sha1" do
30
+ @contact.email_sha1.should_not == @sha1
31
+ end
32
+
33
+ it "should not update salt" do
34
+ @contact.email_salt.should == @salt
35
+ end
36
+
37
+ end
38
+
39
+ context "a contact with same email address" do
40
+
41
+ before(:each) do
42
+ @sha1 = @contact.email_sha1
43
+ @salt = @contact.email_salt
44
+ @contact.update_attributes!(:firstname => 'jane')
45
+ end
46
+
47
+ it "should not update email_sha1" do
48
+ @contact.email_sha1.should == @sha1
49
+ end
50
+
51
+ it "should not update salt" do
52
+ @contact.email_salt.should == @salt
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+
59
+ describe '#interpolation_name_value' do
60
+
61
+ before(:each) do
62
+ @contact.update_attributes!(:firstname => 'Jon')
63
+ end
64
+
65
+ context "not given a name_with_title value in the config" do
66
+
67
+ before(:each) do
68
+ Config.stub!(:get).and_return(nil)
69
+ end
70
+
71
+ it "should return the default value." do
72
+ @contact.interpolation_name_value.should == "Mr Dr. Jon Doe"
73
+ end
74
+
75
+ end
76
+
77
+ context "given a valid method name in the config" do
78
+
79
+ before(:each) do
80
+ Config.stub!(:get).and_return('name_with_title')
81
+ end
82
+
83
+ it "should return the correct value." do
84
+ @contact.interpolation_name_value.should == "Dr. Jon Doe"
85
+ end
86
+
87
+ end
88
+
89
+ context "given not a valid method name in the config" do
90
+
91
+ before(:each) do
92
+ Config.stub!(:get).and_return('password')
93
+ end
94
+
95
+ it "should return the default value." do
96
+ @contact.interpolation_name_value.should == "Mr Dr. Jon Doe"
97
+ end
98
+
99
+ end
100
+
101
+ end
102
+
103
+ after(:all) do
104
+ @contact.destroy
105
+ end
106
+
107
+ end
108
+ end