@flusys/nestjs-email 6.0.2 → 6.1.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/cjs/controllers/email-config.controller.spec.js +85 -0
- package/cjs/controllers/email-send.controller.spec.js +139 -0
- package/cjs/controllers/email-template.controller.spec.js +89 -0
- package/cjs/docs/email-swagger.config.spec.js +62 -0
- package/cjs/entities/index.spec.js +18 -0
- package/cjs/modules/email.module.spec.js +142 -0
- package/cjs/providers/email-factory.service.spec.js +242 -0
- package/cjs/providers/email-provider.registry.spec.js +58 -0
- package/cjs/providers/mailgun-provider.spec.js +244 -0
- package/cjs/providers/sendgrid-provider.spec.js +346 -0
- package/cjs/providers/smtp-provider.js +12 -5
- package/cjs/providers/smtp-provider.spec.js +327 -0
- package/cjs/services/email-config.service.spec.js +69 -0
- package/cjs/services/email-datasource.provider.spec.js +135 -0
- package/cjs/services/email-provider-config.service.spec.js +247 -0
- package/cjs/services/email-send.service.spec.js +546 -0
- package/cjs/services/email-template.service.spec.js +257 -0
- package/cjs/utils/email-templates.util.spec.js +61 -0
- package/fesm/controllers/email-config.controller.spec.js +81 -0
- package/fesm/controllers/email-send.controller.spec.js +135 -0
- package/fesm/controllers/email-template.controller.spec.js +85 -0
- package/fesm/docs/email-swagger.config.spec.js +58 -0
- package/fesm/entities/index.spec.js +14 -0
- package/fesm/modules/email.module.spec.js +138 -0
- package/fesm/providers/email-factory.service.spec.js +238 -0
- package/fesm/providers/email-provider.registry.spec.js +54 -0
- package/fesm/providers/mailgun-provider.spec.js +240 -0
- package/fesm/providers/sendgrid-provider.spec.js +342 -0
- package/fesm/providers/smtp-provider.js +12 -5
- package/fesm/providers/smtp-provider.spec.js +282 -0
- package/fesm/services/email-config.service.spec.js +65 -0
- package/fesm/services/email-datasource.provider.spec.js +131 -0
- package/fesm/services/email-provider-config.service.spec.js +243 -0
- package/fesm/services/email-send.service.spec.js +542 -0
- package/fesm/services/email-template.service.spec.js +253 -0
- package/fesm/utils/email-templates.util.spec.js +57 -0
- package/package.json +3 -3
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
const _loggedusermock = require("@test-utils/mocks/logged-user.mock");
|
|
6
|
+
const _emailconfigcontroller = require("./email-config.controller");
|
|
7
|
+
function buildEmailConfig(overrides = {}) {
|
|
8
|
+
return {
|
|
9
|
+
id: 'email-config-1',
|
|
10
|
+
provider: 'smtp',
|
|
11
|
+
isActive: true,
|
|
12
|
+
isDefault: true,
|
|
13
|
+
readOnly: false,
|
|
14
|
+
createdAt: new Date(),
|
|
15
|
+
updatedAt: new Date(),
|
|
16
|
+
...overrides
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
describe('EmailConfigController', ()=>{
|
|
20
|
+
let controller;
|
|
21
|
+
let mockEmailConfigService;
|
|
22
|
+
beforeEach(()=>{
|
|
23
|
+
mockEmailConfigService = {
|
|
24
|
+
insert: jest.fn(),
|
|
25
|
+
findById: jest.fn(),
|
|
26
|
+
getAll: jest.fn(),
|
|
27
|
+
update: jest.fn(),
|
|
28
|
+
delete: jest.fn()
|
|
29
|
+
};
|
|
30
|
+
controller = new _emailconfigcontroller.EmailConfigController(mockEmailConfigService);
|
|
31
|
+
});
|
|
32
|
+
it('wires the injected service onto the generated controller base', ()=>{
|
|
33
|
+
expect(controller.emailConfigService).toBe(mockEmailConfigService);
|
|
34
|
+
expect(controller.service).toBe(mockEmailConfigService);
|
|
35
|
+
});
|
|
36
|
+
describe('insert', ()=>{
|
|
37
|
+
it('creates an email config and returns the mapped response', async ()=>{
|
|
38
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
39
|
+
mockEmailConfigService.insert.mockResolvedValue(buildEmailConfig());
|
|
40
|
+
const result = await controller.insert({
|
|
41
|
+
provider: 'smtp'
|
|
42
|
+
}, user);
|
|
43
|
+
expect(mockEmailConfigService.insert).toHaveBeenCalledWith({
|
|
44
|
+
provider: 'smtp'
|
|
45
|
+
}, user);
|
|
46
|
+
expect(result.success).toBe(true);
|
|
47
|
+
expect(result.data).toEqual(expect.objectContaining({
|
|
48
|
+
id: 'email-config-1'
|
|
49
|
+
}));
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
describe('getAll', ()=>{
|
|
53
|
+
it('paginates email configs and maps the response list', async ()=>{
|
|
54
|
+
mockEmailConfigService.getAll.mockResolvedValue({
|
|
55
|
+
data: [
|
|
56
|
+
buildEmailConfig()
|
|
57
|
+
],
|
|
58
|
+
total: 1
|
|
59
|
+
});
|
|
60
|
+
const result = await controller.getAll({}, (0, _loggedusermock.buildMockUser)(), '');
|
|
61
|
+
expect(mockEmailConfigService.getAll).toHaveBeenCalledWith('', {}, (0, _loggedusermock.buildMockUser)());
|
|
62
|
+
expect(result.data).toHaveLength(1);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
describe('delete', ()=>{
|
|
66
|
+
it('delegates soft-delete to the service', async ()=>{
|
|
67
|
+
mockEmailConfigService.delete.mockResolvedValue({
|
|
68
|
+
count: 1
|
|
69
|
+
});
|
|
70
|
+
const result = await controller.delete({
|
|
71
|
+
id: [
|
|
72
|
+
'email-config-1'
|
|
73
|
+
],
|
|
74
|
+
type: 'delete'
|
|
75
|
+
}, (0, _loggedusermock.buildMockUser)());
|
|
76
|
+
expect(mockEmailConfigService.delete).toHaveBeenCalledWith({
|
|
77
|
+
id: [
|
|
78
|
+
'email-config-1'
|
|
79
|
+
],
|
|
80
|
+
type: 'delete'
|
|
81
|
+
}, (0, _loggedusermock.buildMockUser)());
|
|
82
|
+
expect(result.success).toBe(true);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
});
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
const _testing = require("@nestjs/testing");
|
|
6
|
+
const _loggedusermock = require("@test-utils/mocks/logged-user.mock");
|
|
7
|
+
const _emailsendcontroller = require("./email-send.controller");
|
|
8
|
+
const _services = require("../services");
|
|
9
|
+
describe('EmailSendController', ()=>{
|
|
10
|
+
let controller;
|
|
11
|
+
let mockService;
|
|
12
|
+
beforeEach(async ()=>{
|
|
13
|
+
mockService = {
|
|
14
|
+
sendEmail: jest.fn(),
|
|
15
|
+
sendTemplateEmail: jest.fn(),
|
|
16
|
+
sendTestEmail: jest.fn()
|
|
17
|
+
};
|
|
18
|
+
const module = await _testing.Test.createTestingModule({
|
|
19
|
+
controllers: [
|
|
20
|
+
_emailsendcontroller.EmailSendController
|
|
21
|
+
],
|
|
22
|
+
providers: [
|
|
23
|
+
{
|
|
24
|
+
provide: _services.EmailSendService,
|
|
25
|
+
useValue: mockService
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}).compile();
|
|
29
|
+
controller = module.get(_emailsendcontroller.EmailSendController);
|
|
30
|
+
});
|
|
31
|
+
describe('sendEmail', ()=>{
|
|
32
|
+
it('delegates to the service and returns a success response', async ()=>{
|
|
33
|
+
mockService.sendEmail.mockResolvedValue({
|
|
34
|
+
success: true,
|
|
35
|
+
messageId: 'msg-1'
|
|
36
|
+
});
|
|
37
|
+
const dto = {
|
|
38
|
+
to: 'a@example.com',
|
|
39
|
+
subject: 'Hi',
|
|
40
|
+
html: '<p/>'
|
|
41
|
+
};
|
|
42
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
43
|
+
const result = await controller.sendEmail(dto, user);
|
|
44
|
+
expect(mockService.sendEmail).toHaveBeenCalledWith(dto, user);
|
|
45
|
+
expect(result).toEqual({
|
|
46
|
+
success: true,
|
|
47
|
+
message: 'Email sent successfully',
|
|
48
|
+
messageKey: 'email.send.success',
|
|
49
|
+
data: {
|
|
50
|
+
success: true,
|
|
51
|
+
messageId: 'msg-1',
|
|
52
|
+
error: undefined
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
it('returns a failure response with the FAILED messageKey when the send fails', async ()=>{
|
|
57
|
+
mockService.sendEmail.mockResolvedValue({
|
|
58
|
+
success: false,
|
|
59
|
+
error: 'SMTP down'
|
|
60
|
+
});
|
|
61
|
+
const result = await controller.sendEmail({
|
|
62
|
+
to: 'a@example.com',
|
|
63
|
+
subject: 'Hi',
|
|
64
|
+
html: '<p/>'
|
|
65
|
+
}, (0, _loggedusermock.buildMockUser)());
|
|
66
|
+
expect(result).toEqual({
|
|
67
|
+
success: false,
|
|
68
|
+
message: 'Failed to send email',
|
|
69
|
+
messageKey: 'email.send.failed',
|
|
70
|
+
data: {
|
|
71
|
+
success: false,
|
|
72
|
+
messageId: undefined,
|
|
73
|
+
error: 'SMTP down'
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
describe('sendTemplateEmail', ()=>{
|
|
79
|
+
it('delegates to the service and returns a success response', async ()=>{
|
|
80
|
+
mockService.sendTemplateEmail.mockResolvedValue({
|
|
81
|
+
success: true,
|
|
82
|
+
messageId: 'msg-2'
|
|
83
|
+
});
|
|
84
|
+
const dto = {
|
|
85
|
+
to: 'a@example.com',
|
|
86
|
+
templateSlug: 'welcome'
|
|
87
|
+
};
|
|
88
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
89
|
+
const result = await controller.sendTemplateEmail(dto, user);
|
|
90
|
+
expect(mockService.sendTemplateEmail).toHaveBeenCalledWith(dto, user);
|
|
91
|
+
expect(result.success).toBe(true);
|
|
92
|
+
expect(result.messageKey).toBe('email.send.success');
|
|
93
|
+
expect(result.message).toBe('Template email sent successfully');
|
|
94
|
+
});
|
|
95
|
+
it('returns a failure response when the template send fails', async ()=>{
|
|
96
|
+
mockService.sendTemplateEmail.mockResolvedValue({
|
|
97
|
+
success: false,
|
|
98
|
+
error: 'Template error'
|
|
99
|
+
});
|
|
100
|
+
const result = await controller.sendTemplateEmail({
|
|
101
|
+
to: 'a@example.com',
|
|
102
|
+
templateSlug: 'welcome'
|
|
103
|
+
}, (0, _loggedusermock.buildMockUser)());
|
|
104
|
+
expect(result.success).toBe(false);
|
|
105
|
+
expect(result.messageKey).toBe('email.send.failed');
|
|
106
|
+
expect(result.message).toBe('Failed to send template email');
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
describe('sendTestEmail', ()=>{
|
|
110
|
+
it('delegates to the service with the emailConfigId and recipient from the dto', async ()=>{
|
|
111
|
+
mockService.sendTestEmail.mockResolvedValue({
|
|
112
|
+
success: true,
|
|
113
|
+
messageId: 'msg-3'
|
|
114
|
+
});
|
|
115
|
+
const dto = {
|
|
116
|
+
emailConfigId: 'config-1',
|
|
117
|
+
recipient: 'a@example.com'
|
|
118
|
+
};
|
|
119
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
120
|
+
const result = await controller.sendTestEmail(dto, user);
|
|
121
|
+
expect(mockService.sendTestEmail).toHaveBeenCalledWith('config-1', 'a@example.com', user);
|
|
122
|
+
expect(result.success).toBe(true);
|
|
123
|
+
expect(result.message).toBe('Test email sent successfully');
|
|
124
|
+
});
|
|
125
|
+
it('returns a failure response when the test send fails', async ()=>{
|
|
126
|
+
mockService.sendTestEmail.mockResolvedValue({
|
|
127
|
+
success: false,
|
|
128
|
+
error: 'Bad config'
|
|
129
|
+
});
|
|
130
|
+
const result = await controller.sendTestEmail({
|
|
131
|
+
emailConfigId: 'config-1',
|
|
132
|
+
recipient: 'a@example.com'
|
|
133
|
+
}, (0, _loggedusermock.buildMockUser)());
|
|
134
|
+
expect(result.success).toBe(false);
|
|
135
|
+
expect(result.message).toBe('Failed to send test email');
|
|
136
|
+
expect(result.messageKey).toBe('email.send.failed');
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
const _common = require("@nestjs/common");
|
|
6
|
+
const _loggedusermock = require("@test-utils/mocks/logged-user.mock");
|
|
7
|
+
const _emailtemplatecontroller = require("./email-template.controller");
|
|
8
|
+
function buildTemplate(overrides = {}) {
|
|
9
|
+
return {
|
|
10
|
+
id: 'template-1',
|
|
11
|
+
slug: 'password-reset',
|
|
12
|
+
subject: 'Reset your password',
|
|
13
|
+
body: '<p>Hello {{name}}</p>',
|
|
14
|
+
isActive: true,
|
|
15
|
+
readOnly: false,
|
|
16
|
+
createdAt: new Date(),
|
|
17
|
+
updatedAt: new Date(),
|
|
18
|
+
...overrides
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
describe('EmailTemplateController', ()=>{
|
|
22
|
+
let controller;
|
|
23
|
+
let mockEmailTemplateService;
|
|
24
|
+
beforeEach(()=>{
|
|
25
|
+
mockEmailTemplateService = {
|
|
26
|
+
insert: jest.fn(),
|
|
27
|
+
findById: jest.fn(),
|
|
28
|
+
getAll: jest.fn(),
|
|
29
|
+
update: jest.fn(),
|
|
30
|
+
delete: jest.fn(),
|
|
31
|
+
findBySlug: jest.fn()
|
|
32
|
+
};
|
|
33
|
+
controller = new _emailtemplatecontroller.EmailTemplateController(mockEmailTemplateService);
|
|
34
|
+
});
|
|
35
|
+
it('wires the injected service onto the generated controller base', ()=>{
|
|
36
|
+
expect(controller.emailTemplateService).toBe(mockEmailTemplateService);
|
|
37
|
+
expect(controller.service).toBe(mockEmailTemplateService);
|
|
38
|
+
});
|
|
39
|
+
describe('insert', ()=>{
|
|
40
|
+
it('creates an email template and returns the mapped response', async ()=>{
|
|
41
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
42
|
+
mockEmailTemplateService.insert.mockResolvedValue(buildTemplate());
|
|
43
|
+
const result = await controller.insert({
|
|
44
|
+
slug: 'password-reset'
|
|
45
|
+
}, user);
|
|
46
|
+
expect(mockEmailTemplateService.insert).toHaveBeenCalledWith({
|
|
47
|
+
slug: 'password-reset'
|
|
48
|
+
}, user);
|
|
49
|
+
expect(result.success).toBe(true);
|
|
50
|
+
expect(result.data).toEqual(expect.objectContaining({
|
|
51
|
+
id: 'template-1'
|
|
52
|
+
}));
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
describe('getAll', ()=>{
|
|
56
|
+
it('paginates templates and maps the response list', async ()=>{
|
|
57
|
+
mockEmailTemplateService.getAll.mockResolvedValue({
|
|
58
|
+
data: [
|
|
59
|
+
buildTemplate()
|
|
60
|
+
],
|
|
61
|
+
total: 1
|
|
62
|
+
});
|
|
63
|
+
const result = await controller.getAll({}, (0, _loggedusermock.buildMockUser)(), '');
|
|
64
|
+
expect(mockEmailTemplateService.getAll).toHaveBeenCalledWith('', {}, (0, _loggedusermock.buildMockUser)());
|
|
65
|
+
expect(result.data).toHaveLength(1);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
describe('getBySlug', ()=>{
|
|
69
|
+
it('returns the template matching the given slug', async ()=>{
|
|
70
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
71
|
+
mockEmailTemplateService.findBySlug.mockResolvedValue(buildTemplate());
|
|
72
|
+
const result = await controller.getBySlug({
|
|
73
|
+
slug: 'password-reset'
|
|
74
|
+
}, user);
|
|
75
|
+
expect(mockEmailTemplateService.findBySlug).toHaveBeenCalledWith('password-reset', user);
|
|
76
|
+
expect(result.success).toBe(true);
|
|
77
|
+
expect(result.data).toEqual(expect.objectContaining({
|
|
78
|
+
slug: 'password-reset'
|
|
79
|
+
}));
|
|
80
|
+
});
|
|
81
|
+
it('throws NotFoundException when no template matches the slug', async ()=>{
|
|
82
|
+
const user = (0, _loggedusermock.buildMockUser)();
|
|
83
|
+
mockEmailTemplateService.findBySlug.mockResolvedValue(null);
|
|
84
|
+
await expect(controller.getBySlug({
|
|
85
|
+
slug: 'missing'
|
|
86
|
+
}, user)).rejects.toThrow(_common.NotFoundException);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
const _emailswaggerconfig = require("./email-swagger.config");
|
|
6
|
+
describe('emailSwaggerConfig', ()=>{
|
|
7
|
+
it('should default to company feature enabled and single-database mode when no config is given', ()=>{
|
|
8
|
+
const config = (0, _emailswaggerconfig.emailSwaggerConfig)();
|
|
9
|
+
expect(config.title).toBe('Email API');
|
|
10
|
+
expect(config.bearerAuth).toBe(true);
|
|
11
|
+
expect(config.excludeSchemaProperties).toBeUndefined();
|
|
12
|
+
expect(config.description).not.toContain('Multi-Tenant Mode');
|
|
13
|
+
});
|
|
14
|
+
it('should exclude companyId schema properties when the company feature is disabled', ()=>{
|
|
15
|
+
const config = (0, _emailswaggerconfig.emailSwaggerConfig)({
|
|
16
|
+
enableCompanyFeature: false
|
|
17
|
+
});
|
|
18
|
+
expect(config.excludeSchemaProperties).toEqual([
|
|
19
|
+
{
|
|
20
|
+
schemaName: 'EmailConfigResponseDto',
|
|
21
|
+
properties: [
|
|
22
|
+
'companyId'
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
schemaName: 'EmailTemplateResponseDto',
|
|
27
|
+
properties: [
|
|
28
|
+
'companyId'
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
]);
|
|
32
|
+
});
|
|
33
|
+
it('should not exclude any schema properties when the company feature is enabled', ()=>{
|
|
34
|
+
const config = (0, _emailswaggerconfig.emailSwaggerConfig)({
|
|
35
|
+
enableCompanyFeature: true
|
|
36
|
+
});
|
|
37
|
+
expect(config.excludeSchemaProperties).toBeUndefined();
|
|
38
|
+
});
|
|
39
|
+
it('should describe company isolation and multi-tenant support only when the company feature is enabled', ()=>{
|
|
40
|
+
const withCompany = (0, _emailswaggerconfig.emailSwaggerConfig)({
|
|
41
|
+
enableCompanyFeature: true
|
|
42
|
+
});
|
|
43
|
+
const withoutCompany = (0, _emailswaggerconfig.emailSwaggerConfig)({
|
|
44
|
+
enableCompanyFeature: false
|
|
45
|
+
});
|
|
46
|
+
expect(withCompany.description).toContain('Company isolation');
|
|
47
|
+
expect(withCompany.description).toContain('## Multi-Tenant Support');
|
|
48
|
+
expect(withCompany.description).toContain('with multi-tenant and company support');
|
|
49
|
+
expect(withoutCompany.description).not.toContain('Company isolation');
|
|
50
|
+
expect(withoutCompany.description).not.toContain('## Multi-Tenant Support');
|
|
51
|
+
});
|
|
52
|
+
it('should mention multi-tenant mode in the description only for multi-tenant database mode', ()=>{
|
|
53
|
+
const multiTenant = (0, _emailswaggerconfig.emailSwaggerConfig)({
|
|
54
|
+
databaseMode: 'multi-tenant'
|
|
55
|
+
});
|
|
56
|
+
const single = (0, _emailswaggerconfig.emailSwaggerConfig)({
|
|
57
|
+
databaseMode: 'single'
|
|
58
|
+
});
|
|
59
|
+
expect(multiTenant.description).toContain('Multi-Tenant Mode');
|
|
60
|
+
expect(single.description).not.toContain('Multi-Tenant Mode');
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
const _index = require("./index");
|
|
6
|
+
describe('getEmailEntitiesByConfig', ()=>{
|
|
7
|
+
it('returns the core entities when the company feature is disabled', ()=>{
|
|
8
|
+
expect((0, _index.getEmailEntitiesByConfig)(false)).toBe(_index.EmailCoreEntities);
|
|
9
|
+
});
|
|
10
|
+
it('returns the company-scoped entities when the company feature is enabled', ()=>{
|
|
11
|
+
expect((0, _index.getEmailEntitiesByConfig)(true)).toBe(_index.EmailCompanyEntities);
|
|
12
|
+
});
|
|
13
|
+
it('core and company entity sets are disjoint (never mixed)', ()=>{
|
|
14
|
+
const core = (0, _index.getEmailEntitiesByConfig)(false);
|
|
15
|
+
const company = (0, _index.getEmailEntitiesByConfig)(true);
|
|
16
|
+
expect(core.some((e)=>company.includes(e))).toBe(false);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
const _emailmodule = require("./email.module");
|
|
6
|
+
const _emailconstants = require("../config/email.constants");
|
|
7
|
+
const _controllers = require("../controllers");
|
|
8
|
+
function _define_property(obj, key, value) {
|
|
9
|
+
if (key in obj) {
|
|
10
|
+
Object.defineProperty(obj, key, {
|
|
11
|
+
value: value,
|
|
12
|
+
enumerable: true,
|
|
13
|
+
configurable: true,
|
|
14
|
+
writable: true
|
|
15
|
+
});
|
|
16
|
+
} else {
|
|
17
|
+
obj[key] = value;
|
|
18
|
+
}
|
|
19
|
+
return obj;
|
|
20
|
+
}
|
|
21
|
+
function providerTokens(providers) {
|
|
22
|
+
return providers.map((p)=>typeof p === 'function' ? p : p.provide);
|
|
23
|
+
}
|
|
24
|
+
describe('EmailModule', ()=>{
|
|
25
|
+
describe('forRoot', ()=>{
|
|
26
|
+
it('should default to a non-global module with all controllers registered', ()=>{
|
|
27
|
+
const dynamicModule = _emailmodule.EmailModule.forRoot({});
|
|
28
|
+
expect(dynamicModule.module).toBe(_emailmodule.EmailModule);
|
|
29
|
+
expect(dynamicModule.global).toBe(false);
|
|
30
|
+
expect(dynamicModule.controllers).toEqual([
|
|
31
|
+
_controllers.EmailConfigController,
|
|
32
|
+
_controllers.EmailTemplateController,
|
|
33
|
+
_controllers.EmailSendController
|
|
34
|
+
]);
|
|
35
|
+
});
|
|
36
|
+
it('should respect global: true', ()=>{
|
|
37
|
+
expect(_emailmodule.EmailModule.forRoot({
|
|
38
|
+
global: true
|
|
39
|
+
}).global).toBe(true);
|
|
40
|
+
});
|
|
41
|
+
it('should register no controllers when includeController is false', ()=>{
|
|
42
|
+
expect(_emailmodule.EmailModule.forRoot({
|
|
43
|
+
includeController: false
|
|
44
|
+
}).controllers).toEqual([]);
|
|
45
|
+
});
|
|
46
|
+
it('should register a EMAIL_MODULE_OPTIONS provider carrying the given options', ()=>{
|
|
47
|
+
const options = {
|
|
48
|
+
bootstrapAppConfig: {
|
|
49
|
+
enableCompanyFeature: true
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const dynamicModule = _emailmodule.EmailModule.forRoot(options);
|
|
53
|
+
const provider = dynamicModule.providers.find((p)=>p.provide === _emailconstants.EMAIL_MODULE_OPTIONS);
|
|
54
|
+
expect(provider.useValue).toBe(options);
|
|
55
|
+
});
|
|
56
|
+
it('should always export the same fixed set of services', ()=>{
|
|
57
|
+
expect(_emailmodule.EmailModule.forRoot({}).exports).toHaveLength(6);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
describe('forRootAsync', ()=>{
|
|
61
|
+
it('should forward external imports alongside CacheModule/UtilsModule', ()=>{
|
|
62
|
+
let FakeImportedModule = class FakeImportedModule {
|
|
63
|
+
};
|
|
64
|
+
const dynamicModule = _emailmodule.EmailModule.forRootAsync({
|
|
65
|
+
bootstrapAppConfig: {},
|
|
66
|
+
imports: [
|
|
67
|
+
FakeImportedModule
|
|
68
|
+
]
|
|
69
|
+
});
|
|
70
|
+
expect(dynamicModule.imports).toEqual(expect.arrayContaining([
|
|
71
|
+
FakeImportedModule
|
|
72
|
+
]));
|
|
73
|
+
});
|
|
74
|
+
it('useFactory: builds an EMAIL_MODULE_OPTIONS provider that merges resolved config into the static options', async ()=>{
|
|
75
|
+
const useFactory = jest.fn().mockResolvedValue({
|
|
76
|
+
defaultFrom: 'noreply@flusys.io'
|
|
77
|
+
});
|
|
78
|
+
const dynamicModule = _emailmodule.EmailModule.forRootAsync({
|
|
79
|
+
bootstrapAppConfig: {},
|
|
80
|
+
useFactory,
|
|
81
|
+
inject: [
|
|
82
|
+
'SOME_TOKEN'
|
|
83
|
+
]
|
|
84
|
+
});
|
|
85
|
+
const provider = dynamicModule.providers.find((p)=>p.provide === _emailconstants.EMAIL_MODULE_OPTIONS);
|
|
86
|
+
expect(provider.inject).toEqual([
|
|
87
|
+
'SOME_TOKEN'
|
|
88
|
+
]);
|
|
89
|
+
const resolved = await provider.useFactory('injected');
|
|
90
|
+
expect(useFactory).toHaveBeenCalledWith('injected');
|
|
91
|
+
expect(resolved.config).toEqual({
|
|
92
|
+
defaultFrom: 'noreply@flusys.io'
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
it('useClass: registers both the class provider and an options provider calling createEmailOptions()', async ()=>{
|
|
96
|
+
let MyOptionsFactory = class MyOptionsFactory {
|
|
97
|
+
constructor(){
|
|
98
|
+
_define_property(this, "createEmailOptions", jest.fn().mockResolvedValue({
|
|
99
|
+
defaultFrom: 'from-class@flusys.io'
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const dynamicModule = _emailmodule.EmailModule.forRootAsync({
|
|
104
|
+
bootstrapAppConfig: {},
|
|
105
|
+
useClass: MyOptionsFactory
|
|
106
|
+
});
|
|
107
|
+
const classProvider = dynamicModule.providers.find((p)=>p.provide === MyOptionsFactory);
|
|
108
|
+
expect(classProvider.useClass).toBe(MyOptionsFactory);
|
|
109
|
+
const optionsProvider = dynamicModule.providers.find((p)=>p.provide === _emailconstants.EMAIL_MODULE_OPTIONS);
|
|
110
|
+
const instance = new MyOptionsFactory();
|
|
111
|
+
const resolved = await optionsProvider.useFactory(instance);
|
|
112
|
+
expect(instance.createEmailOptions).toHaveBeenCalled();
|
|
113
|
+
expect(resolved.config).toEqual({
|
|
114
|
+
defaultFrom: 'from-class@flusys.io'
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
it('useExisting: registers a single options provider without a duplicate class registration', async ()=>{
|
|
118
|
+
let MyOptionsFactory = class MyOptionsFactory {
|
|
119
|
+
constructor(){
|
|
120
|
+
_define_property(this, "createEmailOptions", jest.fn().mockResolvedValue({
|
|
121
|
+
defaultFrom: 'from-existing@flusys.io'
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
const dynamicModule = _emailmodule.EmailModule.forRootAsync({
|
|
126
|
+
bootstrapAppConfig: {},
|
|
127
|
+
useExisting: MyOptionsFactory
|
|
128
|
+
});
|
|
129
|
+
expect(dynamicModule.providers.filter((p)=>p.provide === MyOptionsFactory)).toHaveLength(0);
|
|
130
|
+
const optionsProvider = dynamicModule.providers.find((p)=>p.provide === _emailconstants.EMAIL_MODULE_OPTIONS);
|
|
131
|
+
expect(optionsProvider.inject).toEqual([
|
|
132
|
+
MyOptionsFactory
|
|
133
|
+
]);
|
|
134
|
+
});
|
|
135
|
+
it('should register no EMAIL_MODULE_OPTIONS provider when neither useFactory, useClass, nor useExisting is given', ()=>{
|
|
136
|
+
const dynamicModule = _emailmodule.EmailModule.forRootAsync({
|
|
137
|
+
bootstrapAppConfig: {}
|
|
138
|
+
});
|
|
139
|
+
expect(providerTokens(dynamicModule.providers)).not.toContain(_emailconstants.EMAIL_MODULE_OPTIONS);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
});
|