From 1a9d63c0f5b70394140fe82686fa2763d31ae81e Mon Sep 17 00:00:00 2001 From: Jerome Pratt Date: Tue, 10 Oct 2023 17:35:56 +0100 Subject: [PATCH] [RUBY-2658] Classes and specs for unlock_instructions and reset_password notify emails --- .../devise_notify_mailer.rb | 4 +- .../notify/devise_sender.rb | 27 ++++++++-- ...set_password_instructions_email_service.rb | 25 +++++++++ .../unlock_instructions_email_service.rb | 17 +++--- spec/dummy/config/application.rb | 2 +- .../notify/devise_sender_spec.rb | 43 +++++++++++++++ ...assword_instructions_email_service_spec.rb | 54 +++++++++++++++++++ .../unlock_instructions_email_service_spec.rb | 35 ++++++------ 8 files changed, 170 insertions(+), 37 deletions(-) create mode 100644 app/services/waste_carriers_engine/notify/reset_password_instructions_email_service.rb create mode 100644 spec/services/waste_carriers_engine/notify/devise_sender_spec.rb create mode 100644 spec/services/waste_carriers_engine/notify/reset_password_instructions_email_service_spec.rb diff --git a/app/mailers/waste_carriers_engine/devise_notify_mailer.rb b/app/mailers/waste_carriers_engine/devise_notify_mailer.rb index 25e5c196c..c183dee5a 100644 --- a/app/mailers/waste_carriers_engine/devise_notify_mailer.rb +++ b/app/mailers/waste_carriers_engine/devise_notify_mailer.rb @@ -1,8 +1,8 @@ class DeviseNotifyMailer < Devise::Mailer include Devise::Controllers::UrlHelpers - def password_change(record, opts = {}) - send_via_gov_notify(:password_change, record, opts) + def reset_password_instructions(record, token, opts = {}) + send_via_gov_notify(:reset_password_instructions, record, opts.merge(token: token)) end def unlock_instructions(record, token, opts = {}) diff --git a/app/services/waste_carriers_engine/notify/devise_sender.rb b/app/services/waste_carriers_engine/notify/devise_sender.rb index 0e7d90939..4fbe50995 100644 --- a/app/services/waste_carriers_engine/notify/devise_sender.rb +++ b/app/services/waste_carriers_engine/notify/devise_sender.rb @@ -5,14 +5,31 @@ class DeviseSender include ActionView::Helpers::NumberHelper def run(template:, record:, opts:) - return unless record&.email.present? + service_class = service_for_template(template) + service = service_class.new - @record = record - @token = opts[:token] + service.send_email(record, opts[:token]) + end + + def send_email(record, token) + client.send_email(notify_options(record, token)) + end - client = Notifications::Client.new(WasteCarriersEngine.configuration.notify_api_key) + private + + def service_for_template(template) + case template + when :reset_password_instructions + ResetPasswordInstructionsEmailService + when :unlock_instructions + UnlockInstructionsEmailService + else + raise ArgumentError, "Unknown email template: #{template}" + end + end - client.send_email(notify_options) + def client + @client ||= Notifications::Client.new(WasteCarriersEngine.configuration.notify_api_key) end end end diff --git a/app/services/waste_carriers_engine/notify/reset_password_instructions_email_service.rb b/app/services/waste_carriers_engine/notify/reset_password_instructions_email_service.rb new file mode 100644 index 000000000..9a13eb711 --- /dev/null +++ b/app/services/waste_carriers_engine/notify/reset_password_instructions_email_service.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module WasteCarriersEngine + module Notify + class ResetPasswordInstructionsEmailService < DeviseSender + private + def reset_url(token) + Rails.application.routes.url_helpers.edit_user_password_url( + host: Rails.configuration.wcrs_back_office_url, + reset_password_token: token + ) + end + + def notify_options(record, token) + { + email_address: record.email, + template_id: "bfe66f5e-29ed-4f78-82e1-8baf5548f97a", + personalisation: { + reset_password_link: reset_url(token) + } + } + end + end + end +end diff --git a/app/services/waste_carriers_engine/notify/unlock_instructions_email_service.rb b/app/services/waste_carriers_engine/notify/unlock_instructions_email_service.rb index 1c80a9951..4737a5c5a 100644 --- a/app/services/waste_carriers_engine/notify/unlock_instructions_email_service.rb +++ b/app/services/waste_carriers_engine/notify/unlock_instructions_email_service.rb @@ -2,22 +2,21 @@ module WasteCarriersEngine module Notify - class UnlockInstructionsEmailService < BaseSendEmailService + class UnlockInstructionsEmailService < DeviseSender private - def unlock_url - Rails.application.routes.url_helpers.unlock_url( - @record, - host: Rails.configuration.x.notify.host, - unlock_token: @token + def unlock_url(token) + Rails.application.routes.url_helpers.user_unlock_url( + host: Rails.configuration.wcrs_back_office_url, + unlock_token: token ) end - def notify_options + def notify_options(record, token) { - email_address: @record.email, + email_address: record.email, template_id: "a3295516-26a6-4c01-9e3a-d5000f1a86c6", personalisation: { - unlock_link: unlock_url + unlock_link: unlock_url(token) } } end diff --git a/spec/dummy/config/application.rb b/spec/dummy/config/application.rb index 5316c0fad..6a984c952 100644 --- a/spec/dummy/config/application.rb +++ b/spec/dummy/config/application.rb @@ -59,7 +59,7 @@ class Application < Rails::Application # Paths # This is the domain to use on URLs for FO services such as renewal and deregistration config.wcrs_fo_link_domain = ENV["WCRS_RENEWALS_DOMAIN"] || "http://localhost:3002" - + config.wcrs_back_office_url = ENV["WCRS_BACK_OFFICE_DOMAIN"] || "http://localhost:8001" config.wcrs_frontend_url = ENV["WCRS_FRONTEND_DOMAIN"] || "http://localhost:3000" config.wcrs_services_url = ENV["WCRS_SERVICES_DOMAIN"] || "http://localhost:8003" config.os_places_service_url = ENV["WCRS_OS_PLACES_DOMAIN"] || "http://localhost:8005" diff --git a/spec/services/waste_carriers_engine/notify/devise_sender_spec.rb b/spec/services/waste_carriers_engine/notify/devise_sender_spec.rb new file mode 100644 index 000000000..f02e3b987 --- /dev/null +++ b/spec/services/waste_carriers_engine/notify/devise_sender_spec.rb @@ -0,0 +1,43 @@ +require "rails_helper" + +module WasteCarriersEngine + module Notify + RSpec.describe DeviseSender do + let(:user_with_email) { create(:user, email: "test@example.com") } + let(:user_without_email) { create(:user, email: nil) } + let(:token) { "example_token" } + + let(:notifications_client) { instance_double(Notifications::Client) } + + before do + allow(Notifications::Client).to receive(:new).and_return(notifications_client) + allow(notifications_client).to receive(:send_email) + end + + describe "#run" do + context "with :reset_password_instructions template" do + it "uses ResetPasswordInstructionsEmailService" do + expect(ResetPasswordInstructionsEmailService).to receive(:new).and_call_original + described_class.new.run(template: :reset_password_instructions, record: user_with_email, opts: { token: token }) + end + end + + context "with :unlock_instructions template" do + it "uses UnlockInstructionsEmailService" do + expect(UnlockInstructionsEmailService).to receive(:new).and_call_original + described_class.new.run(template: :unlock_instructions, record: user_with_email, opts: { token: token }) + end + end + + context "with unknown template" do + it "raises an error" do + expect { + described_class.new.run(template: :unknown_template, record: user_with_email, opts: { token: token }) + }.to raise_error(ArgumentError, "Unknown email template: unknown_template") + end + end + end + end + end +end + diff --git a/spec/services/waste_carriers_engine/notify/reset_password_instructions_email_service_spec.rb b/spec/services/waste_carriers_engine/notify/reset_password_instructions_email_service_spec.rb new file mode 100644 index 000000000..cb3062965 --- /dev/null +++ b/spec/services/waste_carriers_engine/notify/reset_password_instructions_email_service_spec.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +require "rails_helper" + +module WasteCarriersEngine + module Notify + RSpec.describe ResetPasswordInstructionsEmailService do + describe ".send_email" do + let(:template_id) { "bfe66f5e-29ed-4f78-82e1-8baf5548f97a" } + let(:user) { create(:user, email: "test@example.com") } + let(:token) { "example_token" } + + let(:expected_notify_options) do + { + email_address: user.email, + template_id: template_id, + personalisation: { + reset_password_link: Rails.application.routes.url_helpers.edit_user_password_url( + host: Rails.configuration.wcrs_back_office_url, + reset_password_token: token + ) + } + } + end + + let(:notifications_client) { instance_double(Notifications::Client) } + + before do + allow(Notifications::Client).to receive(:new).and_return(notifications_client) + allow(notifications_client).to receive(:send_email) + + described_class.new.send_email(user, token) + end + + context "with an email" do + + it "sends an email" do + expect(notifications_client).to have_received(:send_email).with(expected_notify_options) + end + end + + context "with no email" do + before { user.email = nil } + + it "sends an email" do + expect(notifications_client).not_to have_received(:send_email).with(expected_notify_options) + end + end + end + end + end +end + + diff --git a/spec/services/waste_carriers_engine/notify/unlock_instructions_email_service_spec.rb b/spec/services/waste_carriers_engine/notify/unlock_instructions_email_service_spec.rb index daa86de89..ee3e15b4a 100644 --- a/spec/services/waste_carriers_engine/notify/unlock_instructions_email_service_spec.rb +++ b/spec/services/waste_carriers_engine/notify/unlock_instructions_email_service_spec.rb @@ -5,9 +5,9 @@ module WasteCarriersEngine module Notify RSpec.describe UnlockInstructionsEmailService do - describe ".run" do + describe ".send_email" do let(:template_id) { "a3295516-26a6-4c01-9e3a-d5000f1a86c6" } - let(:user) { create(:user, email: "test@example.com") } # Assuming you have a factory for User + let(:user) { create(:user, email: "test@example.com") } let(:token) { "example_token" } let(:expected_notify_options) do @@ -15,8 +15,7 @@ module Notify email_address: user.email, template_id: template_id, personalisation: { - unlock_link: Rails.application.routes.url_helpers.unlock_url( - user, + unlock_link: Rails.application.routes.url_helpers.user_unlock_url( host: Rails.configuration.wcrs_back_office_url, unlock_token: token ) @@ -24,31 +23,27 @@ module Notify } end - context "with an email" do - before do - allow_any_instance_of(Notifications::Client) - .to receive(:send_email) - .with(expected_notify_options) - .and_call_original - end + let(:notifications_client) { instance_double(Notifications::Client) } - subject(:run_service) do - described_class.new.run(template: template_id, record: user, opts: { token: token }) - end + before do + allow(Notifications::Client).to receive(:new).and_return(notifications_client) + allow(notifications_client).to receive(:send_email) + + described_class.new.send_email(user, token) + end + + context "with an email" do it "sends an email" do - expect(run_service).to be_a(Notifications::Client::ResponseNotification) - expect(run_service.template["id"]).to eq(template_id) + expect(notifications_client).to have_received(:send_email).with(expected_notify_options) end end context "with no email" do before { user.email = nil } - it "does not attempt to send an email" do - expect_any_instance_of(Notifications::Client).not_to receive(:send_email) - - described_class.new.run(template: template_id, record: user, opts: { token: token }) + it "sends an email" do + expect(notifications_client).not_to have_received(:send_email).with(expected_notify_options) end end end