# frozen_string_literal: true require "rails_helper" module DefraRubyEmail RSpec.describe LastEmailCache do subject(:instance) { described_class.instance } before(:each) { instance.reset } let(:recipient) { "test@example.com" } let(:add_attachment) { false } let(:expected_keys) { %w[date from to bcc cc reply_to subject body attachments] } describe "#last_email_json" do context "when the no emails have been sent" do let(:expected_keys) { %w[error] } it "returns a JSON string" do result = instance.last_email_json expect(result).to be_a(String) expect { JSON.parse(result) }.to_not raise_error end it "responds with an error message" do result = JSON.parse(instance.last_email_json) expect(result.keys).to match_array(expected_keys) end end context "when a basic email is sent" do context "and it is formatted as plain text" do before(:each) { TestMailer.text_email(recipient, add_attachment).deliver_now } it "returns a JSON string" do result = instance.last_email_json expect(result).to be_a(String) expect { JSON.parse(result) }.to_not raise_error end it "contains the attributes of the email" do result = JSON.parse(instance.last_email_json) expect(result["last_email"].keys).to match_array(expected_keys) end it "extracts the plain text body content" do result = JSON.parse(instance.last_email_json) expect(result["last_email"]["body"]).to start_with("This is the text version of an email") end end context "and it is formatted as html" do before(:each) { TestMailer.html_email(recipient, add_attachment).deliver_now } it "returns a JSON string" do result = instance.last_email_json expect(result).to be_a(String) expect { JSON.parse(result) }.to_not raise_error end it "contains the attributes of the email" do result = JSON.parse(instance.last_email_json) expect(result["last_email"].keys).to match_array(expected_keys) end it "extracts the html body content" do result = JSON.parse(instance.last_email_json) expect(result["last_email"]["body"]).to start_with("

This is the html version of an email

") end end end # Multi-part essentially means the email contains more than 2 elements. An # element can be a HTML version, and plain text version, and an # attachment. If it contains at least 2 of these it will be sent as a # multipart email context "when a multi-part email is sent" do context "and it contains both a html and text version" do before(:each) { TestMailer.multipart_email(recipient, add_attachment).deliver_now } it "returns a JSON string" do result = instance.last_email_json expect(result).to be_a(String) expect { JSON.parse(result) }.to_not raise_error end it "contains the attributes of the email" do result = JSON.parse(instance.last_email_json) expect(result["last_email"].keys).to match_array(expected_keys) end it "extracts the plain text body content" do result = JSON.parse(instance.last_email_json) expect(result["last_email"]["body"]).to start_with("This is the text version of an email") end end context "and contains both a html and text version plus an attachment" do before(:each) { TestMailer.multipart_email(recipient, add_attachment).deliver_now } let(:add_attachment) { true } it "returns a JSON string" do result = instance.last_email_json expect(result).to be_a(String) expect { JSON.parse(result) }.to_not raise_error end it "contains the attributes of the email" do result = JSON.parse(instance.last_email_json) expect(result["last_email"].keys).to match_array(expected_keys) end it "extracts the plain text body content" do result = JSON.parse(instance.last_email_json) expect(result["last_email"]["body"]).to start_with("This is the text version of an email") end end context "but it just contains a plain text part and an attachment" do before(:each) { TestMailer.text_email(recipient, add_attachment).deliver_now } let(:add_attachment) { true } it "returns a JSON string" do result = instance.last_email_json expect(result).to be_a(String) expect { JSON.parse(result) }.to_not raise_error end it "contains the attributes of the email" do result = JSON.parse(instance.last_email_json) expect(result["last_email"].keys).to match_array(expected_keys) end it "extracts the plain text body content" do result = JSON.parse(instance.last_email_json) expect(result["last_email"]["body"]).to start_with("This is the text version of an email") end end context "but it just contains a html part and an attachment" do before(:each) { TestMailer.html_email(recipient, add_attachment).deliver_now } let(:add_attachment) { true } it "returns a JSON string" do result = instance.last_email_json expect(result).to be_a(String) expect { JSON.parse(result) }.to_not raise_error end it "contains the attributes of the email" do result = JSON.parse(instance.last_email_json) expect(result["last_email"].keys).to match_array(expected_keys) end it "extracts the html body content" do result = JSON.parse(instance.last_email_json) expect(result["last_email"]["body"]).to start_with("

This is the html version of an email

") end end end context "when multiple emails have been sent" do before(:each) do TestMailer.text_email(recipient, add_attachment).deliver_now TestMailer.text_email(last_recipient, add_attachment).deliver_now end let(:last_recipient) { "joe.bloggs@example.com" } it "returns a JSON string" do result = instance.last_email_json expect(result).to be_a(String) expect { JSON.parse(result) }.to_not raise_error end it "contains the attributes of the email" do result = JSON.parse(instance.last_email_json) expect(result["last_email"].keys).to match_array(expected_keys) end it "extracts the plain text body content" do result = JSON.parse(instance.last_email_json) expect(result["last_email"]["body"]).to start_with("This is the text version of an email") end it "contains the details of the last email sent" do result = JSON.parse(instance.last_email_json) expect(result["last_email"]["to"]).to eq([last_recipient]) end end end end end