Optimize (some) jobs specs and Jobs (#5301) [deploy]

This commit is contained in:
rhymes 2019-12-30 18:25:33 +01:00 committed by Molly Struve
parent 277c496d4c
commit 258b55e5b0
27 changed files with 398 additions and 186 deletions

View file

@ -4,7 +4,9 @@ module Articles
def perform(article_id)
article = Article.find_by(id: article_id)
article&.update_column(:language, LanguageDetector.new(article).detect)
return unless article
article.update_column(:language, LanguageDetector.new(article).detect)
end
end
end

View file

@ -4,8 +4,9 @@ module Articles
def perform(article_id)
article = Article.find_by(id: article_id)
return unless article
article&.update_column(:main_image_background_hex_color, ColorFromImage.new(article.main_image).main)
article.update_column(:main_image_background_hex_color, ColorFromImage.new(article.main_image).main)
end
end
end

View file

@ -4,7 +4,6 @@ module ClassifiedListings
def perform(classified_listing_id, cache_buster = CacheBuster)
classified_listing = ClassifiedListing.find_by(id: classified_listing_id)
return unless classified_listing
cache_buster.bust_classified_listings(classified_listing)

View file

@ -4,9 +4,13 @@ module Comments
def perform(comment_id)
comment = Comment.find_by(id: comment_id)
return unless comment
comment&.update_columns(score: BlackBox.comment_quality_score(comment), spaminess_rating: BlackBox.calculate_spaminess(comment))
comment.root.save if comment && !comment.is_root?
score = BlackBox.comment_quality_score(comment)
spaminess_rating = BlackBox.calculate_spaminess(comment)
comment.update_columns(score: score, spaminess_rating: spaminess_rating)
comment.root.save unless comment.is_root?
end
end
end

View file

@ -4,8 +4,9 @@ module Comments
def perform(comment_id)
comment = Comment.find_by(id: comment_id)
return unless comment
Reaction.create(user_id: comment.user_id, reactable_id: comment.id, reactable_type: "Comment", category: "like") if comment
Reaction.create(user_id: comment.user_id, reactable_id: comment.id, reactable_type: "Comment", category: "like")
end
end
end

View file

@ -4,6 +4,7 @@ module Comments
def perform(comment_id)
comment = Comment.find_by(id: comment_id)
comment&.update_column(:id_code, comment.id.to_s(26))
end
end

View file

@ -4,7 +4,7 @@ module Comments
def perform(comment_id)
comment = Comment.find_by(id: comment_id)
NotifyMailer.new_reply_email(comment)&.deliver if comment
NotifyMailer.new_reply_email(comment).deliver_now if comment
end
end
end

View file

@ -3,7 +3,9 @@ module Follows
queue_as :create_chat_channel_after_follow
def perform(follow_id)
follow = Follow.includes(:follower, :followable).find_by(id: follow_id, follower_type: "User", followable_type: "User")
follow = Follow.
includes(:follower, :followable).
find_by(id: follow_id, follower_type: "User", followable_type: "User")
return unless follow&.followable&.following?(follow.follower)
ChatChannel.create_with_users([follow.followable, follow.follower])

View file

@ -5,6 +5,7 @@ module Follows
def perform(follow_id, mailer = NotifyMailer)
follow = Follow.find_by(id: follow_id, followable_type: "User")
return unless follow&.followable&.email? && follow.followable.email_follower_notifications
return if EmailMessage.where(user_id: follow.followable_id).
where("sent_at > ?", rand(15..35).hours.ago).
where("subject LIKE ?", "%followed you on dev.to%").any?

View file

@ -1,15 +1,25 @@
require "rails_helper"
RSpec.describe Articles::BustCacheJob, type: :job do
include_examples "#enqueues_job", "articles_bust_cache", 1
describe "#perform_now" do
let(:article) { FactoryBot.create(:article) }
let(:cache_buster) { double }
before { allow(cache_buster).to receive(:bust_article) }
it "async busts cache" do
described_class.perform_now(article.id, cache_buster)
expect(cache_buster).to have_received(:bust_article).with(article)
context "with article" do
let_it_be(:article) { double }
let_it_be(:article_id) { 1 }
before do
allow(Article).to receive(:find_by).with(id: article_id).and_return(article)
end
it "async busts cache" do
described_class.perform_now(article_id, cache_buster)
expect(cache_buster).to have_received(:bust_article).with(article)
end
end
context "without article" do

View file

@ -1,15 +1,17 @@
require "rails_helper"
RSpec.describe Articles::DetectHumanLanguageJob, type: :job do
include_examples "#enqueues_job", "articles_detect_human_language", [1]
describe "#perform_now" do
let(:article) { FactoryBot.create(:article) }
context "with article" do
let_it_be(:article) { create(:article) }
it "updates article language with detected language" do
detector = double
allow(detector).to receive(:detect).and_return("en")
it "updates article language with detected language" do
described_class.perform_now(article.id)
described_class.perform_now(article.id)
expect(article.language).to eql("en")
expect(article.language).to eql("en")
end
end
context "without aritcle" do

View file

@ -4,21 +4,25 @@ RSpec.describe Articles::ScoreCalcJob, type: :job do
include_examples "#enqueues_job", "articles_score_calc", 1
describe "#perform_now" do
let(:article) { FactoryBot.create(:article) }
before do
allow(BlackBox).to receive(:article_hotness_score).and_return(373)
allow(BlackBox).to receive(:calculate_spaminess).and_return(2)
end
it "updates article scores", :aggregate_failures do
allow(Article).to receive(:find_by).and_return(article)
allow(article.reactions).to receive(:sum).and_return(7)
described_class.perform_now(article.id)
article.reload
expect(article.score).to be(7)
expect(article.hotness_score).to be(373)
expect(article.spaminess_rating).to be(2)
context "with article" do
let_it_be(:article) { create(:article) }
it "updates article scores", :aggregate_failures do
allow(Article).to receive(:find_by).and_return(article)
allow(article.reactions).to receive(:sum).and_return(7)
described_class.perform_now(article.id)
article.reload
expect(article.score).to be(7)
expect(article.hotness_score).to be(373)
expect(article.spaminess_rating).to be(2)
end
end
context "without article" do
@ -28,6 +32,7 @@ RSpec.describe Articles::ScoreCalcJob, type: :job do
it "does not calculate scores", :aggregate_failures do
described_class.perform_now(nil)
expect(BlackBox).not_to have_received(:article_hotness_score)
expect(BlackBox).not_to have_received(:calculate_spaminess)
end

View file

@ -1,5 +1,4 @@
require "rails_helper"
require "jobs/shared_examples/enqueues_job"
RSpec.describe Articles::UpdateAnalyticsJob, type: :job do
include_examples "#enqueues_job", "articles_update_analytics", 456

View file

@ -1,16 +1,21 @@
require "rails_helper"
RSpec.describe Articles::UpdateMainImageBackgroundHexJob, type: :job do
include_examples "#enqueues_job", "articles_update_main_image_background_hex", 1
describe "#perform_now" do
let(:article) { FactoryBot.create(:article) }
context "with article" do
let_it_be(:article) { create(:article) }
it "updates articles main image background hex" do
color_from_image = double
allow(color_from_image).to receive(:main).and_return("#eee")
allow(ColorFromImage).to receive(:new).and_return(color_from_image)
it "updates articles main image background hex" do
color_from_image = double
allow(color_from_image).to receive(:main).and_return("#eee")
allow(ColorFromImage).to receive(:new).and_return(color_from_image)
described_class.perform_now(article.id)
expect(article.reload.main_image_background_hex_color).to eql("#eee")
described_class.perform_now(article.id)
expect(article.reload.main_image_background_hex_color).to eql("#eee")
end
end
context "without article" do

View file

@ -1,21 +1,39 @@
require "rails_helper"
RSpec.describe BadgeAchievements::SendEmailNotificationJob, type: :job do
let(:user) { create(:user, email_badge_notifications: true) }
let(:badge_achievement) { create(:badge_achievement, user: user) }
include_examples "#enqueues_job", "badge_achievements_send_email_notification", 1
describe ".perform_later" do
it "add job to the queue :badge_achievements_send_email_notification" do
expect do
described_class.perform_later(1)
end.to have_enqueued_job.with(1).on_queue("badge_achievements_send_email_notification")
end
end
describe "#perform_now" do
context "with badge achievement" do
let_it_be(:badge_achievement) { double }
before do
allow(BadgeAchievement).to receive(:find_by).with(id: 1).and_return(badge_achievement)
end
it "sends badge email" do
mailer = double
allow(mailer).to receive(:deliver_now)
allow(NotifyMailer).to receive(:new_badge_email).with(badge_achievement).and_return(mailer)
described_class.perform_now(1)
describe "#perform" do
it "calls on NotifyMailer" do
described_class.new.perform(badge_achievement.id) do
expect(NotifyMailer).to have_received(:new_badge_email).with(badge_achievement)
expect(mailer).to have_received(:deliver_now)
end
end
context "without badge achievement" do
it "does not error" do
expect { described_class.perform_now(nil) }.not_to raise_error
end
it "does not call NotifyMailer" do
allow(NotifyMailer).to receive(:new_badge_email)
described_class.perform_now(nil)
expect(NotifyMailer).not_to have_received(:new_badge_email)
end
end
end

View file

@ -6,8 +6,8 @@ RSpec.describe ChatChannels::IndexJob, type: :job do
include_examples "#enqueues_job", "chat_channels_index", chat_channel_id: 1
describe "#perform_now" do
let(:chat_channel) { double }
let(:chat_channel_id) { 1 }
let_it_be(:chat_channel) { double }
let_it_be(:chat_channel_id) { 1 }
context "when chat_channel is found" do
before do
@ -17,6 +17,7 @@ RSpec.describe ChatChannels::IndexJob, type: :job do
it "calls index" do
described_class.perform_now(chat_channel_id: chat_channel_id)
expect(chat_channel).to have_received(:index!)
end
end
@ -27,7 +28,7 @@ RSpec.describe ChatChannels::IndexJob, type: :job do
end
it "doesn't fail" do
described_class.perform_now(chat_channel_id: chat_channel_id)
expect { described_class.perform_now(chat_channel_id: chat_channel_id) }.not_to raise_error
end
end
end

View file

@ -1,28 +1,39 @@
require "rails_helper"
RSpec.describe ClassifiedListings::BustCacheJob, type: :job do
include_examples "#enqueues_job", "classified_listings_bust_cache", 789
include_examples "#enqueues_job", "classified_listings_bust_cache", 1
describe "#perform_now" do
let(:user) { create(:user) }
let!(:classified_listing) { FactoryBot.create(:classified_listing, user_id: user.id) }
let(:cache_buster) { double }
before do
allow(cache_buster).to receive(:bust_classified_listings)
end
describe "when no listing is found" do
it "doest not call the service" do
allow(ClassifiedListing).to receive(:find_by).and_return(nil)
described_class.perform_now(789, cache_buster)
expect(cache_buster).not_to have_received(:bust_classified_listings)
context "with listing" do
let_it_be(:listing) { double }
let_it_be(:listing_id) { 1 }
before do
allow(ClassifiedListing).to receive(:find_by).with(id: listing_id).and_return(listing)
end
it "busts cache" do
described_class.perform_now(listing_id, cache_buster)
expect(cache_buster).to have_received(:bust_classified_listings).with(listing)
end
end
it "busts cache" do
described_class.perform_now(classified_listing.id, cache_buster)
expect(cache_buster).to have_received(:bust_classified_listings).with(classified_listing)
describe "when no listing is found" do
it "does not error" do
expect { described_class.perform_now(nil, cache_buster) }.not_to raise_error
end
it "does not bust cache" do
described_class.perform_now(nil, cache_buster)
expect(cache_buster).not_to have_received(:bust_classified_listings)
end
end
end
end

View file

@ -5,27 +5,46 @@ RSpec.describe Comments::BustCacheJob, type: :job do
describe "#perform_now" do
let(:edge_cache_commentable_bust_service) { double }
let(:comment) { create(:comment, commentable: create(:article)) }
before do
allow(edge_cache_commentable_bust_service).to receive(:call)
end
it "calls the service" do
described_class.perform_now(comment.id, edge_cache_commentable_bust_service)
expect(edge_cache_commentable_bust_service).to have_received(:call).
with(comment.commentable).once
context "with comment" do
let(:comment) { double }
let(:comment_id) { 1 }
let(:commentable) { double }
before do
allow(comment).to receive(:commentable).and_return(commentable)
allow(Comment).to receive(:find_by).with(id: comment_id).and_return(comment)
end
it "calls the service" do
described_class.perform_now(comment_id, edge_cache_commentable_bust_service)
expect(edge_cache_commentable_bust_service).to have_received(:call).with(comment.commentable).once
end
it "does not call the service with a comment without a commentable" do
allow(comment).to receive(:commentable).and_return(nil)
described_class.perform_now(comment_id, edge_cache_commentable_bust_service)
expect(edge_cache_commentable_bust_service).not_to have_received(:call)
end
end
it "doesn't call the service with a non existent comment" do
described_class.perform_now(9999, edge_cache_commentable_bust_service)
expect(edge_cache_commentable_bust_service).not_to have_received(:call)
end
context "without comment" do
it "does not break" do
expect { described_class.perform_now(nil, edge_cache_commentable_bust_service) }.not_to raise_error
end
it "doesn't call the service with a comment without a commentable" do
comment.update_columns(commentable_id: nil, commentable_type: nil)
described_class.perform_now(comment, edge_cache_commentable_bust_service)
expect(edge_cache_commentable_bust_service).not_to have_received(:call)
it "doesn't call the service" do
described_class.perform_now(nil, edge_cache_commentable_bust_service)
expect(edge_cache_commentable_bust_service).not_to have_received(:call)
end
end
end
end

View file

@ -1,18 +1,64 @@
require "rails_helper"
RSpec.describe Comments::CalculateScoreJob, type: :job do
include_examples "#enqueues_job", "comments_calculate_score", 1
describe "#perform_now" do
let(:article) { FactoryBot.create(:article) }
let(:comment) { FactoryBot.create(:comment, commentable: article) }
context "with comment" do
let_it_be(:article) { create(:article) }
let_it_be(:comment) { create(:comment, commentable: article) }
it "updates score and spaminess_rating", :aggregate_failures do
allow(BlackBox).to receive(:calculate_spaminess).and_return(99)
allow(BlackBox).to receive(:comment_quality_score).and_return(7)
before do
allow(BlackBox).to receive(:comment_quality_score).and_return(7)
allow(BlackBox).to receive(:calculate_spaminess).and_return(99)
end
described_class.perform_now(comment.id)
comment.reload
expect(comment.score).to be(7)
expect(comment.spaminess_rating).to be(99)
it "updates score and spaminess_rating", :aggregate_failures do
described_class.perform_now(comment.id)
comment.reload
expect(comment.score).to be(7)
expect(comment.spaminess_rating).to be(99)
end
it "calls save on the root comment when given a descendant comment" do
child_comment = double
root_comment = double
allow(root_comment).to receive(:save)
allow(child_comment).to receive(:update_columns)
allow(child_comment).to receive(:is_root?).and_return(false)
allow(child_comment).to receive(:root).and_return(root_comment)
allow(Comment).to receive(:find_by).with(id: 1).and_return(child_comment)
described_class.perform_now(1)
expect(child_comment).to have_received(:is_root?)
expect(child_comment).to have_received(:root)
expect(root_comment).to have_received(:save)
end
it "does not call save on the root comment" do
root_comment = double
allow(root_comment).to receive(:save)
allow(root_comment).to receive(:update_columns)
allow(root_comment).to receive(:is_root?).and_return(true)
allow(root_comment).to receive(:root).and_return(root_comment)
allow(Comment).to receive(:find_by).with(id: 1).and_return(root_comment)
described_class.perform_now(1)
expect(root_comment).to have_received(:is_root?)
expect(root_comment).not_to have_received(:root)
expect(root_comment).not_to have_received(:save)
end
end
context "without comment" do
it "does not break" do
expect { described_class.perform_now(nil) }.not_to raise_error
end
end
end
end

View file

@ -1,14 +1,30 @@
require "rails_helper"
RSpec.describe Comments::CreateFirstReactionJob, type: :job do
describe "#perform_now" do
let(:article) { FactoryBot.create(:article) }
let(:comment) { FactoryBot.create(:comment, commentable: article) }
include_examples "#enqueues_job", "comments_create_first_reaction", 1
it "creates a first reaction" do
expect do
describe "#perform_now" do
context "with comment" do
let_it_be(:article) { create(:article) }
let_it_be(:comment) { create(:comment, commentable: article) }
it "creates a first reaction" do
expect do
described_class.perform_now(comment.id)
end.to change(comment.reactions, :count).by(1)
end
it "creates a like reaction" do
described_class.perform_now(comment.id)
end.to change(Reaction, :count).by(1)
expect(comment.reactions.last.category).to eq("like")
end
end
context "without comment" do
it "does not break" do
expect { described_class.perform_now(nil) }.not_to raise_error
end
end
end
end

View file

@ -1,13 +1,24 @@
require "rails_helper"
RSpec.describe Comments::CreateIdCodeJob, type: :job do
describe "#perform_now" do
let(:article) { FactoryBot.create(:article) }
let(:comment) { FactoryBot.create(:comment, commentable: article) }
include_examples "#enqueues_job", "comments_create_id_code", 1
it "creates an id code" do
described_class.perform_now(comment.id)
expect(comment.reload.id_code).to eql(comment.id.to_s(26))
describe "#perform_now" do
context "with comment" do
let_it_be(:article) { create(:article) }
let_it_be(:comment) { create(:comment, commentable: article) }
it "creates an id code" do
described_class.perform_now(comment.id)
expect(comment.reload.id_code).to eq(comment.id.to_s(26))
end
end
context "without comment" do
it "does not break" do
expect { described_class.perform_now(nil) }.not_to raise_error
end
end
end
end

View file

@ -1,15 +1,40 @@
require "rails_helper"
RSpec.describe Comments::SendEmailNotificationJob, type: :job do
include_examples "#enqueues_job", "comments_send_email_notification", 1
describe "#perform_now" do
let(:article) { FactoryBot.create(:article) }
let(:comment) { FactoryBot.create(:comment, commentable: article) }
context "with comment" do
let_it_be(:comment) { double }
it "sends notify email" do
allow(NotifyMailer).to receive(:new_reply_email)
before do
allow(Comment).to receive(:find_by).with(id: 1).and_return(comment)
end
described_class.perform_now(comment.id)
expect(NotifyMailer).to have_received(:new_reply_email).with(comment)
it "sends reply email" do
mailer = double
allow(mailer).to receive(:deliver_now)
allow(NotifyMailer).to receive(:new_reply_email).and_return(mailer)
described_class.perform_now(1)
expect(NotifyMailer).to have_received(:new_reply_email).with(comment)
expect(mailer).to have_received(:deliver_now)
end
end
context "without comment" do
it "does not error" do
expect { described_class.perform_now(nil) }.not_to raise_error
end
it "does not call NotifyMailer" do
allow(NotifyMailer).to receive(:new_reply_email)
described_class.perform_now(nil)
expect(NotifyMailer).not_to have_received(:new_reply_email)
end
end
end
end

View file

@ -1,18 +1,35 @@
require "rails_helper"
RSpec.describe Comments::TouchUserJob, type: :job do
describe "#perform_now" do
let!(:article) { FactoryBot.create(:article) }
let!(:comment) { FactoryBot.create(:comment, commentable: article) }
let(:user) { comment.user }
let(:touched_at) { 5.minutes.from_now.beginning_of_minute }
include_examples "#enqueues_job", "comments_touch_user", 1
it "touches user updated_at and last_comment_at columns", :aggregate_failures do
Timecop.freeze(touched_at) do
described_class.perform_now(comment.id)
user.reload
expect(user.updated_at).to eql(touched_at)
expect(user.last_comment_at).to eql(touched_at)
describe "#perform_now" do
context "with comment" do
let_it_be(:article) { create(:article) }
let_it_be(:comment) { create(:comment, commentable: article) }
let_it_be(:user) { comment.user }
let_it_be(:touched_at) { 5.minutes.from_now.beginning_of_minute }
it "touches user updated_at and last_comment_at columns", :aggregate_failures do
Timecop.freeze(touched_at) do
described_class.perform_now(comment.id)
user.reload
expect(user.updated_at).to eq(touched_at)
expect(user.last_comment_at).to eq(touched_at)
end
end
it "does not break if the comment has no user" do
comment.update(user: nil)
expect { described_class.perform_now(comment.id) }.not_to raise_error
end
end
context "without comment" do
it "does not break" do
expect { described_class.perform_now(nil) }.not_to raise_error
end
end
end

View file

@ -1,20 +1,18 @@
require "rails_helper"
RSpec.describe Events::BustCacheJob do
let(:cache_buster) { class_double(CacheBuster) }
before do
allow(cache_buster).to receive(:bust_events)
end
include_examples "#enqueues_job", "events_bust_cache"
describe "#perform_now" do
it "busts cache" do
cache_buster = double
allow(cache_buster).to receive(:bust_events)
let(:cache_buster) { class_double(CacheBuster) }
before do
allow(cache_buster).to receive(:bust_events)
end
it "busts cache" do
described_class.perform_now(cache_buster)
expect(cache_buster).to have_received(:bust_events)
end
end

View file

@ -4,38 +4,42 @@ RSpec.describe Follows::CreateChatChannelJob, type: :job do
include_examples "#enqueues_job", "create_chat_channel_after_follow", 3
describe "#perform_now" do
let(:user) { create(:user) }
let(:user2) { create(:user) }
let!(:follow) { create(:follow, follower: user, followable: user2) }
context "with follow" do
let_it_be(:user) { create(:user) }
let_it_be(:user2) { create(:user) }
let_it_be(:follow) { create(:follow, follower: user, followable: user2) }
it "creates a chat channel when mutual followers" do
follow2 = create(:follow, follower: user2, followable: user)
it "creates a chat channel when mutual followers" do
follow2 = create(:follow, follower: user2, followable: user)
# Follow has an after_create callback that creates a channel between the two users,
# so to make sure this test is correct, we delete all channels right after
ChatChannelMembership.delete_all
ChatChannel.delete_all
# Follow has an after_create callback that creates a channel between the two users,
# so to make sure this test is correct, we delete all channels right after
ChatChannelMembership.delete_all
ChatChannel.delete_all
expect do
described_class.perform_now(follow2.id)
end.to change(ChatChannel, :count).by(1)
expect do
described_class.perform_now(follow2.id)
end.to change(ChatChannel, :count).by(1)
end
it "doesn't create a chat channel when the follow is not mutual" do
expect do
described_class.perform_now(follow.id)
end.not_to change(ChatChannel, :count)
end
it "doesn't do anything if follow is not from user to user" do
org_follow = create(:follow, follower: user, followable: create(:organization))
expect do
described_class.perform_now(org_follow.id)
end.not_to change(ChatChannel, :count)
end
end
it "doesn't create a chat channel when the follow is not mutual" do
expect do
described_class.perform_now(follow.id)
end.not_to change(ChatChannel, :count)
end
it "doesn't fail if follow doesn't exist" do
described_class.perform_now(Follow.maximum(:id).to_i + 1)
end
it "doesn't do anything if follow is not from user to user" do
org_follow = create(:follow, follower: user, followable: create(:organization))
expect do
described_class.perform_now(org_follow.id)
end.not_to change(ChatChannel, :count)
context "without follow" do
it "does not break" do
expect { described_class.perform_now(nil) }.not_to raise_error
end
end
end
end

View file

@ -4,36 +4,46 @@ RSpec.describe Follows::SendEmailNotificationJob, type: :job do
include_examples "#enqueues_job", "send_follow_email_notification", 3
describe "#perform_now" do
let(:user) { create(:user) }
let(:user2) { create(:user) }
let!(:follow) { create(:follow, follower: user, followable: user2) }
let(:mailer) { double }
context "with follow" do
let_it_be(:user) { create(:user) }
let_it_be(:user2) { create(:user) }
let_it_be(:follow) { create(:follow, follower: user, followable: user2) }
let(:mailer) { double }
before do
deliverer = double
allow(deliverer).to receive(:deliver)
allow(mailer).to receive(:new_follower_email).and_return(deliverer)
before do
deliverer = double
allow(deliverer).to receive(:deliver)
allow(mailer).to receive(:new_follower_email).and_return(deliverer)
end
it "sends a new_follower_email" do
user2.update_column(:email_follower_notifications, true)
described_class.new(follow.id, mailer).perform_now
expect(mailer).to have_received(:new_follower_email).once
end
it "doesn't create an EmailMessage if it already exists" do
subject = "#{user.username} followed you on dev.to"
EmailMessage.create!(user_id: user2.id, sent_at: Time.current, subject: subject)
described_class.new(follow.id, mailer).perform_now
expect(mailer).not_to have_received(:new_follower_email)
end
it "doesn't send an email if user has disabled notifications" do
user2.update_column(:email_follower_notifications, false)
expect(mailer).not_to have_received(:new_follower_email)
end
end
it "sends a new_follower_email" do
user2.update_column(:email_follower_notifications, true)
described_class.new(follow.id, mailer).perform_now
expect(mailer).to have_received(:new_follower_email).once
end
it "doesn't create an EmailMessage if it already exists" do
EmailMessage.create!(user_id: user2.id, sent_at: Time.current, subject: "#{user.username} followed you on dev.to")
described_class.new(follow.id, mailer).perform_now
expect(mailer).not_to have_received(:new_follower_email)
end
it "doesn't send an email if user has disabled notifications" do
user2.update_column(:email_follower_notifications, false)
expect(mailer).not_to have_received(:new_follower_email)
end
it "doesn't fail if follow doesn't exist" do
described_class.perform_now(Follow.maximum(:id).to_i + 1)
context "without follow" do
it "does not break" do
expect { described_class.perform_now(nil) }.not_to raise_error
end
end
end
end

View file

@ -4,20 +4,24 @@ RSpec.describe Follows::TouchFollowerJob, type: :job do
include_examples "#enqueues_job", "touch_follower", 3
describe "#perform_now" do
it "touches a follower" do
timestamp = 1.day.ago
user = create(:user, updated_at: timestamp, last_followed_at: timestamp)
follow = create(:follow, follower: user)
context "with follow" do
it "touches a follower" do
timestamp = 1.day.ago
user = create(:user, updated_at: timestamp, last_followed_at: timestamp)
follow = create(:follow, follower: user)
described_class.perform_now(follow.id)
user.reload
described_class.perform_now(follow.id)
expect(user.updated_at).to be > timestamp
expect(user.last_followed_at).to be > timestamp
user.reload
expect(user.updated_at).to be > timestamp
expect(user.last_followed_at).to be > timestamp
end
end
it "doesn't fail if follow doesn't exist" do
described_class.perform_now(Follow.maximum(:id).to_i + 1)
context "without follow" do
it "does not break" do
expect { described_class.perform_now(nil) }.not_to raise_error
end
end
end
end