From 6dda660ac1163ea26660f1300d061a2e652d3cad Mon Sep 17 00:00:00 2001 From: Smuzzy-waiii Date: Sun, 10 May 2026 05:13:47 +0530 Subject: [PATCH 1/4] AO3-7406 Move gift exchange notifications to GiftExchangeMailer The following notifications have been moved: - assignments_sent_notification - assignment_default_notification - invalid_signup_notification - potential_match_generation_notification --- app/mailers/gift_exchange_mailer.rb | 48 ++++ app/mailers/user_mailer.rb | 26 --- app/models/challenge_assignment.rb | 4 +- app/models/collection.rb | 8 +- app/models/potential_match.rb | 4 +- .../assignment_default_notification.html.erb | 0 .../assignment_default_notification.text.erb | 0 .../assignments_sent_notification.html.erb | 0 .../assignments_sent_notification.text.erb | 0 .../invalid_signup_notification.html.erb | 0 .../invalid_signup_notification.text.erb | 0 ...ial_match_generation_notification.html.erb | 0 ...ial_match_generation_notification.text.erb | 0 config/locales/mailers/en.yml | 68 +++--- spec/mailers/gift_exchange_mailer_spec.rb | 213 ++++++++++++++++++ spec/mailers/user_mailer_spec.rb | 213 ------------------ .../previews/gift_exchange_mailer_preview.rb | 70 +++++- test/mailers/previews/user_mailer_preview.rb | 66 ------ 18 files changed, 371 insertions(+), 349 deletions(-) rename app/views/{user_mailer => gift_exchange_mailer}/assignment_default_notification.html.erb (100%) rename app/views/{user_mailer => gift_exchange_mailer}/assignment_default_notification.text.erb (100%) rename app/views/{user_mailer => gift_exchange_mailer}/assignments_sent_notification.html.erb (100%) rename app/views/{user_mailer => gift_exchange_mailer}/assignments_sent_notification.text.erb (100%) rename app/views/{user_mailer => gift_exchange_mailer}/invalid_signup_notification.html.erb (100%) rename app/views/{user_mailer => gift_exchange_mailer}/invalid_signup_notification.text.erb (100%) rename app/views/{user_mailer => gift_exchange_mailer}/potential_match_generation_notification.html.erb (100%) rename app/views/{user_mailer => gift_exchange_mailer}/potential_match_generation_notification.text.erb (100%) diff --git a/app/mailers/gift_exchange_mailer.rb b/app/mailers/gift_exchange_mailer.rb index 852e8de2ff4..2115cfd4f97 100644 --- a/app/mailers/gift_exchange_mailer.rb +++ b/app/mailers/gift_exchange_mailer.rb @@ -1,4 +1,41 @@ class GiftExchangeMailer < ApplicationMailer + + def assignment_default_notification(collection_id, assignment_id, email) + @assignment = ChallengeAssignment.find(assignment_id) + + return unless @assignment.offer_signup && @assignment.request_signup + + @collection = Collection.find(collection_id) + @is_collection_email = (email == @collection.collection_email) + mail( + to: email, + subject: default_i18n_subject( + app_name: ArchiveConfig.APP_SHORT_NAME, + collection_title: @collection.title, + offer_byline: @assignment.offering_pseud.byline + ) + ) + end + + def assignments_sent_notification(collection_id, email) + @collection = Collection.find(collection_id) + @is_collection_email = (email == @collection.collection_email) + mail( + to: email, + subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME, collection_title: @collection.title) + ) + end + + def invalid_signup_notification(collection_id, invalid_signup_ids, email) + @collection = Collection.find(collection_id) + @invalid_signups = invalid_signup_ids + @is_collection_email = (email == @collection.collection_email) + mail( + to: email, + subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME, collection_title: @collection.title) + ) + end + def no_potential_matches_notification(collection_id, email) @collection = Collection.find(collection_id) @is_collection_email = (email == @collection.collection_email) @@ -7,4 +44,15 @@ def no_potential_matches_notification(collection_id, email) subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME, collection_title: @collection.title) ) end + + # This is sent at the end of matching, i.e., after assignments are generated. + # It is also sent when assignments are regenerated. + def potential_match_generation_notification(collection_id, email) + @collection = Collection.find(collection_id) + @is_collection_email = (email == @collection.collection_email) + mail( + to: email, + subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME, collection_title: @collection.title) + ) + end end diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index 6c8d85aa576..4adeadcdda9 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -157,32 +157,6 @@ def invite_request_declined(user_id, total, reason) ) end - def assignments_sent_notification(collection_id, email) - @collection = Collection.find(collection_id) - @is_collection_email = (email == @collection.collection_email) - mail( - to: email, - subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME, collection_title: @collection.title) - ) - end - - def assignment_default_notification(collection_id, assignment_id, email) - @assignment = ChallengeAssignment.find(assignment_id) - - return unless @assignment.offer_signup && @assignment.request_signup - - @collection = Collection.find(collection_id) - @is_collection_email = (email == @collection.collection_email) - mail( - to: email, - subject: default_i18n_subject( - app_name: ArchiveConfig.APP_SHORT_NAME, - collection_title: @collection.title, - offer_byline: @assignment.offering_pseud.byline - ) - ) - end - def invalid_signup_notification(collection_id, invalid_signup_ids, email) @collection = Collection.find(collection_id) @invalid_signups = invalid_signup_ids diff --git a/app/models/challenge_assignment.rb b/app/models/challenge_assignment.rb index 0ac4ca5b118..7ad77cda4e9 100755 --- a/app/models/challenge_assignment.rb +++ b/app/models/challenge_assignment.rb @@ -387,11 +387,11 @@ def self.delayed_generate(collection_id) end if collection.collection_email.present? - UserMailer.potential_match_generation_notification(collection.id, collection.collection_email).deliver_later + GiftExchangeMailer.potential_match_generation_notification(collection.id, collection.collection_email).deliver_later else collection.maintainers_list.each do |user| I18n.with_locale(user.preference.locale_for_mails) do - UserMailer.potential_match_generation_notification(collection.id, user.email).deliver_later + GiftExchangeMailer.potential_match_generation_notification(collection.id, user.email).deliver_later end end end diff --git a/app/models/collection.rb b/app/models/collection.rb index b51005911f7..3315542d16f 100755 --- a/app/models/collection.rb +++ b/app/models/collection.rb @@ -326,12 +326,12 @@ def collection_email def notify_maintainers_assignments_sent if self.collection_email.present? - UserMailer.assignments_sent_notification(self.id, self.collection_email).deliver_later + GiftExchangeMailer.assignments_sent_notification(self.id, self.collection_email).deliver_later else # if collection email is not set and collection parent email is not set, loop through maintainers and send each a notice via email self.maintainers_list.each do |user| I18n.with_locale(user.preference.locale_for_mails) do - UserMailer.assignments_sent_notification(self.id, user.email).deliver_later + GiftExchangeMailer.assignments_sent_notification(self.id, user.email).deliver_later end end end @@ -339,12 +339,12 @@ def notify_maintainers_assignments_sent def notify_maintainers_assignment_default(challenge_assignment) if self.collection_email.present? - UserMailer.assignment_default_notification(self.id, challenge_assignment.id, self.collection_email).deliver_later + GiftExchangeMailer.assignment_default_notification(self.id, challenge_assignment.id, self.collection_email).deliver_later else # if collection email is not set and collection parent email is not set, loop through maintainers and send each a notice via email self.maintainers_list.each do |user| I18n.with_locale(user.preference.locale_for_mails) do - UserMailer.assignment_default_notification(self.id, challenge_assignment.id, user.email).deliver_later + GiftExchangeMailer.assignment_default_notification(self.id, challenge_assignment.id, user.email).deliver_later end end end diff --git a/app/models/potential_match.rb b/app/models/potential_match.rb index 25f4d6c5178..af9bbaa94d2 100644 --- a/app/models/potential_match.rb +++ b/app/models/potential_match.rb @@ -91,11 +91,11 @@ def self.generate_in_background(collection_id) invalid_signup_ids.each { |sid| REDIS_GENERAL.sadd?(invalid_signup_key(collection), sid) } if collection.collection_email.present? - UserMailer.invalid_signup_notification(collection.id, invalid_signup_ids, collection.collection_email).deliver_later + GiftExchangeMailer.invalid_signup_notification(collection.id, invalid_signup_ids, collection.collection_email).deliver_later else collection.maintainers_list.each do |user| I18n.with_locale(user.preference.locale_for_mails) do - UserMailer.invalid_signup_notification(collection.id, invalid_signup_ids, user.email).deliver_later + GiftExchangeMailer.invalid_signup_notification(collection.id, invalid_signup_ids, user.email).deliver_later end end end diff --git a/app/views/user_mailer/assignment_default_notification.html.erb b/app/views/gift_exchange_mailer/assignment_default_notification.html.erb similarity index 100% rename from app/views/user_mailer/assignment_default_notification.html.erb rename to app/views/gift_exchange_mailer/assignment_default_notification.html.erb diff --git a/app/views/user_mailer/assignment_default_notification.text.erb b/app/views/gift_exchange_mailer/assignment_default_notification.text.erb similarity index 100% rename from app/views/user_mailer/assignment_default_notification.text.erb rename to app/views/gift_exchange_mailer/assignment_default_notification.text.erb diff --git a/app/views/user_mailer/assignments_sent_notification.html.erb b/app/views/gift_exchange_mailer/assignments_sent_notification.html.erb similarity index 100% rename from app/views/user_mailer/assignments_sent_notification.html.erb rename to app/views/gift_exchange_mailer/assignments_sent_notification.html.erb diff --git a/app/views/user_mailer/assignments_sent_notification.text.erb b/app/views/gift_exchange_mailer/assignments_sent_notification.text.erb similarity index 100% rename from app/views/user_mailer/assignments_sent_notification.text.erb rename to app/views/gift_exchange_mailer/assignments_sent_notification.text.erb diff --git a/app/views/user_mailer/invalid_signup_notification.html.erb b/app/views/gift_exchange_mailer/invalid_signup_notification.html.erb similarity index 100% rename from app/views/user_mailer/invalid_signup_notification.html.erb rename to app/views/gift_exchange_mailer/invalid_signup_notification.html.erb diff --git a/app/views/user_mailer/invalid_signup_notification.text.erb b/app/views/gift_exchange_mailer/invalid_signup_notification.text.erb similarity index 100% rename from app/views/user_mailer/invalid_signup_notification.text.erb rename to app/views/gift_exchange_mailer/invalid_signup_notification.text.erb diff --git a/app/views/user_mailer/potential_match_generation_notification.html.erb b/app/views/gift_exchange_mailer/potential_match_generation_notification.html.erb similarity index 100% rename from app/views/user_mailer/potential_match_generation_notification.html.erb rename to app/views/gift_exchange_mailer/potential_match_generation_notification.html.erb diff --git a/app/views/user_mailer/potential_match_generation_notification.text.erb b/app/views/gift_exchange_mailer/potential_match_generation_notification.text.erb similarity index 100% rename from app/views/user_mailer/potential_match_generation_notification.text.erb rename to app/views/gift_exchange_mailer/potential_match_generation_notification.text.erb diff --git a/config/locales/mailers/en.yml b/config/locales/mailers/en.yml index dd1c6ff8b15..da3952f6c71 100644 --- a/config/locales/mailers/en.yml +++ b/config/locales/mailers/en.yml @@ -200,6 +200,31 @@ en: tag: "[%{app_name}] Edited reply to your comment on the tag %{name}" you_wrote: 'You wrote:' gift_exchange_mailer: + assignment_default_notification: + assign_pinch_hitter: + collection_assignments_page: collection assignments page + html: You can assign a pinch hitter on the %{collection_assignments_page_link}. + text: 'You can assign a pinch hitter on the collection assignments page: %{collection_assignments_page_url}.' + defaulted_on_assignment: + html: "%{offer_byline} has defaulted on their assignment for %{request_byline} in your gift exchange %{collection_link}." + text: '%{offer_byline} has defaulted on their assignment for %{request_byline} in your gift exchange "%{collection_title}" (%{collection_url}).' + subject: "[%{app_name}][%{collection_title}] Assignment default by %{offer_byline}" + assignments_sent_notification: + all_sent_out: + html: All assignments have now been sent out for your gift exchange %{collection_link}. + text: All assignments have now been sent out for your gift exchange "%{collection_title}" (%{collection_url}). + subject: "[%{app_name}][%{collection_title}] Assignments sent" + invalid_signup_notification: + found_invalid: + html: We have found some invalid sign-ups in your gift exchange %{collection_link}. Potential matches can't be generated until these are cleaned up. + text: We have found some invalid sign-ups in your gift exchange "%{collection_title}" (%{collection_url}). Potential matches can't be generated until these are cleaned up. + see_details: + challenge_matching_help: the challenge matching help + html: Invalid sign-ups may be duplicates, or may not meet the requirements you've set for your challenge. Unfortunately, there is no automatic way to fix them, so you will have to manually edit or delete them. For more details, refer to %{challenge_matching_help_link}. + text: 'Invalid sign-ups may be duplicates, or may not meet the requirements you''ve set for your challenge. Unfortunately, there is no automatic way to fix them, so you will have to manually edit or delete them. For more details, refer to the challenge matching help: %{challenge_matching_help_url}.' + signup: 'Signup #%{signup_id}' + signups_here: 'Here are the invalid sign-ups:' + subject: "[%{app_name}][%{collection_title}] Invalid sign-ups found" no_potential_matches_notification: generation_finished: html: Potential match generation for %{collection_link} has finished. Unfortunately, there were no potential matches found. @@ -209,6 +234,15 @@ en: match_settings: Minimum Number to Match settings text: Please update your gift exchange's Minimum Number to Match settings (%{match_settings_url}) and try generating potential matches again. subject: "[%{app_name}][%{collection_title}] No potential matches found" + potential_match_generation_notification: + finished_generating: + html: We have finished generating potential assignments for your gift exchange %{collection_link}. + text: We have finished generating potential assignments for your gift exchange "%{collection_title}" (%{collection_url}). + matches_available: + html: The potential matches and set assignments are available on its %{matching_page_link}. + matching_page: Matching page + text: 'The potential matches and set assignments are available on its Matching page: %{matching_page_url}.' + subject: "[%{app_name}][%{collection_title}] Potential assignment generation complete" kudo_mailer: batch_kudo_notification: guest: @@ -412,20 +446,6 @@ en: work_added: html: The collection maintainers of %{collection_link} have added your work %{work_link} to their collection! text: The collection maintainers of "%{collection_title}" (%{collection_url}) have added your work "%{work_title}" (%{work_url}) to their collection! - assignment_default_notification: - assign_pinch_hitter: - collection_assignments_page: collection assignments page - html: You can assign a pinch hitter on the %{collection_assignments_page_link}. - text: 'You can assign a pinch hitter on the collection assignments page: %{collection_assignments_page_url}.' - defaulted_on_assignment: - html: "%{offer_byline} has defaulted on their assignment for %{request_byline} in your gift exchange %{collection_link}." - text: '%{offer_byline} has defaulted on their assignment for %{request_byline} in your gift exchange "%{collection_title}" (%{collection_url}).' - subject: "[%{app_name}][%{collection_title}] Assignment default by %{offer_byline}" - assignments_sent_notification: - all_sent_out: - html: All assignments have now been sent out for your gift exchange %{collection_link}. - text: All assignments have now been sent out for your gift exchange "%{collection_title}" (%{collection_url}). - subject: "[%{app_name}][%{collection_title}] Assignments sent" batch_subscription_notification: chapter_summary: Chapter Summary footer_note: @@ -669,17 +689,6 @@ en: additional_ticket: If you have additional questions or information, do not hesitate to send in another ticket. introduction: 'We''re working hard to reply to everyone, and we''ll respond to you as soon as we can. Your communication is greatly valued, and it will be reviewed and answered by our volunteer Support team. In the meantime, here is a copy of the information you submitted through the Technical Support and Feedback form:' subject: "[%{app_name}] Support - %{summary}" - invalid_signup_notification: - found_invalid: - html: We have found some invalid sign-ups in your gift exchange %{collection_link}. Potential matches can't be generated until these are cleaned up. - text: We have found some invalid sign-ups in your gift exchange "%{collection_title}" (%{collection_url}). Potential matches can't be generated until these are cleaned up. - see_details: - challenge_matching_help: the challenge matching help - html: Invalid sign-ups may be duplicates, or may not meet the requirements you've set for your challenge. Unfortunately, there is no automatic way to fix them, so you will have to manually edit or delete them. For more details, refer to %{challenge_matching_help_link}. - text: 'Invalid sign-ups may be duplicates, or may not meet the requirements you''ve set for your challenge. Unfortunately, there is no automatic way to fix them, so you will have to manually edit or delete them. For more details, refer to the challenge matching help: %{challenge_matching_help_url}.' - signup: 'Signup #%{signup_id}' - signups_here: 'Here are the invalid sign-ups:' - subject: "[%{app_name}][%{collection_title}] Invalid sign-ups found" invitation: been_invited: You've been invited to join the Archive of Our Own! features: With an account, you can post fanworks, use bookmarks to keep track of works you enjoyed, receive subscription emails when your favorite creators or works update, customize the way the site looks for you, and more! @@ -767,15 +776,6 @@ en: would_like_to_include: html: The collection maintainers of %{collection_link} would like to include your work %{work_link} in their collection! text: The collection maintainers of "%{collection_title}" (%{collection_url}) would like to include your work "%{work_title}" (%{work_url}) in their collection! - potential_match_generation_notification: - finished_generating: - html: We have finished generating potential assignments for your gift exchange %{collection_link}. - text: We have finished generating potential assignments for your gift exchange "%{collection_title}" (%{collection_url}). - matches_available: - html: The potential matches and set assignments are available on its %{matching_page_link}. - matching_page: Matching page - text: 'The potential matches and set assignments are available on its Matching page: %{matching_page_url}.' - subject: "[%{app_name}][%{collection_title}] Potential assignment generation complete" prompter_notification: a_response_to_your_prompt: collection: diff --git a/spec/mailers/gift_exchange_mailer_spec.rb b/spec/mailers/gift_exchange_mailer_spec.rb index ba9c89c53e0..fb8284cdf68 100644 --- a/spec/mailers/gift_exchange_mailer_spec.rb +++ b/spec/mailers/gift_exchange_mailer_spec.rb @@ -1,6 +1,166 @@ require "spec_helper" describe GiftExchangeMailer do + describe "#assignment_default_notification" do + subject(:email) { UserMailer.assignment_default_notification(collection.id, challenge_assignment.id, "test@example.com") } + + let(:collection) { create(:collection) } + let(:challenge_assignment) { create(:challenge_assignment) } + + # Test the headers + it_behaves_like "an email with a valid sender" + + it "has the correct subject line" do + subject = "[#{ArchiveConfig.APP_SHORT_NAME}][#{collection.title}] Assignment default by #{challenge_assignment.offer_byline}" + expect(email.subject).to eq(subject) + end + + # Test both body contents + it_behaves_like "a multipart email" + + it_behaves_like "a translated email" + + describe "HTML version" do + it "has the correct content" do + expect(email).to have_html_part_content("> has defaulted on their assignment for <") + expect(email).to have_html_part_content("assign a pinch hitter on the <") + end + end + + describe "text version" do + it "has the correct content" do + expect(email).to have_text_part_content("has defaulted on their assignment for") + expect(email).to have_text_part_content("assign a pinch hitter on the collection assignments page") + end + end + end + + describe "#assignment_default_notification sent to collection_email" do + subject(:email) { UserMailer.assignment_default_notification(collection.id, challenge_assignment.id, collection.collection_email) } + + let(:collection) { create(:collection) } + let(:challenge_assignment) { create(:challenge_assignment) } + + it_behaves_like "an email with a valid sender" + + describe "HTML version" do + it "has the correct footer content" do + expect(email).to have_html_part_content("your email address has been listed as the collection email") + end + end + + describe "text version" do + it "has the correct footer content" do + expect(email).to have_text_part_content("your email address has been listed as the collection email") + end + end + end + + describe "#assignments_sent_notification" do + subject(:email) { UserMailer.assignments_sent_notification(collection.id, "test@example.com") } + + let(:collection) { create(:collection) } + + # Test the headers + it_behaves_like "an email with a valid sender" + + it "has the correct subject line" do + subject = "[#{ArchiveConfig.APP_SHORT_NAME}][#{collection.title}] Assignments sent" + expect(email.subject).to eq(subject) + end + + # Test both body contents + it_behaves_like "a multipart email" + + it_behaves_like "a translated email" + + describe "HTML version" do + it "has the correct content" do + expect(email).to have_html_part_content("sent out for your gift exchange <") + end + end + + describe "text version" do + it "has the correct content" do + expect(email).to have_text_part_content("sent out for your gift exchange \"#{collection.title}\"") + end + end + end + + describe "#assignments_sent_notification sent to collection_email" do + subject(:email) { UserMailer.assignments_sent_notification(collection.id, collection.collection_email) } + + let(:collection) { create(:collection) } + let(:signup) { create(:challenge_signup) } + + it_behaves_like "an email with a valid sender" + + describe "HTML version" do + it "has the correct footer content" do + expect(email).to have_html_part_content("your email address has been listed as the collection email") + end + end + + describe "text version" do + it "has the correct footer content" do + expect(email).to have_text_part_content("your email address has been listed as the collection email") + end + end + end + + describe "#invalid_signup_notification" do + subject(:email) { UserMailer.invalid_signup_notification(collection.id, [signup.id], "test@example.com") } + + let(:collection) { create(:collection) } + let(:signup) { create(:challenge_signup) } + + # Test the headers + it_behaves_like "an email with a valid sender" + + it "has the correct subject line" do + subject = "[#{ArchiveConfig.APP_SHORT_NAME}][#{collection.title}] Invalid sign-ups found" + expect(email.subject).to eq(subject) + end + + # Test both body contents + it_behaves_like "a multipart email" + + it_behaves_like "a translated email" + + describe "HTML version" do + it "has the correct content" do + expect(email).to have_html_part_content("invalid sign-ups in your gift exchange <") + end + end + + describe "text version" do + it "has the correct content" do + expect(email).to have_text_part_content("invalid sign-ups in your gift exchange \"#{collection.title}\"") + end + end + end + + describe "#invalid_signup_notification sent to collection_email" do + subject(:email) { UserMailer.invalid_signup_notification(collection.id, [signup.id], collection.collection_email) } + + let(:collection) { create(:collection) } + let(:signup) { create(:challenge_signup) } + + it_behaves_like "an email with a valid sender" + + describe "HTML version" do + it "has the correct footer content" do + expect(email).to have_html_part_content("your email address has been listed as the collection email") + end + end + + describe "text version" do + it "has the correct footer content" do + expect(email).to have_text_part_content("your email address has been listed as the collection email") + end + end + end + describe "#no_potential_matches_notification" do subject(:email) { GiftExchangeMailer.no_potential_matches_notification(collection.id, "test@example.com") } @@ -53,4 +213,57 @@ end end end + + describe "#potential_match_generation_notification" do + subject(:email) { UserMailer.potential_match_generation_notification(collection.id, "test@example.com") } + + let(:collection) { create(:collection) } + + # Test the headers + it_behaves_like "an email with a valid sender" + + it "has the correct subject line" do + subject = "[#{ArchiveConfig.APP_SHORT_NAME}][#{collection.title}] Potential assignment generation complete" + expect(email.subject).to eq(subject) + end + + # Test both body contents + it_behaves_like "a multipart email" + + it_behaves_like "a translated email" + + describe "HTML version" do + it "has the correct content" do + expect(email).to have_html_part_content("potential assignments for your gift exchange <") + expect(email).to have_html_part_content("on its <") + end + end + + describe "text version" do + it "has the correct content" do + expect(email).to have_text_part_content("potential assignments for your gift exchange \"#{collection.title}\"") + expect(email).to have_text_part_content("on its Matching page:") + end + end + end + + describe "#potential_match_generation_notification sent to collection_email" do + subject(:email) { UserMailer.potential_match_generation_notification(collection.id, collection.collection_email) } + + let(:collection) { create(:collection) } + + it_behaves_like "an email with a valid sender" + + describe "HTML version" do + it "has the correct footer content" do + expect(email).to have_html_part_content("your email address has been listed as the collection email") + end + end + + describe "text version" do + it "has the correct footer content" do + expect(email).to have_text_part_content("your email address has been listed as the collection email") + end + end + end end diff --git a/spec/mailers/user_mailer_spec.rb b/spec/mailers/user_mailer_spec.rb index 27a57650a67..d01353025de 100644 --- a/spec/mailers/user_mailer_spec.rb +++ b/spec/mailers/user_mailer_spec.rb @@ -1123,219 +1123,6 @@ def queue_adapter_for_test end end - describe "#potential_match_generation_notification" do - subject(:email) { UserMailer.potential_match_generation_notification(collection.id, "test@example.com") } - - let(:collection) { create(:collection) } - - # Test the headers - it_behaves_like "an email with a valid sender" - - it "has the correct subject line" do - subject = "[#{ArchiveConfig.APP_SHORT_NAME}][#{collection.title}] Potential assignment generation complete" - expect(email.subject).to eq(subject) - end - - # Test both body contents - it_behaves_like "a multipart email" - - it_behaves_like "a translated email" - - describe "HTML version" do - it "has the correct content" do - expect(email).to have_html_part_content("potential assignments for your gift exchange <") - expect(email).to have_html_part_content("on its <") - end - end - - describe "text version" do - it "has the correct content" do - expect(email).to have_text_part_content("potential assignments for your gift exchange \"#{collection.title}\"") - expect(email).to have_text_part_content("on its Matching page:") - end - end - end - - describe "#potential_match_generation_notification sent to collection_email" do - subject(:email) { UserMailer.potential_match_generation_notification(collection.id, collection.collection_email) } - - let(:collection) { create(:collection) } - - it_behaves_like "an email with a valid sender" - - describe "HTML version" do - it "has the correct footer content" do - expect(email).to have_html_part_content("your email address has been listed as the collection email") - end - end - - describe "text version" do - it "has the correct footer content" do - expect(email).to have_text_part_content("your email address has been listed as the collection email") - end - end - end - - describe "#invalid_signup_notification" do - subject(:email) { UserMailer.invalid_signup_notification(collection.id, [signup.id], "test@example.com") } - - let(:collection) { create(:collection) } - let(:signup) { create(:challenge_signup) } - - # Test the headers - it_behaves_like "an email with a valid sender" - - it "has the correct subject line" do - subject = "[#{ArchiveConfig.APP_SHORT_NAME}][#{collection.title}] Invalid sign-ups found" - expect(email.subject).to eq(subject) - end - - # Test both body contents - it_behaves_like "a multipart email" - - it_behaves_like "a translated email" - - describe "HTML version" do - it "has the correct content" do - expect(email).to have_html_part_content("invalid sign-ups in your gift exchange <") - end - end - - describe "text version" do - it "has the correct content" do - expect(email).to have_text_part_content("invalid sign-ups in your gift exchange \"#{collection.title}\"") - end - end - end - - describe "#invalid_signup_notification sent to collection_email" do - subject(:email) { UserMailer.invalid_signup_notification(collection.id, [signup.id], collection.collection_email) } - - let(:collection) { create(:collection) } - let(:signup) { create(:challenge_signup) } - - it_behaves_like "an email with a valid sender" - - describe "HTML version" do - it "has the correct footer content" do - expect(email).to have_html_part_content("your email address has been listed as the collection email") - end - end - - describe "text version" do - it "has the correct footer content" do - expect(email).to have_text_part_content("your email address has been listed as the collection email") - end - end - end - - describe "#assignments_sent_notification" do - subject(:email) { UserMailer.assignments_sent_notification(collection.id, "test@example.com") } - - let(:collection) { create(:collection) } - - # Test the headers - it_behaves_like "an email with a valid sender" - - it "has the correct subject line" do - subject = "[#{ArchiveConfig.APP_SHORT_NAME}][#{collection.title}] Assignments sent" - expect(email.subject).to eq(subject) - end - - # Test both body contents - it_behaves_like "a multipart email" - - it_behaves_like "a translated email" - - describe "HTML version" do - it "has the correct content" do - expect(email).to have_html_part_content("sent out for your gift exchange <") - end - end - - describe "text version" do - it "has the correct content" do - expect(email).to have_text_part_content("sent out for your gift exchange \"#{collection.title}\"") - end - end - end - - describe "#assignments_sent_notification sent to collection_email" do - subject(:email) { UserMailer.assignments_sent_notification(collection.id, collection.collection_email) } - - let(:collection) { create(:collection) } - let(:signup) { create(:challenge_signup) } - - it_behaves_like "an email with a valid sender" - - describe "HTML version" do - it "has the correct footer content" do - expect(email).to have_html_part_content("your email address has been listed as the collection email") - end - end - - describe "text version" do - it "has the correct footer content" do - expect(email).to have_text_part_content("your email address has been listed as the collection email") - end - end - end - - describe "#assignment_default_notification" do - subject(:email) { UserMailer.assignment_default_notification(collection.id, challenge_assignment.id, "test@example.com") } - - let(:collection) { create(:collection) } - let(:challenge_assignment) { create(:challenge_assignment) } - - # Test the headers - it_behaves_like "an email with a valid sender" - - it "has the correct subject line" do - subject = "[#{ArchiveConfig.APP_SHORT_NAME}][#{collection.title}] Assignment default by #{challenge_assignment.offer_byline}" - expect(email.subject).to eq(subject) - end - - # Test both body contents - it_behaves_like "a multipart email" - - it_behaves_like "a translated email" - - describe "HTML version" do - it "has the correct content" do - expect(email).to have_html_part_content("> has defaulted on their assignment for <") - expect(email).to have_html_part_content("assign a pinch hitter on the <") - end - end - - describe "text version" do - it "has the correct content" do - expect(email).to have_text_part_content("has defaulted on their assignment for") - expect(email).to have_text_part_content("assign a pinch hitter on the collection assignments page") - end - end - end - - describe "#assignment_default_notification sent to collection_email" do - subject(:email) { UserMailer.assignment_default_notification(collection.id, challenge_assignment.id, collection.collection_email) } - - let(:collection) { create(:collection) } - let(:challenge_assignment) { create(:challenge_assignment) } - - it_behaves_like "an email with a valid sender" - - describe "HTML version" do - it "has the correct footer content" do - expect(email).to have_html_part_content("your email address has been listed as the collection email") - end - end - - describe "text version" do - it "has the correct footer content" do - expect(email).to have_text_part_content("your email address has been listed as the collection email") - end - end - end - describe "prompter_notification" do let(:user) { create(:user) } diff --git a/test/mailers/previews/gift_exchange_mailer_preview.rb b/test/mailers/previews/gift_exchange_mailer_preview.rb index 7045c57d629..750d19135a5 100644 --- a/test/mailers/previews/gift_exchange_mailer_preview.rb +++ b/test/mailers/previews/gift_exchange_mailer_preview.rb @@ -1,16 +1,82 @@ class GiftExchangeMailerPreview < ApplicationMailerPreview - # URL: /rails/mailers/user_mailer/no_potential_matches_notification_collection_email + # URL: /rails/mailers/gift_exchange_mailer/assignment_default_notification_collection_email + def assignment_default_notification_collection_email + collection = create(:collection, email: "collection@example.com") + email = collection.collection_email + challenge_assignment = create(:challenge_assignment) + GiftExchangeMailer.assignment_default_notification(collection.id, challenge_assignment.id, email) + end + + # URL: /rails/mailers/gift_exchange_mailer/assignment_default_notification_maintainer + def assignment_default_notification_maintainer + user = create(:user, :for_mailer_preview) + collection = create(:collection, owners: [user.default_pseud]) + email = user.email + challenge_assignment = create(:challenge_assignment) + GiftExchangeMailer.assignment_default_notification(collection.id, challenge_assignment.id, email) + end + + # URL: /rails/mailers/gift_exchange_mailer/assignments_sent_notification_collection_email + def assignments_sent_notification_collection_email + collection = create(:collection, email: "collection@example.com") + email = collection.collection_email + GiftExchangeMailer.assignments_sent_notification(collection.id, email) + end + + # URL: /rails/mailers/gift_exchange_mailer/assignments_sent_notification_maintainer + def assignments_sent_notification_maintainer + user = create(:user, :for_mailer_preview) + collection = create(:collection, owners: [user.default_pseud]) + email = user.email + GiftExchangeMailer.assignments_sent_notification(collection.id, email) + end + + # URL: /rails/mailers/gift_exchange_mailer/invalid_signup_notification_collection_email?signup_count=2 + def invalid_signup_notification_collection_email + signup_count = params[:signup_count] ? params[:signup_count].to_i : 1 + collection = create(:collection, email: "collection@example.com") + invalid_signup_ids = create_list(:challenge_signup, signup_count).map(&:id) + email = collection.collection_email + GiftExchangeMailer.invalid_signup_notification(collection.id, invalid_signup_ids, email) + end + + # URL: /rails/mailers/gift_exchange_mailer/invalid_signup_notification_maintainer?signup_count=2 + def invalid_signup_notification_maintainer + signup_count = params[:signup_count] ? params[:signup_count].to_i : 1 + user = create(:user, :for_mailer_preview) + collection = create(:collection, owners: [user.default_pseud]) + invalid_signup_ids = create_list(:challenge_signup, signup_count).map(&:id) + email = user.email + GiftExchangeMailer.invalid_signup_notification(collection.id, invalid_signup_ids, email) + end + + # URL: /rails/mailers/gift_exchange_mailer/no_potential_matches_notification_collection_email def no_potential_matches_notification_collection_email collection = create(:collection, email: "collection@example.com") email = collection.collection_email GiftExchangeMailer.no_potential_matches_notification(collection.id, email) end - # URL: /rails/mailers/user_mailer/no_potential_matches_notification_maintainer + # URL: /rails/mailers/gift_exchange_mailer/no_potential_matches_notification_maintainer def no_potential_matches_notification_maintainer user = create(:user, :for_mailer_preview) collection = create(:collection, owners: [user.default_pseud]) email = user.email GiftExchangeMailer.no_potential_matches_notification(collection.id, email) end + + # URL: /rails/mailers/gift_exchange_mailer/potential_match_generation_notification_collection_email + def potential_match_generation_notification_collection_email + collection = create(:collection, email: "collection@example.com") + email = collection.collection_email + GiftExchangeMailer.potential_match_generation_notification(collection.id, email) + end + + # URL: /rails/mailers/gift_exchange_mailer/potential_match_generation_notification_maintainer + def potential_match_generation_notification_maintainer + user = create(:user, :for_mailer_preview) + collection = create(:collection, owners: [user.default_pseud]) + email = user.email + GiftExchangeMailer.potential_match_generation_notification(collection.id, email) + end end diff --git a/test/mailers/previews/user_mailer_preview.rb b/test/mailers/previews/user_mailer_preview.rb index ff22ddfd1fc..d2906898878 100644 --- a/test/mailers/previews/user_mailer_preview.rb +++ b/test/mailers/previews/user_mailer_preview.rb @@ -301,72 +301,6 @@ def recipient_notification_status_collection UserMailer.recipient_notification(user.id, work.id, collection.id) end - # URL: /rails/mailers/user_mailer/potential_match_generation_notification_collection_email - def potential_match_generation_notification_collection_email - collection = create(:collection, email: "collection@example.com") - email = collection.collection_email - UserMailer.potential_match_generation_notification(collection.id, email) - end - - # URL: /rails/mailers/user_mailer/potential_match_generation_notification_maintainer - def potential_match_generation_notification_maintainer - user = create(:user, :for_mailer_preview) - collection = create(:collection, owners: [user.default_pseud]) - email = user.email - UserMailer.potential_match_generation_notification(collection.id, email) - end - - # URL: /rails/mailers/user_mailer/invalid_signup_notification_collection_email?signup_count=2 - def invalid_signup_notification_collection_email - signup_count = params[:signup_count] ? params[:signup_count].to_i : 1 - collection = create(:collection, email: "collection@example.com") - invalid_signup_ids = create_list(:challenge_signup, signup_count).map(&:id) - email = collection.collection_email - UserMailer.invalid_signup_notification(collection.id, invalid_signup_ids, email) - end - - # URL: /rails/mailers/user_mailer/invalid_signup_notification_maintainer?signup_count=2 - def invalid_signup_notification_maintainer - signup_count = params[:signup_count] ? params[:signup_count].to_i : 1 - user = create(:user, :for_mailer_preview) - collection = create(:collection, owners: [user.default_pseud]) - invalid_signup_ids = create_list(:challenge_signup, signup_count).map(&:id) - email = user.email - UserMailer.invalid_signup_notification(collection.id, invalid_signup_ids, email) - end - - # URL: /rails/mailers/user_mailer/assignments_sent_notification_collection_email - def assignments_sent_notification_collection_email - collection = create(:collection, email: "collection@example.com") - email = collection.collection_email - UserMailer.assignments_sent_notification(collection.id, email) - end - - # URL: /rails/mailers/user_mailer/assignments_sent_notification_maintainer - def assignments_sent_notification_maintainer - user = create(:user, :for_mailer_preview) - collection = create(:collection, owners: [user.default_pseud]) - email = user.email - UserMailer.assignments_sent_notification(collection.id, email) - end - - # URL: /rails/mailers/user_mailer/assignment_default_notification_collection_email - def assignment_default_notification_collection_email - collection = create(:collection, email: "collection@example.com") - email = collection.collection_email - challenge_assignment = create(:challenge_assignment) - UserMailer.assignment_default_notification(collection.id, challenge_assignment.id, email) - end - - # URL: /rails/mailers/user_mailer/assignment_default_notification_maintainer - def assignment_default_notification_maintainer - user = create(:user, :for_mailer_preview) - collection = create(:collection, owners: [user.default_pseud]) - email = user.email - challenge_assignment = create(:challenge_assignment) - UserMailer.assignment_default_notification(collection.id, challenge_assignment.id, email) - end - # URL: /rails/mailers/user_mailer/invite_increase_notification?total=2 def invite_increase_notification user = create(:user, :for_mailer_preview) From b0d994b0c3d2ebee326734cd14a6d65ab5e98040 Mon Sep 17 00:00:00 2001 From: Smuzzy-waiii Date: Sun, 10 May 2026 05:29:30 +0530 Subject: [PATCH 2/4] AO3-7406 Remove empty line --- app/mailers/gift_exchange_mailer.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/mailers/gift_exchange_mailer.rb b/app/mailers/gift_exchange_mailer.rb index 2115cfd4f97..2c18e7ace3c 100644 --- a/app/mailers/gift_exchange_mailer.rb +++ b/app/mailers/gift_exchange_mailer.rb @@ -1,5 +1,4 @@ class GiftExchangeMailer < ApplicationMailer - def assignment_default_notification(collection_id, assignment_id, email) @assignment = ChallengeAssignment.find(assignment_id) From 10fc940ca3c39eb7f860a773b0fabcdf6e8272c8 Mon Sep 17 00:00:00 2001 From: Smuzzy-waiii Date: Sun, 10 May 2026 06:18:29 +0530 Subject: [PATCH 3/4] AO3-7406 Fix: move gift exchange notification calls to right mailer in spec fix: move gift exchange notification calls to right mailer in spec Move calls to gift exchange notification functions in spec/mailers/gift_exchange_mailer_spec.rb to be called under GiftExchangeMailer and not UserMailer, which is what was happening due to previous buggy commit(s) --- spec/mailers/gift_exchange_mailer_spec.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/spec/mailers/gift_exchange_mailer_spec.rb b/spec/mailers/gift_exchange_mailer_spec.rb index fb8284cdf68..e7f63657d32 100644 --- a/spec/mailers/gift_exchange_mailer_spec.rb +++ b/spec/mailers/gift_exchange_mailer_spec.rb @@ -2,7 +2,7 @@ describe GiftExchangeMailer do describe "#assignment_default_notification" do - subject(:email) { UserMailer.assignment_default_notification(collection.id, challenge_assignment.id, "test@example.com") } + subject(:email) { GiftExchangeMailer.assignment_default_notification(collection.id, challenge_assignment.id, "test@example.com") } let(:collection) { create(:collection) } let(:challenge_assignment) { create(:challenge_assignment) } @@ -36,7 +36,7 @@ end describe "#assignment_default_notification sent to collection_email" do - subject(:email) { UserMailer.assignment_default_notification(collection.id, challenge_assignment.id, collection.collection_email) } + subject(:email) { GiftExchangeMailer.assignment_default_notification(collection.id, challenge_assignment.id, collection.collection_email) } let(:collection) { create(:collection) } let(:challenge_assignment) { create(:challenge_assignment) } @@ -57,7 +57,7 @@ end describe "#assignments_sent_notification" do - subject(:email) { UserMailer.assignments_sent_notification(collection.id, "test@example.com") } + subject(:email) { GiftExchangeMailer.assignments_sent_notification(collection.id, "test@example.com") } let(:collection) { create(:collection) } @@ -88,7 +88,7 @@ end describe "#assignments_sent_notification sent to collection_email" do - subject(:email) { UserMailer.assignments_sent_notification(collection.id, collection.collection_email) } + subject(:email) { GiftExchangeMailer.assignments_sent_notification(collection.id, collection.collection_email) } let(:collection) { create(:collection) } let(:signup) { create(:challenge_signup) } @@ -109,7 +109,7 @@ end describe "#invalid_signup_notification" do - subject(:email) { UserMailer.invalid_signup_notification(collection.id, [signup.id], "test@example.com") } + subject(:email) { GiftExchangeMailer.invalid_signup_notification(collection.id, [signup.id], "test@example.com") } let(:collection) { create(:collection) } let(:signup) { create(:challenge_signup) } @@ -141,7 +141,7 @@ end describe "#invalid_signup_notification sent to collection_email" do - subject(:email) { UserMailer.invalid_signup_notification(collection.id, [signup.id], collection.collection_email) } + subject(:email) { GiftExchangeMailer.invalid_signup_notification(collection.id, [signup.id], collection.collection_email) } let(:collection) { create(:collection) } let(:signup) { create(:challenge_signup) } @@ -215,7 +215,7 @@ end describe "#potential_match_generation_notification" do - subject(:email) { UserMailer.potential_match_generation_notification(collection.id, "test@example.com") } + subject(:email) { GiftExchangeMailer.potential_match_generation_notification(collection.id, "test@example.com") } let(:collection) { create(:collection) } @@ -248,7 +248,7 @@ end describe "#potential_match_generation_notification sent to collection_email" do - subject(:email) { UserMailer.potential_match_generation_notification(collection.id, collection.collection_email) } + subject(:email) { GiftExchangeMailer.potential_match_generation_notification(collection.id, collection.collection_email) } let(:collection) { create(:collection) } From 7ced1d5602e6c66bc76f627019d9562890ced88e Mon Sep 17 00:00:00 2001 From: Smuzzy-waiii Date: Sun, 10 May 2026 08:25:47 +0530 Subject: [PATCH 4/4] AO3-7406 Remove duplicate gift exchange notifs from UserMailer Remove duplicate gift exchange notifications from UserMailer (app/mailers/user_mailer.rb): - invalid_signup_notification - potential_match_generation_notification --- app/mailers/user_mailer.rb | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index 4adeadcdda9..30345d8a30d 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -157,27 +157,6 @@ def invite_request_declined(user_id, total, reason) ) end - def invalid_signup_notification(collection_id, invalid_signup_ids, email) - @collection = Collection.find(collection_id) - @invalid_signups = invalid_signup_ids - @is_collection_email = (email == @collection.collection_email) - mail( - to: email, - subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME, collection_title: @collection.title) - ) - end - - # This is sent at the end of matching, i.e., after assignments are generated. - # It is also sent when assignments are regenerated. - def potential_match_generation_notification(collection_id, email) - @collection = Collection.find(collection_id) - @is_collection_email = (email == @collection.collection_email) - mail( - to: email, - subject: default_i18n_subject(app_name: ArchiveConfig.APP_SHORT_NAME, collection_title: @collection.title) - ) - end - def challenge_assignment_notification(collection_id, assigned_user_id, assignment_id) @collection = Collection.find(collection_id) @assigned_user = User.find(assigned_user_id)