|
1 | 1 | require 'rails_helper' |
2 | 2 |
|
3 | 3 | RSpec.describe Outgoing::RecipientResolver do |
4 | | - let(:list) { create(:mailing_list, post_address: "real@list.example") } |
5 | | - let(:topic) { create(:topic, mailing_lists: [ list ]) } |
| 4 | + let(:list) { create(:mailing_list, post_address: "real@list.example") } |
| 5 | + let(:topic) { create(:topic, mailing_lists: [ list ]) } |
| 6 | + let(:author) { create(:alias, name: "Bob", email: "bob@x") } |
| 7 | + let(:parent) { create(:message, topic: topic, sender: author) } |
| 8 | + let(:sender) { create(:alias, name: "Alice", email: "alice@x") } |
| 9 | + let(:draft) { |
| 10 | + create(:outgoing_draft, topic: topic, reply_to_message: parent, sender_alias: sender) |
| 11 | + } |
| 12 | + |
| 13 | + def mention(email, name = "Noname") |
| 14 | + create(:mention, message: parent, alias: create(:alias, email: email, name: name)) |
| 15 | + end |
6 | 16 |
|
7 | 17 | context 'in production' do |
8 | 18 | before { allow(Rails.env).to receive(:production?).and_return(true) } |
9 | 19 |
|
10 | | - it 'returns the post_address' do |
11 | | - expect(described_class.for(topic)).to eq("real@list.example") |
| 20 | + it 'puts the parent author in To and the list in Cc' do |
| 21 | + result = described_class.for(draft) |
| 22 | + expect(result.to).to eq([ 'Bob <bob@x>' ]) |
| 23 | + expect(result.cc).to eq([ 'real@list.example' ]) |
| 24 | + end |
| 25 | + |
| 26 | + it 'adds parent participants to Cc after the list' do |
| 27 | + mention('carol@x', 'Carol') |
| 28 | + result = described_class.for(draft) |
| 29 | + expect(result.cc).to eq([ 'real@list.example', 'Carol <carol@x>' ]) |
| 30 | + end |
| 31 | + |
| 32 | + it 'uses the plain email when the participant name is Noname' do |
| 33 | + mention('dave@x') |
| 34 | + expect(described_class.for(draft).cc).to include('dave@x') |
| 35 | + end |
| 36 | + |
| 37 | + it 'falls back to the raw email when the address does not parse with a display name' do |
| 38 | + mention('bob at example dot com', 'Weird') |
| 39 | + expect(described_class.for(draft).cc).to include('bob at example dot com') |
| 40 | + end |
| 41 | + |
| 42 | + it 'excludes the sending alias from recipients' do |
| 43 | + create(:mention, message: parent, alias: sender) |
| 44 | + result = described_class.for(draft) |
| 45 | + expect(result.all.join).not_to include('alice@x') |
| 46 | + end |
| 47 | + |
| 48 | + it 'dedups addresses case-insensitively' do |
| 49 | + mention('BOB@X', 'Bobby') |
| 50 | + mention('carol@x', 'Carol') |
| 51 | + mention('CAROL@x', 'Caroline') |
| 52 | + result = described_class.for(draft) |
| 53 | + expect(result.to).to eq([ 'Bob <bob@x>' ]) |
| 54 | + expect(result.cc).to eq([ 'real@list.example', 'Carol <carol@x>' ]) |
| 55 | + end |
| 56 | + |
| 57 | + it 'drops fabricated unknown.user addresses' do |
| 58 | + mention('ghost@unknown.user', 'Ghost') |
| 59 | + expect(described_class.for(draft).all.join).not_to include('unknown.user') |
12 | 60 | end |
13 | 61 |
|
14 | | - it 'raises MissingPostAddressError when blank' do |
| 62 | + it 'moves the list into To when replying to your own message' do |
| 63 | + parent.update!(sender: sender) |
| 64 | + mention('carol@x', 'Carol') |
| 65 | + result = described_class.for(draft) |
| 66 | + expect(result.to).to eq([ 'real@list.example' ]) |
| 67 | + expect(result.cc).to eq([ 'Carol <carol@x>' ]) |
| 68 | + end |
| 69 | + |
| 70 | + it 'moves the list into To when the parent sender address is fabricated' do |
| 71 | + parent.update!(sender: create(:alias, name: 'Ghost', email: 'ghost@unknown.user')) |
| 72 | + result = described_class.for(draft) |
| 73 | + expect(result.to).to eq([ 'real@list.example' ]) |
| 74 | + end |
| 75 | + |
| 76 | + it 'raises MissingPostAddressError when post_address is blank' do |
15 | 77 | list.update!(post_address: nil) |
16 | | - expect { described_class.for(topic) } |
| 78 | + expect { described_class.for(draft) } |
17 | 79 | .to raise_error(Outgoing::RecipientResolver::MissingPostAddressError) |
18 | 80 | end |
19 | 81 |
|
20 | 82 | it 'raises MissingPostAddressError when topic has no mailing list' do |
21 | 83 | topic.mailing_lists.clear |
22 | | - expect { described_class.for(topic) } |
| 84 | + expect { described_class.for(draft) } |
23 | 85 | .to raise_error(Outgoing::RecipientResolver::MissingPostAddressError) |
24 | 86 | end |
25 | 87 | end |
26 | 88 |
|
27 | 89 | context 'in development' do |
28 | | - it 'returns the override' do |
| 90 | + it 'returns only the override in To with empty Cc' do |
29 | 91 | with_env('HACKORUM_DEV_REPLY_TO' => 'test@example.com') do |
30 | | - expect(described_class.for(topic)).to eq('test@example.com') |
| 92 | + result = described_class.for(draft) |
| 93 | + expect(result.to).to eq([ 'test@example.com' ]) |
| 94 | + expect(result.cc).to eq([]) |
31 | 95 | end |
32 | 96 | end |
33 | 97 |
|
34 | 98 | it 'raises MissingDevOverrideError when override blank' do |
35 | 99 | with_env('HACKORUM_DEV_REPLY_TO' => nil) do |
36 | | - expect { described_class.for(topic) } |
| 100 | + expect { described_class.for(draft) } |
37 | 101 | .to raise_error(Outgoing::RecipientResolver::MissingDevOverrideError) |
38 | 102 | end |
39 | 103 | end |
40 | 104 |
|
41 | 105 | it 'raises MissingDevOverrideError when override is empty string' do |
42 | 106 | with_env('HACKORUM_DEV_REPLY_TO' => '') do |
43 | | - expect { described_class.for(topic) } |
| 107 | + expect { described_class.for(draft) } |
44 | 108 | .to raise_error(Outgoing::RecipientResolver::MissingDevOverrideError) |
45 | 109 | end |
46 | 110 | end |
47 | 111 |
|
48 | 112 | it 'raises RealListAddressInDevError when override matches a real list (case-insensitive)' do |
49 | 113 | with_env('HACKORUM_DEV_REPLY_TO' => 'REAL@list.example') do |
50 | | - expect { described_class.for(topic) } |
| 114 | + expect { described_class.for(draft) } |
51 | 115 | .to raise_error(Outgoing::RecipientResolver::RealListAddressInDevError) |
52 | 116 | end |
53 | 117 | end |
54 | 118 |
|
55 | | - it 'returns the override even when the topic has no mailing list with post_address' do |
| 119 | + it 'returns the override even when the list has no post_address' do |
56 | 120 | list.update!(post_address: nil) |
57 | 121 | with_env('HACKORUM_DEV_REPLY_TO' => 'test@example.com') do |
58 | | - expect(described_class.for(topic)).to eq('test@example.com') |
59 | | - end |
60 | | - end |
61 | | - |
62 | | - it 'returns the override for topics with no mailing list at all' do |
63 | | - orphan_topic = create(:topic) |
64 | | - with_env('HACKORUM_DEV_REPLY_TO' => 'test@example.com') do |
65 | | - expect(described_class.for(orphan_topic)).to eq('test@example.com') |
| 122 | + expect(described_class.for(draft).to).to eq([ 'test@example.com' ]) |
66 | 123 | end |
67 | 124 | end |
68 | 125 | end |
|
0 commit comments