@cakemail-org/cakemail-cli 1.7.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/.claude/settings.local.json +12 -0
  2. package/.env.example +40 -0
  3. package/.env.test.example +45 -0
  4. package/CHANGELOG.md +1031 -0
  5. package/README.md +41 -37
  6. package/audit-formats.js +128 -0
  7. package/cakemail.rb +20 -0
  8. package/dist/client.js +1 -1
  9. package/dist/client.js.map +1 -1
  10. package/dist/commands/account.js +1 -1
  11. package/dist/commands/account.js.map +1 -1
  12. package/dist/commands/attributes.js +1 -1
  13. package/dist/commands/attributes.js.map +1 -1
  14. package/dist/commands/campaigns.js +1 -1
  15. package/dist/commands/campaigns.js.map +1 -1
  16. package/dist/commands/contacts.js +1 -1
  17. package/dist/commands/contacts.js.map +1 -1
  18. package/dist/commands/emails.js +1 -1
  19. package/dist/commands/emails.js.map +1 -1
  20. package/dist/commands/interests.js +1 -1
  21. package/dist/commands/interests.js.map +1 -1
  22. package/dist/commands/lists.js +1 -1
  23. package/dist/commands/lists.js.map +1 -1
  24. package/dist/commands/logs.js +1 -1
  25. package/dist/commands/logs.js.map +1 -1
  26. package/dist/commands/reports.js +1 -1
  27. package/dist/commands/reports.js.map +1 -1
  28. package/dist/commands/segments.js +1 -1
  29. package/dist/commands/segments.js.map +1 -1
  30. package/dist/commands/senders.js +1 -1
  31. package/dist/commands/senders.js.map +1 -1
  32. package/dist/commands/suppressed.js +1 -1
  33. package/dist/commands/suppressed.js.map +1 -1
  34. package/dist/commands/tags.js +1 -1
  35. package/dist/commands/tags.js.map +1 -1
  36. package/dist/commands/templates.js +1 -1
  37. package/dist/commands/templates.js.map +1 -1
  38. package/dist/commands/transactional-templates.js +1 -1
  39. package/dist/commands/transactional-templates.js.map +1 -1
  40. package/dist/commands/webhooks.js +1 -1
  41. package/dist/commands/webhooks.js.map +1 -1
  42. package/dist/utils/config.js +2 -2
  43. package/dist/utils/config.js.map +1 -1
  44. package/dist/utils/errors.js +1 -1
  45. package/dist/utils/errors.js.map +1 -1
  46. package/dist/utils/progress.d.ts.map +1 -1
  47. package/dist/utils/progress.js +32 -4
  48. package/dist/utils/progress.js.map +1 -1
  49. package/dist/utils/spinner.d.ts +17 -0
  50. package/dist/utils/spinner.d.ts.map +1 -0
  51. package/dist/utils/spinner.js +43 -0
  52. package/dist/utils/spinner.js.map +1 -0
  53. package/docs/DOCUMENTATION-STANDARD.md +1068 -0
  54. package/docs/README.md +161 -0
  55. package/docs/developer/ARCHITECTURE.md +516 -0
  56. package/docs/developer/AUTH.md +204 -0
  57. package/docs/developer/CONTRIBUTING.md +227 -0
  58. package/docs/developer/DOCUMENTATION_SUMMARY.md +346 -0
  59. package/docs/developer/PROJECT_INDEX.md +365 -0
  60. package/docs/planning/API_COVERAGE.md +1045 -0
  61. package/docs/planning/BACKLOG.md +1159 -0
  62. package/docs/planning/PROFILE_SYSTEM_TASKS.md +287 -0
  63. package/docs/planning/UX_IMPLEMENTATION_PLAN.md +691 -0
  64. package/docs/planning/archive/RELEASE_CHECKLIST_v1.3.0.md +332 -0
  65. package/docs/planning/archive/RELEASE_v1.3.0.md +428 -0
  66. package/docs/planning/archive/cakemail-cli-ux-improvements.md +438 -0
  67. package/docs/planning/cakemail-profile-system-plan.md +1121 -0
  68. package/docs/testing/AI_USER_SIMULATION_DESIGN.md +1342 -0
  69. package/docs/testing/KENOGAMI_BIDIRECTIONAL_FLOW.md +1517 -0
  70. package/docs/testing/KENOGAMI_TRUTH_RECONCILIATION_SYSTEM.md +1369 -0
  71. package/docs/user-manual/.obsidian/app.json +1 -0
  72. package/docs/user-manual/.obsidian/appearance.json +1 -0
  73. package/docs/user-manual/.obsidian/core-plugins.json +33 -0
  74. package/docs/user-manual/.obsidian/workspace.json +167 -0
  75. package/docs/user-manual/01-getting-started/01-installation.md +214 -0
  76. package/docs/user-manual/01-getting-started/02-quick-start.md +432 -0
  77. package/docs/user-manual/01-getting-started/03-authentication.md +448 -0
  78. package/docs/user-manual/01-getting-started/04-configuration.md +430 -0
  79. package/docs/user-manual/01-getting-started/05-output-formats.md +447 -0
  80. package/docs/user-manual/02-core-concepts/01-accounts.md +514 -0
  81. package/docs/user-manual/02-core-concepts/02-profile-system.md +771 -0
  82. package/docs/user-manual/02-core-concepts/03-smart-defaults.md +485 -0
  83. package/docs/user-manual/02-core-concepts/04-authentication-methods.md +435 -0
  84. package/docs/user-manual/02-core-concepts/05-pagination-filtering.md +600 -0
  85. package/docs/user-manual/02-core-concepts/06-error-handling.md +718 -0
  86. package/docs/user-manual/02-core-concepts/07-api-coverage.md +483 -0
  87. package/docs/user-manual/03-email-operations/01-senders.md +490 -0
  88. package/docs/user-manual/03-email-operations/02-templates.md +444 -0
  89. package/docs/user-manual/03-email-operations/03-transactional-emails.md +706 -0
  90. package/docs/user-manual/03-email-operations/04-email-tracking.md +407 -0
  91. package/docs/user-manual/04-campaign-management/01-campaigns-basics.md +394 -0
  92. package/docs/user-manual/04-campaign-management/02-campaign-scheduling.md +630 -0
  93. package/docs/user-manual/04-campaign-management/03-campaign-testing.md +997 -0
  94. package/docs/user-manual/04-campaign-management/04-campaign-lifecycle.md +709 -0
  95. package/docs/user-manual/04-campaign-management/05-campaign-links.md +934 -0
  96. package/docs/user-manual/05-contact-management/01-lists.md +836 -0
  97. package/docs/user-manual/05-contact-management/02-contacts.md +1035 -0
  98. package/docs/user-manual/05-contact-management/03-custom-attributes.md +788 -0
  99. package/docs/user-manual/05-contact-management/04-segments.md +1028 -0
  100. package/docs/user-manual/05-contact-management/05-contact-import-export.md +1031 -0
  101. package/docs/user-manual/06-analytics-reporting/01-campaign-analytics.md +867 -0
  102. package/docs/user-manual/06-analytics-reporting/02-account-reports.md +227 -0
  103. package/docs/user-manual/07-integrations/01-webhooks-integration.md +259 -0
  104. package/docs/user-manual/07-integrations/02-automation.md +326 -0
  105. package/docs/user-manual/08-advanced-usage/01-scripting-patterns.md +672 -0
  106. package/docs/user-manual/08-advanced-usage/02-bulk-operations.md +932 -0
  107. package/docs/user-manual/08-advanced-usage/03-ci-cd-integration.md +892 -0
  108. package/docs/user-manual/08-advanced-usage/04-performance-optimization.md +766 -0
  109. package/docs/user-manual/09-command-reference/01-config.md +776 -0
  110. package/docs/user-manual/09-command-reference/02-account.md +652 -0
  111. package/docs/user-manual/09-command-reference/03-lists.md +958 -0
  112. package/docs/user-manual/09-command-reference/04-contacts.md +1408 -0
  113. package/docs/user-manual/09-command-reference/05-attributes.md +617 -0
  114. package/docs/user-manual/09-command-reference/06-segments.md +894 -0
  115. package/docs/user-manual/09-command-reference/07-senders.md +803 -0
  116. package/docs/user-manual/09-command-reference/08-templates.md +818 -0
  117. package/docs/user-manual/09-command-reference/09-campaigns.md +1250 -0
  118. package/docs/user-manual/09-command-reference/10-emails.md +807 -0
  119. package/docs/user-manual/09-command-reference/11-reports.md +1135 -0
  120. package/docs/user-manual/09-command-reference/12-webhooks.md +773 -0
  121. package/docs/user-manual/09-command-reference/13-suppressed.md +797 -0
  122. package/docs/user-manual/09-command-reference/14-interests.md +630 -0
  123. package/docs/user-manual/09-command-reference/15-tags.md +584 -0
  124. package/docs/user-manual/09-command-reference/16-logs.md +656 -0
  125. package/docs/user-manual/09-command-reference/17-transactional-templates.md +850 -0
  126. package/docs/user-manual/10-troubleshooting/01-common-errors.md +457 -0
  127. package/docs/user-manual/10-troubleshooting/02-authentication-issues.md +558 -0
  128. package/docs/user-manual/10-troubleshooting/03-connection-problems.md +634 -0
  129. package/docs/user-manual/10-troubleshooting/04-debugging.md +725 -0
  130. package/docs/user-manual/11-appendix/04-faq.md +484 -0
  131. package/docs/user-manual/11-appendix/05-glossary.md +250 -0
  132. package/docs/user-manual/README.md +0 -0
  133. package/package.json +13 -61
  134. package/src/cli.ts +125 -0
  135. package/src/client.ts +16 -0
  136. package/src/commands/account.ts +267 -0
  137. package/src/commands/accounts.ts +78 -0
  138. package/src/commands/actions.ts +249 -0
  139. package/src/commands/attributes.ts +139 -0
  140. package/src/commands/campaign-blueprints.ts +106 -0
  141. package/src/commands/campaigns.ts +469 -0
  142. package/src/commands/config.ts +77 -0
  143. package/src/commands/contacts.ts +612 -0
  144. package/src/commands/custom-attributes.ts +127 -0
  145. package/src/commands/dkims.ts +117 -0
  146. package/src/commands/domains.ts +82 -0
  147. package/src/commands/email-apis.ts +569 -0
  148. package/src/commands/emails.ts +197 -0
  149. package/src/commands/forms.ts +283 -0
  150. package/src/commands/interests.ts +155 -0
  151. package/src/commands/links.ts +38 -0
  152. package/src/commands/lists.ts +406 -0
  153. package/src/commands/logos.ts +71 -0
  154. package/src/commands/logs.ts +386 -0
  155. package/src/commands/reports.ts +306 -0
  156. package/src/commands/segments.ts +158 -0
  157. package/src/commands/senders.ts +204 -0
  158. package/src/commands/sub-accounts.ts +271 -0
  159. package/src/commands/suppressed-emails.ts +234 -0
  160. package/src/commands/suppressed.ts +198 -0
  161. package/src/commands/system-emails.ts +85 -0
  162. package/src/commands/tags.ts +146 -0
  163. package/src/commands/tasks.ts +116 -0
  164. package/src/commands/templates.ts +189 -0
  165. package/src/commands/tokens.ts +83 -0
  166. package/src/commands/transactional-emails.ts +374 -0
  167. package/src/commands/transactional-templates.ts +385 -0
  168. package/src/commands/users.ts +506 -0
  169. package/src/commands/webhooks.ts +172 -0
  170. package/src/commands/workflow-blueprints.ts +123 -0
  171. package/src/commands/workflows.ts +265 -0
  172. package/src/types/profile.ts +93 -0
  173. package/src/utils/auth.ts +272 -0
  174. package/src/utils/config-file.ts +96 -0
  175. package/src/utils/config.ts +134 -0
  176. package/src/utils/confirm.ts +32 -0
  177. package/src/utils/defaults.ts +99 -0
  178. package/src/utils/errors.ts +116 -0
  179. package/src/utils/interactive.ts +91 -0
  180. package/src/utils/list-defaults.ts +74 -0
  181. package/src/utils/output.ts +190 -0
  182. package/src/utils/progress.ts +320 -0
  183. package/src/utils/spinner.ts +22 -0
  184. package/tests/IMPLEMENTATION_STATUS.md +258 -0
  185. package/tests/PTY_SETUP.md +118 -0
  186. package/tests/PTY_TESTING_GUIDE.md +507 -0
  187. package/tests/README.md +244 -0
  188. package/tests/fixtures/api-responses/campaigns.json +34 -0
  189. package/tests/fixtures/test-config.json +13 -0
  190. package/tests/helpers/cli-runner.ts +128 -0
  191. package/tests/helpers/mock-server.ts +301 -0
  192. package/tests/helpers/pty-runner.ts +181 -0
  193. package/tests/integration/campaigns-real-api.test.ts +196 -0
  194. package/tests/integration/setup-integration.ts +50 -0
  195. package/tests/pty/campaigns.test.ts +241 -0
  196. package/tests/setup.ts +34 -0
  197. package/tsconfig.json +15 -0
  198. package/vitest.config.ts +28 -0
@@ -0,0 +1,997 @@
1
+ # Campaign Testing
2
+
3
+ Test campaigns thoroughly before sending to ensure perfect delivery and presentation.
4
+
5
+ ## Overview
6
+
7
+ Campaign testing allows you to:
8
+ - Send test emails to verify appearance
9
+ - Check content, links, and formatting
10
+ - Test merge tags and personalization
11
+ - Preview in multiple email clients
12
+ - Validate before scheduling
13
+ - Catch errors early
14
+
15
+ Testing is critical to ensure campaigns look professional and function correctly across different email clients and devices.
16
+
17
+ ## Quick Start
18
+
19
+ ### Send a Test Email
20
+
21
+ ```bash
22
+ $ cakemail campaigns test 790 -e test@example.com
23
+ ```
24
+
25
+ **Output:**
26
+ ```
27
+ ✓ Test email sent to test@example.com
28
+ ```
29
+
30
+ Check your inbox to review the campaign.
31
+
32
+ ## Test Email Basics
33
+
34
+ ### Send to Single Recipient
35
+
36
+ ```bash
37
+ $ cakemail campaigns test 790 -e john@company.com
38
+ ```
39
+
40
+ **Output:**
41
+ ```
42
+ ✓ Test email sent to john@company.com
43
+ ```
44
+
45
+ ### Send to Multiple Recipients
46
+
47
+ ```bash
48
+ $ cakemail campaigns test 790 -e john@company.com,mary@company.com,team@company.com
49
+ ```
50
+
51
+ **Output:**
52
+ ```
53
+ ✓ Test email sent to 3 recipients:
54
+ • john@company.com
55
+ • mary@company.com
56
+ • team@company.com
57
+ ```
58
+
59
+ ### Send to Team Distribution List
60
+
61
+ ```bash
62
+ # Set up team emails in environment
63
+ $ export TEST_TEAM="editor@company.com,designer@company.com,manager@company.com"
64
+
65
+ $ cakemail campaigns test 790 -e $TEST_TEAM
66
+ ```
67
+
68
+ ## Testing Workflow
69
+
70
+ ### Pre-Send Testing Checklist
71
+
72
+ ```bash
73
+ #!/bin/bash
74
+ # pre-send-test.sh
75
+
76
+ CAMPAIGN_ID=$1
77
+
78
+ if [ -z "$CAMPAIGN_ID" ]; then
79
+ echo "Usage: $0 <campaign-id>"
80
+ exit 1
81
+ fi
82
+
83
+ echo "=== Pre-Send Testing for Campaign $CAMPAIGN_ID ==="
84
+ echo ""
85
+
86
+ # Step 1: Get campaign details
87
+ echo "1. Reviewing campaign details..."
88
+ CAMPAIGN=$(cakemail campaigns get $CAMPAIGN_ID -f json)
89
+ SUBJECT=$(echo "$CAMPAIGN" | jq -r '.subject')
90
+ SENDER=$(echo "$CAMPAIGN" | jq -r '.sender_name')
91
+ FROM=$(echo "$CAMPAIGN" | jq -r '.sender_email')
92
+
93
+ echo " Subject: $SUBJECT"
94
+ echo " From: $SENDER <$FROM>"
95
+ echo ""
96
+
97
+ # Step 2: Send test to review team
98
+ echo "2. Sending test email to review team..."
99
+ cakemail campaigns test $CAMPAIGN_ID -e "editor@company.com,designer@company.com"
100
+ echo ""
101
+
102
+ # Step 3: Wait for review
103
+ echo "3. Review test email for:"
104
+ echo " ☐ Subject line clear and compelling"
105
+ echo " ☐ Sender name correct"
106
+ echo " ☐ Header/footer present"
107
+ echo " ☐ All images load"
108
+ echo " ☐ All links work"
109
+ echo " ☐ Merge tags display correctly"
110
+ echo " ☐ Mobile responsive"
111
+ echo " ☐ Unsubscribe link present"
112
+ echo ""
113
+
114
+ # Step 4: Get approval
115
+ read -p "Tests passed? (yes/no): " APPROVAL
116
+
117
+ if [ "$APPROVAL" == "yes" ]; then
118
+ echo ""
119
+ echo "✅ Campaign ready for scheduling"
120
+ echo " Run: cakemail campaigns schedule $CAMPAIGN_ID"
121
+ else
122
+ echo ""
123
+ echo "⚠️ Review feedback and make changes"
124
+ echo " Run: cakemail campaigns update $CAMPAIGN_ID --subject \"New Subject\""
125
+ fi
126
+ ```
127
+
128
+ ### Make this executable:
129
+
130
+ ```bash
131
+ $ chmod +x pre-send-test.sh
132
+ $ ./pre-send-test.sh 790
133
+ ```
134
+
135
+ ## Testing Merge Tags
136
+
137
+ ### Test Personalization
138
+
139
+ Campaign with merge tags:
140
+
141
+ ```html
142
+ <p>Hi {{first_name}},</p>
143
+ <p>Your account status: {{custom_attributes.plan_type}}</p>
144
+ <p>Signed up: {{custom_attributes.signup_date}}</p>
145
+ ```
146
+
147
+ **Test with sample data:**
148
+
149
+ ```bash
150
+ # Create test contact with sample data
151
+ $ cakemail contacts add \
152
+ -e "testuser@example.com" \
153
+ --first-name "John" \
154
+ --last-name "Doe" \
155
+ -d '{"plan_type":"premium","signup_date":"2024-01-15"}'
156
+
157
+ # Send test
158
+ $ cakemail campaigns test 790 -e testuser@example.com
159
+ ```
160
+
161
+ **Test email will show:**
162
+ ```
163
+ Hi John,
164
+ Your account status: premium
165
+ Signed up: 2024-01-15
166
+ ```
167
+
168
+ ### Test with Missing Data
169
+
170
+ ```bash
171
+ # Create contact without custom attributes
172
+ $ cakemail contacts add -e "incomplete@example.com" --first-name "Jane"
173
+
174
+ # Send test
175
+ $ cakemail campaigns test 790 -e incomplete@example.com
176
+ ```
177
+
178
+ **Verify fallbacks:**
179
+ - Missing first_name → Check fallback text
180
+ - Missing custom_attributes → Ensure no broken tags
181
+
182
+ ### Test Multiple Scenarios
183
+
184
+ ```bash
185
+ #!/bin/bash
186
+ # test-personalization.sh
187
+
188
+ CAMPAIGN_ID=790
189
+
190
+ # Test Scenario 1: Complete data
191
+ echo "Testing with complete data..."
192
+ cakemail campaigns test $CAMPAIGN_ID -e john.complete@test.com
193
+
194
+ # Test Scenario 2: Missing first name
195
+ echo "Testing with missing first name..."
196
+ cakemail campaigns test $CAMPAIGN_ID -e nofirstname@test.com
197
+
198
+ # Test Scenario 3: Missing custom attributes
199
+ echo "Testing with missing attributes..."
200
+ cakemail campaigns test $CAMPAIGN_ID -e noattrs@test.com
201
+
202
+ echo ""
203
+ echo "✅ All test scenarios sent"
204
+ echo "Review each test email to verify merge tag behavior"
205
+ ```
206
+
207
+ ## Testing Links
208
+
209
+ ### Verify All Links Work
210
+
211
+ After sending test:
212
+
213
+ ```bash
214
+ #!/bin/bash
215
+ # check-links.sh
216
+
217
+ TEST_EMAIL="test@example.com"
218
+
219
+ echo "=== Link Testing Checklist ==="
220
+ echo ""
221
+ echo "Test email sent to: $TEST_EMAIL"
222
+ echo ""
223
+ echo "Manual checks required:"
224
+ echo ""
225
+ echo "☐ Header logo links to website"
226
+ echo "☐ CTA button links correctly"
227
+ echo "☐ Product links include tracking parameters"
228
+ echo "☐ Social media icons link to profiles"
229
+ echo "☐ Unsubscribe link works"
230
+ echo "☐ View in browser link works"
231
+ echo "☐ Footer address/contact links work"
232
+ echo ""
233
+ echo "Verify tracking:"
234
+ echo "☐ Links include click tracking"
235
+ echo "☐ UTM parameters present"
236
+ echo "☐ Custom tracking parameters correct"
237
+ echo ""
238
+ ```
239
+
240
+ ### Test Link Tracking
241
+
242
+ ```bash
243
+ # Get campaign with tracking enabled
244
+ $ cakemail campaigns get 790 -f json | jq '{id, name, tracking_enabled: .settings.track_clicks}'
245
+ ```
246
+
247
+ **Output:**
248
+ ```json
249
+ {
250
+ "id": 790,
251
+ "name": "March Newsletter",
252
+ "tracking_enabled": true
253
+ }
254
+ ```
255
+
256
+ **In test email:**
257
+ - Links should be wrapped with tracking domain
258
+ - Example: `https://tracking.cakemail.com/click/abc123...`
259
+ - Clicking link redirects to actual destination
260
+
261
+ ## Cross-Client Testing
262
+
263
+ ### Test in Multiple Email Clients
264
+
265
+ ```bash
266
+ #!/bin/bash
267
+ # multi-client-test.sh
268
+
269
+ CAMPAIGN_ID=790
270
+
271
+ echo "=== Multi-Client Testing ==="
272
+ echo ""
273
+ echo "Sending test emails to various clients..."
274
+ echo ""
275
+
276
+ # Gmail
277
+ cakemail campaigns test $CAMPAIGN_ID -e your.gmail@gmail.com
278
+ echo "✓ Gmail test sent"
279
+
280
+ # Outlook
281
+ cakemail campaigns test $CAMPAIGN_ID -e your.outlook@outlook.com
282
+ echo "✓ Outlook test sent"
283
+
284
+ # Apple Mail
285
+ cakemail campaigns test $CAMPAIGN_ID -e your.apple@icloud.com
286
+ echo "✓ Apple Mail test sent"
287
+
288
+ # Yahoo
289
+ cakemail campaigns test $CAMPAIGN_ID -e your.yahoo@yahoo.com
290
+ echo "✓ Yahoo test sent"
291
+
292
+ echo ""
293
+ echo "Check each client for:"
294
+ echo " • Layout/formatting"
295
+ echo " • Image display"
296
+ echo " • Font rendering"
297
+ echo " • Button styling"
298
+ echo " • Responsive behavior"
299
+ ```
300
+
301
+ ### Device Testing
302
+
303
+ Test on different devices:
304
+
305
+ 1. **Desktop** - Send to desktop email client
306
+ 2. **Mobile** - Check on phone
307
+ 3. **Tablet** - Verify tablet layout
308
+ 4. **Webmail** - Test in browser
309
+
310
+ ```bash
311
+ # Send test for mobile review
312
+ $ cakemail campaigns test 790 -e your.phone@gmail.com
313
+
314
+ # Check on mobile device:
315
+ # - Text readable without zooming
316
+ # - Buttons large enough to tap
317
+ # - Images scale properly
318
+ # - Single-column layout
319
+ # - CTA buttons prominent
320
+ ```
321
+
322
+ ## Testing Templates
323
+
324
+ ### Test Template with Content
325
+
326
+ ```bash
327
+ # Create campaign from template
328
+ $ CAMPAIGN_ID=$(cakemail campaigns create \
329
+ -n "Template Test" \
330
+ -l 123 \
331
+ -s 101 \
332
+ --template 201 \
333
+ -f json | jq -r '.id')
334
+
335
+ # Send test
336
+ $ cakemail campaigns test $CAMPAIGN_ID -e test@example.com
337
+
338
+ # Review:
339
+ # - Template structure correct
340
+ # - Content areas filled properly
341
+ # - Template merge tags work
342
+ # - Styling consistent
343
+ ```
344
+
345
+ ### Test Template Changes
346
+
347
+ ```bash
348
+ #!/bin/bash
349
+ # test-template-changes.sh
350
+
351
+ TEMPLATE_ID=201
352
+
353
+ echo "Testing template changes..."
354
+
355
+ # Create test campaign
356
+ CAMPAIGN=$(cakemail campaigns create \
357
+ -n "Template Test $(date +%s)" \
358
+ -l 123 \
359
+ -s 101 \
360
+ --template $TEMPLATE_ID \
361
+ -f json)
362
+
363
+ CAMPAIGN_ID=$(echo "$CAMPAIGN" | jq -r '.id')
364
+
365
+ echo "Created test campaign: $CAMPAIGN_ID"
366
+
367
+ # Send test
368
+ cakemail campaigns test $CAMPAIGN_ID -e template-review@company.com
369
+
370
+ echo ""
371
+ echo "✓ Test sent to template-review@company.com"
372
+ echo ""
373
+ echo "Verify:"
374
+ echo " • Template changes applied correctly"
375
+ echo " • No broken layouts"
376
+ echo " • All sections render properly"
377
+ echo ""
378
+
379
+ # Clean up
380
+ read -p "Delete test campaign? (yes/no): " DELETE
381
+ if [ "$DELETE" == "yes" ]; then
382
+ cakemail campaigns delete $CAMPAIGN_ID --force
383
+ echo "✓ Test campaign deleted"
384
+ fi
385
+ ```
386
+
387
+ ## A/B Testing
388
+
389
+ ### Test Subject Lines
390
+
391
+ Create variations to test:
392
+
393
+ ```bash
394
+ #!/bin/bash
395
+ # ab-test-subjects.sh
396
+
397
+ LIST_ID=123
398
+ SENDER_ID=101
399
+ TEMPLATE=201
400
+
401
+ # Version A
402
+ ID_A=$(cakemail campaigns create \
403
+ -n "A/B Test - Subject A" \
404
+ -l $LIST_ID \
405
+ -s $SENDER_ID \
406
+ --template $TEMPLATE \
407
+ --subject "Save 20% This Week" \
408
+ -f json | jq -r '.id')
409
+
410
+ # Version B
411
+ ID_B=$(cakemail campaigns create \
412
+ -n "A/B Test - Subject B" \
413
+ -l $LIST_ID \
414
+ -s $SENDER_ID \
415
+ --template $TEMPLATE \
416
+ --subject "Your Exclusive 20% Discount" \
417
+ -f json | jq -r '.id')
418
+
419
+ echo "Created A/B test campaigns:"
420
+ echo "Version A (ID: $ID_A): Save 20% This Week"
421
+ echo "Version B (ID: $ID_B): Your Exclusive 20% Discount"
422
+ echo ""
423
+
424
+ # Send tests
425
+ echo "Sending tests for review..."
426
+ cakemail campaigns test $ID_A -e team@company.com
427
+ cakemail campaigns test $ID_B -e team@company.com
428
+
429
+ echo ""
430
+ echo "✓ Both versions sent to team@company.com"
431
+ echo ""
432
+ echo "Compare and decide which to use"
433
+ ```
434
+
435
+ ### Test Content Variations
436
+
437
+ ```bash
438
+ #!/bin/bash
439
+ # ab-test-content.sh
440
+
441
+ # Version A: Short form
442
+ ID_A=$(cakemail campaigns create \
443
+ -n "A/B Test - Short Content" \
444
+ -l 123 \
445
+ -s 101 \
446
+ --html "<h1>Quick Update</h1><p>Brief message...</p>" \
447
+ --subject "Quick Update" \
448
+ -f json | jq -r '.id')
449
+
450
+ # Version B: Long form
451
+ ID_B=$(cakemail campaigns create \
452
+ -n "A/B Test - Long Content" \
453
+ -l 123 \
454
+ -s 101 \
455
+ --html "<h1>Detailed Update</h1><p>Long detailed message...</p>" \
456
+ --subject "Detailed Update" \
457
+ -f json | jq -r '.id')
458
+
459
+ # Send tests
460
+ cakemail campaigns test $ID_A -e review@company.com
461
+ cakemail campaigns test $ID_B -e review@company.com
462
+
463
+ echo "A/B content test sent"
464
+ echo "Choose version with better engagement"
465
+ ```
466
+
467
+ ## Testing Best Practices
468
+
469
+ ### 1. Always Test Before Scheduling
470
+
471
+ ```bash
472
+ # Bad: Schedule without testing
473
+ $ cakemail campaigns schedule 790 # ❌
474
+
475
+ # Good: Test first, then schedule
476
+ $ cakemail campaigns test 790 -e team@company.com # ✅
477
+ # Review email
478
+ $ cakemail campaigns schedule 790
479
+ ```
480
+
481
+ ### 2. Test with Real Data
482
+
483
+ ```bash
484
+ # Create realistic test contact
485
+ $ cakemail contacts add \
486
+ -e "realistic.test@example.com" \
487
+ --first-name "John" \
488
+ --last-name "Smith" \
489
+ -d '{
490
+ "plan_type": "premium",
491
+ "signup_date": "2024-01-15",
492
+ "purchase_count": 5,
493
+ "is_vip": true
494
+ }'
495
+
496
+ # Test shows how real subscribers will see it
497
+ $ cakemail campaigns test 790 -e realistic.test@example.com
498
+ ```
499
+
500
+ ### 3. Test Multiple Times
501
+
502
+ ```bash
503
+ #!/bin/bash
504
+ # iterative-testing.sh
505
+
506
+ CAMPAIGN_ID=790
507
+
508
+ # Round 1: Initial test
509
+ echo "Round 1: Initial review..."
510
+ cakemail campaigns test $CAMPAIGN_ID -e editor@company.com
511
+ read -p "Issues found? (yes/no): " HAS_ISSUES
512
+
513
+ while [ "$HAS_ISSUES" == "yes" ]; do
514
+ echo "Make changes to campaign..."
515
+ read -p "Press Enter when changes made..."
516
+
517
+ # Send new test
518
+ cakemail campaigns test $CAMPAIGN_ID -e editor@company.com
519
+ read -p "Issues found? (yes/no): " HAS_ISSUES
520
+ done
521
+
522
+ echo "✅ Campaign approved"
523
+ ```
524
+
525
+ ### 4. Document Test Results
526
+
527
+ ```bash
528
+ #!/bin/bash
529
+ # log-test-results.sh
530
+
531
+ CAMPAIGN_ID=$1
532
+ LOG_FILE="campaign-tests.log"
533
+
534
+ echo "=== Test Log ===" >> $LOG_FILE
535
+ echo "Date: $(date)" >> $LOG_FILE
536
+ echo "Campaign: $CAMPAIGN_ID" >> $LOG_FILE
537
+ echo "Tester: $USER" >> $LOG_FILE
538
+ echo "" >> $LOG_FILE
539
+
540
+ read -p "Test passed? (yes/no): " RESULT
541
+ echo "Result: $RESULT" >> $LOG_FILE
542
+
543
+ if [ "$RESULT" != "yes" ]; then
544
+ read -p "Issues found: " ISSUES
545
+ echo "Issues: $ISSUES" >> $LOG_FILE
546
+ fi
547
+
548
+ echo "---" >> $LOG_FILE
549
+ echo "" >> $LOG_FILE
550
+
551
+ cat $LOG_FILE
552
+ ```
553
+
554
+ ### 5. Use Test Distribution Lists
555
+
556
+ Create reusable test groups:
557
+
558
+ ```bash
559
+ # Set in environment or script
560
+ export TEST_EDITORS="editor1@company.com,editor2@company.com"
561
+ export TEST_DESIGNERS="designer1@company.com,designer2@company.com"
562
+ export TEST_ALL="editor1@company.com,editor2@company.com,designer1@company.com,designer2@company.com,manager@company.com"
563
+
564
+ # Use in tests
565
+ $ cakemail campaigns test 790 -e $TEST_EDITORS # Content review
566
+ $ cakemail campaigns test 790 -e $TEST_DESIGNERS # Visual review
567
+ $ cakemail campaigns test 790 -e $TEST_ALL # Final review
568
+ ```
569
+
570
+ ## Advanced Testing Workflows
571
+
572
+ ### Workflow 1: Comprehensive Testing
573
+
574
+ ```bash
575
+ #!/bin/bash
576
+ # comprehensive-test.sh
577
+
578
+ CAMPAIGN_ID=$1
579
+
580
+ echo "=== Comprehensive Campaign Testing ==="
581
+ echo ""
582
+
583
+ # 1. Campaign details
584
+ echo "1. Campaign Details:"
585
+ CAMPAIGN=$(cakemail campaigns get $CAMPAIGN_ID -f json)
586
+ echo " Name: $(echo "$CAMPAIGN" | jq -r '.name')"
587
+ echo " Subject: $(echo "$CAMPAIGN" | jq -r '.subject')"
588
+ echo " List: $(echo "$CAMPAIGN" | jq -r '.list_id')"
589
+ echo ""
590
+
591
+ # 2. Content test
592
+ echo "2. Sending content review test..."
593
+ cakemail campaigns test $CAMPAIGN_ID -e editor@company.com
594
+ echo " ✓ Sent to editor@company.com"
595
+ echo ""
596
+
597
+ # 3. Design test
598
+ echo "3. Sending design review test..."
599
+ cakemail campaigns test $CAMPAIGN_ID -e designer@company.com
600
+ echo " ✓ Sent to designer@company.com"
601
+ echo ""
602
+
603
+ # 4. Multi-client test
604
+ echo "4. Sending multi-client tests..."
605
+ cakemail campaigns test $CAMPAIGN_ID -e gmail.test@gmail.com
606
+ cakemail campaigns test $CAMPAIGN_ID -e outlook.test@outlook.com
607
+ echo " ✓ Sent to multiple clients"
608
+ echo ""
609
+
610
+ # 5. Mobile test
611
+ echo "5. Sending mobile test..."
612
+ cakemail campaigns test $CAMPAIGN_ID -e mobile.test@gmail.com
613
+ echo " ✓ Sent for mobile review"
614
+ echo ""
615
+
616
+ # 6. Link verification
617
+ echo "6. Link Verification:"
618
+ echo " Manual check required:"
619
+ echo " • Click all links in test email"
620
+ echo " • Verify tracking parameters"
621
+ echo " • Test unsubscribe flow"
622
+ echo ""
623
+
624
+ # 7. Approval
625
+ read -p "All tests passed? (yes/no): " APPROVED
626
+
627
+ if [ "$APPROVED" == "yes" ]; then
628
+ echo ""
629
+ echo "✅ Campaign ready for scheduling"
630
+ read -p "Schedule now? (yes/no): " SCHEDULE
631
+
632
+ if [ "$SCHEDULE" == "yes" ]; then
633
+ cakemail campaigns schedule $CAMPAIGN_ID
634
+ fi
635
+ else
636
+ echo ""
637
+ echo "⚠️ Address issues before scheduling"
638
+ fi
639
+ ```
640
+
641
+ ### Workflow 2: Regression Testing
642
+
643
+ Test existing campaigns after template changes:
644
+
645
+ ```bash
646
+ #!/bin/bash
647
+ # regression-test.sh
648
+
649
+ TEMPLATE_ID=201
650
+
651
+ echo "=== Template Regression Testing ==="
652
+ echo ""
653
+
654
+ # Find all campaigns using this template
655
+ CAMPAIGNS=$(cakemail campaigns list \
656
+ --filter "template_id==$TEMPLATE_ID;status==draft" \
657
+ -f json | jq -r '.data[].id')
658
+
659
+ if [ -z "$CAMPAIGNS" ]; then
660
+ echo "No draft campaigns using template $TEMPLATE_ID"
661
+ exit 0
662
+ fi
663
+
664
+ echo "Found campaigns using template $TEMPLATE_ID:"
665
+ for ID in $CAMPAIGNS; do
666
+ NAME=$(cakemail campaigns get $ID -f json | jq -r '.name')
667
+ echo " • $NAME (ID: $ID)"
668
+ done
669
+
670
+ echo ""
671
+ echo "Sending regression tests..."
672
+
673
+ for ID in $CAMPAIGNS; do
674
+ cakemail campaigns test $ID -e regression@company.com
675
+ echo " ✓ Test sent for campaign $ID"
676
+ done
677
+
678
+ echo ""
679
+ echo "✅ All regression tests sent to regression@company.com"
680
+ echo "Verify template changes don't break existing campaigns"
681
+ ```
682
+
683
+ ### Workflow 3: Stakeholder Review
684
+
685
+ ```bash
686
+ #!/bin/bash
687
+ # stakeholder-review.sh
688
+
689
+ CAMPAIGN_ID=$1
690
+
691
+ echo "=== Stakeholder Review Process ==="
692
+ echo ""
693
+
694
+ # Define stakeholders
695
+ STAKEHOLDERS=(
696
+ "editor@company.com:Content Editor"
697
+ "designer@company.com:Designer"
698
+ "manager@company.com:Marketing Manager"
699
+ "legal@company.com:Legal Compliance"
700
+ )
701
+
702
+ # Send to each stakeholder
703
+ for STAKEHOLDER in "${STAKEHOLDERS[@]}"; do
704
+ EMAIL=$(echo $STAKEHOLDER | cut -d: -f1)
705
+ ROLE=$(echo $STAKEHOLDER | cut -d: -f2)
706
+
707
+ echo "Sending to $ROLE ($EMAIL)..."
708
+ cakemail campaigns test $CAMPAIGN_ID -e $EMAIL
709
+ echo " ✓ Sent"
710
+ done
711
+
712
+ echo ""
713
+ echo "✅ Review requests sent to all stakeholders"
714
+ echo ""
715
+ echo "Stakeholder Approval Checklist:"
716
+ for STAKEHOLDER in "${STAKEHOLDERS[@]}"; do
717
+ ROLE=$(echo $STAKEHOLDER | cut -d: -f2)
718
+ echo " ☐ $ROLE approval"
719
+ done
720
+
721
+ echo ""
722
+ read -p "All approvals received? (yes/no): " ALL_APPROVED
723
+
724
+ if [ "$ALL_APPROVED" == "yes" ]; then
725
+ echo "✅ Campaign approved for scheduling"
726
+ else
727
+ echo "⚠️ Waiting for approvals..."
728
+ fi
729
+ ```
730
+
731
+ ### Workflow 4: Automated Quality Checks
732
+
733
+ ```bash
734
+ #!/bin/bash
735
+ # quality-checks.sh
736
+
737
+ CAMPAIGN_ID=$1
738
+
739
+ echo "=== Automated Quality Checks ==="
740
+ echo ""
741
+
742
+ CAMPAIGN=$(cakemail campaigns get $CAMPAIGN_ID -f json)
743
+
744
+ # Check 1: Subject line
745
+ SUBJECT=$(echo "$CAMPAIGN" | jq -r '.subject')
746
+ SUBJECT_LEN=${#SUBJECT}
747
+
748
+ echo "Check 1: Subject Line"
749
+ if [ $SUBJECT_LEN -gt 60 ]; then
750
+ echo " ⚠️ Subject too long ($SUBJECT_LEN chars, recommended < 60)"
751
+ else
752
+ echo " ✅ Subject length OK ($SUBJECT_LEN chars)"
753
+ fi
754
+
755
+ # Check 2: Has HTML content
756
+ HAS_HTML=$(echo "$CAMPAIGN" | jq -r '.html' | grep -v "null")
757
+ echo "Check 2: HTML Content"
758
+ if [ -z "$HAS_HTML" ]; then
759
+ echo " ❌ No HTML content"
760
+ else
761
+ echo " ✅ HTML content present"
762
+ fi
763
+
764
+ # Check 3: Has plain text
765
+ HAS_TEXT=$(echo "$CAMPAIGN" | jq -r '.text' | grep -v "null")
766
+ echo "Check 3: Plain Text Version"
767
+ if [ -z "$HAS_TEXT" ]; then
768
+ echo " ⚠️ No plain text version (recommended)"
769
+ else
770
+ echo " ✅ Plain text present"
771
+ fi
772
+
773
+ # Check 4: Sender verified
774
+ SENDER_ID=$(echo "$CAMPAIGN" | jq -r '.sender_id')
775
+ SENDER_CONFIRMED=$(cakemail senders get $SENDER_ID -f json | jq -r '.confirmed')
776
+ echo "Check 4: Sender Verification"
777
+ if [ "$SENDER_CONFIRMED" != "true" ]; then
778
+ echo " ❌ Sender not verified"
779
+ else
780
+ echo " ✅ Sender verified"
781
+ fi
782
+
783
+ # Check 5: List has contacts
784
+ LIST_ID=$(echo "$CAMPAIGN" | jq -r '.list_id')
785
+ CONTACT_COUNT=$(cakemail contacts list $LIST_ID -f json | jq '.count')
786
+ echo "Check 5: Recipient List"
787
+ if [ "$CONTACT_COUNT" -eq 0 ]; then
788
+ echo " ⚠️ List has 0 contacts"
789
+ else
790
+ echo " ✅ List has $CONTACT_COUNT contacts"
791
+ fi
792
+
793
+ echo ""
794
+
795
+ # Send test if checks pass
796
+ if [ "$SENDER_CONFIRMED" == "true" ] && [ -n "$HAS_HTML" ]; then
797
+ echo "Quality checks passed. Sending test..."
798
+ cakemail campaigns test $CAMPAIGN_ID -e quality@company.com
799
+ echo "✅ Test sent to quality@company.com"
800
+ else
801
+ echo "❌ Quality checks failed. Fix issues before testing."
802
+ fi
803
+ ```
804
+
805
+ ## Testing Checklist
806
+
807
+ ### Before Sending Test
808
+
809
+ ```
810
+ ☐ Campaign created and saved
811
+ ☐ HTML content added
812
+ ☐ Plain text version added (optional but recommended)
813
+ ☐ Subject line written
814
+ ☐ Sender verified
815
+ ☐ List selected
816
+ ☐ Merge tags tested
817
+ ☐ Links include tracking parameters
818
+ ```
819
+
820
+ ### After Receiving Test
821
+
822
+ ```
823
+ ☐ Subject line displays correctly
824
+ ☐ Sender name and email correct
825
+ ☐ Header loads properly
826
+ ☐ Body content formatted correctly
827
+ ☐ Images all load
828
+ ☐ Buttons display and are clickable
829
+ ☐ All links work
830
+ ☐ Merge tags filled correctly
831
+ ☐ Footer present with required info
832
+ ☐ Unsubscribe link works
833
+ ☐ Mobile responsive
834
+ ```
835
+
836
+ ### Cross-Client Checks
837
+
838
+ ```
839
+ ☐ Gmail (web and app)
840
+ ☐ Outlook (desktop and web)
841
+ ☐ Apple Mail
842
+ ☐ iPhone Mail app
843
+ ☐ Android Gmail app
844
+ ☐ Dark mode (if supported)
845
+ ```
846
+
847
+ ## Troubleshooting
848
+
849
+ ### Test Email Not Received
850
+
851
+ **Problem:** Test email not arriving
852
+
853
+ **Solutions:**
854
+
855
+ ```bash
856
+ # Check campaign status
857
+ $ cakemail campaigns get 790 -f json | jq '{status, subject}'
858
+
859
+ # Verify sender is confirmed
860
+ $ cakemail senders list -f json | jq '.data[] | select(.confirmed == true)'
861
+
862
+ # Check spam folder
863
+ # - Test emails sometimes flagged as spam
864
+ # - Add Cakemail to safe senders list
865
+
866
+ # Verify email address
867
+ $ echo "test@example.com" | grep -E '^[^@]+@[^@]+\.[^@]+$'
868
+
869
+ # Try different email address
870
+ $ cakemail campaigns test 790 -e alternate@example.com
871
+ ```
872
+
873
+ ### Merge Tags Not Replacing
874
+
875
+ **Problem:** Merge tags show as {{field_name}} instead of values
876
+
877
+ **Solutions:**
878
+
879
+ ```bash
880
+ # Ensure test contact has data
881
+ $ cakemail contacts get 123 501 -f json | jq '{first_name, custom_attributes}'
882
+
883
+ # If empty, add data
884
+ $ cakemail contacts update 123 501 \
885
+ --first-name "John" \
886
+ -d '{"plan_type":"premium"}'
887
+
888
+ # Send test again
889
+ $ cakemail campaigns test 790 -e test@example.com
890
+
891
+ # Check merge tag syntax
892
+ # Correct: {{first_name}}
893
+ # Correct: {{custom_attributes.plan_type}}
894
+ # Wrong: {{firstName}} or {{plan_type}} (missing custom_attributes)
895
+ ```
896
+
897
+ ### Links Not Working
898
+
899
+ **Problem:** Links broken or not clickable
900
+
901
+ **Solutions:**
902
+
903
+ ```bash
904
+ # Check HTML for proper link format
905
+ # Correct: <a href="https://example.com">Link</a>
906
+ # Wrong: <a href="example.com">Link</a> (missing protocol)
907
+
908
+ # Verify tracking enabled if needed
909
+ $ cakemail campaigns get 790 -f json | jq '.settings.track_clicks'
910
+
911
+ # Test without tracking
912
+ $ cakemail campaigns update 790 --no-track-clicks
913
+ $ cakemail campaigns test 790 -e test@example.com
914
+
915
+ # Re-enable tracking if it was issue
916
+ $ cakemail campaigns update 790 --track-clicks
917
+ ```
918
+
919
+ ### Images Not Loading
920
+
921
+ **Problem:** Images missing in test email
922
+
923
+ **Solutions:**
924
+
925
+ ```bash
926
+ # Verify image URLs are absolute
927
+ # Correct: <img src="https://example.com/image.jpg">
928
+ # Wrong: <img src="/images/image.jpg"> (relative path)
929
+
930
+ # Check image URLs accessible
931
+ $ curl -I https://example.com/image.jpg
932
+ # Should return 200 OK
933
+
934
+ # Test in different clients
935
+ # - Some clients block images by default
936
+ # - Include "display images" instructions
937
+
938
+ # Verify image file size
939
+ # - Large images may fail to load
940
+ # - Recommended: < 100KB per image
941
+ ```
942
+
943
+ ### Mobile Layout Issues
944
+
945
+ **Problem:** Email doesn't display well on mobile
946
+
947
+ **Solutions:**
948
+
949
+ ```bash
950
+ # Use responsive template
951
+ $ cakemail templates list -f json | jq '.data[] | select(.mobile_optimized == true)'
952
+
953
+ # Test mobile-specific version
954
+ $ cakemail campaigns test 790 -e your.phone@gmail.com
955
+ # Check on actual mobile device
956
+
957
+ # Verify viewport meta tag in HTML
958
+ # Required: <meta name="viewport" content="width=device-width, initial-scale=1">
959
+
960
+ # Use single-column layout
961
+ # Avoid multi-column designs for mobile
962
+ ```
963
+
964
+ ### Test Email Goes to Spam
965
+
966
+ **Problem:** Test emails landing in spam folder
967
+
968
+ **Solutions:**
969
+
970
+ ```bash
971
+ # Verify sender authenticated
972
+ $ cakemail senders get 101 -f json | jq '{email, confirmed, dkim_enabled, spf_enabled}'
973
+
974
+ # Check subject line
975
+ # Avoid: ALL CAPS, excessive !!!, "FREE", "ACT NOW"
976
+
977
+ # Add company domain to safe senders
978
+ # In email client settings
979
+
980
+ # Test from different sender
981
+ $ cakemail campaigns update 790 --sender-id 102
982
+ $ cakemail campaigns test 790 -e test@example.com
983
+ ```
984
+
985
+ ## Best Practices Summary
986
+
987
+ 1. **Always test before scheduling** - Never schedule without reviewing test email
988
+ 2. **Test with real data** - Use realistic contact data for accurate previews
989
+ 3. **Test multiple clients** - Verify appearance in Gmail, Outlook, Apple Mail
990
+ 4. **Test on mobile** - Ensure responsive design works on phones
991
+ 5. **Test all links** - Click every link to verify functionality
992
+ 6. **Test merge tags** - Verify personalization with actual contact data
993
+ 7. **Get stakeholder approval** - Send tests to editors, designers, managers
994
+ 8. **Document test results** - Keep log of tests and issues found
995
+ 9. **Iterate and retest** - Test after every significant change
996
+ 10. **Use test distribution lists** - Create reusable test email groups
997
+