@bernierllc/email-template-service 1.0.0 → 1.0.1
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bernierllc/email-template-service",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Email template management service with provider synchronization and variable context validation",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -9,16 +9,6 @@
|
|
|
9
9
|
"README.md",
|
|
10
10
|
"LICENSE"
|
|
11
11
|
],
|
|
12
|
-
"scripts": {
|
|
13
|
-
"test": "jest --watch",
|
|
14
|
-
"test:run": "jest",
|
|
15
|
-
"test:coverage": "jest --coverage",
|
|
16
|
-
"build": "tsc",
|
|
17
|
-
"dev": "tsc --watch",
|
|
18
|
-
"lint": "eslint src/**/*.ts --max-warnings=0",
|
|
19
|
-
"format": "prettier --write src/**/*.ts",
|
|
20
|
-
"clean": "rm -rf dist coverage"
|
|
21
|
-
},
|
|
22
12
|
"keywords": [
|
|
23
13
|
"email",
|
|
24
14
|
"template",
|
|
@@ -36,10 +26,10 @@
|
|
|
36
26
|
"url": "https://github.com/bernierllc/tools.git"
|
|
37
27
|
},
|
|
38
28
|
"dependencies": {
|
|
39
|
-
"@bernierllc/template-variable-registry": "
|
|
40
|
-
"@bernierllc/template-engine": "
|
|
41
|
-
"@bernierllc/email-sender": "
|
|
42
|
-
"@bernierllc/logger": "
|
|
29
|
+
"@bernierllc/template-variable-registry": "1.0.1",
|
|
30
|
+
"@bernierllc/template-engine": "0.2.1",
|
|
31
|
+
"@bernierllc/email-sender": "3.0.4",
|
|
32
|
+
"@bernierllc/logger": "1.0.3"
|
|
43
33
|
},
|
|
44
34
|
"devDependencies": {
|
|
45
35
|
"@types/node": "^20.0.0",
|
|
@@ -51,5 +41,19 @@
|
|
|
51
41
|
"ts-jest": "^29.4.0",
|
|
52
42
|
"eslint": "^8.0.0",
|
|
53
43
|
"prettier": "^3.0.0"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public",
|
|
47
|
+
"registry": "https://registry.npmjs.org/"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"test": "jest --watch",
|
|
51
|
+
"test:run": "jest",
|
|
52
|
+
"test:coverage": "jest --coverage",
|
|
53
|
+
"build": "tsc",
|
|
54
|
+
"dev": "tsc --watch",
|
|
55
|
+
"lint": "eslint src/**/*.ts --max-warnings=0",
|
|
56
|
+
"format": "prettier --write src/**/*.ts",
|
|
57
|
+
"clean": "rm -rf dist coverage"
|
|
54
58
|
}
|
|
55
|
-
}
|
|
59
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"email-template-service.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/email-template-service.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,583 +0,0 @@
|
|
|
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
|
-
/* eslint-disable @typescript-eslint/require-await */
|
|
11
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
12
|
-
const index_1 = require("../index");
|
|
13
|
-
// Mock template engine
|
|
14
|
-
class MockTemplateEngine {
|
|
15
|
-
async extractVariables(content) {
|
|
16
|
-
const matches = content.match(/\{\{([^}]+)\}\}/g) || [];
|
|
17
|
-
return matches.map((match, index) => ({
|
|
18
|
-
name: match.replace(/[{}]/g, '').trim(),
|
|
19
|
-
path: match.replace(/[{}]/g, '').trim(),
|
|
20
|
-
type: 'string',
|
|
21
|
-
required: true,
|
|
22
|
-
usageCount: 1
|
|
23
|
-
}));
|
|
24
|
-
}
|
|
25
|
-
async validateTemplate(content) {
|
|
26
|
-
const errors = [];
|
|
27
|
-
if (content.includes('<script>')) {
|
|
28
|
-
errors.push('Script tags not allowed');
|
|
29
|
-
}
|
|
30
|
-
if (content.includes('{{undefined}}')) {
|
|
31
|
-
errors.push('Undefined variable referenced');
|
|
32
|
-
}
|
|
33
|
-
return {
|
|
34
|
-
isValid: errors.length === 0,
|
|
35
|
-
errors,
|
|
36
|
-
warnings: []
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
async buildCompleteTemplate(base, content, variables) {
|
|
40
|
-
let result = base.headerHtml + content + base.footerHtml;
|
|
41
|
-
if (variables) {
|
|
42
|
-
for (const [key, value] of Object.entries(variables)) {
|
|
43
|
-
result = result.replace(new RegExp(`\\{\\{${key}\\}\\}`, 'g'), String(value));
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return result;
|
|
47
|
-
}
|
|
48
|
-
async generateTextVersion(html) {
|
|
49
|
-
return html.replace(/<[^>]*>/g, '').trim();
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
// Mock variable registry
|
|
53
|
-
class MockVariableRegistry {
|
|
54
|
-
constructor() {
|
|
55
|
-
this.contexts = new Map();
|
|
56
|
-
}
|
|
57
|
-
async registerContext(name, context) {
|
|
58
|
-
this.contexts.set(name, context);
|
|
59
|
-
}
|
|
60
|
-
async validateTemplate(contextName, content) {
|
|
61
|
-
const context = this.contexts.get(contextName);
|
|
62
|
-
if (!context) {
|
|
63
|
-
return {
|
|
64
|
-
isValid: false,
|
|
65
|
-
errors: [`Context not found: ${contextName}`],
|
|
66
|
-
warnings: []
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
const usedVars = (content.match(/\{\{([^}]+)\}\}/g) || [])
|
|
70
|
-
.map(v => v.replace(/[{}]/g, '').trim());
|
|
71
|
-
const contextVars = Object.keys(context.variables);
|
|
72
|
-
const undefinedVars = usedVars.filter(v => !contextVars.includes(v));
|
|
73
|
-
return {
|
|
74
|
-
isValid: undefinedVars.length === 0,
|
|
75
|
-
errors: undefinedVars.map(v => `Undefined variable: ${v}`),
|
|
76
|
-
warnings: [],
|
|
77
|
-
undefinedVariables: undefinedVars
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
async getSuggestions(contextName, prefix) {
|
|
81
|
-
const context = this.contexts.get(contextName);
|
|
82
|
-
if (!context) {
|
|
83
|
-
return [];
|
|
84
|
-
}
|
|
85
|
-
return Object.entries(context.variables)
|
|
86
|
-
.filter(([name]) => !prefix || name.startsWith(prefix))
|
|
87
|
-
.map(([name, config]) => ({
|
|
88
|
-
name,
|
|
89
|
-
path: name,
|
|
90
|
-
type: config.type,
|
|
91
|
-
description: config.description,
|
|
92
|
-
required: config.required || false
|
|
93
|
-
}));
|
|
94
|
-
}
|
|
95
|
-
async getContext(name) {
|
|
96
|
-
return this.contexts.get(name) || null;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
describe('EmailTemplateService', () => {
|
|
100
|
-
let service;
|
|
101
|
-
let database;
|
|
102
|
-
let templateEngine;
|
|
103
|
-
let variableRegistry;
|
|
104
|
-
let mockProvider;
|
|
105
|
-
beforeEach(async () => {
|
|
106
|
-
database = new index_1.InMemoryDatabaseAdapter();
|
|
107
|
-
templateEngine = new MockTemplateEngine();
|
|
108
|
-
variableRegistry = new MockVariableRegistry();
|
|
109
|
-
mockProvider = new index_1.MockProviderPlugin();
|
|
110
|
-
await mockProvider.initialize({ apiKey: 'test' });
|
|
111
|
-
service = new index_1.EmailTemplateService({
|
|
112
|
-
database,
|
|
113
|
-
templateEngine,
|
|
114
|
-
variableRegistry,
|
|
115
|
-
providers: [mockProvider],
|
|
116
|
-
syncConfig: {
|
|
117
|
-
enabled: true,
|
|
118
|
-
providers: {
|
|
119
|
-
mock: {
|
|
120
|
-
enabled: true,
|
|
121
|
-
strategy: 'manual',
|
|
122
|
-
direction: 'bidirectional'
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
defaultStrategy: 'manual',
|
|
126
|
-
conflictResolution: 'local_wins'
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
|
-
afterEach(() => {
|
|
131
|
-
database.clear();
|
|
132
|
-
mockProvider.clear();
|
|
133
|
-
});
|
|
134
|
-
describe('Template CRUD Operations', () => {
|
|
135
|
-
describe('createTemplate', () => {
|
|
136
|
-
it('should create a new template successfully', async () => {
|
|
137
|
-
const template = await service.createTemplate({
|
|
138
|
-
name: 'Welcome Email',
|
|
139
|
-
subject: 'Welcome to our platform',
|
|
140
|
-
htmlContent: '<html><body>Hello {{name}}!</body></html>',
|
|
141
|
-
textContent: 'Hello {{name}}!',
|
|
142
|
-
tags: ['welcome', 'onboarding'],
|
|
143
|
-
createdBy: 'test-user'
|
|
144
|
-
});
|
|
145
|
-
expect(template.id).toBeDefined();
|
|
146
|
-
expect(template.name).toBe('Welcome Email');
|
|
147
|
-
expect(template.subject).toBe('Welcome to our platform');
|
|
148
|
-
expect(template.version).toBe('1.0.0');
|
|
149
|
-
expect(template.isActive).toBe(true);
|
|
150
|
-
expect(template.variables).toHaveLength(1);
|
|
151
|
-
expect(template.variables[0].name).toBe('name');
|
|
152
|
-
});
|
|
153
|
-
it('should extract variables from template content', async () => {
|
|
154
|
-
const template = await service.createTemplate({
|
|
155
|
-
name: 'Test Template',
|
|
156
|
-
subject: 'Hello {{firstName}} {{lastName}}',
|
|
157
|
-
htmlContent: '<html><body>Welcome {{firstName}}! Your email is {{email}}.</body></html>',
|
|
158
|
-
createdBy: 'test-user'
|
|
159
|
-
});
|
|
160
|
-
expect(template.variables.length).toBeGreaterThan(0);
|
|
161
|
-
const varNames = template.variables.map(v => v.name);
|
|
162
|
-
expect(varNames).toContain('firstName');
|
|
163
|
-
});
|
|
164
|
-
it('should fail validation for invalid template', async () => {
|
|
165
|
-
await expect(service.createTemplate({
|
|
166
|
-
name: 'Invalid Template',
|
|
167
|
-
subject: 'Test',
|
|
168
|
-
htmlContent: '<html><body><script>alert("xss")</script></body></html>',
|
|
169
|
-
createdBy: 'test-user'
|
|
170
|
-
})).rejects.toThrow(index_1.TemplateValidationError);
|
|
171
|
-
});
|
|
172
|
-
it('should fail validation for empty template name', async () => {
|
|
173
|
-
await expect(service.createTemplate({
|
|
174
|
-
name: '',
|
|
175
|
-
subject: 'Test',
|
|
176
|
-
htmlContent: '<html><body>Test</body></html>',
|
|
177
|
-
createdBy: 'test-user'
|
|
178
|
-
})).rejects.toThrow(index_1.TemplateValidationError);
|
|
179
|
-
});
|
|
180
|
-
it('should fail validation for empty subject', async () => {
|
|
181
|
-
await expect(service.createTemplate({
|
|
182
|
-
name: 'Test',
|
|
183
|
-
subject: '',
|
|
184
|
-
htmlContent: '<html><body>Test</body></html>',
|
|
185
|
-
createdBy: 'test-user'
|
|
186
|
-
})).rejects.toThrow(index_1.TemplateValidationError);
|
|
187
|
-
});
|
|
188
|
-
it('should fail validation for empty HTML content', async () => {
|
|
189
|
-
await expect(service.createTemplate({
|
|
190
|
-
name: 'Test',
|
|
191
|
-
subject: 'Test',
|
|
192
|
-
htmlContent: '',
|
|
193
|
-
createdBy: 'test-user'
|
|
194
|
-
})).rejects.toThrow(index_1.TemplateValidationError);
|
|
195
|
-
});
|
|
196
|
-
});
|
|
197
|
-
describe('updateTemplate', () => {
|
|
198
|
-
it('should update template successfully', async () => {
|
|
199
|
-
const template = await service.createTemplate({
|
|
200
|
-
name: 'Original Name',
|
|
201
|
-
subject: 'Original Subject',
|
|
202
|
-
htmlContent: '<html><body>Original</body></html>',
|
|
203
|
-
createdBy: 'test-user'
|
|
204
|
-
});
|
|
205
|
-
const updated = await service.updateTemplate(template.id, {
|
|
206
|
-
name: 'Updated Name',
|
|
207
|
-
subject: 'Updated Subject',
|
|
208
|
-
lastModifiedBy: 'test-user'
|
|
209
|
-
});
|
|
210
|
-
expect(updated.name).toBe('Updated Name');
|
|
211
|
-
expect(updated.subject).toBe('Updated Subject');
|
|
212
|
-
expect(updated.updatedAt.getTime()).toBeGreaterThan(template.updatedAt.getTime());
|
|
213
|
-
});
|
|
214
|
-
it('should re-extract variables when HTML content changes', async () => {
|
|
215
|
-
const template = await service.createTemplate({
|
|
216
|
-
name: 'Test',
|
|
217
|
-
subject: 'Test',
|
|
218
|
-
htmlContent: '<html><body>Hello {{name}}!</body></html>',
|
|
219
|
-
createdBy: 'test-user'
|
|
220
|
-
});
|
|
221
|
-
const updated = await service.updateTemplate(template.id, {
|
|
222
|
-
htmlContent: '<html><body>Hello {{firstName}} {{lastName}}!</body></html>',
|
|
223
|
-
lastModifiedBy: 'test-user'
|
|
224
|
-
});
|
|
225
|
-
expect(updated.variables.length).toBeGreaterThan(template.variables.length);
|
|
226
|
-
});
|
|
227
|
-
it('should throw error for non-existent template', async () => {
|
|
228
|
-
await expect(service.updateTemplate('non-existent', {
|
|
229
|
-
name: 'Updated'
|
|
230
|
-
})).rejects.toThrow(index_1.TemplateNotFoundError);
|
|
231
|
-
});
|
|
232
|
-
it('should validate updated content', async () => {
|
|
233
|
-
const template = await service.createTemplate({
|
|
234
|
-
name: 'Test',
|
|
235
|
-
subject: 'Test',
|
|
236
|
-
htmlContent: '<html><body>Valid</body></html>',
|
|
237
|
-
createdBy: 'test-user'
|
|
238
|
-
});
|
|
239
|
-
await expect(service.updateTemplate(template.id, {
|
|
240
|
-
htmlContent: '<html><body><script>alert("xss")</script></body></html>'
|
|
241
|
-
})).rejects.toThrow(index_1.TemplateValidationError);
|
|
242
|
-
});
|
|
243
|
-
});
|
|
244
|
-
describe('deleteTemplate', () => {
|
|
245
|
-
it('should delete template successfully', async () => {
|
|
246
|
-
const template = await service.createTemplate({
|
|
247
|
-
name: 'To Delete',
|
|
248
|
-
subject: 'Test',
|
|
249
|
-
htmlContent: '<html><body>Test</body></html>',
|
|
250
|
-
createdBy: 'test-user'
|
|
251
|
-
});
|
|
252
|
-
await service.deleteTemplate(template.id);
|
|
253
|
-
const retrieved = await service.getTemplate(template.id);
|
|
254
|
-
expect(retrieved).toBeNull();
|
|
255
|
-
});
|
|
256
|
-
it('should throw error for non-existent template', async () => {
|
|
257
|
-
await expect(service.deleteTemplate('non-existent')).rejects.toThrow(index_1.TemplateNotFoundError);
|
|
258
|
-
});
|
|
259
|
-
it('should delete from providers when synced', async () => {
|
|
260
|
-
const template = await service.createTemplate({
|
|
261
|
-
name: 'Test',
|
|
262
|
-
subject: 'Test',
|
|
263
|
-
htmlContent: '<html><body>Test</body></html>',
|
|
264
|
-
createdBy: 'test-user'
|
|
265
|
-
});
|
|
266
|
-
await service.syncToProvider(template.id, 'mock');
|
|
267
|
-
await service.deleteTemplate(template.id);
|
|
268
|
-
// Template should be deleted from provider
|
|
269
|
-
const providerTemplates = await mockProvider.listTemplates();
|
|
270
|
-
expect(providerTemplates).toHaveLength(0);
|
|
271
|
-
});
|
|
272
|
-
});
|
|
273
|
-
describe('getTemplate', () => {
|
|
274
|
-
it('should retrieve existing template', async () => {
|
|
275
|
-
const created = await service.createTemplate({
|
|
276
|
-
name: 'Test',
|
|
277
|
-
subject: 'Test',
|
|
278
|
-
htmlContent: '<html><body>Test</body></html>',
|
|
279
|
-
createdBy: 'test-user'
|
|
280
|
-
});
|
|
281
|
-
const retrieved = await service.getTemplate(created.id);
|
|
282
|
-
expect(retrieved).toBeDefined();
|
|
283
|
-
expect(retrieved?.id).toBe(created.id);
|
|
284
|
-
expect(retrieved?.name).toBe(created.name);
|
|
285
|
-
});
|
|
286
|
-
it('should return null for non-existent template', async () => {
|
|
287
|
-
const retrieved = await service.getTemplate('non-existent');
|
|
288
|
-
expect(retrieved).toBeNull();
|
|
289
|
-
});
|
|
290
|
-
});
|
|
291
|
-
describe('listTemplates', () => {
|
|
292
|
-
beforeEach(async () => {
|
|
293
|
-
await service.createTemplate({
|
|
294
|
-
name: 'Template 1',
|
|
295
|
-
subject: 'Test 1',
|
|
296
|
-
htmlContent: '<html><body>Test 1</body></html>',
|
|
297
|
-
category: 'marketing',
|
|
298
|
-
tags: ['promo'],
|
|
299
|
-
createdBy: 'test-user'
|
|
300
|
-
});
|
|
301
|
-
await service.createTemplate({
|
|
302
|
-
name: 'Template 2',
|
|
303
|
-
subject: 'Test 2',
|
|
304
|
-
htmlContent: '<html><body>Test 2</body></html>',
|
|
305
|
-
category: 'transactional',
|
|
306
|
-
tags: ['receipt'],
|
|
307
|
-
createdBy: 'test-user'
|
|
308
|
-
});
|
|
309
|
-
await service.createTemplate({
|
|
310
|
-
name: 'Template 3',
|
|
311
|
-
subject: 'Test 3',
|
|
312
|
-
htmlContent: '<html><body>Test 3</body></html>',
|
|
313
|
-
category: 'marketing',
|
|
314
|
-
tags: ['newsletter'],
|
|
315
|
-
createdBy: 'test-user'
|
|
316
|
-
});
|
|
317
|
-
});
|
|
318
|
-
it('should list all templates with default options', async () => {
|
|
319
|
-
const result = await service.listTemplates();
|
|
320
|
-
expect(result.items).toHaveLength(3);
|
|
321
|
-
expect(result.total).toBe(3);
|
|
322
|
-
});
|
|
323
|
-
it('should filter by category', async () => {
|
|
324
|
-
const result = await service.listTemplates({ category: 'marketing' });
|
|
325
|
-
expect(result.items).toHaveLength(2);
|
|
326
|
-
expect(result.items.every(t => t.category === 'marketing')).toBe(true);
|
|
327
|
-
});
|
|
328
|
-
it('should filter by tags', async () => {
|
|
329
|
-
const result = await service.listTemplates({ tags: ['promo'] });
|
|
330
|
-
expect(result.items).toHaveLength(1);
|
|
331
|
-
expect(result.items[0].tags).toContain('promo');
|
|
332
|
-
});
|
|
333
|
-
it('should paginate results', async () => {
|
|
334
|
-
const result = await service.listTemplates({ page: 1, limit: 2 });
|
|
335
|
-
expect(result.items).toHaveLength(2);
|
|
336
|
-
expect(result.page).toBe(1);
|
|
337
|
-
expect(result.limit).toBe(2);
|
|
338
|
-
expect(result.hasMore).toBe(true);
|
|
339
|
-
});
|
|
340
|
-
it('should search by name', async () => {
|
|
341
|
-
const result = await service.listTemplates({ search: 'Template 1' });
|
|
342
|
-
expect(result.items).toHaveLength(1);
|
|
343
|
-
expect(result.items[0].name).toBe('Template 1');
|
|
344
|
-
});
|
|
345
|
-
});
|
|
346
|
-
});
|
|
347
|
-
describe('Provider Synchronization', () => {
|
|
348
|
-
describe('syncToProvider', () => {
|
|
349
|
-
it('should create template in provider on first sync', async () => {
|
|
350
|
-
const template = await service.createTemplate({
|
|
351
|
-
name: 'Test',
|
|
352
|
-
subject: 'Test',
|
|
353
|
-
htmlContent: '<html><body>Test</body></html>',
|
|
354
|
-
createdBy: 'test-user'
|
|
355
|
-
});
|
|
356
|
-
const result = await service.syncToProvider(template.id, 'mock');
|
|
357
|
-
expect(result.success).toBe(true);
|
|
358
|
-
expect(result.action).toBe('created');
|
|
359
|
-
expect(result.providerTemplateId).toBeDefined();
|
|
360
|
-
const providerTemplates = await mockProvider.listTemplates();
|
|
361
|
-
expect(providerTemplates).toHaveLength(1);
|
|
362
|
-
});
|
|
363
|
-
it('should update template in provider on subsequent sync', async () => {
|
|
364
|
-
const template = await service.createTemplate({
|
|
365
|
-
name: 'Test',
|
|
366
|
-
subject: 'Test',
|
|
367
|
-
htmlContent: '<html><body>Test</body></html>',
|
|
368
|
-
createdBy: 'test-user'
|
|
369
|
-
});
|
|
370
|
-
await service.syncToProvider(template.id, 'mock');
|
|
371
|
-
await service.updateTemplate(template.id, {
|
|
372
|
-
name: 'Updated'
|
|
373
|
-
});
|
|
374
|
-
const result = await service.syncToProvider(template.id, 'mock');
|
|
375
|
-
expect(result.success).toBe(true);
|
|
376
|
-
expect(result.action).toBe('updated');
|
|
377
|
-
});
|
|
378
|
-
it('should throw error for non-existent template', async () => {
|
|
379
|
-
await expect(service.syncToProvider('non-existent', 'mock')).rejects.toThrow(index_1.TemplateNotFoundError);
|
|
380
|
-
});
|
|
381
|
-
it('should throw error for non-existent provider', async () => {
|
|
382
|
-
const template = await service.createTemplate({
|
|
383
|
-
name: 'Test',
|
|
384
|
-
subject: 'Test',
|
|
385
|
-
htmlContent: '<html><body>Test</body></html>',
|
|
386
|
-
createdBy: 'test-user'
|
|
387
|
-
});
|
|
388
|
-
await expect(service.syncToProvider(template.id, 'non-existent')).rejects.toThrow(index_1.ProviderNotFoundError);
|
|
389
|
-
});
|
|
390
|
-
});
|
|
391
|
-
describe('syncFromProvider', () => {
|
|
392
|
-
it('should create local template from provider template', async () => {
|
|
393
|
-
const providerTemplate = await mockProvider.createTemplate({
|
|
394
|
-
id: 'local-temp',
|
|
395
|
-
name: 'Provider Template',
|
|
396
|
-
subject: 'Test',
|
|
397
|
-
htmlContent: '<html><body>Test</body></html>',
|
|
398
|
-
textContent: '',
|
|
399
|
-
tags: [],
|
|
400
|
-
version: '1.0.0',
|
|
401
|
-
isActive: true,
|
|
402
|
-
context: undefined,
|
|
403
|
-
variables: [],
|
|
404
|
-
requiredVariables: [],
|
|
405
|
-
providerTemplateIds: {},
|
|
406
|
-
lastSyncedAt: {},
|
|
407
|
-
syncStatus: {},
|
|
408
|
-
createdAt: new Date(),
|
|
409
|
-
updatedAt: new Date(),
|
|
410
|
-
createdBy: 'system',
|
|
411
|
-
lastModifiedBy: 'system'
|
|
412
|
-
});
|
|
413
|
-
const template = await service.syncFromProvider(providerTemplate, 'mock');
|
|
414
|
-
expect(template.name).toBe('Provider Template');
|
|
415
|
-
expect(template.providerTemplateIds['mock']).toBe(providerTemplate);
|
|
416
|
-
});
|
|
417
|
-
it('should throw error for non-existent provider', async () => {
|
|
418
|
-
await expect(service.syncFromProvider('template-id', 'non-existent')).rejects.toThrow(index_1.ProviderNotFoundError);
|
|
419
|
-
});
|
|
420
|
-
});
|
|
421
|
-
describe('syncAllTemplates', () => {
|
|
422
|
-
it('should sync all templates to provider', async () => {
|
|
423
|
-
await service.createTemplate({
|
|
424
|
-
name: 'Template 1',
|
|
425
|
-
subject: 'Test 1',
|
|
426
|
-
htmlContent: '<html><body>Test 1</body></html>',
|
|
427
|
-
createdBy: 'test-user'
|
|
428
|
-
});
|
|
429
|
-
await service.createTemplate({
|
|
430
|
-
name: 'Template 2',
|
|
431
|
-
subject: 'Test 2',
|
|
432
|
-
htmlContent: '<html><body>Test 2</body></html>',
|
|
433
|
-
createdBy: 'test-user'
|
|
434
|
-
});
|
|
435
|
-
const result = await service.syncAllTemplates('mock');
|
|
436
|
-
expect(result.total).toBe(2);
|
|
437
|
-
expect(result.successful).toBe(2);
|
|
438
|
-
expect(result.failed).toBe(0);
|
|
439
|
-
const providerTemplates = await mockProvider.listTemplates();
|
|
440
|
-
expect(providerTemplates).toHaveLength(2);
|
|
441
|
-
});
|
|
442
|
-
it('should report errors for failed syncs', async () => {
|
|
443
|
-
await service.createTemplate({
|
|
444
|
-
name: 'Valid Template',
|
|
445
|
-
subject: 'Test',
|
|
446
|
-
htmlContent: '<html><body>Test</body></html>',
|
|
447
|
-
createdBy: 'test-user'
|
|
448
|
-
});
|
|
449
|
-
const result = await service.syncAllTemplates('mock');
|
|
450
|
-
// All should succeed with mock provider
|
|
451
|
-
expect(result.successful).toBeGreaterThan(0);
|
|
452
|
-
});
|
|
453
|
-
});
|
|
454
|
-
});
|
|
455
|
-
describe('Base Template Management', () => {
|
|
456
|
-
describe('createBaseTemplate', () => {
|
|
457
|
-
it('should create base template successfully', async () => {
|
|
458
|
-
const baseTemplate = await service.createBaseTemplate({
|
|
459
|
-
name: 'Corporate Template',
|
|
460
|
-
headerHtml: '<header>Header</header>',
|
|
461
|
-
footerHtml: '<footer>Footer</footer>',
|
|
462
|
-
theme: 'corporate'
|
|
463
|
-
});
|
|
464
|
-
expect(baseTemplate.id).toBeDefined();
|
|
465
|
-
expect(baseTemplate.name).toBe('Corporate Template');
|
|
466
|
-
expect(baseTemplate.theme).toBe('corporate');
|
|
467
|
-
expect(baseTemplate.version).toBe('1.0.0');
|
|
468
|
-
});
|
|
469
|
-
it('should fail validation for empty header', async () => {
|
|
470
|
-
await expect(service.createBaseTemplate({
|
|
471
|
-
name: 'Invalid',
|
|
472
|
-
headerHtml: '',
|
|
473
|
-
footerHtml: '<footer>Footer</footer>'
|
|
474
|
-
})).rejects.toThrow();
|
|
475
|
-
});
|
|
476
|
-
it('should fail validation for empty footer', async () => {
|
|
477
|
-
await expect(service.createBaseTemplate({
|
|
478
|
-
name: 'Invalid',
|
|
479
|
-
headerHtml: '<header>Header</header>',
|
|
480
|
-
footerHtml: ''
|
|
481
|
-
})).rejects.toThrow();
|
|
482
|
-
});
|
|
483
|
-
});
|
|
484
|
-
describe('buildTemplate', () => {
|
|
485
|
-
it('should build complete template from base and content', async () => {
|
|
486
|
-
const baseTemplate = await service.createBaseTemplate({
|
|
487
|
-
name: 'Base',
|
|
488
|
-
headerHtml: '<header>Header {{companyName}}</header>',
|
|
489
|
-
footerHtml: '<footer>Footer</footer>'
|
|
490
|
-
});
|
|
491
|
-
const built = await service.buildTemplate(baseTemplate.id, '<main>Content {{userName}}</main>', { companyName: 'ACME Corp', userName: 'John' });
|
|
492
|
-
expect(built.html).toContain('Header ACME Corp');
|
|
493
|
-
expect(built.html).toContain('Content John');
|
|
494
|
-
expect(built.html).toContain('Footer');
|
|
495
|
-
expect(built.text).toBeDefined();
|
|
496
|
-
expect(built.variables.length).toBeGreaterThan(0);
|
|
497
|
-
});
|
|
498
|
-
it('should throw error for non-existent base template', async () => {
|
|
499
|
-
await expect(service.buildTemplate('non-existent', '<main>Content</main>')).rejects.toThrow(index_1.BaseTemplateNotFoundError);
|
|
500
|
-
});
|
|
501
|
-
});
|
|
502
|
-
});
|
|
503
|
-
describe('Variable Context Integration', () => {
|
|
504
|
-
describe('registerContext', () => {
|
|
505
|
-
it('should register variable context successfully', async () => {
|
|
506
|
-
await service.registerContext('user', {
|
|
507
|
-
description: 'User context',
|
|
508
|
-
variables: {
|
|
509
|
-
firstName: { type: 'string', required: true },
|
|
510
|
-
lastName: { type: 'string', required: true },
|
|
511
|
-
email: { type: 'string', required: true }
|
|
512
|
-
}
|
|
513
|
-
});
|
|
514
|
-
const suggestions = await service.getVariableSuggestions('user');
|
|
515
|
-
expect(suggestions).toHaveLength(3);
|
|
516
|
-
});
|
|
517
|
-
});
|
|
518
|
-
describe('validateTemplate', () => {
|
|
519
|
-
beforeEach(async () => {
|
|
520
|
-
await service.registerContext('user', {
|
|
521
|
-
variables: {
|
|
522
|
-
firstName: { type: 'string', required: true },
|
|
523
|
-
lastName: { type: 'string', required: true }
|
|
524
|
-
}
|
|
525
|
-
});
|
|
526
|
-
});
|
|
527
|
-
it('should validate template against context', async () => {
|
|
528
|
-
const template = await service.createTemplate({
|
|
529
|
-
name: 'Test',
|
|
530
|
-
subject: 'Hello {{firstName}}',
|
|
531
|
-
htmlContent: '<html><body>Hello {{firstName}} {{lastName}}</body></html>',
|
|
532
|
-
context: 'user',
|
|
533
|
-
createdBy: 'test-user'
|
|
534
|
-
});
|
|
535
|
-
const validation = await service.validateTemplate(template.id);
|
|
536
|
-
expect(validation.isValid).toBe(true);
|
|
537
|
-
});
|
|
538
|
-
it('should detect undefined variables', async () => {
|
|
539
|
-
const template = await service.createTemplate({
|
|
540
|
-
name: 'Test',
|
|
541
|
-
subject: 'Test',
|
|
542
|
-
htmlContent: '<html><body>Hello {{undefinedVar}}</body></html>',
|
|
543
|
-
context: 'user',
|
|
544
|
-
createdBy: 'test-user'
|
|
545
|
-
});
|
|
546
|
-
const validation = await service.validateTemplate(template.id);
|
|
547
|
-
expect(validation.isValid).toBe(false);
|
|
548
|
-
expect(validation.undefinedVariables).toContain('undefinedVar');
|
|
549
|
-
});
|
|
550
|
-
it('should return valid for templates without context', async () => {
|
|
551
|
-
const template = await service.createTemplate({
|
|
552
|
-
name: 'Test',
|
|
553
|
-
subject: 'Test',
|
|
554
|
-
htmlContent: '<html><body>Test</body></html>',
|
|
555
|
-
createdBy: 'test-user'
|
|
556
|
-
});
|
|
557
|
-
const validation = await service.validateTemplate(template.id);
|
|
558
|
-
expect(validation.isValid).toBe(true);
|
|
559
|
-
});
|
|
560
|
-
});
|
|
561
|
-
describe('getVariableSuggestions', () => {
|
|
562
|
-
beforeEach(async () => {
|
|
563
|
-
await service.registerContext('user', {
|
|
564
|
-
variables: {
|
|
565
|
-
firstName: { type: 'string', description: 'User first name' },
|
|
566
|
-
lastName: { type: 'string', description: 'User last name' },
|
|
567
|
-
email: { type: 'string', description: 'User email address' }
|
|
568
|
-
}
|
|
569
|
-
});
|
|
570
|
-
});
|
|
571
|
-
it('should return all suggestions without prefix', async () => {
|
|
572
|
-
const suggestions = await service.getVariableSuggestions('user');
|
|
573
|
-
expect(suggestions).toHaveLength(3);
|
|
574
|
-
});
|
|
575
|
-
it('should filter suggestions by prefix', async () => {
|
|
576
|
-
const suggestions = await service.getVariableSuggestions('user', 'first');
|
|
577
|
-
expect(suggestions).toHaveLength(1);
|
|
578
|
-
expect(suggestions[0].name).toBe('firstName');
|
|
579
|
-
});
|
|
580
|
-
});
|
|
581
|
-
});
|
|
582
|
-
});
|
|
583
|
-
//# sourceMappingURL=email-template-service.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"email-template-service.test.js","sourceRoot":"","sources":["../../src/__tests__/email-template-service.test.ts"],"names":[],"mappings":"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"}
|