|
5 | 5 | RSpec.describe Supermail::MailTo do |
6 | 6 | describe ".href" do |
7 | 7 | context "with minimal parameters" do |
8 | | - it "generates a simple mailto URL" do |
9 | | - result = described_class.href(to: "test@example.com") |
10 | | - expect(result).to eq("mailto:test@example.com") |
11 | | - end |
| 8 | + subject { described_class.href(to: "test@example.com") } |
| 9 | + |
| 10 | + it { is_expected.to eq("mailto:test@example.com") } |
12 | 11 | end |
13 | 12 |
|
14 | 13 | context "with all parameters" do |
15 | | - let(:params) do |
16 | | - { |
| 14 | + subject do |
| 15 | + described_class.href( |
17 | 16 | to: "recipient@example.com", |
18 | 17 | from: "sender@example.com", |
19 | 18 | cc: "cc@example.com", |
20 | 19 | bcc: "bcc@example.com", |
21 | 20 | subject: "Test Subject", |
22 | 21 | body: "Test body content" |
23 | | - } |
| 22 | + ) |
24 | 23 | end |
25 | 24 |
|
26 | | - it "generates a complete mailto URL with query parameters" do |
27 | | - result = described_class.href(**params) |
28 | | - expected_query = [ |
29 | | - "from=sender%40example.com", |
30 | | - "cc=cc%40example.com", |
31 | | - "bcc=bcc%40example.com", |
32 | | - "subject=Test%20Subject", |
33 | | - "body=Test%20body%20content" |
34 | | - ].join("&") |
35 | | - |
36 | | - expect(result).to eq("mailto:recipient@example.com?#{expected_query}") |
37 | | - end |
| 25 | + it { is_expected.to start_with("mailto:recipient@example.com?") } |
| 26 | + it { is_expected.to include("from=sender%40example.com") } |
| 27 | + it { is_expected.to include("cc=cc%40example.com") } |
| 28 | + it { is_expected.to include("bcc=bcc%40example.com") } |
| 29 | + it { is_expected.to include("subject=Test%20Subject") } |
| 30 | + it { is_expected.to include("body=Test%20body%20content") } |
38 | 31 | end |
39 | 32 |
|
40 | 33 | context "with nil parameters" do |
41 | | - it "excludes nil parameters from the query string" do |
42 | | - result = described_class.href( |
| 34 | + subject do |
| 35 | + described_class.href( |
43 | 36 | to: "test@example.com", |
44 | 37 | from: nil, |
45 | 38 | subject: "Hello", |
46 | 39 | cc: nil |
47 | 40 | ) |
48 | | - |
49 | | - expect(result).to eq("mailto:test@example.com?subject=Hello") |
50 | 41 | end |
| 42 | + |
| 43 | + it { is_expected.to eq("mailto:test@example.com?subject=Hello") } |
51 | 44 | end |
52 | 45 |
|
53 | 46 | context "with empty arrays" do |
54 | | - it "excludes empty arrays from the query string" do |
55 | | - result = described_class.href( |
56 | | - to: "test@example.com", |
57 | | - cc: [] |
58 | | - ) |
| 47 | + subject { described_class.href(to: "test@example.com", cc: []) } |
59 | 48 |
|
60 | | - expect(result).to eq("mailto:test@example.com") |
61 | | - end |
| 49 | + it { is_expected.to eq("mailto:test@example.com") } |
62 | 50 | end |
63 | 51 |
|
64 | 52 | context "with special characters" do |
65 | | - it "properly escapes email addresses and content" do |
66 | | - result = described_class.href( |
| 53 | + subject do |
| 54 | + described_class.href( |
67 | 55 | to: "test+tag@example.com", |
68 | 56 | subject: "Hello & Welcome!", |
69 | 57 | body: "Line 1\nLine 2" |
70 | 58 | ) |
71 | | - |
72 | | - expected_query = [ |
73 | | - "subject=Hello%20%26%20Welcome%21", |
74 | | - "body=Line%201%0ALine%202" |
75 | | - ].join("&") |
76 | | - |
77 | | - expect(result).to eq("mailto:test+tag@example.com?#{expected_query}") |
78 | 59 | end |
| 60 | + |
| 61 | + it { is_expected.to start_with("mailto:test+tag@example.com?") } |
| 62 | + it { is_expected.to include("subject=Hello%20%26%20Welcome%21") } |
| 63 | + it { is_expected.to include("body=Line%201%0ALine%202") } |
79 | 64 | end |
80 | 65 |
|
81 | 66 | context "with unicode characters" do |
82 | | - it "properly handles unicode content" do |
83 | | - result = described_class.href( |
84 | | - to: "test@example.com", |
85 | | - subject: "Héllo Wørld! 🎉" |
86 | | - ) |
| 67 | + subject { described_class.href(to: "test@example.com", subject: "Héllo Wørld! 🎉") } |
87 | 68 |
|
88 | | - expect(result).to include("mailto:test@example.com?subject=") |
89 | | - expect(result).to include("H%C3%A9llo") |
90 | | - expect(result).to include("W%C3%B8rld") |
91 | | - end |
| 69 | + it { is_expected.to start_with("mailto:test@example.com?subject=") } |
| 70 | + it { is_expected.to include("H%C3%A9llo") } |
| 71 | + it { is_expected.to include("W%C3%B8rld") } |
92 | 72 | end |
93 | 73 |
|
94 | 74 | context "with multiple CC recipients" do |
95 | | - it "handles array of CC recipients" do |
96 | | - result = described_class.href( |
97 | | - to: "test@example.com", |
98 | | - cc: ["cc1@example.com", "cc2@example.com"] |
99 | | - ) |
| 75 | + subject { described_class.href(to: "test@example.com", cc: ["cc1@example.com", "cc2@example.com"]) } |
100 | 76 |
|
101 | | - expect(result).to eq("mailto:test@example.com?cc=%5B%22cc1%40example.com%22%2C%20%22cc2%40example.com%22%5D") |
102 | | - end |
| 77 | + it { is_expected.to eq("mailto:test@example.com?cc=%5B%22cc1%40example.com%22%2C%20%22cc2%40example.com%22%5D") } |
103 | 78 | end |
104 | 79 |
|
105 | 80 | context "with multiple BCC recipients" do |
106 | | - it "handles array of BCC recipients" do |
107 | | - result = described_class.href( |
108 | | - to: "test@example.com", |
109 | | - bcc: ["bcc1@example.com", "bcc2@example.com"] |
110 | | - ) |
| 81 | + subject { described_class.href(to: "test@example.com", bcc: ["bcc1@example.com", "bcc2@example.com"]) } |
111 | 82 |
|
112 | | - expect(result).to eq("mailto:test@example.com?bcc=%5B%22bcc1%40example.com%22%2C%20%22bcc2%40example.com%22%5D") |
113 | | - end |
| 83 | + it { is_expected.to eq("mailto:test@example.com?bcc=%5B%22bcc1%40example.com%22%2C%20%22bcc2%40example.com%22%5D") } |
114 | 84 | end |
115 | 85 | end |
116 | 86 |
|
117 | 87 | describe ".query" do |
118 | 88 | context "with simple parameters" do |
119 | | - it "generates a proper query string" do |
120 | | - params = { subject: "Hello", body: "World" } |
121 | | - result = described_class.query(**params) |
| 89 | + subject { described_class.query(subject: "Hello", body: "World") } |
122 | 90 |
|
123 | | - expect(result).to eq("subject=Hello&body=World") |
124 | | - end |
| 91 | + it { is_expected.to eq("subject=Hello&body=World") } |
125 | 92 | end |
126 | 93 |
|
127 | 94 | context "with no parameters" do |
128 | | - it "returns an empty string" do |
129 | | - result = described_class.query |
130 | | - expect(result).to eq("") |
131 | | - end |
| 95 | + subject { described_class.query } |
| 96 | + |
| 97 | + it { is_expected.to eq("") } |
132 | 98 | end |
133 | 99 |
|
134 | 100 | context "with nil values" do |
135 | | - it "excludes nil values from the query string" do |
136 | | - params = { subject: "Hello", from: nil, body: "World" } |
137 | | - result = described_class.query(**params) |
| 101 | + subject { described_class.query(subject: "Hello", from: nil, body: "World") } |
138 | 102 |
|
139 | | - expect(result).to eq("subject=Hello&body=World") |
140 | | - end |
| 103 | + it { is_expected.to eq("subject=Hello&body=World") } |
141 | 104 | end |
142 | 105 |
|
143 | 106 | context "with special characters" do |
144 | | - it "properly escapes parameter values" do |
145 | | - params = { subject: "Hello & Goodbye", body: "Line 1\nLine 2" } |
146 | | - result = described_class.query(**params) |
| 107 | + subject { described_class.query(subject: "Hello & Goodbye", body: "Line 1\nLine 2") } |
147 | 108 |
|
148 | | - expect(result).to eq("subject=Hello%20%26%20Goodbye&body=Line%201%0ALine%202") |
149 | | - end |
| 109 | + it { is_expected.to eq("subject=Hello%20%26%20Goodbye&body=Line%201%0ALine%202") } |
150 | 110 | end |
151 | 111 |
|
152 | 112 | context "with mixed parameter types" do |
153 | | - it "handles strings, arrays, and nil values" do |
154 | | - params = { |
| 113 | + subject do |
| 114 | + described_class.query( |
155 | 115 | subject: "Test", |
156 | 116 | cc: ["test1@example.com", "test2@example.com"], |
157 | 117 | from: nil, |
158 | 118 | body: "" |
159 | | - } |
160 | | - result = described_class.query(**params) |
161 | | - |
162 | | - expect(result).to include("subject=Test") |
163 | | - expect(result).to include("cc=%5B%22test1%40example.com%22%2C%20%22test2%40example.com%22%5D") |
164 | | - expect(result).to include("body=") |
165 | | - expect(result).not_to include("from=") |
| 119 | + ) |
166 | 120 | end |
| 121 | + |
| 122 | + it { is_expected.to include("subject=Test") } |
| 123 | + it { is_expected.to include("cc=%5B%22test1%40example.com%22%2C%20%22test2%40example.com%22%5D") } |
| 124 | + it { is_expected.to include("body=") } |
| 125 | + it { is_expected.not_to include("from=") } |
167 | 126 | end |
168 | 127 |
|
169 | 128 | context "with empty arrays" do |
170 | | - it "excludes empty arrays from query string" do |
171 | | - params = { |
172 | | - subject: "Test", |
173 | | - cc: [], |
174 | | - bcc: [], |
175 | | - from: "test@example.com" |
176 | | - } |
177 | | - result = described_class.query(**params) |
178 | | - |
179 | | - expect(result).to eq("subject=Test&from=test%40example.com") |
180 | | - expect(result).not_to include("cc=") |
181 | | - expect(result).not_to include("bcc=") |
182 | | - end |
| 129 | + subject { described_class.query(subject: "Test", cc: [], bcc: [], from: "test@example.com") } |
| 130 | + |
| 131 | + it { is_expected.to eq("subject=Test&from=test%40example.com") } |
183 | 132 | end |
184 | 133 |
|
185 | 134 | context "with mixed empty arrays and nil values" do |
186 | | - it "excludes both empty arrays and nil values from query string" do |
187 | | - params = { |
188 | | - subject: "Test", |
189 | | - cc: [], |
190 | | - bcc: nil, |
191 | | - from: "test@example.com", |
192 | | - body: "" |
193 | | - } |
194 | | - result = described_class.query(**params) |
| 135 | + subject { described_class.query(subject: "Test", cc: [], bcc: nil, from: "test@example.com", body: "") } |
195 | 136 |
|
196 | | - expect(result).to eq("subject=Test&from=test%40example.com&body=") |
197 | | - expect(result).not_to include("cc=") |
198 | | - expect(result).not_to include("bcc=") |
199 | | - end |
| 137 | + it { is_expected.to eq("subject=Test&from=test%40example.com&body=") } |
200 | 138 | end |
201 | 139 | end |
202 | 140 |
|
|
205 | 143 | expect(described_class.private_methods).to include(:mailto_escape) |
206 | 144 | end |
207 | 145 |
|
208 | | - context "accessing via send" do |
209 | | - it "properly escapes strings" do |
210 | | - result = described_class.send(:mailto_escape, "Hello World") |
211 | | - expect(result).to eq("Hello%20World") |
212 | | - end |
| 146 | + context "with simple string" do |
| 147 | + subject { described_class.send(:mailto_escape, "Hello World") } |
213 | 148 |
|
214 | | - it "converts plus signs to %20" do |
215 | | - result = described_class.send(:mailto_escape, "test+tag@example.com") |
216 | | - expect(result).to eq("test%2Btag%40example.com") |
217 | | - end |
| 149 | + it { is_expected.to eq("Hello%20World") } |
| 150 | + end |
218 | 151 |
|
219 | | - it "handles newlines" do |
220 | | - result = described_class.send(:mailto_escape, "Line 1\nLine 2") |
221 | | - expect(result).to eq("Line%201%0ALine%202") |
222 | | - end |
| 152 | + context "with plus signs" do |
| 153 | + subject { described_class.send(:mailto_escape, "test+tag@example.com") } |
223 | 154 |
|
224 | | - it "handles ampersands" do |
225 | | - result = described_class.send(:mailto_escape, "Hello & Goodbye") |
226 | | - expect(result).to eq("Hello%20%26%20Goodbye") |
227 | | - end |
| 155 | + it { is_expected.to eq("test%2Btag%40example.com") } |
| 156 | + end |
228 | 157 |
|
229 | | - it "converts non-string objects to strings" do |
230 | | - result = described_class.send(:mailto_escape, 123) |
231 | | - expect(result).to eq("123") |
232 | | - end |
| 158 | + context "with newlines" do |
| 159 | + subject { described_class.send(:mailto_escape, "Line 1\nLine 2") } |
233 | 160 |
|
234 | | - it "handles special email characters" do |
235 | | - result = described_class.send(:mailto_escape, "user+tag@example.com") |
236 | | - expect(result).to eq("user%2Btag%40example.com") |
237 | | - end |
| 161 | + it { is_expected.to eq("Line%201%0ALine%202") } |
| 162 | + end |
238 | 163 |
|
239 | | - it "handles carriage returns and line feeds" do |
240 | | - result = described_class.send(:mailto_escape, "Line 1\r\nLine 2") |
241 | | - expect(result).to eq("Line%201%0D%0ALine%202") |
242 | | - end |
| 164 | + context "with ampersands" do |
| 165 | + subject { described_class.send(:mailto_escape, "Hello & Goodbye") } |
243 | 166 |
|
244 | | - it "handles unicode characters" do |
245 | | - result = described_class.send(:mailto_escape, "Héllo 🎉") |
246 | | - expect(result).to include("H%C3%A9llo") |
247 | | - end |
| 167 | + it { is_expected.to eq("Hello%20%26%20Goodbye") } |
| 168 | + end |
248 | 169 |
|
249 | | - it "handles percent signs" do |
250 | | - result = described_class.send(:mailto_escape, "50% off") |
251 | | - expect(result).to eq("50%25%20off") |
252 | | - end |
| 170 | + context "with non-string objects" do |
| 171 | + subject { described_class.send(:mailto_escape, 123) } |
253 | 172 |
|
254 | | - it "handles empty strings" do |
255 | | - result = described_class.send(:mailto_escape, "") |
256 | | - expect(result).to eq("") |
257 | | - end |
| 173 | + it { is_expected.to eq("123") } |
| 174 | + end |
| 175 | + |
| 176 | + context "with carriage returns and line feeds" do |
| 177 | + subject { described_class.send(:mailto_escape, "Line 1\r\nLine 2") } |
| 178 | + |
| 179 | + it { is_expected.to eq("Line%201%0D%0ALine%202") } |
| 180 | + end |
| 181 | + |
| 182 | + context "with unicode characters" do |
| 183 | + subject { described_class.send(:mailto_escape, "Héllo 🎉") } |
| 184 | + |
| 185 | + it { is_expected.to include("H%C3%A9llo") } |
| 186 | + end |
| 187 | + |
| 188 | + context "with percent signs" do |
| 189 | + subject { described_class.send(:mailto_escape, "50% off") } |
| 190 | + |
| 191 | + it { is_expected.to eq("50%25%20off") } |
| 192 | + end |
| 193 | + |
| 194 | + context "with empty strings" do |
| 195 | + subject { described_class.send(:mailto_escape, "") } |
| 196 | + |
| 197 | + it { is_expected.to eq("") } |
258 | 198 | end |
259 | 199 | end |
260 | 200 | end |
0 commit comments