@bernierllc/email-testing-suite 0.1.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.
- package/LICENSE +21 -0
- package/README.md +347 -0
- package/dist/analytics.d.ts +52 -0
- package/dist/analytics.d.ts.map +1 -0
- package/dist/analytics.js +211 -0
- package/dist/analytics.js.map +1 -0
- package/dist/best-practices.d.ts +34 -0
- package/dist/best-practices.d.ts.map +1 -0
- package/dist/best-practices.js +268 -0
- package/dist/best-practices.js.map +1 -0
- package/dist/email-testing-suite.d.ts +74 -0
- package/dist/email-testing-suite.d.ts.map +1 -0
- package/dist/email-testing-suite.js +424 -0
- package/dist/email-testing-suite.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/test-patterns.d.ts +48 -0
- package/dist/test-patterns.d.ts.map +1 -0
- package/dist/test-patterns.js +132 -0
- package/dist/test-patterns.js.map +1 -0
- package/dist/types.d.ts +258 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/package.json +71 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Bernier LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
# @bernierllc/email-testing-suite
|
|
2
|
+
|
|
3
|
+
Complete email testing solution with opinionated defaults and best practices.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **One-Command Setup** - Start testing emails with minimal configuration
|
|
8
|
+
- **Opinionated Defaults** - Pre-configured validations and best practices
|
|
9
|
+
- **Comprehensive Validation** - Template, compliance, accessibility, performance, and security checks
|
|
10
|
+
- **Advanced Analytics** - Track trends, identify issues, generate reports
|
|
11
|
+
- **Best Practices Enforcement** - Automatic validation against email standards
|
|
12
|
+
- **Integration Ready** - Works with Jest, Mocha, Vitest, and other test frameworks
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @bernierllc/email-testing-suite
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
### One-Line Testing
|
|
23
|
+
|
|
24
|
+
The simplest way to test an email:
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { testEmail } from '@bernierllc/email-testing-suite';
|
|
28
|
+
|
|
29
|
+
const result = await testEmail({
|
|
30
|
+
template: './templates/welcome.html',
|
|
31
|
+
data: { name: 'John Doe', product: 'Pro Plan' },
|
|
32
|
+
recipient: 'test@example.com'
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
expect(result.success).toBe(true);
|
|
36
|
+
expect(result.score).toBeGreaterThan(90);
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Full Suite Usage
|
|
40
|
+
|
|
41
|
+
For more control and advanced features:
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { EmailTestingSuite } from '@bernierllc/email-testing-suite';
|
|
45
|
+
|
|
46
|
+
const suite = new EmailTestingSuite({
|
|
47
|
+
smtp: { port: 2525 },
|
|
48
|
+
defaults: { compliance: 'US', timeout: 30000 }
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
await suite.start();
|
|
52
|
+
|
|
53
|
+
const result = await suite.testEmailTemplate({
|
|
54
|
+
name: 'Welcome Email',
|
|
55
|
+
template: './templates/welcome.html',
|
|
56
|
+
data: { name: 'Jane Doe' },
|
|
57
|
+
recipients: ['test@example.com'],
|
|
58
|
+
expectations: {
|
|
59
|
+
delivery: true,
|
|
60
|
+
templateCompletion: true,
|
|
61
|
+
compliance: 'US',
|
|
62
|
+
accessibility: true,
|
|
63
|
+
performance: { renderTime: 2000, size: '100kb' }
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
await suite.stop();
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Configuration
|
|
71
|
+
|
|
72
|
+
### Suite Configuration
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
interface EmailTestingSuiteConfig {
|
|
76
|
+
smtp?: {
|
|
77
|
+
port: number; // Default: 2525
|
|
78
|
+
host: string; // Default: 'localhost'
|
|
79
|
+
auth?: { user: string; pass: string; };
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
defaults?: {
|
|
83
|
+
compliance: 'US' | 'EU' | 'GLOBAL'; // Default: 'US'
|
|
84
|
+
timeout: number; // Default: 30000
|
|
85
|
+
retries: number; // Default: 3
|
|
86
|
+
expectations?: Partial<EmailExpectations>;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
validation?: {
|
|
90
|
+
enabledValidators?: ValidatorType[]; // All enabled by default
|
|
91
|
+
strictMode?: boolean; // Default: false
|
|
92
|
+
customRules?: ValidationRule[]; // Custom validation rules
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
reporting?: {
|
|
96
|
+
enableAnalytics?: boolean; // Default: true
|
|
97
|
+
generateTrendReports?: boolean; // Default: true
|
|
98
|
+
exportFormats?: ReportFormat[]; // Default: ['json', 'html']
|
|
99
|
+
retainHistory?: number; // Days, default: 30
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Expectations
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
interface EmailExpectations {
|
|
108
|
+
delivery: boolean; // Email should be delivered
|
|
109
|
+
templateCompletion: boolean; // All variables resolved
|
|
110
|
+
compliance: 'US' | 'EU' | 'GLOBAL'; // Compliance standard
|
|
111
|
+
accessibility: boolean; // Accessibility validation
|
|
112
|
+
performance: {
|
|
113
|
+
renderTime?: number; // Max render time (ms)
|
|
114
|
+
size?: string; // Max email size (e.g., '100kb')
|
|
115
|
+
deliveryTime?: number; // Max delivery time (ms)
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Test Patterns
|
|
121
|
+
|
|
122
|
+
Pre-configured test patterns for common scenarios:
|
|
123
|
+
|
|
124
|
+
### Welcome Email
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
import { EmailTestPatterns } from '@bernierllc/email-testing-suite';
|
|
128
|
+
|
|
129
|
+
const result = await EmailTestPatterns.testWelcomeEmail(
|
|
130
|
+
'./templates/welcome.html',
|
|
131
|
+
{ name: 'John Doe', email: 'john@example.com' }
|
|
132
|
+
);
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Password Reset Email
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
const result = await EmailTestPatterns.testPasswordResetEmail(
|
|
139
|
+
'./templates/reset.html',
|
|
140
|
+
{ email: 'user@example.com', resetLink: 'https://example.com/reset?token=abc' }
|
|
141
|
+
);
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Newsletter Email
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
const result = await EmailTestPatterns.testNewsletterEmail(
|
|
148
|
+
'./templates/newsletter.html',
|
|
149
|
+
{ title: 'Monthly Update', articles: [...] },
|
|
150
|
+
'subscriber@example.com'
|
|
151
|
+
);
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Transactional Email
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
const result = await EmailTestPatterns.testTransactionalEmail(
|
|
158
|
+
'./templates/order-confirmation.html',
|
|
159
|
+
{ orderNumber: '12345', total: '$99.99' },
|
|
160
|
+
'customer@example.com'
|
|
161
|
+
);
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Email Flow Testing
|
|
165
|
+
|
|
166
|
+
Test multi-step email workflows:
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
const flowResult = await suite.testEmailFlow({
|
|
170
|
+
name: 'User Onboarding Flow',
|
|
171
|
+
steps: [
|
|
172
|
+
{ trigger: 'user.signup', template: 'welcome', delay: 0 },
|
|
173
|
+
{ trigger: 'user.verify', template: 'verification', delay: 300000 },
|
|
174
|
+
{ trigger: 'user.complete', template: 'onboarding', delay: 86400000 }
|
|
175
|
+
],
|
|
176
|
+
assertions: [
|
|
177
|
+
{ step: 1, assertion: 'delivered' },
|
|
178
|
+
{ step: 2, assertion: 'contains_verification_link' },
|
|
179
|
+
{ step: 3, assertion: 'personalized_content' }
|
|
180
|
+
]
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Analytics
|
|
185
|
+
|
|
186
|
+
Track and analyze email testing performance:
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
import { EmailTestAnalytics } from '@bernierllc/email-testing-suite';
|
|
190
|
+
|
|
191
|
+
const analytics = new EmailTestAnalytics();
|
|
192
|
+
|
|
193
|
+
// Add test results
|
|
194
|
+
analytics.addTestResult(result);
|
|
195
|
+
|
|
196
|
+
// Generate analytics
|
|
197
|
+
const data = analytics.generateAnalytics('last_30_days');
|
|
198
|
+
console.log(`Success Rate: ${data.successRate}%`);
|
|
199
|
+
console.log(`Average Score: ${data.performanceMetrics.averageRenderTime}ms`);
|
|
200
|
+
|
|
201
|
+
// Export analytics
|
|
202
|
+
const json = analytics.exportAsJSON();
|
|
203
|
+
const csv = analytics.exportAsCSV();
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Best Practices
|
|
207
|
+
|
|
208
|
+
Get best practice recommendations:
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
import { BestPracticesValidator } from '@bernierllc/email-testing-suite';
|
|
212
|
+
|
|
213
|
+
// Validate email
|
|
214
|
+
const validation = BestPracticesValidator.validateEmail(emailData);
|
|
215
|
+
console.log(`Score: ${validation.score}`);
|
|
216
|
+
console.log(`Recommendations: ${validation.recommendations.length}`);
|
|
217
|
+
|
|
218
|
+
// Get compliance checklist
|
|
219
|
+
const checklist = BestPracticesValidator.getComplianceChecklist('US');
|
|
220
|
+
|
|
221
|
+
// Get accessibility guidelines
|
|
222
|
+
const guidelines = BestPracticesValidator.getAccessibilityGuidelines();
|
|
223
|
+
|
|
224
|
+
// Get performance tips
|
|
225
|
+
const tips = BestPracticesValidator.getPerformanceOptimizationTips();
|
|
226
|
+
|
|
227
|
+
// Get recommended coverage
|
|
228
|
+
const coverage = BestPracticesValidator.getRecommendedCoverage('marketing');
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Test Suite Execution
|
|
232
|
+
|
|
233
|
+
Run multiple tests together:
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
const tests = [
|
|
237
|
+
{
|
|
238
|
+
name: 'Welcome Email',
|
|
239
|
+
template: 'welcome.html',
|
|
240
|
+
data: { name: 'User 1' },
|
|
241
|
+
recipients: ['test1@example.com']
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
name: 'Newsletter',
|
|
245
|
+
template: 'newsletter.html',
|
|
246
|
+
data: { content: '...' },
|
|
247
|
+
recipients: ['test2@example.com']
|
|
248
|
+
}
|
|
249
|
+
];
|
|
250
|
+
|
|
251
|
+
const suiteResult = await suite.runTestSuite(tests);
|
|
252
|
+
|
|
253
|
+
console.log(`Total: ${suiteResult.totalTests}`);
|
|
254
|
+
console.log(`Passed: ${suiteResult.passedTests}`);
|
|
255
|
+
console.log(`Failed: ${suiteResult.failedTests}`);
|
|
256
|
+
console.log(`Average Score: ${suiteResult.summary.averageScore}`);
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Jest Integration
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
describe('Email Templates', () => {
|
|
263
|
+
let suite: EmailTestingSuite;
|
|
264
|
+
|
|
265
|
+
beforeAll(async () => {
|
|
266
|
+
suite = new EmailTestingSuite({
|
|
267
|
+
smtp: { port: process.env.SMTP_PORT || 2525 },
|
|
268
|
+
defaults: { compliance: 'US', timeout: 30000 }
|
|
269
|
+
});
|
|
270
|
+
await suite.start();
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
afterAll(async () => {
|
|
274
|
+
await suite.stop();
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
test('welcome email passes validation', async () => {
|
|
278
|
+
const result = await suite.testEmailTemplate({
|
|
279
|
+
name: 'Welcome Email',
|
|
280
|
+
template: './templates/welcome.html',
|
|
281
|
+
data: { name: 'Test User' },
|
|
282
|
+
recipients: ['test@example.com']
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
expect(result.success).toBe(true);
|
|
286
|
+
expect(result.score).toBeGreaterThan(90);
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Data Generation
|
|
292
|
+
|
|
293
|
+
Generate test data from a schema:
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
const schema = {
|
|
297
|
+
name: { type: 'string', required: true },
|
|
298
|
+
email: { type: 'email', required: true },
|
|
299
|
+
age: { type: 'number', min: 18, max: 100 },
|
|
300
|
+
joinDate: { type: 'date' },
|
|
301
|
+
website: { type: 'url' },
|
|
302
|
+
userId: { type: 'uuid' }
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
const testData = suite.generateTestData(schema);
|
|
306
|
+
// Returns: { name: 'test-name', email: 'test-email@example.com', age: 18, ... }
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## API Reference
|
|
310
|
+
|
|
311
|
+
### EmailTestingSuite
|
|
312
|
+
|
|
313
|
+
- `constructor(config?: EmailTestingSuiteConfig)` - Create new suite instance
|
|
314
|
+
- `async start()` - Start the testing environment
|
|
315
|
+
- `async stop()` - Stop the testing environment
|
|
316
|
+
- `async reset()` - Reset captured emails and state
|
|
317
|
+
- `async testEmailTemplate(spec: EmailTemplateTest)` - Test an email template
|
|
318
|
+
- `async testEmailFlow(flow: EmailFlowTest)` - Test an email flow
|
|
319
|
+
- `async runTestSuite(tests: EmailTest[])` - Run multiple tests
|
|
320
|
+
- `getTestingEnvironment()` - Get current environment state
|
|
321
|
+
- `generateTestData(schema: DataSchema)` - Generate test data
|
|
322
|
+
- `getTestHistory()` - Get all test results
|
|
323
|
+
- `clearTestHistory()` - Clear test history
|
|
324
|
+
|
|
325
|
+
### EmailTestAnalytics
|
|
326
|
+
|
|
327
|
+
- `addTestResult(result: EmailTestResult)` - Add single result
|
|
328
|
+
- `addTestResults(results: EmailTestResult[])` - Add multiple results
|
|
329
|
+
- `generateAnalytics(period: string)` - Generate analytics report
|
|
330
|
+
- `exportAsJSON(period?: string)` - Export as JSON
|
|
331
|
+
- `exportAsCSV(period?: string)` - Export as CSV
|
|
332
|
+
- `getTestHistory()` - Get all results
|
|
333
|
+
- `clearHistory()` - Clear history
|
|
334
|
+
|
|
335
|
+
### BestPracticesValidator
|
|
336
|
+
|
|
337
|
+
- `static validateEmail(email: EmailData)` - Validate email against best practices
|
|
338
|
+
- `static getRecommendedCoverage(emailType: string)` - Get recommended validators
|
|
339
|
+
- `static getComplianceChecklist(region: 'US' | 'EU' | 'GLOBAL')` - Get compliance checklist
|
|
340
|
+
- `static getAccessibilityGuidelines()` - Get accessibility guidelines
|
|
341
|
+
- `static getPerformanceOptimizationTips()` - Get performance tips
|
|
342
|
+
|
|
343
|
+
## License
|
|
344
|
+
|
|
345
|
+
Copyright (c) 2025 Bernier LLC
|
|
346
|
+
|
|
347
|
+
This file is licensed to the client under a limited-use license.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { EmailTestResult, AnalyticsData } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Analytics engine for email testing data
|
|
4
|
+
*/
|
|
5
|
+
export declare class EmailTestAnalytics {
|
|
6
|
+
private testHistory;
|
|
7
|
+
/**
|
|
8
|
+
* Add test result to analytics history
|
|
9
|
+
*/
|
|
10
|
+
addTestResult(result: EmailTestResult): void;
|
|
11
|
+
/**
|
|
12
|
+
* Add multiple test results
|
|
13
|
+
*/
|
|
14
|
+
addTestResults(results: EmailTestResult[]): void;
|
|
15
|
+
/**
|
|
16
|
+
* Generate analytics for a given period
|
|
17
|
+
*/
|
|
18
|
+
generateAnalytics(period?: string): AnalyticsData;
|
|
19
|
+
/**
|
|
20
|
+
* Filter test results by period
|
|
21
|
+
*/
|
|
22
|
+
private filterByPeriod;
|
|
23
|
+
/**
|
|
24
|
+
* Calculate trend data
|
|
25
|
+
*/
|
|
26
|
+
private calculateTrends;
|
|
27
|
+
/**
|
|
28
|
+
* Identify top issues from test results
|
|
29
|
+
*/
|
|
30
|
+
private identifyTopIssues;
|
|
31
|
+
/**
|
|
32
|
+
* Calculate performance metrics
|
|
33
|
+
*/
|
|
34
|
+
private calculatePerformanceMetrics;
|
|
35
|
+
/**
|
|
36
|
+
* Get test history
|
|
37
|
+
*/
|
|
38
|
+
getTestHistory(): EmailTestResult[];
|
|
39
|
+
/**
|
|
40
|
+
* Clear analytics history
|
|
41
|
+
*/
|
|
42
|
+
clearHistory(): void;
|
|
43
|
+
/**
|
|
44
|
+
* Export analytics data as JSON
|
|
45
|
+
*/
|
|
46
|
+
exportAsJSON(period?: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* Export analytics data as CSV
|
|
49
|
+
*/
|
|
50
|
+
exportAsCSV(period?: string): string;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=analytics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EAId,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,WAAW,CAAyB;IAE5C;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAI5C;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,IAAI;IAIhD;;OAEG;IACH,iBAAiB,CAAC,MAAM,GAAE,MAAuB,GAAG,aAAa;IAqBjE;;OAEG;IACH,OAAO,CAAC,cAAc;IAwBtB;;OAEG;IACH,OAAO,CAAC,eAAe;IA2BvB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAiDzB;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAuBnC;;OAEG;IACH,cAAc,IAAI,eAAe,EAAE;IAInC;;OAEG;IACH,YAAY,IAAI,IAAI;IAIpB;;OAEG;IACH,YAAY,CAAC,MAAM,GAAE,MAAuB,GAAG,MAAM;IAKrD;;OAEG;IACH,WAAW,CAAC,MAAM,GAAE,MAAuB,GAAG,MAAM;CAoCrD"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
Copyright (c) 2025 Bernier LLC
|
|
4
|
+
|
|
5
|
+
This file is licensed to the client under a limited-use license.
|
|
6
|
+
The client may use and modify this code *only within the scope of the project it was delivered for*.
|
|
7
|
+
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.EmailTestAnalytics = void 0;
|
|
11
|
+
/**
|
|
12
|
+
* Analytics engine for email testing data
|
|
13
|
+
*/
|
|
14
|
+
class EmailTestAnalytics {
|
|
15
|
+
testHistory = [];
|
|
16
|
+
/**
|
|
17
|
+
* Add test result to analytics history
|
|
18
|
+
*/
|
|
19
|
+
addTestResult(result) {
|
|
20
|
+
this.testHistory.push(result);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Add multiple test results
|
|
24
|
+
*/
|
|
25
|
+
addTestResults(results) {
|
|
26
|
+
this.testHistory.push(...results);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Generate analytics for a given period
|
|
30
|
+
*/
|
|
31
|
+
generateAnalytics(period = 'last_30_days') {
|
|
32
|
+
const filteredResults = this.filterByPeriod(period);
|
|
33
|
+
const testCount = filteredResults.length;
|
|
34
|
+
const successCount = filteredResults.filter((r) => r.success).length;
|
|
35
|
+
const successRate = testCount > 0 ? (successCount / testCount) * 100 : 0;
|
|
36
|
+
const trends = this.calculateTrends(filteredResults);
|
|
37
|
+
const topIssues = this.identifyTopIssues(filteredResults);
|
|
38
|
+
const performanceMetrics = this.calculatePerformanceMetrics(filteredResults);
|
|
39
|
+
return {
|
|
40
|
+
period,
|
|
41
|
+
testCount,
|
|
42
|
+
successRate,
|
|
43
|
+
trends,
|
|
44
|
+
topIssues,
|
|
45
|
+
performanceMetrics,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Filter test results by period
|
|
50
|
+
*/
|
|
51
|
+
filterByPeriod(period) {
|
|
52
|
+
const now = new Date();
|
|
53
|
+
let cutoffDate;
|
|
54
|
+
switch (period) {
|
|
55
|
+
case 'last_7_days':
|
|
56
|
+
cutoffDate = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
|
|
57
|
+
break;
|
|
58
|
+
case 'last_30_days':
|
|
59
|
+
cutoffDate = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
|
|
60
|
+
break;
|
|
61
|
+
case 'last_90_days':
|
|
62
|
+
cutoffDate = new Date(now.getTime() - 90 * 24 * 60 * 60 * 1000);
|
|
63
|
+
break;
|
|
64
|
+
default:
|
|
65
|
+
cutoffDate = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
|
|
66
|
+
}
|
|
67
|
+
return this.testHistory.filter((result) => {
|
|
68
|
+
const resultDate = new Date(result.timestamp);
|
|
69
|
+
return resultDate >= cutoffDate;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Calculate trend data
|
|
74
|
+
*/
|
|
75
|
+
calculateTrends(results) {
|
|
76
|
+
const trendMap = new Map();
|
|
77
|
+
for (const result of results) {
|
|
78
|
+
const date = new Date(result.timestamp).toISOString().split('T')[0];
|
|
79
|
+
if (!trendMap.has(date)) {
|
|
80
|
+
trendMap.set(date, {
|
|
81
|
+
date,
|
|
82
|
+
successRate: 0,
|
|
83
|
+
testCount: 0,
|
|
84
|
+
averageScore: 0,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
const trend = trendMap.get(date);
|
|
88
|
+
trend.testCount++;
|
|
89
|
+
trend.averageScore = (trend.averageScore * (trend.testCount - 1) + result.score) / trend.testCount;
|
|
90
|
+
if (result.success) {
|
|
91
|
+
trend.successRate = ((trend.successRate * (trend.testCount - 1)) / trend.testCount) * 100;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return Array.from(trendMap.values()).sort((a, b) => a.date.localeCompare(b.date));
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Identify top issues from test results
|
|
98
|
+
*/
|
|
99
|
+
identifyTopIssues(results) {
|
|
100
|
+
const issueMap = new Map();
|
|
101
|
+
for (const result of results) {
|
|
102
|
+
if (result.errors && result.errors.length > 0) {
|
|
103
|
+
for (const error of result.errors) {
|
|
104
|
+
const key = error.substring(0, 100); // Normalize error message
|
|
105
|
+
if (!issueMap.has(key)) {
|
|
106
|
+
issueMap.set(key, {
|
|
107
|
+
issue: key,
|
|
108
|
+
count: 0,
|
|
109
|
+
severity: 'error',
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
const issue = issueMap.get(key);
|
|
113
|
+
issue.count++;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Check validation warnings
|
|
117
|
+
if (result.validations) {
|
|
118
|
+
for (const validation of result.validations) {
|
|
119
|
+
if (validation.warnings && validation.warnings.length > 0) {
|
|
120
|
+
for (const warning of validation.warnings) {
|
|
121
|
+
const key = warning.substring(0, 100);
|
|
122
|
+
if (!issueMap.has(key)) {
|
|
123
|
+
issueMap.set(key, {
|
|
124
|
+
issue: key,
|
|
125
|
+
count: 0,
|
|
126
|
+
severity: 'warning',
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
const issue = issueMap.get(key);
|
|
130
|
+
issue.count++;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return Array.from(issueMap.values())
|
|
137
|
+
.sort((a, b) => b.count - a.count)
|
|
138
|
+
.slice(0, 10);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Calculate performance metrics
|
|
142
|
+
*/
|
|
143
|
+
calculatePerformanceMetrics(results) {
|
|
144
|
+
if (results.length === 0) {
|
|
145
|
+
return {
|
|
146
|
+
averageRenderTime: 0,
|
|
147
|
+
averageDeliveryTime: 0,
|
|
148
|
+
averageSize: 0,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
const totalDuration = results.reduce((sum, r) => sum + r.duration, 0);
|
|
152
|
+
const averageRenderTime = totalDuration / results.length;
|
|
153
|
+
// Mock delivery time and size calculations
|
|
154
|
+
const averageDeliveryTime = averageRenderTime * 1.5;
|
|
155
|
+
const averageSize = 50000; // Mock value
|
|
156
|
+
return {
|
|
157
|
+
averageRenderTime,
|
|
158
|
+
averageDeliveryTime,
|
|
159
|
+
averageSize,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Get test history
|
|
164
|
+
*/
|
|
165
|
+
getTestHistory() {
|
|
166
|
+
return [...this.testHistory];
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Clear analytics history
|
|
170
|
+
*/
|
|
171
|
+
clearHistory() {
|
|
172
|
+
this.testHistory = [];
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Export analytics data as JSON
|
|
176
|
+
*/
|
|
177
|
+
exportAsJSON(period = 'last_30_days') {
|
|
178
|
+
const analytics = this.generateAnalytics(period);
|
|
179
|
+
return JSON.stringify(analytics, null, 2);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Export analytics data as CSV
|
|
183
|
+
*/
|
|
184
|
+
exportAsCSV(period = 'last_30_days') {
|
|
185
|
+
const analytics = this.generateAnalytics(period);
|
|
186
|
+
const lines = [];
|
|
187
|
+
// Header
|
|
188
|
+
lines.push('Metric,Value');
|
|
189
|
+
// Summary metrics
|
|
190
|
+
lines.push(`Test Count,${analytics.testCount}`);
|
|
191
|
+
lines.push(`Success Rate,${analytics.successRate.toFixed(2)}%`);
|
|
192
|
+
lines.push(`Average Render Time,${analytics.performanceMetrics.averageRenderTime.toFixed(2)}ms`);
|
|
193
|
+
lines.push(`Average Delivery Time,${analytics.performanceMetrics.averageDeliveryTime.toFixed(2)}ms`);
|
|
194
|
+
lines.push(`Average Size,${analytics.performanceMetrics.averageSize} bytes`);
|
|
195
|
+
// Trends
|
|
196
|
+
lines.push('');
|
|
197
|
+
lines.push('Date,Test Count,Success Rate,Average Score');
|
|
198
|
+
for (const trend of analytics.trends) {
|
|
199
|
+
lines.push(`${trend.date},${trend.testCount},${trend.successRate.toFixed(2)}%,${trend.averageScore.toFixed(2)}`);
|
|
200
|
+
}
|
|
201
|
+
// Top Issues
|
|
202
|
+
lines.push('');
|
|
203
|
+
lines.push('Issue,Count,Severity');
|
|
204
|
+
for (const issue of analytics.topIssues) {
|
|
205
|
+
lines.push(`"${issue.issue}",${issue.count},${issue.severity}`);
|
|
206
|
+
}
|
|
207
|
+
return lines.join('\n');
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
exports.EmailTestAnalytics = EmailTestAnalytics;
|
|
211
|
+
//# sourceMappingURL=analytics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.js","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { EmailData, Recommendation } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Best practices validator for email testing
|
|
4
|
+
*/
|
|
5
|
+
export declare class BestPracticesValidator {
|
|
6
|
+
/**
|
|
7
|
+
* Validate email against best practices
|
|
8
|
+
*/
|
|
9
|
+
static validateEmail(email: EmailData): {
|
|
10
|
+
passed: boolean;
|
|
11
|
+
score: number;
|
|
12
|
+
recommendations: Recommendation[];
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Get recommended test coverage for email type
|
|
16
|
+
*/
|
|
17
|
+
static getRecommendedCoverage(emailType: string): {
|
|
18
|
+
validators: string[];
|
|
19
|
+
description: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Generate compliance checklist
|
|
23
|
+
*/
|
|
24
|
+
static getComplianceChecklist(region: 'US' | 'EU' | 'GLOBAL'): string[];
|
|
25
|
+
/**
|
|
26
|
+
* Get accessibility guidelines
|
|
27
|
+
*/
|
|
28
|
+
static getAccessibilityGuidelines(): Recommendation[];
|
|
29
|
+
/**
|
|
30
|
+
* Get performance optimization tips
|
|
31
|
+
*/
|
|
32
|
+
static getPerformanceOptimizationTips(): Recommendation[];
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=best-practices.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"best-practices.d.ts","sourceRoot":"","sources":["../src/best-practices.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzD;;GAEG;AACH,qBAAa,sBAAsB;IACjC;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG;QACtC,MAAM,EAAE,OAAO,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,eAAe,EAAE,cAAc,EAAE,CAAC;KACnC;IA4HD;;OAEG;IACH,MAAM,CAAC,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG;QAChD,UAAU,EAAE,MAAM,EAAE,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;KACrB;IA8BD;;OAEG;IACH,MAAM,CAAC,sBAAsB,CAAC,MAAM,EAAE,IAAI,GAAG,IAAI,GAAG,QAAQ,GAAG,MAAM,EAAE;IA4BvE;;OAEG;IACH,MAAM,CAAC,0BAA0B,IAAI,cAAc,EAAE;IAwCrD;;OAEG;IACH,MAAM,CAAC,8BAA8B,IAAI,cAAc,EAAE;CAuC1D"}
|