@5minds/node-red-contrib-processcube-tools 1.0.1-develop-8bf22b-mffg2ve3 → 1.0.1-develop-4412ca-mfm8hzs3

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.
@@ -1,309 +1,304 @@
1
- const should = require('should');
2
- const {
3
- createMockNodeRED,
4
- setupModuleMocks,
5
- testConfigs,
6
- testUtils
7
- } = require('../helpers/email-receiver.mocks.js');
8
-
9
- describe('Email Receiver Node - Unit Tests with Helpers', function() {
10
- this.timeout(10000);
11
-
12
- let emailReceiverNode;
13
- let cleanupMocks;
14
-
15
- before(function() {
16
- // Set up module mocks using helper
17
- cleanupMocks = setupModuleMocks();
18
-
19
- // Load the node with mocked dependencies
20
- emailReceiverNode = require('../../email-receiver/email-receiver.js');
21
- });
22
-
23
- after(function() {
24
- // Clean up mocks
25
- if (cleanupMocks) {
26
- cleanupMocks();
27
- }
28
- });
29
-
30
- describe('Module Export', function() {
31
- it('should export a function', function() {
32
- emailReceiverNode.should.be.type('function');
33
- });
34
- });
35
-
36
- describe('Node Registration', function() {
37
- it('should register node type without errors', function() {
38
- // ARRANGE: Create mock Node-RED with tracking
39
- const mockRED = createMockNodeRED();
1
+ const { expect } = require('chai');
2
+ const { createMockNodeRED, setupModuleMocks, testConfigs, testUtils } = require('../helpers/email-receiver.mocks.js');
40
3
 
41
- // ACT: Register the node
42
- emailReceiverNode(mockRED);
4
+ describe('E-Mail Receiver Node - Unit Tests', function () {
5
+ this.timeout(10000);
43
6
 
44
- // ASSERT: Verify registration
45
- mockRED.nodes.lastRegisteredType.should.equal('email-receiver');
46
- mockRED.nodes.lastRegisteredConstructor.should.be.type('function');
47
- });
48
- });
49
-
50
- describe('Node Instantiation', function() {
51
- it('should handle node instantiation with valid config', function() {
52
- // ARRANGE: Track node creation
53
- let createdNode = null;
54
- const mockRED = createMockNodeRED({
55
- onHandler: function(event, callback) {
56
- createdNode = this;
57
- }
58
- });
7
+ let emailReceiverNode;
8
+ let cleanupMocks;
59
9
 
60
- // ACT: Register and create node instance
61
- emailReceiverNode(mockRED);
62
- new mockRED.nodes.lastRegisteredConstructor(testConfigs.valid);
10
+ before(function () {
11
+ // Set up module mocks using helper
12
+ cleanupMocks = setupModuleMocks();
63
13
 
64
- // ASSERT: Verify node was created with correct properties
65
- should.exist(createdNode);
66
- createdNode.should.have.property('name', testConfigs.valid.name);
67
- createdNode.should.have.property('id', testConfigs.valid.id);
14
+ // Load the node with mocked dependencies
15
+ emailReceiverNode = require('../../email-receiver/email-receiver.js');
68
16
  });
69
17
 
70
- it('should handle minimal config', function() {
71
- // ARRANGE: Use minimal test config
72
- let createdNode = null;
73
- const mockRED = createMockNodeRED({
74
- onHandler: function(event, callback) {
75
- createdNode = this;
18
+ after(function () {
19
+ // Clean up mocks
20
+ if (cleanupMocks) {
21
+ cleanupMocks();
76
22
  }
77
- });
78
-
79
- // ACT: Register and create node with minimal config
80
- emailReceiverNode(mockRED);
81
- new mockRED.nodes.lastRegisteredConstructor(testConfigs.minimal);
23
+ });
82
24
 
83
- // ASSERT: Verify node creation
84
- should.exist(createdNode);
85
- createdNode.should.have.property('id', testConfigs.minimal.id);
25
+ describe('Module Export', function () {
26
+ it('should export a function', function () {
27
+ expect(emailReceiverNode).to.be.a('function');
28
+ });
86
29
  });
87
- });
88
-
89
- describe('Folder Configuration', function() {
90
- it('should handle array of folders', async function() {
91
- // ARRANGE: Set up message tracking
92
- let sentMessage = null;
93
- const mockRED = createMockNodeRED({
94
- sendHandler: function(msg) {
95
- sentMessage = msg;
96
- }
97
- });
98
30
 
99
- // ACT: Register node and create instance with array folders
100
- emailReceiverNode(mockRED);
101
- const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
102
- const nodeInstance = new nodeConstructor(testConfigs.arrayFolders);
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();
103
35
 
104
- // Wait for processing
105
- await testUtils.wait(50);
36
+ // ACT: Register the node
37
+ emailReceiverNode(mockRED);
106
38
 
107
- // ASSERT: Should handle array folders without error
108
- should.exist(nodeInstance);
109
- nodeInstance.should.have.property('name', testConfigs.arrayFolders.name);
110
- });
111
- });
112
-
113
- describe('Error Handling', function() {
114
- it('should call node.error for invalid folder type', function(done) {
115
- // ARRANGE: Set up error tracking
116
- const mockRED = createMockNodeRED({
117
- onHandler: function(event, callback) {
118
- if (event === 'input') {
119
- this.inputCallback = callback;
120
- }
121
- },
122
- errorHandler: function(err) {
123
- // ASSERT: Should receive appropriate error message
124
- err.should.containEql("The 'folders' property must be an array of strings.");
125
- done();
126
- }
127
- });
128
-
129
- // ACT: Register node and create instance with invalid config
130
- emailReceiverNode(mockRED);
131
- const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
132
- const nodeInstance = new nodeConstructor(testConfigs.invalidFolderType);
133
-
134
- // Trigger the error by sending an input message
135
- // Use a small delay to ensure the constructor has completed
136
- setTimeout(() => {
137
- if (nodeInstance.inputCallback) {
138
- nodeInstance.inputCallback({ payload: "test" });
139
- } else {
140
- done(new Error('inputCallback was not set on the node instance'));
141
- }
142
- }, 10);
39
+ // ASSERT: Verify registration
40
+ expect(mockRED.nodes.lastRegisteredType).to.equal('email-receiver');
41
+ expect(mockRED.nodes.lastRegisteredConstructor).to.be.a('function');
42
+ });
143
43
  });
144
44
 
145
- it('should call node.error for missing config', function(done) {
146
- // ARRANGE: Set up error and status tracking
147
- let statusCalled = false;
148
- const mockRED = createMockNodeRED({
149
- onHandler: function(event, callback) {
150
- if (event === 'input') {
151
- this.inputCallback = callback;
152
- }
153
- },
154
- statusHandler: function(status) {
155
- statusCalled = true;
156
- if (status.fill) {
157
- status.fill.should.equal('red');
158
- }
159
- },
160
- errorHandler: function(err) {
161
- // ASSERT: Should receive config error
162
- err.should.containEql('Missing required IMAP config');
163
- statusCalled.should.be.true();
164
- done();
165
- }
166
- });
167
-
168
- // ACT: Register node and create instance with invalid config
169
- emailReceiverNode(mockRED);
170
- const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
171
- const nodeInstance = new nodeConstructor(testConfigs.invalidConfig);
172
-
173
- // Trigger the error by sending an input message
174
- // Use a small delay to ensure the constructor has completed
175
- setTimeout(() => {
176
- if (nodeInstance.inputCallback) {
177
- nodeInstance.inputCallback({ payload: "test" });
178
- } else {
179
- done(new Error('inputCallback was not set on the node instance'));
180
- }
181
- }, 10);
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
+ });
182
82
  });
183
83
 
184
- it('should handle connection errors gracefully', function(done) {
185
- // ARRANGE: Set up connection error scenario with done() protection
186
- let testCompleted = false;
187
-
188
- const completeDone = () => {
189
- if (!testCompleted) {
190
- testCompleted = true;
191
- done();
192
- }
193
- };
194
-
195
- const mockRED = createMockNodeRED({
196
- onHandler: function(event, callback) {
197
- if (event === 'input') {
198
- this.inputCallback = callback;
199
- }
200
- },
201
- statusHandler: function(status) {
202
- if (status.fill === 'red' && status.text && status.text.includes('error')) {
203
- completeDone(); // Success - error status was set
204
- }
205
- },
206
- errorHandler: function(err) {
207
- // Also accept errors as valid completion
208
- should.exist(err);
209
- completeDone();
210
- }
211
- });
212
-
213
- // Use a config that should cause connection issues
214
- const badConfig = {
215
- ...testConfigs.valid,
216
- host: 'nonexistent.invalid.host.com',
217
- port: 12345 // Invalid port
218
- };
219
-
220
- // ACT: Register node and create instance with invalid config
221
- emailReceiverNode(mockRED);
222
- const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
223
- const nodeInstance = new nodeConstructor(badConfig);
224
-
225
- // Trigger the error by sending an input message
226
- // Use a small delay to ensure the constructor has completed
227
- setTimeout(() => {
228
- if (nodeInstance.inputCallback) {
229
- nodeInstance.inputCallback({ payload: "test" });
230
- } else {
231
- completeDone(new Error('inputCallback was not set on the node instance'));
232
- }
233
- }, 10);
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
+ });
234
106
  });
235
- });
236
-
237
- describe('IMAP Connection', function() {
238
- it('should handle connection success', function(done) {
239
- // ARRANGE: Set up connection tracking
240
- const mockRED = createMockNodeRED({
241
- onHandler: function(event, callback) {
242
- if (event === 'input') {
243
- this.inputCallback = callback;
244
- }
245
- },
246
- statusHandler: function(status) {
247
- // ASSERT: Check for 'connected' status and then complete the test
248
- if (status.fill === 'green' && status.text === 'connected') {
249
- done();
250
- }
251
- }
252
- });
253
-
254
- // ACT: Create node with config that should fail
255
- emailReceiverNode(mockRED);
256
- const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
257
- const nodeInstance = new nodeConstructor(testConfigs.valid);
258
-
259
- // Trigger the connection attempt by sending an input message
260
- setTimeout(() => {
261
- if (nodeInstance.inputCallback) {
262
- nodeInstance.inputCallback({ payload: "test" });
263
- } else {
264
- done(new Error('inputCallback was not set on the node instance'));
265
- }
266
- }, 10);
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
+ });
267
230
  });
268
231
 
269
- it('should handle connection errors', function(done) {
270
- // ARRANGE: Set up error tracking
271
- const mockRED = createMockNodeRED({
272
- onHandler: function(event, callback) {
273
- if (event === 'input') {
274
- // Store the callback on the node instance
275
- this.inputCallback = callback;
276
- }
277
- },
278
- errorHandler: function(err) {
279
- // ASSERT: Should handle connection errors gracefully
280
- should.exist(err);
281
- done();
282
- },
283
- statusHandler: function(status) {
284
- if (status.fill === 'red') {
285
- // Connection failed status
286
- status.text.should.containEql('error');
287
- }
288
- }
289
- });
290
-
291
- // ACT: Create node with config that should fail
292
- emailReceiverNode(mockRED);
293
- const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
294
-
295
- // Use invalid config to trigger connection error
296
- const invalidConfig = { ...testConfigs.valid, host: 'invalid.host.com' };
297
- const nodeInstance = new nodeConstructor(invalidConfig);
298
-
299
- // Trigger the connection attempt by sending an input message
300
- setTimeout(() => {
301
- if (nodeInstance.inputCallback) {
302
- nodeInstance.inputCallback({ payload: "test" });
303
- } else {
304
- done(new Error('inputCallback was not set on the node instance'));
305
- }
306
- }, 10);
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
+ });
307
303
  });
308
- });
309
- });
304
+ });