From c95c598f82dc51c7e6b8a2bdd3cde5c11bbf97cf Mon Sep 17 00:00:00 2001 From: filipefurtad0 Date: Wed, 26 Mar 2025 08:03:36 +0000 Subject: [PATCH 01/12] Asserts that the enterprise welcome email has no reply to address Asserts that manager invitation email has the inviting enterprise as reply to address --- spec/mailers/enterprise_mailer_spec.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/spec/mailers/enterprise_mailer_spec.rb b/spec/mailers/enterprise_mailer_spec.rb index e7de3e3a89..51bde20f73 100644 --- a/spec/mailers/enterprise_mailer_spec.rb +++ b/spec/mailers/enterprise_mailer_spec.rb @@ -14,6 +14,11 @@ RSpec.describe EnterpriseMailer do expect(mail.subject) .to eq "#{enterprise.name} is now on #{Spree::Config[:site_name]}" end + + it "does not set a reply-to email" do + EnterpriseMailer.welcome(enterprise).deliver_now + expect(ActionMailer::Base.deliveries.first.reply_to).to be nil + end end describe "#manager_invitation" do @@ -23,5 +28,10 @@ RSpec.describe EnterpriseMailer do mail = ActionMailer::Base.deliveries.first expect(mail.subject).to eq "#{enterprise.name} has invited you to be a manager" end + + it "sets a reply-to of the enterprise email" do + EnterpriseMailer.manager_invitation(enterprise, user).deliver_now + expect(ActionMailer::Base.deliveries.first.reply_to).to eq([enterprise.contact.email]) + end end end From 6ee1c8ca29f9b9d34b85d6912bd84abd8dec5ce7 Mon Sep 17 00:00:00 2001 From: filipefurtad0 Date: Wed, 26 Mar 2025 08:59:35 +0000 Subject: [PATCH 02/12] Asserts that the order cancellation email for shops has the customer's email as reply to address --- spec/mailers/order_mailer_spec.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/mailers/order_mailer_spec.rb b/spec/mailers/order_mailer_spec.rb index a991f8659d..966190d320 100644 --- a/spec/mailers/order_mailer_spec.rb +++ b/spec/mailers/order_mailer_spec.rb @@ -150,6 +150,10 @@ RSpec.describe Spree::OrderMailer do it "includes a link to the cancelled order in admin" do expect(mail.body).to match /#{admin_order_link_href}/ end + + it "sets a reply-to of the customer email" do + expect(mail.reply_to).to eq([order.email]) + end end describe "order confimation" do From 9a161cae5b3540a1e9698c5686f286bf95338c06 Mon Sep 17 00:00:00 2001 From: filipefurtad0 Date: Wed, 26 Mar 2025 09:07:34 +0000 Subject: [PATCH 03/12] Asserts that the order confirmation email for shops has the customer's email as reply to address --- spec/mailers/order_mailer_spec.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/mailers/order_mailer_spec.rb b/spec/mailers/order_mailer_spec.rb index 966190d320..ec33c45fdc 100644 --- a/spec/mailers/order_mailer_spec.rb +++ b/spec/mailers/order_mailer_spec.rb @@ -69,6 +69,10 @@ RSpec.describe Spree::OrderMailer do expect(email.body).to include('Payment summary') end + it "sets a reply-to of the customer email" do + expect(email.reply_to).to eq([order.email]) + end + context 'when the order has outstanding balance' do before { allow(order).to receive(:new_outstanding_balance) { 123 } } From ea82b162acf58a689470da7aea132a6068d940b6 Mon Sep 17 00:00:00 2001 From: filipefurtad0 Date: Wed, 26 Mar 2025 09:32:28 +0000 Subject: [PATCH 04/12] Asserts that the order cancellation email for customer has the distributors email as reply to address --- spec/mailers/order_mailer_spec.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/spec/mailers/order_mailer_spec.rb b/spec/mailers/order_mailer_spec.rb index ec33c45fdc..3214c808ee 100644 --- a/spec/mailers/order_mailer_spec.rb +++ b/spec/mailers/order_mailer_spec.rb @@ -160,6 +160,24 @@ RSpec.describe Spree::OrderMailer do end end + describe "#cancel_email (for_customer)" do + let(:distributor) { create(:distributor_enterprise) } + let(:order) { create(:order, distributor:, state: "canceled") } + let(:mail) { Spree::OrderMailer.cancel_email(order) } + + it "sends an email to the customer" do + expect(mail.to).to eq([order.email]) + end + + it "displays the order number" do + expect(mail.body).to include(order.number.to_s) + end + + it "sets a reply-to of the customer email" do + expect(mail.reply_to).to eq([order.distributor.contact.email]) + end + end + describe "order confimation" do let(:bill_address) { create(:address) } let(:distributor_address) { From 98cba128e081da4785f81bf8171a94222470cb0d Mon Sep 17 00:00:00 2001 From: filipefurtad0 Date: Wed, 26 Mar 2025 09:41:16 +0000 Subject: [PATCH 05/12] Asserts that the invoice email has the distributors email as reply to address --- spec/mailers/order_mailer_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/mailers/order_mailer_spec.rb b/spec/mailers/order_mailer_spec.rb index 3214c808ee..345ad9247a 100644 --- a/spec/mailers/order_mailer_spec.rb +++ b/spec/mailers/order_mailer_spec.rb @@ -271,6 +271,7 @@ RSpec.describe Spree::OrderMailer do expect(deliveries.count).to eq(1) expect(deliveries.first.attachments.count).to eq(1) expect(deliveries.first.attachments.first.filename).to eq(attachment_filename) + expect(email.reply_to).to eq([order.distributor.contact.email]) end end From df3cbe84b6aa25bcdd0acdaf34c521dfae3e7202 Mon Sep 17 00:00:00 2001 From: filipefurtad0 Date: Wed, 26 Mar 2025 09:54:04 +0000 Subject: [PATCH 06/12] Asserts that the order shipment and pick up emails have the distributors email as reply to address --- spec/mailers/shipment_mailer_spec.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/spec/mailers/shipment_mailer_spec.rb b/spec/mailers/shipment_mailer_spec.rb index e81ea4d0cb..bf234ce496 100644 --- a/spec/mailers/shipment_mailer_spec.rb +++ b/spec/mailers/shipment_mailer_spec.rb @@ -55,4 +55,14 @@ RSpec.describe Spree::ShipmentMailer do shipment_email = Spree::ShipmentMailer.shipped_email(shipment, delivery: false) expect(shipment_email.subject).to include("#{distributor.name} Pick up Notification") end + + it "picked_up email has as the reply to email as the distributor" do + shipment_email = Spree::ShipmentMailer.shipped_email(shipment, delivery: false) + expect(shipment_email.reply_to).to eq([distributor.contact.email]) + end + + it "shipment_email email has as the reply to email as the distributor" do + shipment_email = Spree::ShipmentMailer.shipped_email(shipment, delivery: true) + expect(shipment_email.reply_to).to eq([distributor.contact.email]) + end end From e017b14f31a6f18a59072652172c74a57e24da40 Mon Sep 17 00:00:00 2001 From: filipefurtad0 Date: Wed, 26 Mar 2025 11:56:39 +0000 Subject: [PATCH 07/12] Adds spec for payment authorization emails --- spec/mailers/payment_mailer_spec.rb | 40 +++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 spec/mailers/payment_mailer_spec.rb diff --git a/spec/mailers/payment_mailer_spec.rb b/spec/mailers/payment_mailer_spec.rb new file mode 100644 index 0000000000..7f30bc8c7f --- /dev/null +++ b/spec/mailers/payment_mailer_spec.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe PaymentMailer do + describe '#payment_mailer' do + let(:enterprise) { create(:enterprise) } + let(:payment_method) { + create(:payment_method, distributors: [order.distributor]) + } + let(:payment) { + create(:payment, order:, payment_method:) + } + let(:order) { create(:completed_order_with_totals) } + + context "authorize payment email" do + subject(:email) { described_class.authorize_payment(payment) } + + it "includes the distributor's name in the subject" do + expect(email.subject).to include("authorize your payment to #{order.distributor.name}") + end + + it "sets a reply-to of the customer email" do + expect(email.reply_to).to eq([order.distributor.contact.email]) + end + end + + context "authorization required email" do + subject(:email) { described_class.authorization_required(payment) } + + it "includes the distributor's name in the subject" do + expect(email.subject).to include("A payment requires authorization from the customer") + end + + it "sets a reply-to of the customer email" do + expect(email.reply_to).to eq([order.email]) + end + end + end +end From e12c51edd1085a0908c80a5a7643547ac3596a9e Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Thu, 27 Mar 2025 11:29:15 +1100 Subject: [PATCH 08/12] Use RSpec matchers for emails --- spec/mailers/enterprise_mailer_spec.rb | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/spec/mailers/enterprise_mailer_spec.rb b/spec/mailers/enterprise_mailer_spec.rb index 51bde20f73..e68168d8d1 100644 --- a/spec/mailers/enterprise_mailer_spec.rb +++ b/spec/mailers/enterprise_mailer_spec.rb @@ -7,31 +7,27 @@ RSpec.describe EnterpriseMailer do let!(:user) { create(:user) } describe "#welcome" do - it "sends a welcome email when given an enterprise" do - EnterpriseMailer.welcome(enterprise).deliver_now + subject(:mail) { EnterpriseMailer.welcome(enterprise) } - mail = ActionMailer::Base.deliveries.first + it "sends a welcome email when given an enterprise" do expect(mail.subject) .to eq "#{enterprise.name} is now on #{Spree::Config[:site_name]}" end it "does not set a reply-to email" do - EnterpriseMailer.welcome(enterprise).deliver_now - expect(ActionMailer::Base.deliveries.first.reply_to).to be nil + expect(mail.reply_to).to eq nil end end describe "#manager_invitation" do + subject(:mail) { EnterpriseMailer.manager_invitation(enterprise, user) } + it "should send a manager invitation email when given an enterprise and user" do - EnterpriseMailer.manager_invitation(enterprise, user).deliver_now - expect(ActionMailer::Base.deliveries.count).to eq 1 - mail = ActionMailer::Base.deliveries.first expect(mail.subject).to eq "#{enterprise.name} has invited you to be a manager" end it "sets a reply-to of the enterprise email" do - EnterpriseMailer.manager_invitation(enterprise, user).deliver_now - expect(ActionMailer::Base.deliveries.first.reply_to).to eq([enterprise.contact.email]) + expect(mail.reply_to).to eq([enterprise.contact.email]) end end end From edcb04ed5036d7570ae458bcdaf823f6ecfb6795 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Thu, 27 Mar 2025 11:31:16 +1100 Subject: [PATCH 09/12] Save time by not storing test data in DB --- spec/mailers/enterprise_mailer_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/mailers/enterprise_mailer_spec.rb b/spec/mailers/enterprise_mailer_spec.rb index e68168d8d1..95fb5ef445 100644 --- a/spec/mailers/enterprise_mailer_spec.rb +++ b/spec/mailers/enterprise_mailer_spec.rb @@ -3,8 +3,7 @@ require 'spec_helper' RSpec.describe EnterpriseMailer do - let!(:enterprise) { create(:enterprise) } - let!(:user) { create(:user) } + let(:enterprise) { build(:enterprise) } describe "#welcome" do subject(:mail) { EnterpriseMailer.welcome(enterprise) } @@ -21,6 +20,7 @@ RSpec.describe EnterpriseMailer do describe "#manager_invitation" do subject(:mail) { EnterpriseMailer.manager_invitation(enterprise, user) } + let(:user) { build(:user) } it "should send a manager invitation email when given an enterprise and user" do expect(mail.subject).to eq "#{enterprise.name} has invited you to be a manager" From 1b8ebc3105194e3caff39d0fceaf7a0ac4e17343 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Thu, 27 Mar 2025 11:38:35 +1100 Subject: [PATCH 10/12] Test with known text --- spec/mailers/enterprise_mailer_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/mailers/enterprise_mailer_spec.rb b/spec/mailers/enterprise_mailer_spec.rb index 95fb5ef445..797dd78ddc 100644 --- a/spec/mailers/enterprise_mailer_spec.rb +++ b/spec/mailers/enterprise_mailer_spec.rb @@ -3,14 +3,14 @@ require 'spec_helper' RSpec.describe EnterpriseMailer do - let(:enterprise) { build(:enterprise) } + let(:enterprise) { build(:enterprise, name: "Fred's Farm") } describe "#welcome" do subject(:mail) { EnterpriseMailer.welcome(enterprise) } it "sends a welcome email when given an enterprise" do expect(mail.subject) - .to eq "#{enterprise.name} is now on #{Spree::Config[:site_name]}" + .to eq "Fred's Farm is now on OFN Demo Site" end it "does not set a reply-to email" do @@ -23,7 +23,7 @@ RSpec.describe EnterpriseMailer do let(:user) { build(:user) } it "should send a manager invitation email when given an enterprise and user" do - expect(mail.subject).to eq "#{enterprise.name} has invited you to be a manager" + expect(mail.subject).to eq "Fred's Farm has invited you to be a manager" end it "sets a reply-to of the enterprise email" do From b554248cfe2a991b746e140d78f82810abca4808 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Thu, 27 Mar 2025 11:48:41 +1100 Subject: [PATCH 11/12] Test for email content --- spec/mailers/payment_mailer_spec.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spec/mailers/payment_mailer_spec.rb b/spec/mailers/payment_mailer_spec.rb index 7f30bc8c7f..97d3ab8cdd 100644 --- a/spec/mailers/payment_mailer_spec.rb +++ b/spec/mailers/payment_mailer_spec.rb @@ -23,6 +23,11 @@ RSpec.describe PaymentMailer do it "sets a reply-to of the customer email" do expect(email.reply_to).to eq([order.distributor.contact.email]) end + + it "includes a link to authorize the payment" do + expect(email.text_part.body).to match "/payments/#{payment.id}/authorize" + expect(email.html_part.body).to match "/payments/#{payment.id}/authorize" + end end context "authorization required email" do From 8a8602158b325c0f8f45307e4a30e356a4880518 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Thu, 27 Mar 2025 12:06:05 +1100 Subject: [PATCH 12/12] Test link in HTML email with Capybara --- spec/base_spec_helper.rb | 1 + spec/mailers/payment_mailer_spec.rb | 5 ++-- spec/mailers/producer_mailer_spec.rb | 34 ++++++++++++---------------- spec/support/mailers_helper.rb | 7 ++++++ 4 files changed, 26 insertions(+), 21 deletions(-) create mode 100644 spec/support/mailers_helper.rb diff --git a/spec/base_spec_helper.rb b/spec/base_spec_helper.rb index 7f7ef01a12..b44827a64e 100644 --- a/spec/base_spec_helper.rb +++ b/spec/base_spec_helper.rb @@ -265,6 +265,7 @@ RSpec.configure do |config| config.include OpenFoodNetwork::PerformanceHelper config.include ActiveJob::TestHelper config.include ReportsHelper + config.include MailersHelper, type: :mailer config.include TomSelectHelper, type: :system config.include ViewComponent::TestHelpers, type: :component diff --git a/spec/mailers/payment_mailer_spec.rb b/spec/mailers/payment_mailer_spec.rb index 97d3ab8cdd..cee814ef16 100644 --- a/spec/mailers/payment_mailer_spec.rb +++ b/spec/mailers/payment_mailer_spec.rb @@ -25,8 +25,9 @@ RSpec.describe PaymentMailer do end it "includes a link to authorize the payment" do - expect(email.text_part.body).to match "/payments/#{payment.id}/authorize" - expect(email.html_part.body).to match "/payments/#{payment.id}/authorize" + link = "http://test.host/payments/#{payment.id}/authorize" + expect(email.text_part.body).to match link + expect(html_body(email)).to have_link link, href: link end end diff --git a/spec/mailers/producer_mailer_spec.rb b/spec/mailers/producer_mailer_spec.rb index 20702419e8..387c42eea0 100644 --- a/spec/mailers/producer_mailer_spec.rb +++ b/spec/mailers/producer_mailer_spec.rb @@ -83,13 +83,13 @@ RSpec.describe ProducerMailer, type: :mailer do expect(line).to include 'QTY: 3' expect(line).to include '@ $10.00 = $30.00' end - expect(body_as_html(mail).find("table.order-summary tr", text: p1.name)) + expect(html_body(mail).find("table.order-summary tr", text: p1.name)) .to have_selector("td", text: "$30.00") end it "displays tax totals for each product" do # Tax for p1 line items - expect(body_as_html(mail).find("table.order-summary tr", text: p1.name)) + expect(html_body(mail).find("table.order-summary tr", text: p1.name)) .to have_selector("td.tax", text: "$2.73") expect( product_line_from_order_summary_text(mail, p1.name) @@ -122,7 +122,7 @@ RSpec.describe ProducerMailer, type: :mailer do it "includes the total" do expect(mail.body.encoded).to include 'Total: $50.00' - expect(body_as_html(mail).find("tr.total-row")) + expect(html_body(mail).find("tr.total-row")) .to have_selector("td", text: "$50.00") end @@ -151,15 +151,15 @@ RSpec.describe ProducerMailer, type: :mailer do end it "adds customer names table" do - expect(body_as_html(mail).find(".order-summary.customer-order")).not_to be_nil + expect(html_body(mail).find(".order-summary.customer-order")).not_to be_nil expect(customer_details_summary_text(mail)).to be_present end it "displays last name for each order" do product_name = order.line_items.first.product.name last_name = order.billing_address.lastname - expect(body_as_html(mail).find("table.order-summary.customer-order tr", - text: product_name)).to have_selector("td", text: last_name) + expect(html_body(mail).find("table.order-summary.customer-order tr", + text: product_name)).to have_selector("td", text: last_name) expect( product_line_from_details_summary_text(mail, product_name) ).to include(last_name) @@ -168,8 +168,8 @@ RSpec.describe ProducerMailer, type: :mailer do it "displays first name for each order" do product_name = order.line_items.first.product.name first_name = order.billing_address.firstname - expect(body_as_html(mail).find("table.order-summary.customer-order tr", - text: product_name)).to have_selector("td", text: first_name) + expect(html_body(mail).find("table.order-summary.customer-order tr", + text: product_name)).to have_selector("td", text: first_name) expect( product_line_from_details_summary_text(mail, product_name) ).to include(first_name) @@ -186,7 +186,7 @@ RSpec.describe ProducerMailer, type: :mailer do context "validate business name" do let(:table_header) do - body_as_html(mail).find("table.order-summary.customer-order thead") + html_body(mail).find("table.order-summary.customer-order thead") end context "when no customer has customer code" do @@ -202,7 +202,7 @@ RSpec.describe ProducerMailer, type: :mailer do it 'displays business name for the customer' do expect(table_header).to have_selector("th", text: 'Business Name') expect( - body_as_html(mail).find("table.order-summary.customer-order tbody tr") + html_body(mail).find("table.order-summary.customer-order tbody tr") ).to have_selector("td", text: 'Test Business Name') expect(customer_details_summary_text(mail)).to include('Test Business Name') end @@ -217,7 +217,7 @@ RSpec.describe ProducerMailer, type: :mailer do it "does not add customer names table" do expect { - body_as_html(mail).find(".order-summary.customer-order") + html_body(mail).find(".order-summary.customer-order") }.to raise_error(Capybara::ElementNotFound) expect(customer_details_summary_text(mail)).to be_nil end @@ -236,7 +236,7 @@ RSpec.describe ProducerMailer, type: :mailer do end it "displays a supplier column" do - expect(body_as_html(mail).find(".order-summary")) + expect(html_body(mail).find(".order-summary")) .to have_selector("th", text: "Supplier") end @@ -244,7 +244,7 @@ RSpec.describe ProducerMailer, type: :mailer do before { order_cycle.coordinator.update!(show_customer_names_to_suppliers: true) } it "displays a supplier column in the summary of orders grouped by customer" do - expect(body_as_html(mail).find(".customer-order")) + expect(html_body(mail).find(".customer-order")) .to have_selector("th", text: "Supplier") end end @@ -252,7 +252,7 @@ RSpec.describe ProducerMailer, type: :mailer do context "products from only one supplier" do it "doesn't display a supplier column" do - expect(body_as_html(mail).find(".order-summary")) + expect(html_body(mail).find(".order-summary")) .not_to have_selector("th", text: "Supplier") end @@ -260,7 +260,7 @@ RSpec.describe ProducerMailer, type: :mailer do before { order_cycle.coordinator.update!(show_customer_names_to_suppliers: true) } it "doesn't display a supplier column in the summary of orders grouped by customer" do - expect(body_as_html(mail).find(".customer-order")) + expect(html_body(mail).find(".customer-order")) .not_to have_selector("th", text: "Supplier") end end @@ -272,10 +272,6 @@ RSpec.describe ProducerMailer, type: :mailer do mail.body.to_s.lines.select { |line| line.include? str } end - def body_as_html(mail) - Capybara.string(mail.html_part.body.encoded) - end - def body_as_text(mail) mail.text_part.body.decoded end diff --git a/spec/support/mailers_helper.rb b/spec/support/mailers_helper.rb new file mode 100644 index 0000000000..bc4688062e --- /dev/null +++ b/spec/support/mailers_helper.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module MailersHelper + def html_body(mail) + Capybara.string(mail.html_part.body.to_s) + end +end