@5minds/node-red-contrib-processcube-tools 1.2.0-develop-d19f89-mg68thdf → 1.2.0-develop-59ef22-mg9d9ja5
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/.mocharc.json +5 -0
- package/package.json +26 -10
- package/src/custom-node-template/custom-node-template.html.template +45 -0
- package/src/custom-node-template/custom-node-template.ts.template +69 -0
- package/src/email-receiver/email-receiver.ts +439 -0
- package/src/email-sender/email-sender.ts +210 -0
- package/{processcube-html-to-text/processcube-html-to-text.html → src/html-to-text/html-to-text.html} +3 -3
- package/src/html-to-text/html-to-text.ts +53 -0
- package/src/index.ts +12 -0
- package/src/interfaces/EmailReceiverMessage.ts +22 -0
- package/src/interfaces/EmailSenderNodeProperties.ts +37 -0
- package/src/interfaces/FetchState.ts +9 -0
- package/src/interfaces/ImapConnectionConfig.ts +14 -0
- package/src/test/framework/advanced-test-patterns.ts +224 -0
- package/src/test/framework/generic-node-test-suite.ts +58 -0
- package/src/test/framework/index.ts +17 -0
- package/src/test/framework/integration-assertions.ts +67 -0
- package/src/test/framework/integration-scenario-builder.ts +77 -0
- package/src/test/framework/integration-test-runner.ts +101 -0
- package/src/test/framework/node-assertions.ts +63 -0
- package/src/test/framework/node-test-runner.ts +260 -0
- package/src/test/framework/test-scenario-builder.ts +74 -0
- package/src/test/framework/types.ts +61 -0
- package/src/test/helpers/email-receiver-test-configs.ts +67 -0
- package/src/test/helpers/email-receiver-test-flows.ts +16 -0
- package/src/test/helpers/email-sender-test-configs.ts +123 -0
- package/src/test/helpers/email-sender-test-flows.ts +16 -0
- package/src/test/integration/email-receiver.integration.test.ts +41 -0
- package/src/test/integration/email-sender.integration.test.ts +129 -0
- package/src/test/interfaces/email-data.ts +10 -0
- package/src/test/interfaces/email-receiver-config.ts +12 -0
- package/src/test/interfaces/email-sender-config.ts +26 -0
- package/src/test/interfaces/imap-config.ts +9 -0
- package/src/test/interfaces/imap-mailbox.ts +5 -0
- package/src/test/interfaces/mail-options.ts +20 -0
- package/src/test/interfaces/parsed-email.ts +11 -0
- package/src/test/interfaces/send-mail-result.ts +7 -0
- package/src/test/mocks/imap-mock.ts +147 -0
- package/src/test/mocks/mailparser-mock.ts +82 -0
- package/src/test/mocks/nodemailer-mock.ts +118 -0
- package/src/test/unit/email-receiver.unit.test.ts +471 -0
- package/src/test/unit/email-sender.unit.test.ts +550 -0
- package/tsconfig.json +23 -0
- package/email-receiver/email-receiver.js +0 -304
- package/email-sender/email-sender.js +0 -178
- package/examples/.gitkeep +0 -0
- package/processcube-html-to-text/processcube-html-to-text.js +0 -22
- package/test/helpers/email-receiver.mocks.js +0 -447
- package/test/helpers/email-sender.mocks.js +0 -368
- package/test/integration/email-receiver.integration.test.js +0 -515
- package/test/integration/email-sender.integration.test.js +0 -239
- package/test/unit/email-receiver.unit.test.js +0 -304
- package/test/unit/email-sender.unit.test.js +0 -570
- /package/{email-receiver → src/email-receiver}/email-receiver.html +0 -0
- /package/{email-sender → src/email-sender}/email-sender.html +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { Node, NodeMessageInFlow } from 'node-red';
|
|
2
|
+
|
|
3
|
+
export interface TestScenario {
|
|
4
|
+
name: string;
|
|
5
|
+
config: any;
|
|
6
|
+
input?: any;
|
|
7
|
+
expectedOutput?: any;
|
|
8
|
+
expectedError?: string | RegExp;
|
|
9
|
+
expectedStatus?: { fill: string; shape?: string; text?: string };
|
|
10
|
+
timeout?: number;
|
|
11
|
+
mockOptions?: MockNodeREDOptions;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface TestContext {
|
|
15
|
+
mockRED: any;
|
|
16
|
+
nodeInstance: any;
|
|
17
|
+
messages: any[];
|
|
18
|
+
errors: any[];
|
|
19
|
+
statuses: any[];
|
|
20
|
+
logs?: any[];
|
|
21
|
+
warnings?: any[];
|
|
22
|
+
debugs?: any[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface MockNodeREDOptions {
|
|
26
|
+
dependencies?: Record<string, any>;
|
|
27
|
+
onHandler?: (this: Node, event: string, callback: Function) => void;
|
|
28
|
+
sendHandler?: (msg: any) => void;
|
|
29
|
+
errorHandler?: (err: any) => void;
|
|
30
|
+
statusHandler?: (status: any) => void;
|
|
31
|
+
logHandler?: (msg: any) => void;
|
|
32
|
+
warnHandler?: (msg: any) => void;
|
|
33
|
+
debugHandler?: (msg: any) => void;
|
|
34
|
+
traceHandler?: (msg: any) => void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Integration Test Types
|
|
38
|
+
export interface IntegrationTestScenario {
|
|
39
|
+
name: string;
|
|
40
|
+
flow: any[];
|
|
41
|
+
nodeId: string;
|
|
42
|
+
input?: any;
|
|
43
|
+
expectedMessages?: Array<{
|
|
44
|
+
nodeId: string;
|
|
45
|
+
expectedMsg: any;
|
|
46
|
+
timeout?: number;
|
|
47
|
+
}>;
|
|
48
|
+
timeout?: number;
|
|
49
|
+
setup?: (nodes: Record<string, Node>) => void;
|
|
50
|
+
cleanup?: () => void;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface IntegrationTestContext {
|
|
54
|
+
nodes: Record<string, Node>;
|
|
55
|
+
messages: Array<{
|
|
56
|
+
nodeId: string;
|
|
57
|
+
message: NodeMessageInFlow;
|
|
58
|
+
timestamp: number;
|
|
59
|
+
}>;
|
|
60
|
+
errors: any[];
|
|
61
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { EmailReceiverConfig } from '../interfaces/email-receiver-config';
|
|
2
|
+
|
|
3
|
+
export const EmailReceiverTestConfigs = {
|
|
4
|
+
valid: {
|
|
5
|
+
id: 'test-node-1',
|
|
6
|
+
type: 'email-receiver',
|
|
7
|
+
name: 'Test Email Receiver',
|
|
8
|
+
host: 'imap.test.com',
|
|
9
|
+
port: 993,
|
|
10
|
+
user: 'test@test.com',
|
|
11
|
+
password: 'testpass',
|
|
12
|
+
folder: ['INBOX'],
|
|
13
|
+
tls: true,
|
|
14
|
+
markseen: true,
|
|
15
|
+
} as EmailReceiverConfig,
|
|
16
|
+
|
|
17
|
+
minimal: {
|
|
18
|
+
id: 'test-node-minimal',
|
|
19
|
+
type: 'email-receiver',
|
|
20
|
+
host: 'imap.minimal.com',
|
|
21
|
+
port: 993,
|
|
22
|
+
user: 'minimal@test.com',
|
|
23
|
+
password: 'minimalpass',
|
|
24
|
+
folder: 'INBOX',
|
|
25
|
+
} as EmailReceiverConfig,
|
|
26
|
+
|
|
27
|
+
arrayFolders: {
|
|
28
|
+
id: 'test-node-array',
|
|
29
|
+
type: 'email-receiver',
|
|
30
|
+
name: 'Array Folders Test',
|
|
31
|
+
host: 'imap.test.com',
|
|
32
|
+
port: 993,
|
|
33
|
+
user: 'test@test.com',
|
|
34
|
+
password: 'testpass',
|
|
35
|
+
folder: ['INBOX', 'SENT', 'DRAFTS'],
|
|
36
|
+
} as EmailReceiverConfig,
|
|
37
|
+
|
|
38
|
+
invalidFolderType: {
|
|
39
|
+
id: 'test-node-invalid-folder',
|
|
40
|
+
type: 'email-receiver',
|
|
41
|
+
host: 'imap.test.com',
|
|
42
|
+
port: 993,
|
|
43
|
+
user: 'test@test.com',
|
|
44
|
+
password: 'testpass',
|
|
45
|
+
folder: 123 as any, // Invalid type
|
|
46
|
+
} as EmailReceiverConfig,
|
|
47
|
+
|
|
48
|
+
invalidConfig: {
|
|
49
|
+
id: 'test-node-invalid',
|
|
50
|
+
type: 'email-receiver',
|
|
51
|
+
host: '', // Missing host
|
|
52
|
+
port: 993,
|
|
53
|
+
user: 'test@test.com',
|
|
54
|
+
password: '', // Missing password
|
|
55
|
+
folder: ['INBOX'],
|
|
56
|
+
} as EmailReceiverConfig,
|
|
57
|
+
|
|
58
|
+
networkError: {
|
|
59
|
+
id: 'test-node-network-error',
|
|
60
|
+
type: 'email-receiver',
|
|
61
|
+
host: 'unreachable.invalid.host.com',
|
|
62
|
+
port: 993,
|
|
63
|
+
user: 'test@test.com',
|
|
64
|
+
password: 'testpass',
|
|
65
|
+
folder: ['INBOX'],
|
|
66
|
+
} as EmailReceiverConfig,
|
|
67
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EmailReceiverTestConfigs } from './email-receiver-test-configs';
|
|
2
|
+
|
|
3
|
+
export const testFlows = {
|
|
4
|
+
single: [EmailReceiverTestConfigs.valid],
|
|
5
|
+
|
|
6
|
+
connected: [
|
|
7
|
+
{ ...EmailReceiverTestConfigs.valid, wires: [['h1']] },
|
|
8
|
+
{ id: 'h1', type: 'helper' },
|
|
9
|
+
],
|
|
10
|
+
|
|
11
|
+
multiOutput: [
|
|
12
|
+
{ ...EmailReceiverTestConfigs.valid, wires: [['h1', 'h2']] },
|
|
13
|
+
{ id: 'h1', type: 'helper' },
|
|
14
|
+
{ id: 'h2', type: 'helper' },
|
|
15
|
+
],
|
|
16
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { EmailSenderConfig } from '../interfaces/email-sender-config';
|
|
2
|
+
|
|
3
|
+
const EmailSenderTestConfigs = {
|
|
4
|
+
valid: {
|
|
5
|
+
id: 'test-sender-1',
|
|
6
|
+
type: 'email-sender',
|
|
7
|
+
name: 'Test Email Sender',
|
|
8
|
+
sender: 'Test Sender',
|
|
9
|
+
address: 'test.sender@example.com',
|
|
10
|
+
to: 'recipient@example.com',
|
|
11
|
+
subject: 'Test Subject',
|
|
12
|
+
htmlContent: '<b>Test Content</b>',
|
|
13
|
+
attachments: '',
|
|
14
|
+
attachmentsType: 'str',
|
|
15
|
+
host: 'smtp.example.com',
|
|
16
|
+
port: 587,
|
|
17
|
+
user: 'testuser',
|
|
18
|
+
password: 'testpass',
|
|
19
|
+
secure: false,
|
|
20
|
+
rejectUnauthorized: true,
|
|
21
|
+
} as EmailSenderConfig,
|
|
22
|
+
|
|
23
|
+
minimal: {
|
|
24
|
+
id: 'test-sender-minimal',
|
|
25
|
+
type: 'email-sender',
|
|
26
|
+
sender: 'Test Sender',
|
|
27
|
+
address: 'test.sender@example.com',
|
|
28
|
+
to: 'recipient@example.com',
|
|
29
|
+
subject: 'Minimal Subject',
|
|
30
|
+
htmlContent: 'Minimal content',
|
|
31
|
+
host: 'smtp.minimal.com',
|
|
32
|
+
port: 587,
|
|
33
|
+
user: 'minimal-user',
|
|
34
|
+
password: 'minimal-pass',
|
|
35
|
+
secure: false,
|
|
36
|
+
rejectUnauthorized: true,
|
|
37
|
+
} as EmailSenderConfig,
|
|
38
|
+
|
|
39
|
+
invalid: {
|
|
40
|
+
id: 'test-sender-invalid',
|
|
41
|
+
type: 'email-sender',
|
|
42
|
+
name: 'Invalid Sender',
|
|
43
|
+
sender: '', // Missing sender
|
|
44
|
+
to: 'test@example.com',
|
|
45
|
+
subject: 'Invalid Test',
|
|
46
|
+
host: '', // Missing host
|
|
47
|
+
port: 587,
|
|
48
|
+
user: 'user',
|
|
49
|
+
password: '', // Missing password
|
|
50
|
+
} as EmailSenderConfig,
|
|
51
|
+
|
|
52
|
+
minimalDataDriven: {
|
|
53
|
+
id: 'test-sender-minimal',
|
|
54
|
+
type: 'email-sender',
|
|
55
|
+
sender: 'Test Sender',
|
|
56
|
+
address: 'test.sender@example.com',
|
|
57
|
+
subject: 'Minimal Subject',
|
|
58
|
+
htmlContent: 'Minimal content',
|
|
59
|
+
host: 'smtp.minimal.com',
|
|
60
|
+
port: 587,
|
|
61
|
+
user: 'minimal-user',
|
|
62
|
+
password: 'minimal-pass',
|
|
63
|
+
secure: false,
|
|
64
|
+
rejectUnauthorized: true,
|
|
65
|
+
} as EmailSenderConfig,
|
|
66
|
+
|
|
67
|
+
withAttachments: {
|
|
68
|
+
id: 'test-sender-attachments',
|
|
69
|
+
type: 'email-sender',
|
|
70
|
+
name: 'Sender With Attachments',
|
|
71
|
+
to: 'recipient@example.com',
|
|
72
|
+
subject: 'Attachment Test',
|
|
73
|
+
htmlContent: 'Email with attachments',
|
|
74
|
+
attachments: JSON.stringify([{ filename: 'test.txt', content: 'Test attachment' }]),
|
|
75
|
+
attachmentsType: 'json',
|
|
76
|
+
host: 'smtp.example.com',
|
|
77
|
+
port: 587,
|
|
78
|
+
user: 'testuser',
|
|
79
|
+
password: 'testpass',
|
|
80
|
+
} as EmailSenderConfig,
|
|
81
|
+
|
|
82
|
+
errorScenarios: {
|
|
83
|
+
networkError: {
|
|
84
|
+
id: 'test-sender-network-error',
|
|
85
|
+
type: 'email-sender',
|
|
86
|
+
name: 'Network Error Scenario',
|
|
87
|
+
host: 'unreachable.invalid.host.com',
|
|
88
|
+
shouldFail: true,
|
|
89
|
+
} as EmailSenderConfig,
|
|
90
|
+
|
|
91
|
+
rejectedEmail: {
|
|
92
|
+
id: 'test-sender-rejected',
|
|
93
|
+
type: 'email-sender',
|
|
94
|
+
name: 'Rejected Email Scenario',
|
|
95
|
+
rejectedEmails: ['recipient@example.com'],
|
|
96
|
+
} as EmailSenderConfig,
|
|
97
|
+
|
|
98
|
+
pendingEmail: {
|
|
99
|
+
id: 'test-sender-pending',
|
|
100
|
+
type: 'email-sender',
|
|
101
|
+
name: 'Pending Email Scenario',
|
|
102
|
+
pendingEmails: ['recipient@example.com'],
|
|
103
|
+
} as EmailSenderConfig,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const baseConfig = EmailSenderTestConfigs.valid;
|
|
108
|
+
EmailSenderTestConfigs.errorScenarios.networkError = {
|
|
109
|
+
...baseConfig,
|
|
110
|
+
...EmailSenderTestConfigs.errorScenarios.networkError,
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
EmailSenderTestConfigs.errorScenarios.rejectedEmail = {
|
|
114
|
+
...baseConfig,
|
|
115
|
+
...EmailSenderTestConfigs.errorScenarios.rejectedEmail,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
EmailSenderTestConfigs.errorScenarios.pendingEmail = {
|
|
119
|
+
...baseConfig,
|
|
120
|
+
...EmailSenderTestConfigs.errorScenarios.pendingEmail,
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export { EmailSenderTestConfigs };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EmailSenderTestConfigs } from './email-sender-test-configs';
|
|
2
|
+
|
|
3
|
+
export const testFlows = {
|
|
4
|
+
single: [EmailSenderTestConfigs.valid],
|
|
5
|
+
|
|
6
|
+
connected: [
|
|
7
|
+
{ ...EmailSenderTestConfigs.valid, wires: [['h1']] },
|
|
8
|
+
{ id: 'h1', type: 'helper' },
|
|
9
|
+
],
|
|
10
|
+
|
|
11
|
+
multiOutput: [
|
|
12
|
+
{ ...EmailSenderTestConfigs.valid, wires: [['h1', 'h2']] },
|
|
13
|
+
{ id: 'h1', type: 'helper' },
|
|
14
|
+
{ id: 'h2', type: 'helper' },
|
|
15
|
+
],
|
|
16
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import emailReceiverNode from '../../email-receiver/email-receiver';
|
|
3
|
+
import { EmailReceiverTestConfigs } from '../helpers/email-receiver-test-configs';
|
|
4
|
+
|
|
5
|
+
// Import our comprehensive test framework
|
|
6
|
+
import { NodeTestRunner, NodeAssertions, type TestScenario, MockNodeREDOptions } from '../framework';
|
|
7
|
+
|
|
8
|
+
import { MockImap } from '../mocks/imap-mock';
|
|
9
|
+
import { createMockMailparser } from '../mocks/mailparser-mock';
|
|
10
|
+
|
|
11
|
+
describe('E-Mail Receiver Node - Integration Tests', function () {
|
|
12
|
+
// ========================================================================
|
|
13
|
+
// INTEGRATION WITH EXISTING MOCK SYSTEM
|
|
14
|
+
// ========================================================================
|
|
15
|
+
|
|
16
|
+
describe('Mock System Integration', function () {
|
|
17
|
+
it('should work with all mock configurations', async function () {
|
|
18
|
+
const mockConfigs = [
|
|
19
|
+
EmailReceiverTestConfigs.valid,
|
|
20
|
+
EmailReceiverTestConfigs.minimal,
|
|
21
|
+
EmailReceiverTestConfigs.arrayFolders,
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
for (const config of mockConfigs) {
|
|
25
|
+
const scenario: TestScenario = {
|
|
26
|
+
name: `mock integration - ${config.name || 'unnamed'}`,
|
|
27
|
+
config,
|
|
28
|
+
input: { payload: 'test' },
|
|
29
|
+
timeout: 2000,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const context = await NodeTestRunner.runScenario(emailReceiverNode, scenario);
|
|
33
|
+
expect(context.nodeInstance).to.exist;
|
|
34
|
+
|
|
35
|
+
if (config.name) {
|
|
36
|
+
NodeAssertions.expectNodeProperty(context, 'name', config.name);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { describe, it } from 'mocha';
|
|
2
|
+
import { expect } from 'chai';
|
|
3
|
+
import {
|
|
4
|
+
IntegrationTestRunner,
|
|
5
|
+
IntegrationAssertions,
|
|
6
|
+
IntegrationScenarioBuilder,
|
|
7
|
+
type IntegrationTestScenario,
|
|
8
|
+
} from '../framework';
|
|
9
|
+
import { EmailSenderTestConfigs } from '../helpers/email-sender-test-configs';
|
|
10
|
+
import { testFlows } from '../helpers/email-sender-test-flows';
|
|
11
|
+
|
|
12
|
+
const emailSenderNode = require('../../email-sender/email-sender');
|
|
13
|
+
|
|
14
|
+
describe('E-Mail Sender Node - Integration Tests (Framework)', function () {
|
|
15
|
+
// ========================================================================
|
|
16
|
+
// NODE LOADING TESTS USING FRAMEWORK
|
|
17
|
+
// ========================================================================
|
|
18
|
+
|
|
19
|
+
describe('Node Loading (Enhanced)', function () {
|
|
20
|
+
const loadingTests = new IntegrationScenarioBuilder()
|
|
21
|
+
.addLoadingScenario('valid configuration', [EmailSenderTestConfigs.valid], EmailSenderTestConfigs.valid.id)
|
|
22
|
+
.addLoadingScenario(
|
|
23
|
+
'minimal configuration',
|
|
24
|
+
[EmailSenderTestConfigs.minimal],
|
|
25
|
+
EmailSenderTestConfigs.minimal.id,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
loadingTests.getScenarios().forEach((scenario) => {
|
|
29
|
+
it(`should load with ${scenario.name}`, async function () {
|
|
30
|
+
const context = await IntegrationTestRunner.runIntegrationScenario(emailSenderNode, scenario);
|
|
31
|
+
|
|
32
|
+
IntegrationAssertions.expectNodeExists(context, scenario.nodeId);
|
|
33
|
+
IntegrationAssertions.expectNodeProperty(context, scenario.nodeId, 'type', 'email-sender');
|
|
34
|
+
|
|
35
|
+
const nodeConfig = scenario.flow.find((n) => n.id === scenario.nodeId);
|
|
36
|
+
if (nodeConfig.name) {
|
|
37
|
+
IntegrationAssertions.expectNodeProperty(context, scenario.nodeId, 'name', nodeConfig.name);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// ========================================================================
|
|
44
|
+
// CONNECTION TESTS USING FRAMEWORK
|
|
45
|
+
// ========================================================================
|
|
46
|
+
|
|
47
|
+
describe('Node Connections', function () {
|
|
48
|
+
it('should load node in a flow configuration', async function () {
|
|
49
|
+
const scenario: IntegrationTestScenario = {
|
|
50
|
+
name: 'node in flow',
|
|
51
|
+
flow: testFlows.connected,
|
|
52
|
+
nodeId: EmailSenderTestConfigs.valid.id,
|
|
53
|
+
timeout: 2000,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const context = await IntegrationTestRunner.runIntegrationScenario(emailSenderNode, scenario);
|
|
57
|
+
|
|
58
|
+
// Only verify the main node exists - helper nodes aren't actually created
|
|
59
|
+
IntegrationAssertions.expectNodeExists(context, EmailSenderTestConfigs.valid.id);
|
|
60
|
+
IntegrationAssertions.expectNodeProperty(
|
|
61
|
+
context,
|
|
62
|
+
EmailSenderTestConfigs.valid.id,
|
|
63
|
+
'name',
|
|
64
|
+
EmailSenderTestConfigs.valid.name,
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// ========================================================================
|
|
70
|
+
// CONFIGURATION VALIDATION INTEGRATION
|
|
71
|
+
// ========================================================================
|
|
72
|
+
|
|
73
|
+
describe('Configuration Validation Integration', function () {
|
|
74
|
+
const validationTests = new IntegrationScenarioBuilder()
|
|
75
|
+
.addScenario({
|
|
76
|
+
name: 'minimal configuration handling',
|
|
77
|
+
flow: [EmailSenderTestConfigs.minimal],
|
|
78
|
+
nodeId: EmailSenderTestConfigs.minimal.id,
|
|
79
|
+
input: { payload: 'test', topic: 'test' },
|
|
80
|
+
timeout: 2000,
|
|
81
|
+
})
|
|
82
|
+
.addScenario({
|
|
83
|
+
name: 'complex configuration handling',
|
|
84
|
+
flow: [
|
|
85
|
+
{
|
|
86
|
+
...EmailSenderTestConfigs.valid,
|
|
87
|
+
attachments: JSON.stringify([{ filename: 'config-test.txt', content: 'Configuration test' }]),
|
|
88
|
+
priority: 'high',
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
nodeId: EmailSenderTestConfigs.valid.id,
|
|
92
|
+
input: { payload: 'complex test', topic: 'complex' },
|
|
93
|
+
timeout: 3000,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
validationTests.getScenarios().forEach((scenario) => {
|
|
97
|
+
it(`should handle ${scenario.name}`, async function () {
|
|
98
|
+
const context = await IntegrationTestRunner.runIntegrationScenario(emailSenderNode, scenario);
|
|
99
|
+
IntegrationAssertions.expectNodeExists(context, scenario.nodeId);
|
|
100
|
+
// Node should handle different configurations gracefully
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// ========================================================================
|
|
106
|
+
// LIFECYCLE TESTS USING FRAMEWORK
|
|
107
|
+
// ========================================================================
|
|
108
|
+
|
|
109
|
+
describe('Node Lifecycle', function () {
|
|
110
|
+
it('should handle multiple load/unload cycles', async function () {
|
|
111
|
+
const cycles = 3;
|
|
112
|
+
|
|
113
|
+
for (let i = 0; i < cycles; i++) {
|
|
114
|
+
const scenario: IntegrationTestScenario = {
|
|
115
|
+
name: `lifecycle cycle ${i}`,
|
|
116
|
+
flow: testFlows.single,
|
|
117
|
+
nodeId: EmailSenderTestConfigs.valid.id,
|
|
118
|
+
input: { payload: `test cycle ${i}`, topic: `cycle ${i}` },
|
|
119
|
+
timeout: 1000,
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const context = await IntegrationTestRunner.runIntegrationScenario(emailSenderNode, scenario);
|
|
123
|
+
IntegrationAssertions.expectNodeExists(context, EmailSenderTestConfigs.valid.id);
|
|
124
|
+
|
|
125
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface EmailSenderConfig {
|
|
2
|
+
id: string;
|
|
3
|
+
type: string;
|
|
4
|
+
name?: string;
|
|
5
|
+
sender?: string;
|
|
6
|
+
address?: string;
|
|
7
|
+
to?: string;
|
|
8
|
+
cc?: string;
|
|
9
|
+
bcc?: string;
|
|
10
|
+
subject?: string;
|
|
11
|
+
htmlContent?: string;
|
|
12
|
+
attachments?: string;
|
|
13
|
+
attachmentsType?: string;
|
|
14
|
+
host?: string;
|
|
15
|
+
port?: number;
|
|
16
|
+
user?: string;
|
|
17
|
+
password?: string;
|
|
18
|
+
secure?: boolean;
|
|
19
|
+
rejectUnauthorized?: boolean;
|
|
20
|
+
wires?: string[][];
|
|
21
|
+
// Test-specific properties
|
|
22
|
+
shouldFail?: boolean;
|
|
23
|
+
rejectedEmails?: string[];
|
|
24
|
+
pendingEmails?: string[];
|
|
25
|
+
acceptedEmails?: string[];
|
|
26
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface MailOptions {
|
|
2
|
+
to: string | string[];
|
|
3
|
+
from?: string;
|
|
4
|
+
subject?: string;
|
|
5
|
+
html?: string;
|
|
6
|
+
text?: string;
|
|
7
|
+
attachments?: any[];
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface MockNodemailerOptions {
|
|
12
|
+
onSendMail?: (mailOptions: MailOptions) => void;
|
|
13
|
+
shouldFail?: boolean;
|
|
14
|
+
shouldFailVerify?: boolean;
|
|
15
|
+
failureMessage?: string;
|
|
16
|
+
failureCode?: string;
|
|
17
|
+
rejectedEmails?: string[];
|
|
18
|
+
pendingEmails?: string[];
|
|
19
|
+
acceptedEmails?: string[];
|
|
20
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface ParsedEmail {
|
|
2
|
+
subject?: string;
|
|
3
|
+
text?: string;
|
|
4
|
+
html?: string;
|
|
5
|
+
from?: { text: string; value: Array<{ address: string; name?: string }> };
|
|
6
|
+
to?: { text: string; value: Array<{ address: string; name?: string }> };
|
|
7
|
+
date?: Date;
|
|
8
|
+
messageId?: string;
|
|
9
|
+
headers: Map<string, string>;
|
|
10
|
+
attachments?: any[];
|
|
11
|
+
}
|