@5minds/node-red-contrib-processcube-tools 1.0.1 → 1.0.2-develop-e3d5d9-mfm8oea8
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/.env.template +4 -0
- package/README.md +1 -1
- package/email-receiver/email-receiver.html +219 -0
- package/email-receiver/email-receiver.js +250 -0
- package/email-sender/email-sender.html +306 -0
- package/email-sender/email-sender.js +174 -0
- package/package.json +25 -4
- package/{processcube-html-to-text.html → processcube-html-to-text/processcube-html-to-text.html} +9 -9
- package/{processcube-html-to-text.js → processcube-html-to-text/processcube-html-to-text.js} +0 -3
- package/test/helpers/email-receiver.mocks.js +447 -0
- package/test/helpers/email-sender.mocks.js +368 -0
- package/test/integration/email-receiver.integration.test.js +515 -0
- package/test/integration/email-sender.integration.test.js +239 -0
- package/test/unit/email-receiver.unit.test.js +304 -0
- package/test/unit/email-sender.unit.test.js +570 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
const { expect } = require('chai');
|
|
2
|
+
const helper = require('node-red-node-test-helper');
|
|
3
|
+
const {
|
|
4
|
+
setupModuleMocks,
|
|
5
|
+
emailSenderConfigs,
|
|
6
|
+
testFlows,
|
|
7
|
+
testUtils,
|
|
8
|
+
} = require('../../test/helpers/email-sender.mocks.js');
|
|
9
|
+
|
|
10
|
+
describe('E-Mail Sender Node - Integration Tests', function () {
|
|
11
|
+
// Set a reasonable timeout for integration tests
|
|
12
|
+
this.timeout(10000);
|
|
13
|
+
|
|
14
|
+
let emailSenderNode;
|
|
15
|
+
let cleanupMocks;
|
|
16
|
+
|
|
17
|
+
beforeEach(function (done) {
|
|
18
|
+
// Set up mocks using helper
|
|
19
|
+
cleanupMocks = setupModuleMocks();
|
|
20
|
+
|
|
21
|
+
// Load the node with mocked dependencies
|
|
22
|
+
emailSenderNode = require('../../email-sender/email-sender.js');
|
|
23
|
+
|
|
24
|
+
// CRITICAL: Initialize the helper with Node-RED
|
|
25
|
+
helper.init(require.resolve('node-red'));
|
|
26
|
+
done();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
afterEach(function () {
|
|
30
|
+
// Clean up mocks using helper cleanup function
|
|
31
|
+
if (cleanupMocks) {
|
|
32
|
+
cleanupMocks();
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
beforeEach(function (done) {
|
|
37
|
+
helper.startServer(done);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
afterEach(function (done) {
|
|
41
|
+
helper.unload();
|
|
42
|
+
helper.stopServer(done);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe('Node Loading', function () {
|
|
46
|
+
it('should load in Node-RED test environment', function (done) {
|
|
47
|
+
// ARRANGE: Use test flow from helpers
|
|
48
|
+
const flow = [emailSenderConfigs.valid];
|
|
49
|
+
|
|
50
|
+
// ACT: Load the node in the test helper environment
|
|
51
|
+
helper.load(emailSenderNode, flow, function () {
|
|
52
|
+
try {
|
|
53
|
+
// ASSERT: Verify the node loaded correctly
|
|
54
|
+
const n1 = helper.getNode(emailSenderConfigs.valid.id);
|
|
55
|
+
expect(n1).to.exist;
|
|
56
|
+
expect(n1).to.have.property('name', emailSenderConfigs.valid.name);
|
|
57
|
+
expect(n1).to.have.property('type', 'email-sender');
|
|
58
|
+
done();
|
|
59
|
+
} catch (err) {
|
|
60
|
+
done(err);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should load with minimal configuration', function (done) {
|
|
66
|
+
// ARRANGE: Use minimal test config from helpers
|
|
67
|
+
const flow = [emailSenderConfigs.minimal];
|
|
68
|
+
|
|
69
|
+
// ACT: Load the node
|
|
70
|
+
helper.load(emailSenderNode, flow, function () {
|
|
71
|
+
try {
|
|
72
|
+
// ASSERT: Verify the node loaded with minimal config
|
|
73
|
+
const n1 = helper.getNode(emailSenderConfigs.minimal.id);
|
|
74
|
+
expect(n1).to.exist;
|
|
75
|
+
expect(n1).to.have.property('type', 'email-sender');
|
|
76
|
+
done();
|
|
77
|
+
} catch (err) {
|
|
78
|
+
done(err);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
describe('Node Connections', function () {
|
|
85
|
+
it('should create wired connections correctly', function (done) {
|
|
86
|
+
// ARRANGE: Use connected test flow from helpers
|
|
87
|
+
const flow = testFlows.connected;
|
|
88
|
+
|
|
89
|
+
// ACT: Load nodes and verify connections
|
|
90
|
+
helper.load(emailSenderNode, flow, function () {
|
|
91
|
+
try {
|
|
92
|
+
const n1 = helper.getNode(emailSenderConfigs.valid.id);
|
|
93
|
+
const h1 = helper.getNode('h1');
|
|
94
|
+
|
|
95
|
+
// ASSERT: Both nodes should exist and be connected
|
|
96
|
+
expect(n1).to.exist;
|
|
97
|
+
expect(h1).to.exist;
|
|
98
|
+
expect(n1).to.have.property('name', emailSenderConfigs.valid.name);
|
|
99
|
+
expect(h1).to.have.property('type', 'helper');
|
|
100
|
+
|
|
101
|
+
done();
|
|
102
|
+
} catch (err) {
|
|
103
|
+
done(err);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('should handle multiple output connections', function (done) {
|
|
109
|
+
// ARRANGE: Use multi-output test flow from helpers
|
|
110
|
+
const flow = testFlows.multiOutput;
|
|
111
|
+
|
|
112
|
+
// ACT: Load nodes
|
|
113
|
+
helper.load(emailSenderNode, flow, function () {
|
|
114
|
+
try {
|
|
115
|
+
const n1 = helper.getNode(emailSenderConfigs.valid.id);
|
|
116
|
+
const h1 = helper.getNode('h1');
|
|
117
|
+
const h2 = helper.getNode('h2');
|
|
118
|
+
|
|
119
|
+
// ASSERT: All nodes should exist
|
|
120
|
+
expect(n1).to.exist;
|
|
121
|
+
expect(h1).to.exist;
|
|
122
|
+
expect(h2).to.exist;
|
|
123
|
+
expect(n1).to.have.property('name', emailSenderConfigs.valid.name);
|
|
124
|
+
|
|
125
|
+
done();
|
|
126
|
+
} catch (err) {
|
|
127
|
+
done(err);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
describe('Message Flow', function () {
|
|
134
|
+
it('should handle input without crashing', async function () {
|
|
135
|
+
// ARRANGE: Use test flow from helpers
|
|
136
|
+
const flow = testFlows.single;
|
|
137
|
+
|
|
138
|
+
return new Promise((resolve, reject) => {
|
|
139
|
+
helper.load(emailSenderNode, flow, function () {
|
|
140
|
+
try {
|
|
141
|
+
const n1 = helper.getNode(emailSenderConfigs.valid.id);
|
|
142
|
+
expect(n1).to.exist;
|
|
143
|
+
|
|
144
|
+
// Send input - this should not crash due to mocked IMAP
|
|
145
|
+
n1.receive({ payload: 'test input' });
|
|
146
|
+
|
|
147
|
+
// ASSERT: If we reach here, the node handled input gracefully
|
|
148
|
+
testUtils.wait(500).then(() => {
|
|
149
|
+
resolve(); // Success if no errors thrown
|
|
150
|
+
});
|
|
151
|
+
} catch (err) {
|
|
152
|
+
reject(err);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('should process messages through connected nodes', function (done) {
|
|
159
|
+
// ARRANGE: Use connected test flow from helpers
|
|
160
|
+
const flow = testFlows.connected;
|
|
161
|
+
|
|
162
|
+
// ACT: Load nodes and set up message listener
|
|
163
|
+
helper.load(emailSenderNode, flow, function () {
|
|
164
|
+
try {
|
|
165
|
+
const n1 = helper.getNode(emailSenderConfigs.valid.id);
|
|
166
|
+
const h1 = helper.getNode('h1');
|
|
167
|
+
|
|
168
|
+
// Set up listener for messages from email receiver
|
|
169
|
+
h1.on('input', function (msg) {
|
|
170
|
+
try {
|
|
171
|
+
// ASSERT: Should receive a message with expected properties
|
|
172
|
+
expect(msg).to.exist;
|
|
173
|
+
expect(msg.payload).to.exist;
|
|
174
|
+
done();
|
|
175
|
+
} catch (err) {
|
|
176
|
+
done(err);
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// Simulate the email processing
|
|
181
|
+
// The email-sender node likely starts processing emails automatically
|
|
182
|
+
// Let's trigger the mock IMAP flow by simulating what happens when emails are found
|
|
183
|
+
setTimeout(() => {
|
|
184
|
+
// Simulate the email receiver processing emails and sending a message
|
|
185
|
+
// This is what your email-sender node should do internally
|
|
186
|
+
try {
|
|
187
|
+
const mockEmailMessage = {
|
|
188
|
+
payload: 'This is a mock email body for testing purposes.',
|
|
189
|
+
topic: 'email',
|
|
190
|
+
from: 'sender@test.com',
|
|
191
|
+
subject: 'Mock Email Subject',
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
// Directly send a message through the node (simulating internal processing)
|
|
195
|
+
n1.send(mockEmailMessage);
|
|
196
|
+
} catch (err) {
|
|
197
|
+
done(err);
|
|
198
|
+
}
|
|
199
|
+
}, 100);
|
|
200
|
+
} catch (err) {
|
|
201
|
+
done(err);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('should handle message timeout gracefully', async function () {
|
|
207
|
+
// ARRANGE: Use connected test flow
|
|
208
|
+
const flow = testFlows.connected;
|
|
209
|
+
|
|
210
|
+
return new Promise((resolve, reject) => {
|
|
211
|
+
helper.load(emailSenderNode, flow, function () {
|
|
212
|
+
try {
|
|
213
|
+
const n1 = helper.getNode(emailSenderConfigs.valid.id);
|
|
214
|
+
const h1 = helper.getNode('h1');
|
|
215
|
+
|
|
216
|
+
// Use testUtils.waitForMessage with timeout
|
|
217
|
+
testUtils
|
|
218
|
+
.waitForMessage(h1, 1000)
|
|
219
|
+
.then((msg) => {
|
|
220
|
+
// ASSERT: Should receive message within timeout
|
|
221
|
+
expect(msg).to.exist;
|
|
222
|
+
resolve();
|
|
223
|
+
})
|
|
224
|
+
.catch((err) => {
|
|
225
|
+
// ASSERT: Should handle timeout appropriately
|
|
226
|
+
expect(err.message).to.include('Timeout waiting for message');
|
|
227
|
+
resolve(); // This is expected behavior for this test
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// Don't trigger anything to test timeout behavior
|
|
231
|
+
// The timeout should occur as expected
|
|
232
|
+
} catch (err) {
|
|
233
|
+
reject(err);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
});
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
const { expect } = require('chai');
|
|
2
|
+
const { createMockNodeRED, setupModuleMocks, testConfigs, testUtils } = require('../helpers/email-receiver.mocks.js');
|
|
3
|
+
|
|
4
|
+
describe('E-Mail Receiver Node - Unit Tests', function () {
|
|
5
|
+
this.timeout(10000);
|
|
6
|
+
|
|
7
|
+
let emailReceiverNode;
|
|
8
|
+
let cleanupMocks;
|
|
9
|
+
|
|
10
|
+
before(function () {
|
|
11
|
+
// Set up module mocks using helper
|
|
12
|
+
cleanupMocks = setupModuleMocks();
|
|
13
|
+
|
|
14
|
+
// Load the node with mocked dependencies
|
|
15
|
+
emailReceiverNode = require('../../email-receiver/email-receiver.js');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
after(function () {
|
|
19
|
+
// Clean up mocks
|
|
20
|
+
if (cleanupMocks) {
|
|
21
|
+
cleanupMocks();
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('Module Export', function () {
|
|
26
|
+
it('should export a function', function () {
|
|
27
|
+
expect(emailReceiverNode).to.be.a('function');
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('Node Registration', function () {
|
|
32
|
+
it('should register node type without errors', function () {
|
|
33
|
+
// ARRANGE: Create mock Node-RED with tracking
|
|
34
|
+
const mockRED = createMockNodeRED();
|
|
35
|
+
|
|
36
|
+
// ACT: Register the node
|
|
37
|
+
emailReceiverNode(mockRED);
|
|
38
|
+
|
|
39
|
+
// ASSERT: Verify registration
|
|
40
|
+
expect(mockRED.nodes.lastRegisteredType).to.equal('email-receiver');
|
|
41
|
+
expect(mockRED.nodes.lastRegisteredConstructor).to.be.a('function');
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe('Node Instantiation', function () {
|
|
46
|
+
it('should handle node instantiation with valid config', function () {
|
|
47
|
+
// ARRANGE: Track node creation
|
|
48
|
+
let createdNode = null;
|
|
49
|
+
const mockRED = createMockNodeRED({
|
|
50
|
+
onHandler: function (event, callback) {
|
|
51
|
+
createdNode = this;
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// ACT: Register and create node instance
|
|
56
|
+
emailReceiverNode(mockRED);
|
|
57
|
+
new mockRED.nodes.lastRegisteredConstructor(testConfigs.valid);
|
|
58
|
+
|
|
59
|
+
// ASSERT: Verify node was created with correct properties
|
|
60
|
+
expect(createdNode).to.exist;
|
|
61
|
+
expect(createdNode).to.have.property('name', testConfigs.valid.name);
|
|
62
|
+
expect(createdNode).to.have.property('id', testConfigs.valid.id);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should handle minimal config', function () {
|
|
66
|
+
// ARRANGE: Use minimal test config
|
|
67
|
+
let createdNode = null;
|
|
68
|
+
const mockRED = createMockNodeRED({
|
|
69
|
+
onHandler: function (event, callback) {
|
|
70
|
+
createdNode = this;
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// ACT: Register and create node with minimal config
|
|
75
|
+
emailReceiverNode(mockRED);
|
|
76
|
+
new mockRED.nodes.lastRegisteredConstructor(testConfigs.minimal);
|
|
77
|
+
|
|
78
|
+
// ASSERT: Verify node creation
|
|
79
|
+
expect(createdNode).to.exist;
|
|
80
|
+
expect(createdNode).to.have.property('id', testConfigs.minimal.id);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
describe('Folder Configuration', function () {
|
|
85
|
+
it('should handle array of folders', async function () {
|
|
86
|
+
// ARRANGE: Set up message tracking
|
|
87
|
+
let sentMessage = null;
|
|
88
|
+
const mockRED = createMockNodeRED({
|
|
89
|
+
sendHandler: function (msg) {
|
|
90
|
+
sentMessage = msg;
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// ACT: Register node and create instance with array folders
|
|
95
|
+
emailReceiverNode(mockRED);
|
|
96
|
+
const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
|
|
97
|
+
const nodeInstance = new nodeConstructor(testConfigs.arrayFolders);
|
|
98
|
+
|
|
99
|
+
// Wait for processing
|
|
100
|
+
await testUtils.wait(50);
|
|
101
|
+
|
|
102
|
+
// ASSERT: Should handle array folders without error
|
|
103
|
+
expect(nodeInstance).to.exist;
|
|
104
|
+
expect(nodeInstance).to.have.property('name', testConfigs.arrayFolders.name);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe('Error Handling', function () {
|
|
109
|
+
it('should call node.error for invalid folder type', function (done) {
|
|
110
|
+
// ARRANGE: Set up error tracking
|
|
111
|
+
const mockRED = createMockNodeRED({
|
|
112
|
+
onHandler: function (event, callback) {
|
|
113
|
+
if (event === 'input') {
|
|
114
|
+
this.inputCallback = callback;
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
errorHandler: function (err) {
|
|
118
|
+
// ASSERT: Should receive appropriate error message
|
|
119
|
+
expect(err).to.include("The 'folders' property must be an array of strings.");
|
|
120
|
+
done();
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// ACT: Register node and create instance with invalid config
|
|
125
|
+
emailReceiverNode(mockRED);
|
|
126
|
+
const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
|
|
127
|
+
const nodeInstance = new nodeConstructor(testConfigs.invalidFolderType);
|
|
128
|
+
|
|
129
|
+
// Trigger the error by sending an input message
|
|
130
|
+
// Use a small delay to ensure the constructor has completed
|
|
131
|
+
setTimeout(() => {
|
|
132
|
+
if (nodeInstance.inputCallback) {
|
|
133
|
+
nodeInstance.inputCallback({ payload: 'test' });
|
|
134
|
+
} else {
|
|
135
|
+
done(new Error('inputCallback was not set on the node instance'));
|
|
136
|
+
}
|
|
137
|
+
}, 10);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('should call node.error for missing config', function (done) {
|
|
141
|
+
// ARRANGE: Set up error and status tracking
|
|
142
|
+
let statusCalled = false;
|
|
143
|
+
const mockRED = createMockNodeRED({
|
|
144
|
+
onHandler: function (event, callback) {
|
|
145
|
+
if (event === 'input') {
|
|
146
|
+
this.inputCallback = callback;
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
statusHandler: function (status) {
|
|
150
|
+
statusCalled = true;
|
|
151
|
+
if (status.fill) {
|
|
152
|
+
expect(status.fill).to.equal('red');
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
errorHandler: function (err) {
|
|
156
|
+
// ASSERT: Should receive config error
|
|
157
|
+
expect(err).to.include('Missing required IMAP config');
|
|
158
|
+
expect(statusCalled).to.be.true;
|
|
159
|
+
done();
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// ACT: Register node and create instance with invalid config
|
|
164
|
+
emailReceiverNode(mockRED);
|
|
165
|
+
const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
|
|
166
|
+
const nodeInstance = new nodeConstructor(testConfigs.invalidConfig);
|
|
167
|
+
|
|
168
|
+
// Trigger the error by sending an input message
|
|
169
|
+
// Use a small delay to ensure the constructor has completed
|
|
170
|
+
setTimeout(() => {
|
|
171
|
+
if (nodeInstance.inputCallback) {
|
|
172
|
+
nodeInstance.inputCallback({ payload: 'test' });
|
|
173
|
+
} else {
|
|
174
|
+
done(new Error('inputCallback was not set on the node instance'));
|
|
175
|
+
}
|
|
176
|
+
}, 10);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('should handle connection errors gracefully', function (done) {
|
|
180
|
+
// ARRANGE: Set up connection error scenario with done() protection
|
|
181
|
+
let testCompleted = false;
|
|
182
|
+
|
|
183
|
+
const completeDone = () => {
|
|
184
|
+
if (!testCompleted) {
|
|
185
|
+
testCompleted = true;
|
|
186
|
+
done();
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const mockRED = createMockNodeRED({
|
|
191
|
+
onHandler: function (event, callback) {
|
|
192
|
+
if (event === 'input') {
|
|
193
|
+
this.inputCallback = callback;
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
statusHandler: function (status) {
|
|
197
|
+
if (status.fill === 'red' && status.text && status.text.includes('error')) {
|
|
198
|
+
completeDone(); // Success - error status was set
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
errorHandler: function (err) {
|
|
202
|
+
// Also accept errors as valid completion
|
|
203
|
+
expect(err).to.exist;
|
|
204
|
+
completeDone();
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Use a config that should cause connection issues
|
|
209
|
+
const badConfig = {
|
|
210
|
+
...testConfigs.valid,
|
|
211
|
+
host: 'nonexistent.invalid.host.com',
|
|
212
|
+
port: 12345, // Invalid port
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// ACT: Register node and create instance with invalid config
|
|
216
|
+
emailReceiverNode(mockRED);
|
|
217
|
+
const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
|
|
218
|
+
const nodeInstance = new nodeConstructor(badConfig);
|
|
219
|
+
|
|
220
|
+
// Trigger the error by sending an input message
|
|
221
|
+
// Use a small delay to ensure the constructor has completed
|
|
222
|
+
setTimeout(() => {
|
|
223
|
+
if (nodeInstance.inputCallback) {
|
|
224
|
+
nodeInstance.inputCallback({ payload: 'test' });
|
|
225
|
+
} else {
|
|
226
|
+
completeDone(new Error('inputCallback was not set on the node instance'));
|
|
227
|
+
}
|
|
228
|
+
}, 10);
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
describe('IMAP Connection', function () {
|
|
233
|
+
it('should handle connection success', function (done) {
|
|
234
|
+
// ARRANGE: Set up connection tracking
|
|
235
|
+
const mockRED = createMockNodeRED({
|
|
236
|
+
onHandler: function (event, callback) {
|
|
237
|
+
if (event === 'input') {
|
|
238
|
+
this.inputCallback = callback;
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
statusHandler: function (status) {
|
|
242
|
+
// ASSERT: Check for 'connected' status and then complete the test
|
|
243
|
+
if (status.fill === 'green' && status.text === 'connected') {
|
|
244
|
+
done();
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// ACT: Create node with config that should fail
|
|
250
|
+
emailReceiverNode(mockRED);
|
|
251
|
+
const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
|
|
252
|
+
const nodeInstance = new nodeConstructor(testConfigs.valid);
|
|
253
|
+
|
|
254
|
+
// Trigger the connection attempt by sending an input message
|
|
255
|
+
setTimeout(() => {
|
|
256
|
+
if (nodeInstance.inputCallback) {
|
|
257
|
+
nodeInstance.inputCallback({ payload: 'test' });
|
|
258
|
+
} else {
|
|
259
|
+
done(new Error('inputCallback was not set on the node instance'));
|
|
260
|
+
}
|
|
261
|
+
}, 10);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it('should handle connection errors', function (done) {
|
|
265
|
+
// ARRANGE: Set up error tracking
|
|
266
|
+
const mockRED = createMockNodeRED({
|
|
267
|
+
onHandler: function (event, callback) {
|
|
268
|
+
if (event === 'input') {
|
|
269
|
+
// Store the callback on the node instance
|
|
270
|
+
this.inputCallback = callback;
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
errorHandler: function (err) {
|
|
274
|
+
// ASSERT: Should handle connection errors gracefully
|
|
275
|
+
expect(err).to.exist;
|
|
276
|
+
done();
|
|
277
|
+
},
|
|
278
|
+
statusHandler: function (status) {
|
|
279
|
+
if (status.fill === 'red') {
|
|
280
|
+
// Connection failed status
|
|
281
|
+
expect(status.text).to.include('error');
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
// ACT: Create node with config that should fail
|
|
287
|
+
emailReceiverNode(mockRED);
|
|
288
|
+
const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
|
|
289
|
+
|
|
290
|
+
// Use invalid config to trigger connection error
|
|
291
|
+
const invalidConfig = { ...testConfigs.valid, host: 'invalid.host.com' };
|
|
292
|
+
const nodeInstance = new nodeConstructor(invalidConfig);
|
|
293
|
+
|
|
294
|
+
// Trigger the connection attempt by sending an input message
|
|
295
|
+
setTimeout(() => {
|
|
296
|
+
if (nodeInstance.inputCallback) {
|
|
297
|
+
nodeInstance.inputCallback({ payload: 'test' });
|
|
298
|
+
} else {
|
|
299
|
+
done(new Error('inputCallback was not set on the node instance'));
|
|
300
|
+
}
|
|
301
|
+
}, 10);
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
});
|