Skip to content

Commit 80d00a4

Browse files
committed
feat: update event invitation email to handle Action Text descriptions and ensure plain text formatting
1 parent 682166f commit 80d00a4

File tree

2 files changed

+135
-1
lines changed

2 files changed

+135
-1
lines changed

app/views/better_together/event_invitations_mailer/invite.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
<% if @event.description.present? %>
3232
<div style="margin: 12px 0;">
33-
<%= simple_format(@event.description) %>
33+
<%= simple_format(@event.description.to_plain_text) %>
3434
</div>
3535
<% end %>
3636
</div>
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# frozen_string_literal: true
2+
3+
require 'rails_helper'
4+
5+
module BetterTogether # rubocop:todo Metrics/ModuleLength
6+
RSpec.describe EventInvitationsMailer do
7+
let(:person) { create(:person) }
8+
let(:event) { create(:event, :upcoming, :with_simple_location) }
9+
let(:event_invitation) { create(:event_invitation, invitable: event, invitee: person) }
10+
11+
describe '#invite' do
12+
let(:mail) { described_class.with(invitation: event_invitation).invite }
13+
14+
context 'with valid invitation' do
15+
it 'renders the headers correctly' do
16+
expect(mail.to).to eq([event_invitation.invitee_email])
17+
expect(mail.subject).to be_present
18+
expect(mail.from).to eq(['[email protected]'])
19+
end
20+
21+
it 'renders the body with event details' do
22+
expect(mail.body.encoded).to include(event.name)
23+
# Check for invitation content without requiring specific language
24+
expect(mail.body.encoded).to match(/invit/i) # Should contain some form of "invited"
25+
end
26+
27+
it 'includes invitation URL' do
28+
expect(mail.body.encoded).to include(event_invitation.url_for_review)
29+
end
30+
31+
context 'when event has location' do
32+
it 'includes location information' do
33+
expect(mail.body.encoded).to include(event.location_display_name)
34+
end
35+
end
36+
37+
context 'when event has starts_at time' do
38+
it 'includes formatted start time' do
39+
# Check that some representation of the start time is present
40+
expect(mail.body.encoded).to include(event.starts_at.year.to_s)
41+
expect(mail.body.encoded).to include(event.starts_at.day.to_s)
42+
end
43+
end
44+
45+
context 'when invitation has inviter' do
46+
let(:inviter) { create(:person) }
47+
let(:event_invitation_with_inviter) do
48+
create(:event_invitation, invitable: event, invitee: person, inviter: inviter)
49+
end
50+
let(:mail) { described_class.with(invitation: event_invitation_with_inviter).invite }
51+
52+
it 'includes inviter information' do
53+
expect(mail.body.encoded).to include(inviter.name)
54+
# Check for inviter reference without requiring specific language
55+
expect(mail.body.encoded).to match(/invit.*#{Regexp.escape(inviter.name)}/i)
56+
end
57+
end
58+
59+
context 'when event has description with Action Text and Mobility translations' do
60+
let(:event_with_description) do
61+
create(:event, :upcoming, :with_simple_location).tap do |e|
62+
# Set description using Mobility's translation system
63+
I18n.with_locale(:en) do
64+
e.update!(description: 'This is a test event description with **bold** text.')
65+
end
66+
end
67+
end
68+
let(:event_invitation_with_description) do
69+
create(:event_invitation, invitable: event_with_description, invitee: person)
70+
end
71+
let(:mail) { described_class.with(invitation: event_invitation_with_description).invite }
72+
73+
it 'handles Action Text description correctly without errors' do
74+
expect { mail.body.encoded }.not_to raise_error
75+
end
76+
77+
it 'includes description content in plain text format' do
78+
body = mail.body.encoded
79+
expect(body).to include('This is a test event description')
80+
# Should include the text content but not the rich text HTML tags
81+
expect(body).to include('bold')
82+
end
83+
84+
it 'converts Action Text to plain text for email display' do
85+
# The fix ensures that simple_format receives plain text, not a Mobility translation object
86+
description_text = event_with_description.description.to_plain_text
87+
expect(mail.body.encoded).to include(description_text)
88+
end
89+
end
90+
91+
context 'when event has no description' do
92+
let(:event_without_description) { create(:event, :upcoming, :with_simple_location, description: nil) }
93+
let(:event_invitation_no_desc) do
94+
create(:event_invitation, invitable: event_without_description, invitee: person)
95+
end
96+
let(:mail) { described_class.with(invitation: event_invitation_no_desc).invite }
97+
98+
it 'does not include description section' do
99+
# Should not fail and should not have empty description blocks
100+
expect { mail.body.encoded }.not_to raise_error
101+
body = mail.body.encoded
102+
expect(body).not_to include('<strong>Description:</strong>')
103+
end
104+
end
105+
end
106+
107+
context 'with invalid invitation' do
108+
let(:event_invitation_no_email) do
109+
build(:event_invitation, invitable: event, invitee: person, invitee_email: '')
110+
end
111+
let(:mail) { described_class.with(invitation: event_invitation_no_email).invite }
112+
113+
it 'does not send email when invitee_email is blank' do
114+
expect(mail.to).to be_nil
115+
end
116+
end
117+
118+
context 'localization' do
119+
let(:french_invitation) do
120+
create(:event_invitation, invitable: event, invitee: person, locale: 'fr')
121+
end
122+
let(:mail) { described_class.with(invitation: french_invitation).invite }
123+
124+
it 'uses invitation locale for email content' do
125+
I18n.with_locale(:fr) do
126+
# This tests that the mailer respects the invitation's locale setting
127+
expect { mail.body.encoded }.not_to raise_error
128+
expect { mail.subject }.not_to raise_error
129+
end
130+
end
131+
end
132+
end
133+
end
134+
end

0 commit comments

Comments
 (0)