@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.
@@ -3,450 +3,445 @@
3
3
  */
4
4
 
5
5
  /**
6
- * Mock IMAP implementation for testing
6
+ * Create mock Node-RED object for unit testing
7
7
  */
8
- function createMockImap() {
9
- return function MockImap(config) {
10
- this.config = config;
11
- this.events = {};
12
-
13
- // Simulate connection behavior
14
- this.connect = () => {
15
- // Check if we should simulate a connection error
16
- if (this.config.host && this.config.host.includes('invalid')) {
17
- // Simulate connection error
18
- if (this.events && this.events.error) {
19
- setTimeout(() => {
20
- const error = new Error('Connection failed');
21
- error.code = 'ENOTFOUND';
22
- this.events.error(error);
23
- }, 10);
24
- }
25
- } else {
26
- // Simulate successful connection by emitting 'ready' event
27
- if (this.events && this.events.ready) {
28
- setTimeout(() => this.events.ready(), 10);
29
- }
30
- }
31
- };
8
+ function createMockNodeRED(options = {}) {
9
+ // Store input callback in the mock RED context
10
+ let storedInputCallback = null;
11
+ let nodeInstance = null;
12
+
13
+ const mockRED = {
14
+ nodes: {
15
+ createNode: function (node, config) {
16
+ nodeInstance = node; // Capture the node instance
17
+
18
+ // Apply config properties to node
19
+ Object.assign(node, {
20
+ id: config.id || 'mock-node-id',
21
+ type: config.type || 'email-receiver',
22
+ name: config.name || 'Mock Node',
23
+ on: function (event, callback) {
24
+ if (event === 'input') {
25
+ storedInputCallback = callback;
26
+ // Store the callback on the node instance for easy access
27
+ node.inputCallback = callback;
28
+ }
29
+ // Call the original onHandler if provided
30
+ if (options.onHandler) {
31
+ options.onHandler.call(node, event, callback);
32
+ }
33
+ },
34
+ status: options.statusHandler || function () {},
35
+ error: options.errorHandler || function () {},
36
+ send: options.sendHandler || function () {},
37
+ log: options.logHandler || function () {},
38
+ warn: options.warnHandler || function () {},
39
+ debug: options.debugHandler || function () {},
40
+ });
41
+ return node;
42
+ },
43
+ registerType: function (type, constructor) {
44
+ // Store registration for verification in tests
45
+ this.lastRegisteredType = type;
46
+ this.lastRegisteredConstructor = constructor;
47
+ },
48
+ // Helper method to get the stored input callback
49
+ getInputCallback: function () {
50
+ return storedInputCallback;
51
+ },
52
+ // Helper method to get the node instance
53
+ getNodeInstance: function () {
54
+ return nodeInstance;
55
+ },
56
+ },
57
+ util: {
58
+ evaluateNodeProperty: function (value, type, node, msg, callback) {
59
+ if (type === 'json') {
60
+ try {
61
+ // Simulate parsing a JSON string into an object
62
+ return JSON.parse(JSON.stringify(value));
63
+ } catch (e) {
64
+ if (callback) {
65
+ callback(e, null);
66
+ }
67
+ return null;
68
+ }
69
+ }
32
70
 
33
- // Simulate opening a mailbox
34
- this.openBox = (folder, readOnly, callback) => {
35
- setTimeout(() => {
36
- callback(null, {
37
- messages: { total: 1 },
38
- name: folder,
39
- readOnly: readOnly
40
- });
41
- }, 10);
71
+ // Simple mock implementation
72
+ if (callback) {
73
+ callback(null, value);
74
+ }
75
+ return value;
76
+ },
77
+ encrypt: function (value) {
78
+ return 'encrypted:' + value;
79
+ },
80
+ decrypt: function (value) {
81
+ return value.replace('encrypted:', '');
82
+ },
83
+ },
84
+ log: {
85
+ info: options.logInfo || function () {},
86
+ warn: options.logWarn || function () {},
87
+ error: options.logError || function () {},
88
+ debug: options.logDebug || function () {},
89
+ },
42
90
  };
43
91
 
44
- // Simulate searching for emails
45
- this.search = (criteria, callback) => {
46
- setTimeout(() => {
47
- // Return mock message IDs
48
- callback(null, [123, 456, 789]);
49
- }, 10);
50
- };
92
+ return mockRED;
93
+ }
51
94
 
52
- // Simulate fetching email messages
53
- this.fetch = (results, options) => {
54
- const fetchEmitter = {
55
- on: (event, callback) => {
56
- if (event === 'message') {
57
- setTimeout(() => {
58
- const mockMessage = {
59
- on: (messageEvent, messageCallback) => {
60
- if (messageEvent === 'body') {
61
- setTimeout(() => {
62
- // Return a mock email body that will be parsed
63
- const mockEmailContent = `From: sender@test.com\r\nTo: recipient@test.com\r\nSubject: Mock Email Subject\r\n\r\nThis is a mock email body for testing purposes.`;
64
- messageCallback(Buffer.from(mockEmailContent));
65
- }, 5);
66
- } else if (messageEvent === 'attributes') {
95
+ /**
96
+ * Mock IMAP implementation for testing
97
+ */
98
+ function createMockImap() {
99
+ return function MockImap(config) {
100
+ this.config = config;
101
+ this.events = {};
102
+
103
+ // Simulate connection behavior
104
+ this.connect = () => {
105
+ // Check if we should simulate a connection error
106
+ if (this.config.host && this.config.host.includes('invalid')) {
107
+ // Simulate connection error
108
+ if (this.events && this.events.error) {
67
109
  setTimeout(() => {
68
- messageCallback({
69
- uid: 123,
70
- flags: ['\\Seen'],
71
- date: new Date(),
72
- size: 1024
73
- });
74
- }, 5);
75
- }
76
- },
77
- once: (messageEvent, messageCallback) => {
78
- if (messageEvent === 'end') {
79
- setTimeout(() => messageCallback(), 15);
80
- }
110
+ const error = new Error('Connection failed');
111
+ error.code = 'ENOTFOUND';
112
+ this.events.error(error);
113
+ }, 10);
81
114
  }
82
- };
83
- callback(mockMessage);
84
- }, 10);
85
- }
86
- },
87
- once: (event, callback) => {
88
- if (event === 'end') {
89
- setTimeout(() => callback(), 20);
90
- } else if (event === 'error') {
91
- // Store error callback for potential use
92
- this.errorCallback = callback;
93
- }
94
- }
95
- };
96
-
97
- // Store the fetch emitter so we can trigger events manually in tests
98
- this.lastFetchEmitter = fetchEmitter;
99
- return fetchEmitter;
100
- };
101
-
102
- // Simulate closing connection
103
- this.end = () => {
104
- if (this.events && this.events.end) {
105
- setTimeout(() => this.events.end(), 5);
106
- }
107
- };
115
+ } else {
116
+ // Simulate successful connection by emitting 'ready' event
117
+ if (this.events && this.events.ready) {
118
+ setTimeout(() => this.events.ready(), 10);
119
+ }
120
+ }
121
+ };
108
122
 
109
- // Event listener setup
110
- this.once = (event, callback) => {
111
- if (!this.events) this.events = {};
112
- this.events[event] = callback;
113
- };
123
+ // Simulate opening a mailbox
124
+ this.openBox = (folder, readOnly, callback) => {
125
+ setTimeout(() => {
126
+ callback(null, {
127
+ messages: { total: 1 },
128
+ name: folder,
129
+ readOnly: readOnly,
130
+ });
131
+ }, 10);
132
+ };
114
133
 
115
- this.on = (event, callback) => {
116
- if (!this.events) this.events = {};
117
- this.events[event] = callback;
118
- };
134
+ // Simulate searching for emails
135
+ this.search = (criteria, callback) => {
136
+ setTimeout(() => {
137
+ // Return mock message IDs
138
+ callback(null, [123, 456, 789]);
139
+ }, 10);
140
+ };
141
+
142
+ // Simulate fetching email messages
143
+ this.fetch = (results, options) => {
144
+ const fetchEmitter = {
145
+ on: (event, callback) => {
146
+ if (event === 'message') {
147
+ setTimeout(() => {
148
+ const mockMessage = {
149
+ on: (messageEvent, messageCallback) => {
150
+ if (messageEvent === 'body') {
151
+ setTimeout(() => {
152
+ // Return a mock email body that will be parsed
153
+ const mockEmailContent = `From: sender@test.com\r\nTo: recipient@test.com\r\nSubject: Mock Email Subject\r\n\r\nThis is a mock email body for testing purposes.`;
154
+ messageCallback(Buffer.from(mockEmailContent));
155
+ }, 5);
156
+ } else if (messageEvent === 'attributes') {
157
+ setTimeout(() => {
158
+ messageCallback({
159
+ uid: 123,
160
+ flags: ['\\Seen'],
161
+ date: new Date(),
162
+ size: 1024,
163
+ });
164
+ }, 5);
165
+ }
166
+ },
167
+ once: (messageEvent, messageCallback) => {
168
+ if (messageEvent === 'end') {
169
+ setTimeout(() => messageCallback(), 15);
170
+ }
171
+ },
172
+ };
173
+ callback(mockMessage);
174
+ }, 10);
175
+ }
176
+ },
177
+ once: (event, callback) => {
178
+ if (event === 'end') {
179
+ setTimeout(() => callback(), 20);
180
+ } else if (event === 'error') {
181
+ // Store error callback for potential use
182
+ this.errorCallback = callback;
183
+ }
184
+ },
185
+ };
119
186
 
120
- // Additional IMAP methods that might be used
121
- this.addFlags = (source, flags, callback) => {
122
- setTimeout(() => callback(null), 5);
123
- };
187
+ // Store the fetch emitter so we can trigger events manually in tests
188
+ this.lastFetchEmitter = fetchEmitter;
189
+ return fetchEmitter;
190
+ };
124
191
 
125
- this.removeFlags = (source, flags, callback) => {
126
- setTimeout(() => callback(null), 5);
127
- };
192
+ // Simulate closing connection
193
+ this.end = () => {
194
+ if (this.events && this.events.end) {
195
+ setTimeout(() => this.events.end(), 5);
196
+ }
197
+ };
198
+
199
+ // Event listener setup
200
+ this.once = (event, callback) => {
201
+ if (!this.events) this.events = {};
202
+ this.events[event] = callback;
203
+ };
204
+
205
+ this.on = (event, callback) => {
206
+ if (!this.events) this.events = {};
207
+ this.events[event] = callback;
208
+ };
209
+
210
+ // Additional IMAP methods that might be used
211
+ this.addFlags = (source, flags, callback) => {
212
+ setTimeout(() => callback(null), 5);
213
+ };
214
+
215
+ this.removeFlags = (source, flags, callback) => {
216
+ setTimeout(() => callback(null), 5);
217
+ };
218
+
219
+ // Helper method to trigger the email processing flow
220
+ this.simulateNewEmail = (emailData = {}) => {
221
+ if (this.events && this.events.mail) {
222
+ setTimeout(() => {
223
+ this.events.mail(1); // Simulate 1 new email
224
+ }, 10);
225
+ }
226
+ };
128
227
 
129
- // Helper method to trigger the email processing flow
130
- this.simulateNewEmail = (emailData = {}) => {
131
- if (this.events && this.events.mail) {
132
- setTimeout(() => {
133
- this.events.mail(1); // Simulate 1 new email
134
- }, 10);
135
- }
228
+ return this;
136
229
  };
137
-
138
- return this;
139
- };
140
230
  }
141
231
 
142
232
  /**
143
233
  * Mock Mailparser implementation for testing
144
234
  */
145
235
  function createMockMailparser() {
146
- return {
147
- simpleParser: function(source, options = {}) {
148
- return Promise.resolve({
149
- subject: options.subject || 'Mock Email Subject',
150
- text: options.text || 'This is a mock email body for testing purposes.',
151
- html: options.html || '<p>This is a mock email body for testing purposes.</p>',
152
- from: {
153
- text: options.from || 'sender@test.com',
154
- value: [{ address: options.from || 'sender@test.com', name: 'Test Sender' }]
155
- },
156
- to: {
157
- text: options.to || 'recipient@test.com',
158
- value: [{ address: options.to || 'recipient@test.com', name: 'Test Recipient' }]
236
+ return {
237
+ simpleParser: function (source, options = {}) {
238
+ return Promise.resolve({
239
+ subject: options.subject || 'Mock Email Subject',
240
+ text: options.text || 'This is a mock email body for testing purposes.',
241
+ html: options.html || '<p>This is a mock email body for testing purposes.</p>',
242
+ from: {
243
+ text: options.from || 'sender@test.com',
244
+ value: [{ address: options.from || 'sender@test.com', name: 'Test Sender' }],
245
+ },
246
+ to: {
247
+ text: options.to || 'recipient@test.com',
248
+ value: [{ address: options.to || 'recipient@test.com', name: 'Test Recipient' }],
249
+ },
250
+ date: options.date || new Date(),
251
+ messageId: options.messageId || '<mock-message-id@test.com>',
252
+ headers: new Map([
253
+ ['message-id', '<mock-message-id@test.com>'],
254
+ ['subject', options.subject || 'Mock Email Subject'],
255
+ ['from', options.from || 'sender@test.com'],
256
+ ['to', options.to || 'recipient@test.com'],
257
+ ]),
258
+ attachments: options.attachments || [],
259
+ });
159
260
  },
160
- date: options.date || new Date(),
161
- messageId: options.messageId || '<mock-message-id@test.com>',
162
- headers: new Map([
163
- ['message-id', '<mock-message-id@test.com>'],
164
- ['subject', options.subject || 'Mock Email Subject'],
165
- ['from', options.from || 'sender@test.com'],
166
- ['to', options.to || 'recipient@test.com']
167
- ]),
168
- attachments: options.attachments || []
169
- });
170
- }
171
- };
261
+ };
172
262
  }
173
263
 
174
264
  /**
175
- * Create mock Node-RED object for unit testing
265
+ * Enhanced module mocks setup with better email simulation
176
266
  */
177
- function createMockNodeRED(options = {}) {
178
- // Store input callback in the mock RED context
179
- let storedInputCallback = null;
180
- let nodeInstance = null;
181
-
182
- const mockRED = {
183
- nodes: {
184
- createNode: function(node, config) {
185
- nodeInstance = node; // Capture the node instance
186
-
187
- // Apply config properties to node
188
- Object.assign(node, {
189
- id: config.id || 'mock-node-id',
190
- type: config.type || 'email-receiver',
191
- name: config.name || 'Mock Node',
192
- on: function(event, callback) {
193
- if (event === 'input') {
194
- storedInputCallback = callback;
195
- // Store the callback on the node instance for easy access
196
- node.inputCallback = callback;
197
- }
198
- // Call the original onHandler if provided
199
- if (options.onHandler) {
200
- options.onHandler.call(node, event, callback);
201
- }
202
- },
203
- status: options.statusHandler || function() {},
204
- error: options.errorHandler || function() {},
205
- send: options.sendHandler || function() {},
206
- log: options.logHandler || function() {},
207
- warn: options.warnHandler || function() {},
208
- debug: options.debugHandler || function() {}
209
- });
210
- return node;
211
- },
212
- registerType: function(type, constructor) {
213
- // Store registration for verification in tests
214
- this.lastRegisteredType = type;
215
- this.lastRegisteredConstructor = constructor;
216
- },
217
- // Helper method to get the stored input callback
218
- getInputCallback: function() {
219
- return storedInputCallback;
220
- },
221
- // Helper method to get the node instance
222
- getNodeInstance: function() {
223
- return nodeInstance;
224
- }
225
- },
226
- util: {
227
- evaluateNodeProperty: function(value, type, node, msg, callback) {
228
- if (type === 'json') {
229
- try {
230
- // Simulate parsing a JSON string into an object
231
- return JSON.parse(JSON.stringify(value));
232
- } catch (e) {
233
- if (callback) {
234
- callback(e, null);
235
- }
236
- return null;
237
- }
238
- }
267
+ function setupModuleMocks() {
268
+ const mockModules = {
269
+ 'node-imap': createMockImap(),
270
+ mailparser: createMockMailparser(),
271
+ };
272
+
273
+ const Module = require('module');
274
+ const originalLoad = Module._load;
239
275
 
240
- // Simple mock implementation
241
- if (callback) {
242
- callback(null, value);
276
+ Module._load = function (request, parent) {
277
+ if (mockModules[request]) {
278
+ return mockModules[request];
243
279
  }
244
- return value;
245
- },
246
- encrypt: function(value) {
247
- return 'encrypted:' + value;
248
- },
249
- decrypt: function(value) {
250
- return value.replace('encrypted:', '');
251
- }
252
- },
253
- log: {
254
- info: options.logInfo || function() {},
255
- warn: options.logWarn || function() {},
256
- error: options.logError || function() {},
257
- debug: options.logDebug || function() {}
258
- }
259
- };
260
-
261
- return mockRED;
262
- }
280
+ return originalLoad.apply(this, arguments);
281
+ };
263
282
 
264
- /**
265
- * Enhanced module mocks setup with better email simulation
266
- */
267
- function setupModuleMocks() {
268
- const mockModules = {
269
- 'node-imap': createMockImap(),
270
- 'mailparser': createMockMailparser()
271
- };
272
-
273
- const Module = require('module');
274
- const originalLoad = Module._load;
275
-
276
- Module._load = function(request, parent) {
277
- if (mockModules[request]) {
278
- return mockModules[request];
279
- }
280
- return originalLoad.apply(this, arguments);
281
- };
282
-
283
- // Return cleanup function
284
- return function cleanup() {
285
- Module._load = originalLoad;
286
- };
283
+ // Return cleanup function
284
+ return function cleanup() {
285
+ Module._load = originalLoad;
286
+ };
287
287
  }
288
288
 
289
289
  /**
290
290
  * Create test configurations for different scenarios
291
291
  */
292
292
  const testConfigs = {
293
- valid: {
294
- id: 'test-node-1',
295
- type: 'email-receiver',
296
- name: 'Test Email Receiver',
297
- host: 'imap.test.com',
298
- hostType: 'str',
299
- port: 993,
300
- portType: 'num',
301
- tls: true,
302
- tlsType: 'bool',
303
- user: 'test@test.com',
304
- userType: 'str',
305
- password: 'testpass',
306
- passwordType: 'str',
307
- folder: ['INBOX'],
308
- folderType: 'str',
309
- markseen: true,
310
- markseenType: 'bool'
311
- },
312
-
313
- arrayFolders: {
314
- id: 'test-node-3',
315
- type: 'email-receiver',
316
- name: 'Array Folders Test',
317
- host: 'imap.test.com',
318
- hostType: 'str',
319
- port: 993,
320
- portType: 'num',
321
- user: 'test@test.com',
322
- userType: 'str',
323
- password: 'testpass',
324
- passwordType: 'str',
325
- folder: ['INBOX', 'Junk', 'Drafts'],
326
- folderType: 'json',
327
- markseen: false,
328
- markseenType: 'bool'
329
- },
330
-
331
- invalidFolderType: {
332
- id: 'test-node-4',
333
- type: 'email-receiver',
334
- name: 'Invalid Config Test',
335
- host: '', // Missing host
336
- hostType: 'str',
337
- port: 993,
338
- portType: 'num',
339
- user: 'test@test.com',
340
- userType: 'str',
341
- password: '', // Missing password
342
- passwordType: 'str',
343
- folder: 123,
344
- folderType: 'num'
345
- },
346
-
347
- invalidConfig: {
348
- id: 'test-node-4',
349
- type: 'email-receiver',
350
- name: 'Invalid Config Test',
351
- host: '', // Missing host
352
- hostType: 'str',
353
- port: 993,
354
- portType: 'num',
355
- user: 'test@test.com',
356
- userType: 'str',
357
- password: '', // Missing password
358
- passwordType: 'str',
359
- folder: ["Inbox"],
360
- folderType: 'num'
361
- },
362
-
363
- minimal: {
364
- id: 'test-node-5',
365
- type: 'email-receiver',
366
- host: 'imap.minimal.com',
367
- hostType: 'str',
368
- port: 993,
369
- portType: 'num',
370
- user: 'minimal@test.com',
371
- userType: 'str',
372
- password: 'minimalpass',
373
- passwordType: 'str',
374
- folder: 'INBOX',
375
- folderType: 'str'
376
- }
293
+ valid: {
294
+ id: 'test-node-1',
295
+ type: 'email-receiver',
296
+ name: 'Test Email Receiver',
297
+ host: 'imap.test.com',
298
+ hostType: 'str',
299
+ port: 993,
300
+ portType: 'num',
301
+ tls: true,
302
+ tlsType: 'bool',
303
+ user: 'test@test.com',
304
+ userType: 'str',
305
+ password: 'testpass',
306
+ passwordType: 'str',
307
+ folder: ['INBOX'],
308
+ folderType: 'str',
309
+ markseen: true,
310
+ markseenType: 'bool',
311
+ },
312
+
313
+ arrayFolders: {
314
+ id: 'test-node-3',
315
+ type: 'email-receiver',
316
+ name: 'Array Folders Test',
317
+ host: 'imap.test.com',
318
+ hostType: 'str',
319
+ port: 993,
320
+ portType: 'num',
321
+ user: 'test@test.com',
322
+ userType: 'str',
323
+ password: 'testpass',
324
+ passwordType: 'str',
325
+ folder: ['INBOX', 'Junk', 'Drafts'],
326
+ folderType: 'json',
327
+ markseen: false,
328
+ markseenType: 'bool',
329
+ },
330
+
331
+ invalidFolderType: {
332
+ id: 'test-node-4',
333
+ type: 'email-receiver',
334
+ name: 'Invalid Config Test',
335
+ host: '', // Missing host
336
+ hostType: 'str',
337
+ port: 993,
338
+ portType: 'num',
339
+ user: 'test@test.com',
340
+ userType: 'str',
341
+ password: '', // Missing password
342
+ passwordType: 'str',
343
+ folder: 123,
344
+ folderType: 'num',
345
+ },
346
+
347
+ invalidConfig: {
348
+ id: 'test-node-4',
349
+ type: 'email-receiver',
350
+ name: 'Invalid Config Test',
351
+ host: '', // Missing host
352
+ hostType: 'str',
353
+ port: 993,
354
+ portType: 'num',
355
+ user: 'test@test.com',
356
+ userType: 'str',
357
+ password: '', // Missing password
358
+ passwordType: 'str',
359
+ folder: ['Inbox'],
360
+ folderType: 'num',
361
+ },
362
+
363
+ minimal: {
364
+ id: 'test-node-5',
365
+ type: 'email-receiver',
366
+ host: 'imap.minimal.com',
367
+ hostType: 'str',
368
+ port: 993,
369
+ portType: 'num',
370
+ user: 'minimal@test.com',
371
+ userType: 'str',
372
+ password: 'minimalpass',
373
+ passwordType: 'str',
374
+ folder: 'INBOX',
375
+ folderType: 'str',
376
+ },
377
377
  };
378
378
 
379
379
  /**
380
380
  * Create test flows for Node-RED integration tests
381
381
  */
382
382
  const testFlows = {
383
- single: [
384
- testConfigs.valid
385
- ],
386
-
387
- withHelper: [
388
- testConfigs.valid,
389
- { id: 'h1', type: 'helper' }
390
- ],
391
-
392
- connected: [
393
- { ...testConfigs.valid, wires: [['h1']] },
394
- { id: 'h1', type: 'helper' }
395
- ],
396
-
397
- multiOutput: [
398
- { ...testConfigs.valid, wires: [['h1', 'h2']] },
399
- { id: 'h1', type: 'helper' },
400
- { id: 'h2', type: 'helper' }
401
- ]
383
+ single: [testConfigs.valid],
384
+
385
+ withHelper: [testConfigs.valid, { id: 'h1', type: 'helper' }],
386
+
387
+ connected: [
388
+ { ...testConfigs.valid, wires: [['h1']] },
389
+ { id: 'h1', type: 'helper' },
390
+ ],
391
+
392
+ multiOutput: [
393
+ { ...testConfigs.valid, wires: [['h1', 'h2']] },
394
+ { id: 'h1', type: 'helper' },
395
+ { id: 'h2', type: 'helper' },
396
+ ],
402
397
  };
403
398
 
404
399
  /**
405
400
  * Utility functions for test assertions and email simulation
406
401
  */
407
402
  const testUtils = {
408
- /**
409
- * Wait for a specified amount of time
410
- */
411
- wait: (ms = 100) => new Promise(resolve => setTimeout(resolve, ms)),
412
-
413
- /**
414
- * Create a promise that resolves when a node receives a message
415
- */
416
- waitForMessage: (node, timeout = 1000) => {
417
- return new Promise((resolve, reject) => {
418
- const timer = setTimeout(() => {
419
- reject(new Error('Timeout waiting for message'));
420
- }, timeout);
421
-
422
- node.on('input', (msg) => {
423
- clearTimeout(timer);
424
- resolve(msg);
425
- });
426
- });
427
- },
428
-
429
- /**
430
- * Verify that a message has expected properties
431
- */
432
- verifyMessage: (msg, expectedProps = {}) => {
433
- const should = require('should');
434
- should.exist(msg);
435
-
436
- Object.keys(expectedProps).forEach(prop => {
437
- if (expectedProps[prop] !== undefined) {
438
- msg.should.have.property(prop, expectedProps[prop]);
439
- }
440
- });
441
- }
403
+ /**
404
+ * Wait for a specified amount of time
405
+ */
406
+ wait: (ms = 100) => new Promise((resolve) => setTimeout(resolve, ms)),
407
+
408
+ /**
409
+ * Create a promise that resolves when a node receives a message
410
+ */
411
+ waitForMessage: (node, timeout = 1000) => {
412
+ return new Promise((resolve, reject) => {
413
+ const timer = setTimeout(() => {
414
+ reject(new Error('Timeout waiting for message'));
415
+ }, timeout);
416
+
417
+ node.on('input', (msg) => {
418
+ clearTimeout(timer);
419
+ resolve(msg);
420
+ });
421
+ });
422
+ },
423
+
424
+ /**
425
+ * Verify that a message has expected properties
426
+ */
427
+ verifyMessage: (msg, expectedProps = {}) => {
428
+ const should = require('should');
429
+ should.exist(msg);
430
+
431
+ Object.keys(expectedProps).forEach((prop) => {
432
+ if (expectedProps[prop] !== undefined) {
433
+ msg.should.have.property(prop, expectedProps[prop]);
434
+ }
435
+ });
436
+ },
442
437
  };
443
438
 
444
439
  module.exports = {
445
- createMockImap,
446
- createMockMailparser,
447
- createMockNodeRED,
448
- setupModuleMocks,
449
- testConfigs,
450
- testFlows,
451
- testUtils
452
- };
440
+ createMockNodeRED,
441
+ createMockImap,
442
+ createMockMailparser,
443
+ setupModuleMocks,
444
+ testConfigs,
445
+ testFlows,
446
+ testUtils,
447
+ };