diff --git a/Gemfile b/Gemfile index 84d11b7..46da0bf 100644 --- a/Gemfile +++ b/Gemfile @@ -18,10 +18,12 @@ gem 'sendgrid' # Use mongoid to utilise mongodb gem 'mongoid' -# The following gems for testing purpose in development and testing environment -group :development, :test do +# The following gems for testing purpose in testing environment +group :test do # Rspec is used to write the test cases - gem 'rspec-rails' + gem 'rspec-rails', '~> 3.1' + gem 'mongoid-rspec' + gem 'byebug' # Use factory girl to pass random data for test cases gem 'factory_girl_rails' # Use faker to generate fake strings and data @@ -30,9 +32,6 @@ group :development, :test do gem 'database_cleaner' # Use to track how much code has been tested gem 'simplecov', '~> 0.7.1' -end - -group :test do # Webmock to stub http requests gem 'webmock' # VCR to record the responses from web and replay them when needed diff --git a/Gemfile.lock b/Gemfile.lock index a20dff9..4237c26 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,6 +7,16 @@ GIT oauth (>= 0.3.6) oauth2 (>= 0.5.0) +GIT + remote: git://github.com/aq1018/mongoid-history.git + revision: 2935da05ccf24027c83b3bd1a92b39edc78ee6b8 + specs: + mongoid-history (0.8.4) + activesupport + easy_diff + mongoid (>= 3.0) + mongoid-compatibility (>= 0.5.1) + PATH remote: . specs: @@ -25,12 +35,13 @@ PATH jquery-rails mini_magick mongoid + mongoid-history omniauth-google-oauth2 rails (~> 4.2.5.2) redactor-rails (= 0.4.5) redis-namespace redis-rails - rest_client + rest-client sass-rails (~> 4.0.3) select2-rails sendgrid @@ -85,16 +96,17 @@ GEM addressable (>= 2.3.1) extlib (>= 0.9.15) multi_json (>= 1.0.0) - autoprefixer-rails (7.2.2) + autoprefixer-rails (9.8.6) execjs bcrypt (3.1.7) bootstrap-datepicker-rails (1.3.0.2) railties (>= 3.0) - bootstrap-sass (3.3.5) - autoprefixer-rails (>= 5.0.0.1) - sass (>= 3.2.19) + bootstrap-sass (3.4.1) + autoprefixer-rails (>= 5.2.1) + sassc (>= 2.0.0) bson (2.3.0) builder (3.2.3) + byebug (10.0.2) carrierwave (0.10.0) activemodel (>= 3.2.0) activesupport (>= 3.2.0) @@ -104,7 +116,7 @@ GEM carrierwave (>= 0.8.0, < 0.11.0) mongoid (>= 3.0, < 5.0) mongoid-grid_fs (>= 1.3, < 3.0) - celluloid (0.17.3) + celluloid (0.17.4) celluloid-essentials celluloid-extras celluloid-fsm @@ -148,7 +160,10 @@ GEM devise_invitable (1.6.1) actionmailer (>= 3.2.6) devise (>= 3.2.0) - diff-lcs (1.2.5) + diff-lcs (1.4.4) + domain_name (0.5.20190701) + unf (>= 0.0.5, < 1.0.0) + easy_diff (1.0.0) erubis (2.7.0) execjs (2.7.0) extlib (0.9.16) @@ -161,7 +176,8 @@ GEM i18n (~> 0.5) faraday (0.9.0) multipart-post (>= 1.2, < 3) - globalid (0.4.1) + ffi (1.12.2) + globalid (0.4.2) activesupport (>= 4.2.0) google-api-client (0.7.1) addressable (>= 2.3.2) @@ -174,7 +190,7 @@ GEM retriable (>= 1.4) signet (>= 0.5.0) uuidtools (>= 2.1.0) - haml (5.0.4) + haml (5.2.0) temple (>= 0.8.0) tilt haml-rails (1.0.0) @@ -186,22 +202,23 @@ GEM hashdiff (0.2.3) hashie (2.1.2) hike (1.2.3) - hitimes (1.2.6) html2haml (2.2.0) erubis (~> 2.7.0) haml (>= 4.0, < 6) nokogiri (>= 1.6.0) ruby_parser (~> 3.5) + http-accept (1.7.0) + http-cookie (1.0.3) + domain_name (~> 0.5) httparty (0.13.1) json (~> 1.8) multi_xml (>= 0.5.2) i18n (0.9.1) concurrent-ruby (~> 1.0) imgkit (1.6.0) - jbuilder (2.7.0) + jbuilder (2.9.1) activesupport (>= 4.2.0) - multi_json (>= 1.2) - jquery-rails (4.3.1) + jquery-rails (4.4.0) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) @@ -213,7 +230,7 @@ GEM loofah (2.1.1) crass (~> 1.0.2) nokogiri (>= 1.5.9) - mail (2.7.0) + mail (2.7.1) mini_mime (>= 0.1.1) method_source (0.8.2) mime-types (2.99.3) @@ -223,7 +240,7 @@ GEM mina_extensions (0.0.2) mini_magick (3.8.0) subexec (~> 0.2.1) - mini_mime (1.0.0) + mini_mime (1.0.2) mini_portile2 (2.3.0) minitest (5.10.3) mongoid (4.0.0) @@ -231,11 +248,21 @@ GEM moped (~> 2.0.0) origin (~> 2.1) tzinfo (>= 0.3.37) + mongoid-compatibility (0.5.1) + activesupport + mongoid (>= 2.0) mongoid-grid_fs (2.1.0) mime-types (>= 1.0, < 3.0) mongoid (>= 3.0, < 5.0) mongoid-paperclip (0.0.9) paperclip (>= 2.3.6) + mongoid-rspec (4.1.0) + activesupport (>= 3.0.0) + mongoid (>= 3.1) + mongoid-compatibility (>= 0.5.1) + rspec-core (~> 3.3) + rspec-expectations (~> 3.3) + rspec-mocks (~> 3.3) mongoid_slug (3.2.1) mongoid (> 3.0) stringex (~> 2.0) @@ -246,7 +273,7 @@ GEM multi_json (1.12.2) multi_xml (0.5.5) multipart-post (2.0.0) - netrc (0.7.7) + netrc (0.11.0) nokogiri (1.8.1) mini_portile2 (~> 2.3.0) oauth (0.4.7) @@ -336,26 +363,30 @@ GEM ref (1.0.5) responders (2.1.1) railties (>= 4.2.0, < 5.1) - rest_client (1.7.3) - netrc (~> 0.7.7) + rest-client (2.1.0) + http-accept (>= 1.7.0, < 2.0) + http-cookie (>= 1.0.2, < 2.0) + mime-types (>= 1.16, < 4.0) + netrc (~> 0.8) retriable (1.4.1) - rspec-core (3.0.3) - rspec-support (~> 3.0.0) - rspec-expectations (3.0.3) + rspec-core (3.9.3) + rspec-support (~> 3.9.3) + rspec-expectations (3.9.4) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.9.0) + rspec-mocks (3.9.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.0.0) - rspec-mocks (3.0.3) - rspec-support (~> 3.0.0) - rspec-rails (3.0.2) + rspec-support (~> 3.9.0) + rspec-rails (3.9.1) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 3.0.0) - rspec-expectations (~> 3.0.0) - rspec-mocks (~> 3.0.0) - rspec-support (~> 3.0.0) - rspec-support (3.0.3) - ruby_parser (3.10.1) + rspec-core (~> 3.9.0) + rspec-expectations (~> 3.9.0) + rspec-mocks (~> 3.9.0) + rspec-support (~> 3.9.0) + rspec-support (3.9.4) + ruby_parser (3.15.0) sexp_processor (~> 4.9) safe_yaml (1.0.3) sass (3.2.19) @@ -364,13 +395,15 @@ GEM sass (~> 3.2.2) sprockets (~> 2.8, < 3.0) sprockets-rails (~> 2.0) + sassc (2.4.0) + ffi (~> 1.9) select2-rails (3.5.9) thor (~> 0.14) sendgrid (1.2.0) json sendgrid_toolkit (1.4.0) httparty (>= 0.7.6) - sexp_processor (4.10.0) + sexp_processor (4.15.1) sidekiq (3.3.0) celluloid (>= 0.16.0) connection_pool (>= 2.0.0) @@ -396,7 +429,7 @@ GEM slop (3.6.0) spring (2.0.2) activesupport (>= 4.2) - sprockets (2.12.4) + sprockets (2.12.5) hike (~> 1.2) multi_json (~> 1.0) rack (~> 1.0) @@ -407,22 +440,24 @@ GEM sprockets (>= 2.8, < 4.0) stringex (2.5.2) subexec (0.2.3) - temple (0.8.0) + temple (0.8.2) therubyracer (0.12.1) libv8 (~> 3.16.14.0) ref thor (0.20.0) thread_safe (0.3.6) tilt (1.4.1) - timers (4.1.2) - hitimes - turbolinks (5.0.1) - turbolinks-source (~> 5) - turbolinks-source (5.0.3) + timers (4.3.2) + turbolinks (5.2.1) + turbolinks-source (~> 5.2) + turbolinks-source (5.2.0) tzinfo (1.2.4) thread_safe (~> 0.1) - uglifier (4.0.1) + uglifier (4.2.0) execjs (>= 0.3.0, < 3) + unf (0.1.4) + unf_ext + unf_ext (0.0.7.7) uuidtools (2.1.4) vcr (2.9.2) warden (1.2.3) @@ -436,6 +471,7 @@ PLATFORMS ruby DEPENDENCIES + byebug carrierwave carrierwave-mongoid database_cleaner @@ -449,7 +485,9 @@ DEPENDENCIES mina_extensions mini_magick mongoid + mongoid-history! mongoid-paperclip + mongoid-rspec mongoid_slug omniauth-google-oauth2 pry @@ -457,8 +495,8 @@ DEPENDENCIES redis-namespace redis-rails responders (~> 2.0) - rest_client - rspec-rails + rest-client + rspec-rails (~> 3.1) select2-rails sendgrid sendgrid_toolkit @@ -469,5 +507,8 @@ DEPENDENCIES vcr webmock +RUBY VERSION + ruby 2.2.4p230 + BUNDLED WITH - 1.11.2 + 1.17.3 diff --git a/Rakefile b/Rakefile index 3c32ad9..67cfae3 100644 --- a/Rakefile +++ b/Rakefile @@ -4,10 +4,10 @@ rescue LoadError puts 'You must `gem install bundler` and `bundle install` to run rake tasks' end -APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile",_FILE_) +APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile",__FILE__) load 'rails/tasks/engine.rake' Bundler::GemHelper.install_tasks -Dir[File.join(File.dirname(_FILE_), 'tasks/**/*.rake')].each {|f| load f } +Dir[File.join(File.dirname(__FILE__), 'tasks/**/*.rake')].each {|f| load f } #require 'rdoc/task' require 'rspec/core' diff --git a/app/controllers/light/newsletters_controller.rb b/app/controllers/light/newsletters_controller.rb index acabd75..3e81778 100644 --- a/app/controllers/light/newsletters_controller.rb +++ b/app/controllers/light/newsletters_controller.rb @@ -1,95 +1,108 @@ -require_dependency "light/application_controller" +require_dependency 'light/application_controller' module Light class NewslettersController < ApplicationController - before_filter :load_newsletter, only: [:send_opt_in, :send_opt_in_test, :test_opt_in, - :send_opt_out, :send_opt_out_test, :test_opt_out] + before_filter :load_newsletter, only: [:send_newsletter, :send_test_mail, :test_mail, + :show, :edit, :update, :destroy, :web_version] def index - @newsletters = Newsletter.monthly_letters.order_by([:sent_on, :desc]) - end - - def opt_in - @newsletters = Newsletter.opt_in_letters.order_by([:sent_on, :desc]) - end - - def opt_out - @newsletters = Newsletter.opt_out_letters.order_by([:sent_on, :desc]) + type = params[:type].present? ? params[:type] : Newsletter::VALID_NEWSLETTER_TYPES[:MONTHLY] + @newsletters = Newsletter.where(newsletter_type: type).order_by([:sent_on, :desc]) end def show - @newsletter = Newsletter.find(params[:id]) end - def new + def new @newsletter = Newsletter.new end - def create + def create @newsletter = Newsletter.new(newsletters_params) if @newsletter.save @newsletter.update(sent_on: Date.today) Light::CreateImageWorker.perform_async(@newsletter.id.to_s) - redirect_to newsletters_path + flash[:success] = 'Newsletter created successfully' + redirect_to newsletters_path(type: @newsletter.newsletter_type) else + flash[:error] = 'Error while creating newsletter' render action: 'new' end end def edit - @newsletter = Newsletter.find(params[:id]) end def update - @newsletter = Newsletter.find(params[:id]) if @newsletter.update_attributes(newsletters_params) Light::CreateImageWorker.perform_async(@newsletter.id.to_s) - redirect_to newsletters_path + flash[:success] = 'Newsletter updated successfully' + redirect_to newsletters_path(type: @newsletter.newsletter_type) else + flash[:error] = 'Error while updating newsletter' render action: 'edit' end end def destroy - @newsletter = Newsletter.find(params[:id]) - @newsletter.destroy - redirect_to newsletters_path + if @newsletter && @newsletter.destroy + flash[:success] = 'Newsletter deleted successfully' + redirect_to newsletters_path(type: @newsletter.newsletter_type) + else + flash[:error] = 'Error while deleting newsletter' + redirect_to newsletters_path + end end def web_version - @newsletter = Newsletter.find(params[:id]) render layout: false end - def test_opt_in - end - - def send_opt_in_test - emails = params[:email][:email_id].split(",") - Light::UserMailer.welcome_message(emails, @newsletter, 'test_user_dummy_id').deliver if @newsletter - redirect_to newsletter_path(@newsletter) + def send_newsletter + if @newsletter + type = @newsletter.newsletter_type + + case type + when Newsletter::VALID_NEWSLETTER_TYPES[:OPT_IN] + Light::OptInWorker.perform_async(@newsletter.id.to_s) + flash[:notice] = 'Sent Opt-In newsletter successfully' + when Newsletter::VALID_NEWSLETTER_TYPES[:OPT_OUT] + Light::OptOutWorker.perform_async(@newsletter.id.to_s) + flash[:notice] = 'Sent Opt-Out newsletter successfully' + when Newsletter::VALID_NEWSLETTER_TYPES[:MONTHLY] + Light::UserWorker.perform_async(@newsletter.id.to_s) + flash[:notice] = 'Sent Monthly newsletter successfully' + else + flash[:error] = 'Invalid newsletter type' + end + redirect_to newsletters_path(type: type) + else + flash[:error] = 'Newsletter not found.' + redirect_to newsletters_path + end end - def send_opt_in - Light::OptInWorker.perform_async(@newsletter.id.to_s) - redirect_to opt_in_newsletters_path - end - - def test_opt_out + def send_test_mail + emails = params[:email][:email_id].split(',') + unless emails.empty? + if @newsletter + Light::UserMailer.welcome_message(emails, @newsletter, 'test_user_dummy_id').deliver + flash[:notice] = 'You will receive newsletter on the given email ids shortly.' + redirect_to newsletters_path(type: @newsletter.newsletter_type) + else + flash[:error] = 'Newsletter not found.' + redirect_to newsletters_path + end + else + flash[:error] = 'Atleast one email ID is expected.' + render 'test_mail' + end end - def send_opt_out_test - emails = params[:email][:email_id].split(",") - Light::UserMailer.welcome_message(emails, @newsletter, 'test_user_dummy_id').deliver if @newsletter - redirect_to newsletter_path(@newsletter) + def test_mail end - def send_opt_out - Light::OptOutWorker.perform_async(@newsletter.id.to_s) - redirect_to opt_out_newsletters_path - end - private def newsletters_params diff --git a/app/controllers/light/users_controller.rb b/app/controllers/light/users_controller.rb index a53e4d2..f0400e3 100644 --- a/app/controllers/light/users_controller.rb +++ b/app/controllers/light/users_controller.rb @@ -1,8 +1,9 @@ -require_dependency "light/application_controller" +require_dependency 'light/application_controller' module Light class UsersController < ApplicationController respond_to :js, :json, :html before_filter :user_with_token, only: [:remove, :unsubscribe, :subscribe] + before_filter :load_user, only: [:show, :edit, :update, :destroy] def index offset_val = params[:offset] || 0 @@ -14,7 +15,6 @@ def index end def show - @user = Light::User.find(params[:id]) end def new @@ -26,27 +26,21 @@ def create @user.sent_on = Array.new if @user.save @user.update(source: 'Manual', sent_on: Array.new, sidekiq_status: 'new user' ) + flash[:success] = 'User created successfully' redirect_to users_path else + flash[:error] = 'Error while creating user' render action: 'new' end end - def testmail - end - - def sendtest - emails = params[:email][:email_id].split(",") - Light::Enqueue.perform_async(emails) - - redirect_to newsletters_path - end - def unsubscribe if @user.present? && @user.sidekiq_status == 'Subscribed' - @user.update(is_subscribed: 'false', - unsubscribed_at: DateTime.now, - sidekiq_status: 'Unsubscribed') + @user.update( + is_subscribed: false, + unsubscribed_at: DateTime.now, + sidekiq_status: 'Unsubscribed' + ) @message = 'Unsubscribed successfully!!' else @message = response_message('unsubscribed') @@ -55,47 +49,47 @@ def unsubscribe def subscribe if @user.present? && @user.sidekiq_status == 'Unsubscribed' - @user.update(is_subscribed: 'true', - sidekiq_status: 'Subscribed', - subscribed_at: DateTime.now, - remote_ip: request.remote_ip, - user_agent: request.env['HTTP_USER_AGENT']) + @user.update( + is_subscribed: true, + sidekiq_status: 'Subscribed', + subscribed_at: DateTime.now, + remote_ip: request.remote_ip, + user_agent: request.env['HTTP_USER_AGENT'] + ) @message = 'Subscribed successfully!!' else @message = response_message('subscribed') end end - def sendmailer - Light::UserWorker.perform_async - redirect_to newsletters_path - end - def edit - @user = Light::User.find(params[:id]) end def update - @user = Light::User.find(params[:id]) - if @user.update_attributes(users_params) + if @user && @user.update_attributes(users_params) + flash[:success] = 'User info updated successfully' redirect_to users_path else + flash[:error] = 'Error while updating user' render action: 'edit' end end def destroy - @user = Light::User.find(params[:id]) - @user.destroy + if @user && @user.destroy + flash[:success] = 'User deleted successfully' + else + flash[:error] = 'Error while deleting user' + end redirect_to users_path end def remove if @user.present? @user.destroy - @message = "We have removed you from our database!" + @message = 'We have removed you from our database!' else - @message = "No user with this token exists!" + @message = 'No user with this token exists!' end end @@ -116,19 +110,23 @@ def auto_opt_in def opt_in @user = Light::User.where(email_id: params[:email]).first if @user.present? - @user.update_attributes(is_subscribed: true, - sidekiq_status: 'Subscribed', - subscribed_at: DateTime.now) + @user.update_attributes( + is_subscribed: true, + sidekiq_status: 'Subscribed', + subscribed_at: DateTime.now + ) else u_name = params[:username].blank? ? params[:email] : params[:username] - @user = Light::User.new(username: u_name, - email_id: params[:email], - source: 'web subscription request', - subscribed_at: DateTime.now, - sidekiq_status: 'Subscribed') + @user = Light::User.new( + username: u_name, + email_id: params[:email], + source: 'web subscription request', + subscribed_at: DateTime.now, + sidekiq_status: 'Subscribed' + ) end respond_to do |format| - format.json { head :no_content } + format.json {head :no_content} format.html {redirect_to main_app.users_thank_you_path} end end @@ -154,12 +152,16 @@ def response_message(status) if dummy_token? "#{status.capitalize} successfully!!" elsif @user.nil? - "Hey, it seems request you are trying to access is invalid. If you have any " + - "concerns about our newsletter's subscription, kindly get in touch with " + + 'Hey, it seems request you are trying to access is invalid. If you have any ' + + 'concerns about our newsletters subscription, kindly get in touch with ' + "hr@joshsoftware.com" else "You have already #{status}!!" end end + + def load_user + @user = Light::User.find(params[:id]) + end end end diff --git a/app/models/light/newsletter.rb b/app/models/light/newsletter.rb index 828b286..f261554 100644 --- a/app/models/light/newsletter.rb +++ b/app/models/light/newsletter.rb @@ -4,12 +4,14 @@ class Newsletter include Mongoid::Slug include Mongoid::Paperclip - VALID_NEWSLETTER_TYPES = { MONTHLY: 'Monthly Newsletter', - OPT_IN: 'Opt-In Letter', - OPT_OUT: 'Opt-Out Letter' } + VALID_NEWSLETTER_TYPES = { + MONTHLY: 'Monthly Newsletter', + OPT_IN: 'Opt-In Letter', + OPT_OUT: 'Opt-Out Letter' + } field :subject, type: String - field :content, type: String + field :content, type: String field :sent_on, type: Date field :users_count, type: Integer, default: 0 field :newsletter_type, type: String, default: VALID_NEWSLETTER_TYPES[:MONTHLY] @@ -21,14 +23,14 @@ class Newsletter scope :opt_in_letters, -> { where(newsletter_type: VALID_NEWSLETTER_TYPES[:OPT_IN]) } scope :opt_out_letters, -> { where(newsletter_type: VALID_NEWSLETTER_TYPES[:OPT_OUT]) } scope :monthly_letters, -> { where(newsletter_type: VALID_NEWSLETTER_TYPES[:MONTHLY]) } - - has_mongoid_attached_file :photo,:styles => {:original => ['1920x1680>', :png],:small => ['240x200!', :png]} - validates_attachment_content_type :photo, :content_type => ["image/jpg", "image/jpeg", "image/png", "application/pdf"] + + has_mongoid_attached_file :photo,styles: {original: ['1920x1680>', :png],small: ['240x200!', :png]} + validates_attachment_content_type :photo, content_type: ['image/jpg', 'image/jpeg', 'image/png', 'application/pdf'] slug :subject def get_image - photo.present? ? photo.url(:small) : "/images/newsletter.jpg" + photo.present? ? photo.url(:small) : '/images/newsletter.jpg' end def opt_in? diff --git a/app/models/light/user.rb b/app/models/light/user.rb index 8309e65..d3714b2 100644 --- a/app/models/light/user.rb +++ b/app/models/light/user.rb @@ -1,10 +1,12 @@ +require 'devise' + module Light class User include Mongoid::Document include Mongoid::Slug include Mongoid::History::Trackable - NEW_USER = "new user" + NEW_USER = 'new user' field :email_id, type: String field :username, type: String @@ -28,7 +30,7 @@ class User slug :username - track_history on: [:opt_in_mail_sent_at, :subscribed_at, :remote_ip, + track_history on: [:opt_in_mail_sent_at, :subscribed_at, :remote_ip, :user_agent, :is_subscribed, :unsubscribed_at] before_create do self.joined_on = Date.today @@ -57,7 +59,8 @@ def self.add_users_from_worksheet(worksheet, column = 1) username: worksheet[i + 1, column - 1], is_subscribed: true, joined_on: Date.today, - source: 'Google Spreadsheet') + source: 'Google Spreadsheet' + ) if user.save else @@ -69,8 +72,8 @@ def self.add_users_from_worksheet(worksheet, column = 1) end def self.import(file, email='') - return {error: "Please select CSV file"} if (file.blank? or file.content_type != 'text/csv') - file = CSV.open(file.path, :row_sep => :auto, :col_sep => ",") + return {error: 'Please select CSV file'} if (file.blank? or file.content_type != 'text/csv') + file = CSV.open(file.path, :row_sep => :auto, :col_sep => ',') rows = file.read header = rows.delete_at(0) if header.first.strip.downcase != 'full name' and header[1].strip.downcase != 'email' @@ -80,13 +83,8 @@ def self.import(file, email='') {success: 'You will get an update email.'} end - def self.users_for_opt_in_mail - date = Date.today.strftime("%Y%m") - self.new_users.where(:sent_on.nin => [date], is_blocked: false).order_by([:email_id, :asc]) - end - - def self.users_for_opt_out_mail - date = Date.today.strftime("%Y%m") + def self.get_new_users + date = Date.today.strftime('%Y%m') self.new_users.where(:sent_on.nin => [date], is_blocked: false).order_by([:email_id, :asc]) end end diff --git a/app/views/light/newsletters/_newsletters.html.haml b/app/views/light/newsletters/_newsletters.html.haml index 7ca5be3..54cd9d8 100644 --- a/app/views/light/newsletters/_newsletters.html.haml +++ b/app/views/light/newsletters/_newsletters.html.haml @@ -18,7 +18,9 @@ = "(#{newsletter.users_count} users)" %center %hr - = link_to "Edit", edit_newsletter_path(newsletter), class: "btn btn-mini btn-success", data: { no_turbolink: true } - = link_to "Delete", newsletter_path(newsletter), method: :delete, class: "btn btn-mini btn-danger" + = link_to "", edit_newsletter_path(newsletter), class: "btn btn-lg icon-edit", data: { no_turbolink: true } + = link_to "", newsletter_path(newsletter), method: :delete, class: 'btn btn-lg icon-trash', :data => { :confirm => 'Are you sure, you want to delete newsletter?'} + = link_to "Send Mail", send_newsletter_path(newsletter), method: :post, :class => 'btn btn-mini btn-danger', :data => { :confirm => 'Are you sure ?'} + = link_to "Test Mail", test_mail_newsletter_path(newsletter), :class => 'btn btn-mini btn-success' -count+=1 diff --git a/app/views/light/newsletters/_top_navbar.html.haml b/app/views/light/newsletters/_top_navbar.html.haml index bbabe36..9c8294e 100644 --- a/app/views/light/newsletters/_top_navbar.html.haml +++ b/app/views/light/newsletters/_top_navbar.html.haml @@ -1,16 +1,18 @@ = nav_bar :brand => 'Newsletters', :responsive => true, :static => :top, :fluid => :true do = menu_group do = menu_item "Add Newsletter", new_newsletter_path - = menu_item "Opt in letters", opt_in_newsletters_path - = menu_item "Opt out letters", opt_out_newsletters_path + = menu_item "Opt in letters", newsletters_path(type: "Opt-In Letter") + = menu_item "Opt out letters", newsletters_path(type: "Opt-Out Letter") = drop_down "Add Users" do = menu_item "Add Manually", new_user_path = menu_item "Import Opt-in Users", users_import_path = menu_item "Google Spreadsheets", spreadsheets_path = menu_item "Show Users", users_path, ({:method => 'get'} if params[:controller] == 'light/users' && params[:action].in?(['new', 'create'])) - = menu_group :pull => :right do - .btn-mail - = content_tag :a, "Send Mail", :href => sendmailer_path, :class => 'btn btn-danger', :data => { :confirm => 'Are you sure ?'} - = content_tag :a, "Test Mail", :href => testmail_path, :class => 'btn btn-success' %br + +:javascript + $(document).ready(function() { + $(".nav").find(".active").removeClass("active"); + $('a[href="' + location.pathname + location.search + '"]').closest('li').addClass('active'); + }); diff --git a/app/views/light/newsletters/opt_in.html.haml b/app/views/light/newsletters/opt_in.html.haml deleted file mode 100644 index e3024f7..0000000 --- a/app/views/light/newsletters/opt_in.html.haml +++ /dev/null @@ -1,3 +0,0 @@ -= render 'newsletters' - - diff --git a/app/views/light/newsletters/opt_out.html.haml b/app/views/light/newsletters/opt_out.html.haml deleted file mode 100644 index 0537ed9..0000000 --- a/app/views/light/newsletters/opt_out.html.haml +++ /dev/null @@ -1 +0,0 @@ -= render 'newsletters' diff --git a/app/views/light/newsletters/show.html.haml b/app/views/light/newsletters/show.html.haml index d1c70c9..2696852 100644 --- a/app/views/light/newsletters/show.html.haml +++ b/app/views/light/newsletters/show.html.haml @@ -1,11 +1,9 @@ = render 'top_navbar' +%h2.text-center + = @newsletter.subject + = link_to "", edit_newsletter_path(@newsletter), class: "icon-edit pull-right", data: { no_turbolink: true } = raw @newsletter.content -- if @newsletter.opt_in? - = link_to "Send Opt-In Mail", send_opt_in_newsletter_path(@newsletter), +%center + = link_to "Send Mail", send_newsletter_path(@newsletter), :class => 'btn btn-danger', :data => { :confirm => 'Are you sure ?'}, method: :post - = link_to "Send Opt-In Test Mail", test_opt_in_newsletter_path(@newsletter), :class => "btn btn-success" - -- elsif @newsletter.opt_out? - = link_to "Send Opt-Out Mail", send_opt_out_newsletter_path(@newsletter), - :class => 'btn btn-danger', :data => { :confirm => 'Are you sure ?'}, method: :post - = link_to "Send Opt-Out Test Mail", test_opt_out_newsletter_path(@newsletter), :class => "btn btn-success" + = link_to "Send Test Mail", test_mail_newsletter_path(@newsletter), :class => "btn btn-success" \ No newline at end of file diff --git a/app/views/light/newsletters/test_mail.html.haml b/app/views/light/newsletters/test_mail.html.haml new file mode 100644 index 0000000..56f58ac --- /dev/null +++ b/app/views/light/newsletters/test_mail.html.haml @@ -0,0 +1,18 @@ += render 'top_navbar' +%center + .panel.panel-primary + .panel-heading + %h2 + = @newsletter.subject + Test Mail + .panel-body + = simple_form_for :email, as: :post, url: send_test_mail_newsletter_path(@newsletter), html: {role: 'form', class: 'form-horizontal'} do |f| + %table + %tr + %td + = f.label :email_id + = f.input :email_id, input_html: { placeholder: 'For multiple email ids - separate them by comma', class: 'span4 required'}, + as: :text, label: false, autofocus: true + %tr + %td + = f.button :submit, "Sent Test Mail", class: "btn btn-success span4 pull-right" diff --git a/app/views/light/newsletters/test_opt_in.html.haml b/app/views/light/newsletters/test_opt_in.html.haml deleted file mode 100644 index 3adf6ae..0000000 --- a/app/views/light/newsletters/test_opt_in.html.haml +++ /dev/null @@ -1,7 +0,0 @@ -.panel.panel-primary - .panel-heading - Test Mail - .panel-body - = form_for :email, as: :post, url: send_opt_in_test_newsletter_path(@newsletter) do |f| - = f.text_area :email_id - = f.button :submit, class: "btn btn-success" diff --git a/app/views/light/newsletters/test_opt_out.html.haml b/app/views/light/newsletters/test_opt_out.html.haml deleted file mode 100644 index 3636de0..0000000 --- a/app/views/light/newsletters/test_opt_out.html.haml +++ /dev/null @@ -1,7 +0,0 @@ -.panel.panel-primary - .panel-heading - Test Mail - .panel-body - = form_for :email, as: :post, url: send_opt_out_test_newsletter_path(@newsletter) do |f| - = f.text_area :email_id - = f.button :submit, class: "btn btn-success" diff --git a/app/views/light/users/index.html.haml b/app/views/light/users/index.html.haml index ce54cf5..5328086 100644 --- a/app/views/light/users/index.html.haml +++ b/app/views/light/users/index.html.haml @@ -51,9 +51,9 @@ %td.text-center= '{{email_id}}' %td.text-center= '{{username}}' %td.text-center - %a{ :href => "/newsletter/users/{{_id.$oid}}/edit", :class => 'btn btn-sm btn-success'} Edit + %a{ :href => "/newsletter/users/{{id}}/edit", :class => 'btn btn-sm btn-success'} Edit - %a{ :href => "/newsletter/users/{{_id.$oid}}", data:{ :confirm => 'Are you sure?', method: 'delete'}, :class => 'btn btn-sm btn-danger' } Delete + %a{ :href => "/newsletter/users/{{id}}", data:{ :confirm => 'Are you sure?', method: 'delete'}, :class => 'btn btn-sm btn-danger' } Delete .col-lg-12.padding_none.pull-right #user_pagination.col-lg-12 diff --git a/app/views/light/users/sendmailer.html.haml b/app/views/light/users/sendmailer.html.haml deleted file mode 100644 index 8b13789..0000000 --- a/app/views/light/users/sendmailer.html.haml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/app/views/light/users/testmail.html.haml b/app/views/light/users/testmail.html.haml deleted file mode 100644 index 5b6f6a2..0000000 --- a/app/views/light/users/testmail.html.haml +++ /dev/null @@ -1,7 +0,0 @@ -.panel.panel-primary - .panel-heading - Test Mail - .panel-body - = form_for :email, as: :post, url: sendtest_path do |f| - = f.text_area :email_id - = f.button :submit, class: "btn btn-success" diff --git a/app/workers/light/hard_worker.rb b/app/workers/light/hard_worker.rb index 3b86625..d2ddba4 100644 --- a/app/workers/light/hard_worker.rb +++ b/app/workers/light/hard_worker.rb @@ -1,7 +1,7 @@ module Light class HardWorker include Sidekiq::Worker - sidekiq_options :queue => :lightair + sidekiq_options queue: :lightair def perform(user_ids, newsletter_id, date, status = nil) newsletter = Light::Newsletter.where(id: newsletter_id).first @@ -11,14 +11,18 @@ def perform(user_ids, newsletter_id, date, status = nil) Light::UserMailer.welcome_message(user.email_id, newsletter, user.token).deliver sent_on = user.sent_on << date if status.present? && status.include?('Opt in') - user.update_attributes(sent_on: sent_on, - sidekiq_status: status, - opt_in_mail_sent_at: DateTime.now) + user.update_attributes( + sent_on: sent_on, + sidekiq_status: status, + opt_in_mail_sent_at: DateTime.now + ) elsif status.present? && status.include?('Opt out') - user.update_attributes(sent_on: sent_on, - sidekiq_status: 'Subscribed', - subscribed_at: DateTime.now, - is_subscribed: true) + user.update_attributes( + sent_on: sent_on, + sidekiq_status: 'Subscribed', + subscribed_at: DateTime.now, + is_subscribed: true + ) else user.update_attributes(sent_on: sent_on) end diff --git a/app/workers/light/import_worker.rb b/app/workers/light/import_worker.rb index 3b3a522..f32896a 100644 --- a/app/workers/light/import_worker.rb +++ b/app/workers/light/import_worker.rb @@ -1,19 +1,24 @@ module Light class ImportWorker include Sidekiq::Worker - sidekiq_options :queue => :lightair + sidekiq_options queue: :lightair - def perform(rows, email_id, source = "Business Card") + def perform(rows, email_id, source = 'Business Card') file_path = "#{Rails.root.to_s}/tmp/import_contacts_#{Time.now.to_i}.csv" - CSV.open(file_path, "wb") do |csv| #creates a tempfile csv + CSV.open(file_path, 'wb') do |csv| #creates a tempfile csv csv << ['Total number of users in the database', Light::User.count] csv << ['Total number of rows in uploaded CSV (including blank)', rows.count] - csv << ["Email", "Name", "Error"] + csv << ['Email', 'Name', 'Error'] rows.each do |row| email = "#{row[1]}" name = "#{row[0] || row[1]}" - user = Light::User.create(username: name, email_id: email, source: source, - is_subscribed: false, sidekiq_status: Light::User::NEW_USER) if email.present? or name.present? + user = Light::User.create( + username: name, + email_id: email, + source: source, + is_subscribed: false, + sidekiq_status: Light::User::NEW_USER + ) if email.present? or name.present? csv << [email, row[0], user.errors.messages] if user.present? and user.errors.present? end UserMailer.import_contacts_update(email_id, file_path).deliver diff --git a/app/workers/light/opt_in_worker.rb b/app/workers/light/opt_in_worker.rb index ffc4f24..c1a9726 100644 --- a/app/workers/light/opt_in_worker.rb +++ b/app/workers/light/opt_in_worker.rb @@ -5,12 +5,12 @@ class OptInWorker def perform(newsletter_id) date = Date.today.strftime("%Y%m") - users = Light::User.users_for_opt_in_mail + users = Light::User.get_new_users number_of_opt_in_users = users.count number_of_opt_in_users_count = number_of_opt_in_users current_batch = 0 users_in_batch = 250 - newsletter = Light::Newsletter.find_by(id: newsletter_id) + newsletter = Light::Newsletter.where(id: newsletter_id).first if newsletter while number_of_opt_in_users > 0 user_ids = users.limit(users_in_batch).skip(users_in_batch*current_batch).collect { |user| user.id.to_s } diff --git a/app/workers/light/opt_out_worker.rb b/app/workers/light/opt_out_worker.rb index 72da0b3..01bbc49 100644 --- a/app/workers/light/opt_out_worker.rb +++ b/app/workers/light/opt_out_worker.rb @@ -5,12 +5,12 @@ class OptOutWorker def perform(newsletter_id) date = Date.today.strftime("%Y%m") - users = Light::User.users_for_opt_out_mail + users = Light::User.get_new_users number_of_opt_out_users = users.count number_of_opt_out_users_count = number_of_opt_out_users current_batch = 0 users_in_batch = 250 - newsletter = Light::Newsletter.find_by(id: newsletter_id) + newsletter = Light::Newsletter.where(id: newsletter_id).first if newsletter while number_of_opt_out_users > 0 user_ids = users.limit(users_in_batch).skip(users_in_batch*current_batch).collect { |user| user.id.to_s } diff --git a/app/workers/light/user_worker.rb b/app/workers/light/user_worker.rb index 992b28c..55d8f74 100644 --- a/app/workers/light/user_worker.rb +++ b/app/workers/light/user_worker.rb @@ -3,22 +3,21 @@ class UserWorker include Sidekiq::Worker sidekiq_options :queue => :lightair - def perform + def perform(newsletter_id) date = Date.today.strftime("%Y%m") number_of_subscribed_users = Light::User.where(is_subscribed: true, :sent_on.nin => [date], is_blocked: {"$ne" => true}).count - #number_of_subscribed_users = Light::User.users_for_opt_in_mail.count + #number_of_subscribed_users = Light::User.get_new_users.count number_of_subscribed_users_count = number_of_subscribed_users current_batch = 0 users_in_batch = 250 - newsletter = Light::Newsletter.where(newsletter_type: Light::Newsletter::VALID_NEWSLETTER_TYPES[:MONTHLY]). - order_by([:sent_on, :desc]).first + newsletter = Light::Newsletter.where(id: newsletter_id).first #newsletter = Light::Newsletter.where(newsletter_type: Light::Newsletter::VALID_NEWSLETTER_TYPES[:OPT_IN]). # order_by([:sent_on, :desc]).first if newsletter while number_of_subscribed_users > 0 user_ids = Light::User.where(is_subscribed: true, :sent_on.nin => [date] , is_blocked: {"$ne" => true}).order_by([:email_id, :asc]).limit(users_in_batch).skip(users_in_batch*current_batch).collect { |user| user.id.to_s } - #user_ids = Light::User.users_for_opt_in_mail.order_by([:email_id, :asc]).limit(users_in_batch).skip(users_in_batch*current_batch).collect { |user| user.id.to_s } + #user_ids = Light::User.get_new_users.order_by([:email_id, :asc]).limit(users_in_batch).skip(users_in_batch*current_batch).collect { |user| user.id.to_s } current_batch += 1 number_of_subscribed_users -= users_in_batch Light::HardWorker.perform_async(user_ids, newsletter.id.to_s, date) diff --git a/config/routes.rb b/config/routes.rb index 732fe8f..b945b9f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,9 +1,6 @@ Light::Engine.routes.draw do mount RedactorRails::Engine => '/redactor_rails' - get '/users/sendmailer', to: 'users#sendmailer', as: 'sendmailer' get '/users/subscribe', to: 'users#subscribe', as: 'subscribe' - get '/users/testmail', to: 'users#testmail', as: 'testmail' - post '/users/sendtest', to: 'users#sendtest', as: 'sendtest' get '/users/remove', to: 'users#remove', as: 'remove' get '/auth/:provider/callback', to: 'spreadsheets#new', as: 'google_spreadsheet' @@ -11,18 +8,10 @@ match 'users/import', to: 'users#import', via: [:get, :post] resources :newsletters do - collection do - get 'opt-in', as: 'opt_in' - get 'opt-out', as: 'opt_out' - end - member do - get 'test-opt-in' , as: 'test_opt_in' - post 'send-opt-in' , as: 'send_opt_in' - post 'send-opt-in-test' , as: 'send_opt_in_test' - get 'test-opt-out' , as: 'test_opt_out' - post 'send-opt-out' , as: 'send_opt_out' - post 'send-opt-out-test' , as: 'send_opt_out_test' + get 'test' , to: 'newsletters#test_mail' , as: 'test_mail' + post 'send' , to: 'newsletters#send_newsletter', as: 'send' + post 'sendtest' , to: 'newsletters#send_test_mail', as: 'send_test_mail' end end diff --git a/spec/controllers/light/newsletters_controller_spec.rb b/spec/controllers/light/newsletters_controller_spec.rb index 095a979..95a0de2 100644 --- a/spec/controllers/light/newsletters_controller_spec.rb +++ b/spec/controllers/light/newsletters_controller_spec.rb @@ -2,74 +2,201 @@ module Light -RSpec.describe NewslettersController, :type => :controller do + RSpec.describe NewslettersController, type: :controller do - routes { Light::Engine.routes} + routes { Light::Engine.routes} - context "GET index" do - it "list all the newsletters" do - get :index - expect(response).to render_template("index") - end - end + context 'GET index' do + it 'list all the newsletters' do + get :index + expect(response).to have_http_status(:success) + end - context "GET show" do - let(:newsletter) {FactoryGirl.create(:newsletter)} - it "show the deatails of the newsletters" do - get :show, {:id => newsletter.id} - expect(response).to render_template("show") + it 'list all the newsletters' do + get :index, {type: 'Opt-In Letter'} + expect(response).to have_http_status(:success) + end end - end - context "GET new" do - let(:new_newsletter) {FactoryGirl.create(:newsletter)} - it "display new form for adding newsletter" do - post :new, {newsletter: new_newsletter} - expect(response).to render_template("new") + context 'GET show' do + let(:newsletter) {FactoryGirl.create(:newsletter)} + it 'show the deatails of the newsletters' do + get :show, {id: newsletter.id} + expect(assigns(:newsletter).subject).to eq(newsletter.subject) + expect(response).to render_template('show') + end end - end - context "POST create" do - let(:new_newsletter) {FactoryGirl.attributes_for(:newsletter)} - it "display new form for adding newsletter" do - post :create, {newsletter: new_newsletter} - expect(response).to redirect_to(newsletters_path) + context 'GET new' do + let(:new_newsletter) {FactoryGirl.create(:newsletter)} + it 'display new form for adding newsletter' do + get :new, {newsletter: new_newsletter} + expect(response).to render_template('new') + end end - it "not arise" do - post :create, {newsletter: {content: "",sent_on: "2014-1-1", users_count: 0}} - expect(response).to render_template("new") + context 'POST create' do + let(:new_newsletter) {FactoryGirl.attributes_for(:newsletter)} + it 'display new form for adding newsletter' do + post :create, {newsletter: new_newsletter} + expect(flash[:success]).to eq('Newsletter created successfully') + expect(response).to redirect_to(newsletters_path(type: 'Monthly Newsletter')) + end + + it 'create a newsletter failure' do + post :create, {newsletter: {content: '', sent_on: '2014-1-1', users_count: 0}} + expect(flash[:error]).to eq('Error while creating newsletter') + expect(response).to render_template('new') + end end - end - context "GET update" do + context 'GET edit' do let(:new_newsletter) {FactoryGirl.create(:newsletter)} - it "fetches the specific newsletter" do + it 'fetches the specific newsletter' do get :edit, {id: new_newsletter.id} - expect(response).to render_template("edit") + expect(response).to render_template('edit') + end + end + + context 'PUT update' do + let(:new_newsletter) {FactoryGirl.create(:newsletter)} + it 'updates details of specified newsletter' do + put :update, {id: new_newsletter.id, newsletter: {content: new_newsletter.content}} + expect(flash[:success]).to eq('Newsletter updated successfully') + expect(response).to redirect_to(newsletters_path(type: new_newsletter.newsletter_type)) + end + + it 'update a newsletter failure' do + put :update, {id: new_newsletter.id, newsletter: {content: ''}} + expect(flash[:error]).to eq('Error while updating newsletter') + expect(response).to render_template('edit') end end - context "DELETE delete" do + context 'DELETE delete' do let(:newsletter) {FactoryGirl.create(:newsletter)} - it "delete a newsletter" do + it 'delete a newsletter success' do delete :destroy, {id: newsletter.id} + expect(flash[:success]).to eq('Newsletter deleted successfully') + expect(response).to redirect_to(newsletters_path(type: newsletter.newsletter_type)) + end + + it 'delete a newsletter failure' do + delete :destroy, {id: 0} + expect(flash[:error]).to eq('Error while deleting newsletter') expect(response).to redirect_to(newsletters_path) end end - context "PUT update" do - let(:new_newsletter) {FactoryGirl.create(:newsletter)} - it "updates details of specified newsletter" do - put :update, {id: new_newsletter.id, newsletter: {content: new_newsletter.content}} - expect(response).to redirect_to(newsletters_path) + context 'GET test_mail' do + let(:newsletter) {FactoryGirl.create(:newsletter)} + it 'should render test mail template' do + get :test_mail, {id: newsletter} + expect(response).to render_template('test_mail') + end + end + + context 'POST test_mail' do + let(:newsletter) {FactoryGirl.create(:newsletter)} + before :each do + ActionMailer::Base.deliveries = [] end - it "not arise" do - put :update, {id: new_newsletter.id, newsletter: {content: ""}} - expect(response).to render_template("edit") + it 'should send test mail to email ids passed to it' do + post :send_test_mail, {id: newsletter.id, email: {email_id: 'pamela@joshsoftware.com,winona@joshsoftware.com'}} + expect(flash[:notice]).to eq('You will receive newsletter on the given email ids shortly.') + expect(ActionMailer::Base.deliveries.count).to eq(1) + expect(ActionMailer::Base.deliveries.first.subject).to eq(newsletter.subject) + expect(ActionMailer::Base.deliveries.first.to.count).to eq(2) + expect(response).to redirect_to(newsletters_path(type: 'Monthly Newsletter')) + end + + it 'should fail if not email ids passed to it' do + post :send_test_mail, {id: newsletter.id, email: {email_id: ''}} + expect(flash[:error]).to eq('Atleast one email ID is expected.') + expect(ActionMailer::Base.deliveries.count).to eq(0) + expect(response).to render_template('test_mail') + end + + it 'should fail if newsletter not found' do + post :send_test_mail, {id: 0, email: {email_id: 'test@joshsoftware.com'}} + expect(flash[:error]).to eq('Newsletter not found.') + expect(ActionMailer::Base.deliveries.count).to eq(0) + expect(response).to redirect_to(newsletters_path) end end -end + context 'POST send_newsletter' do + before :each do + @new_user = FactoryGirl.create(:user, is_subscribed: false, sidekiq_status: 'new user') + @subscribed = FactoryGirl.create(:user, is_subscribed: true, sidekiq_status: 'Subscribed') + @unsubscribed = FactoryGirl.create(:user, is_subscribed: false, sidekiq_status: 'Unubscribed') + @date = Date.today.strftime('%Y%m') + @sent_on_date = DateTime.now + ActionMailer::Base.deliveries = [] + end + + it 'should fail if newsletter not found' do + post :send_newsletter, {id: 0} + expect(flash[:error]).to eq('Newsletter not found.') + expect(response).to redirect_to(newsletters_path) + end + + it 'should send monthly newsletter to subscribed users only' + + 'and update the sent_on attribute for user and newsletter' do + Sidekiq::Testing.inline! do + @monthly = FactoryGirl.create(:newsletter, sent_on: []) + post :send_newsletter, {id: @monthly.id} + expect(flash[:notice]).to eq('Sent Monthly newsletter successfully') + expect(ActionMailer::Base.deliveries.count).to eq(1) + expect(ActionMailer::Base.deliveries.first.subject).to eq(@monthly.subject) + expect(ActionMailer::Base.deliveries.first.to).to eq([@subscribed.email_id]) + expect(@monthly.reload.users_count).to eq(1) + expect(@subscribed.reload.sent_on).to include(@date) + expect(@unsubscribed.reload.sent_on.empty?).to eq(true) + expect(@new_user.reload.sent_on.empty?).to eq(true) + expect(response).to redirect_to(newsletters_path(type: @monthly.newsletter_type)) + end + end + + it 'should send opt-in newsletter to new users only' + + 'and update necessary attributes for user and newsletter' do + Sidekiq::Testing.inline! do + @opt_in = FactoryGirl.create(:newsletter, sent_on: [], newsletter_type: 'Opt-In Letter') + post :send_newsletter, {id: @opt_in.id} + expect(flash[:notice]).to eq('Sent Opt-In newsletter successfully') + expect(ActionMailer::Base.deliveries.count).to eq(1) + expect(ActionMailer::Base.deliveries.first.subject).to eq(@opt_in.subject) + expect(ActionMailer::Base.deliveries.first.to).to eq([@new_user.email_id]) + expect(@opt_in.reload.users_count).to eq(1) + expect(@new_user.reload.sent_on).to include(@date) + expect(@subscribed.reload.sent_on.empty?).to eq(true) + expect(@unsubscribed.reload.sent_on.empty?).to eq(true) + expect(@new_user.sidekiq_status).to eq('Opt in mail sent') + expect(@new_user.opt_in_mail_sent_at).to be > @sent_on_date + expect(response).to redirect_to(newsletters_path(type: @opt_in.newsletter_type)) + end + end + + it 'should send opt-out newsletter to new users only' + + 'and update necessary attributes for user and newsletter' do + Sidekiq::Testing.inline! do + @opt_out = FactoryGirl.create(:newsletter, sent_on: [], newsletter_type: 'Opt-Out Letter') + post :send_newsletter, {id: @opt_out.id} + expect(flash[:notice]).to eq('Sent Opt-Out newsletter successfully') + expect(ActionMailer::Base.deliveries.count).to eq(1) + expect(ActionMailer::Base.deliveries.first.subject).to eq(@opt_out.subject) + expect(ActionMailer::Base.deliveries.first.to).to eq([@new_user.email_id]) + expect(@opt_out.reload.users_count).to eq(1) + expect(@new_user.reload.sent_on).to include(@date) + expect(@subscribed.reload.sent_on.empty?).to eq(true) + expect(@unsubscribed.reload.sent_on.empty?).to eq(true) + expect(@new_user.sidekiq_status).to eq('Subscribed') + expect(@new_user.subscribed_at).to be > @sent_on_date + expect(@new_user.is_subscribed).to eq(true) + expect(response).to redirect_to(newsletters_path(type: @opt_out.newsletter_type)) + end + end + end + end end diff --git a/spec/controllers/light/users_controller_spec.rb b/spec/controllers/light/users_controller_spec.rb index 379bd2b..1780a67 100644 --- a/spec/controllers/light/users_controller_spec.rb +++ b/spec/controllers/light/users_controller_spec.rb @@ -2,118 +2,119 @@ require 'sidekiq/testing' module Light - RSpec.describe UsersController, :type => :controller do + RSpec.describe UsersController, type: :controller do routes { Light::Engine.routes} - context "Get index" do - it "list of user email" do + context 'Get index' do + it 'list of user email' do get :index - expect(response).to render_template("index") + expect(response).to render_template('index') end end - context "GET show" do + context 'GET show' do let(:user) {FactoryGirl.create(:user)} - it "show the details of the users" do + it 'show the details of the users' do get :show, {id: user.id} - expect(response).to render_template("show") + expect(response).to render_template('show') end end - context "GET new" do + context 'GET new' do let(:new_user) {FactoryGirl.attributes_for(:user)} - it "display new form for adding user" do + it 'display new form for adding user' do post :new, {user: new_user} - expect(response).to render_template("new") + expect(response).to render_template('new') end end - context " POST create" do + context 'POST create' do context 'creates new user' do before(:all) do @create_params = {email_id: 'test@sub.com', username: 'test'} end - it "redirects to users path" do + it 'redirects to users path' do post :create, {user: @create_params} + expect(flash[:success]).to eq('User created successfully') expect(response).to redirect_to(users_path) end - it "default status is new user and is_subscribed is false" do + it 'default status is new user and is_subscribed is false' do post :create, {user: @create_params} user = User.find_by(email_id: 'test@sub.com') + expect(flash[:success]).to eq('User created successfully') expect(user.sidekiq_status).to eq 'new user' expect(user.is_subscribed).to eq false end end - it "not arise" do - post :create, {user: {email_id: "",username: "kanhaiya", is_subscribed: "false"}} - expect(response).to render_template("new") + it 'not arise' do + post :create, {user: {email_id: '',username: 'kanhaiya', is_subscribed: false}} + expect(flash[:error]).to eq('Error while creating user') + expect(response).to render_template('new') end end - context "GET edit" do + context 'GET edit' do let(:new_user) {FactoryGirl.create(:user)} - it "fetches the specific all the users" do + it 'fetches the specific all the users' do get :edit, {id: new_user.id} - expect(response).to render_template("edit") + expect(response).to render_template('edit') end end - context "DELETE delete" do + context 'DELETE delete' do let(:user) {FactoryGirl.create(:user)} - it "delete an user" do + it 'delete an user success' do delete :destroy, {id: user.id} + expect(flash[:success]).to eq('User deleted successfully') expect(response).to redirect_to(users_path) end end + context 'GET remove' do + let(:user) {FactoryGirl.create(:user)} + it 'remove an user success' do + get :remove, {token: user.token} + expect(assigns(:message)).to eq('We have removed you from our database!') + end - context "PUT update" do + it 'remove an user failure' do + get :remove, {token: 'dummy_token'} + expect(assigns(:message)).to eq('No user with this token exists!') + end + end + + + context 'PUT update' do let(:new_user) {FactoryGirl.create(:user)} - it "updates details of specified user" do + it 'updates details of specified user' do patch :update, {id: new_user.id, user: { email_id: new_user.email_id}} + expect(flash[:success]).to eq('User info updated successfully') expect(response).to redirect_to(users_path) end - it " not arise" do - put :update, {id: new_user.id, user: { email_id: ""}} - expect(response).to render_template("edit") + it 'not arise' do + put :update, {id: new_user.id, user: { email_id: ''}} + expect(flash[:error]).to eq('Error while updating user') + expect(response).to render_template('edit') end end - context "GET subscribe" do + context 'GET subscribe' do let(:new_user) {FactoryGirl.create(:user)} - it "unsubcribes a particular user" do + it 'unsubcribes a particular user' do get :subscribe, {id: new_user.id} - expect(response).to render_template("subscribe") - end - end - - context "GET sendmailer" do - it "sends mails to user" do - VCR.use_cassette 'controllers/user-mails', record: :new_episodes do - get :sendmailer - expect(response).to redirect_to(newsletters_path) - end - end - end - - context "GET sendTest" do - it "sends Test mails to user" do - VCR.use_cassette 'controllers/user-mails', record: :new_episodes do - get :sendtest, email: {email_id: "pankajb@joshsoftware.com"} - expect(response).to redirect_to(newsletters_path) - end + expect(response).to render_template('subscribe') end end context 'GET import' do it 'should render import template' do get :import - expect(response).to render_template("import") + expect(response).to render_template('import') end end @@ -122,14 +123,15 @@ module Light context 'data from file import_users.csv' do let(:file) { Rack::Test::UploadedFile.new("#{Rails.root}/files/import_users.csv", 'text/csv') } - let!(:existing_user) {create :user, username: "Winona Bayer", email_id: "winona@gmail.com", is_subscribed: false } + let!(:existing_user) {create :user, username: 'Winona Bayer', email_id: 'winona@gmail.com', is_subscribed: false } it 'File to be imported should contain following data ' do - users = [['Full Name', 'Email'], - ["Miss Pamela Kovacek","pamela@gmail.com"], - [nil, "claud@gmail.com"], - ["Delmer Botsford", nil], - ["Winona Bayer", "winona@gmail.com"], + users = [ + ['Full Name', 'Email'], + ['Miss Pamela Kovacek','pamela@gmail.com'], + [nil, 'claud@gmail.com'], + ['Delmer Botsford', nil], + ['Winona Bayer', 'winona@gmail.com'] ] expect(User.find_by(email_id: users.last.last)).to be_present rows = CSV.read(file.path) @@ -139,22 +141,22 @@ module Light it 'should import users with valid information' do post :import, file: file - expect(flash['success']).to eq("You will get an update email.") + expect(flash['success']).to eq('You will get an update email.') expect(ImportWorker.jobs.size).to eq(1) ImportWorker.drain expect(ImportWorker.jobs.size).to eq(0) expect(User.count).to eq(3) - expect(User.find_by(email_id: "pamela@gmail.com")).to be_present + expect(User.find_by(email_id: 'pamela@gmail.com')).to be_present existing_user.reload expect(existing_user).to be_present expect(existing_user.is_subscribed).to eq(false) - user = User.find_by(email_id: "claud@gmail.com") + user = User.find_by(email_id: 'claud@gmail.com') expect(user).to be_present expect(user.is_subscribed).to eq(false) expect(user.sidekiq_status).to eq('new user') - expect(user.source).to eq("Business Card") + expect(user.source).to eq('Business Card') expect(user.username).to eq(user.email_id) # Since username is empty we are storing email id in username end @@ -162,16 +164,16 @@ module Light context 'should return success if' do after do - create :user, username: "Winona Bayer", email_id: "winona@gmail.com", is_subscribed: false + create :user, username: 'Winona Bayer', email_id: 'winona@gmail.com', is_subscribed: false file = Rack::Test::UploadedFile.new(@file_path, 'text/csv') post :import, file: file - expect(flash['success']).to eq("You will get an update email.") + expect(flash['success']).to eq('You will get an update email.') expect(ImportWorker.jobs.size).to eq(1) ImportWorker.drain expect(ImportWorker.jobs.size).to eq(0) expect(User.count).to eq(3) - expect(User.find_by(email_id: "pamela@gmail.com")).to be_present + expect(User.find_by(email_id: 'pamela@gmail.com')).to be_present end it 'header contains spaces before or after name' do @@ -187,7 +189,7 @@ module Light end end - context "should raise error if " do + context 'should raise error if' do it "headers doesn't match" do User.destroy_all file2 = Rack::Test::UploadedFile.new("#{Rails.root}/files/import_without_header.csv", 'text/csv') @@ -200,7 +202,7 @@ module Light User.destroy_all file2 = Rack::Test::UploadedFile.new("#{Rails.root}/files/contacts.txt") post :import, file: file2 - expect(flash[:error]).to eq("Please select CSV file") + expect(flash[:error]).to eq('Please select CSV file') expect(User.all).to be_empty end end diff --git a/spec/dummy/config/environments/test.rb b/spec/dummy/config/environments/test.rb index ec2c5f8..e47be32 100644 --- a/spec/dummy/config/environments/test.rb +++ b/spec/dummy/config/environments/test.rb @@ -14,7 +14,7 @@ config.eager_load = false # Configure static asset server for tests with Cache-Control for performance. - config.serve_static_assets = true + config.serve_static_files = true config.static_cache_control = 'public, max-age=3600' # Show full error reports and disable caching. diff --git a/spec/models/light/newsletter_spec.rb b/spec/models/light/newsletter_spec.rb index 902b5ad..e7ec0ef 100644 --- a/spec/models/light/newsletter_spec.rb +++ b/spec/models/light/newsletter_spec.rb @@ -1,20 +1,52 @@ require 'rails_helper' module Light - RSpec.describe Newsletter, :type => :model do + RSpec.describe Newsletter, type: :model do before(:each) do @newsletter = FactoryGirl.create(:newsletter) end - it "validates presence of content" do - expect(@newsletter.content).to be_present + describe 'validates' do + it 'presence of content' do + expect(@newsletter.content).to be_present + end + + it 'presence of sent date' do + expect(@newsletter.sent_on).to be_present + end + + it 'presence of user count' do + expect(@newsletter.users_count).to be_present + end + + it 'default value of type to be Monthly Newsletter' do + @newsletter.update_attribute(:newsletter_type, 'Monthly Newsletter') + expect(@newsletter.newsletter_type).to include('Monthly Newsletter') + end end - it "validates presence of sent date" do - expect(@newsletter.sent_on).to be_present + context 'get_image' do + it 'should return default url if no photo present' do + expect(@newsletter.get_image).to include('/images/newsletter.jpg') + end + end + + context 'opt_in?' do + it 'should return true if type of newsletter is opt-in' do + @newsletter.update_attribute(:newsletter_type, 'Opt-In Letter') + expect(@newsletter.opt_in?).to eq(true) + end + + it 'should return false if type of newsletter is not opt-in' do + @newsletter.update_attribute(:newsletter_type, 'Monthly Newsletter') + expect(@newsletter.opt_in?).to eq(false) + end end - it "validates presence of user count" do - expect(@newsletter.users_count).to be_present + context 'opt_out?' do + it 'should return false if type of newsletter is not opt-out' do + @newsletter.update_attribute(:newsletter_type, 'Monthly Newsletter') + expect(@newsletter.opt_out?).to eq(false) + end end end end diff --git a/spec/models/light/user_spec.rb b/spec/models/light/user_spec.rb index c837dde..56198b7 100644 --- a/spec/models/light/user_spec.rb +++ b/spec/models/light/user_spec.rb @@ -1,32 +1,32 @@ require 'rails_helper' module Light -RSpec.describe User, :type => :model do - before(:each) do - @user = FactoryGirl.create(:user) - end + RSpec.describe User, type: :model do + before(:each) do + @user = FactoryGirl.create(:user) + end - it "validates presence of email_id" do - expect(@user.email_id).to be_present - end + it 'validates presence of email_id' do + expect(@user.email_id).to be_present + end - it "validates presence of subcription" do - expect(@user.is_subscribed).to be_present - end + it 'validates presence of subcription' do + expect(@user.is_subscribed).to be_present + end - it "validates presence of joined date" do - expect(@user.joined_on).to be_present - end + it 'validates presence of joined date' do + expect(@user.joined_on).to be_present + end - it "validates presence of source" do - expect(@user.source).to be_present - end + it 'validates presence of source' do + expect(@user.source).to be_present + end - it "validates uniqueness of email id" do - k=User.new(@user.attributes) - expect(k).not_to be_valid - end + it 'validates uniqueness of email id' do + k=User.new(@user.attributes) + expect(k).not_to be_valid + end - let(:user) {FactoryGirl.create(:user)} - let(:newsletter) {FactoryGirl.create(:newsletter)} -end + let(:user) {FactoryGirl.create(:user)} + let(:newsletter) {FactoryGirl.create(:newsletter)} + end end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 8330fe5..b738dee 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -1,13 +1,7 @@ ENV["RAILS_ENV"] ||= 'test' -require_relative 'dummy/config/environment' require 'spec_helper' -#require 'rspec/autorun' require 'rspec/rails' -ENGINE_RAILS_ROOT = File.join(File.dirname(__FILE__), '../') - -Dir[File.join(ENGINE_RAILS_ROOT, "spec/helpers/**/*.rb")].each {|f| require f } -Dir[File.join(ENGINE_RAILS_ROOT, "spec/factories/**/*.rb")].each {|f| require f } # This file was generated by the `rails generate rspec:install` command. Conventionally, all # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. # The generated `.rspec` file contains `--require spec_helper` which will cause this diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index c1f0efb..d38bca6 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -4,13 +4,15 @@ require 'simplecov' SimpleCov.start 'rails' require_relative 'dummy/config/environment' -require 'rspec/autorun' require 'rspec/rails' require 'database_cleaner' require 'sidekiq/testing' require 'webmock/rspec' Sidekiq::Testing.fake! +# globally disable all history tracking by default +Mongoid::History.disable! + ENGINE_RAILS_ROOT = File.join(File.dirname(__FILE__), '../') Dir[File.join(ENGINE_RAILS_ROOT, "spec/helpers/**/*.rb")].each {|f| require f } @@ -39,7 +41,6 @@ end config.before(:each) do - Rails.application.load_seed DatabaseCleaner.start end