@5minds/node-red-contrib-processcube-tools 1.0.1-feature-2a3502-mfe1ptiw → 1.0.1-feature-20a8ee-mff2npts

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@5minds/node-red-contrib-processcube-tools",
3
- "version": "1.0.1-feature-2a3502-mfe1ptiw",
3
+ "version": "1.0.1-feature-20a8ee-mff2npts",
4
4
  "license": "MIT",
5
5
  "description": "Node-RED tools nodes for ProcessCube",
6
6
  "scripts": {
@@ -144,15 +144,31 @@ function createMockMailparser() {
144
144
  * Create mock Node-RED object for unit testing
145
145
  */
146
146
  function createMockNodeRED(options = {}) {
147
- return {
147
+ // Store input callback in the mock RED context
148
+ let storedInputCallback = null;
149
+ let nodeInstance = null;
150
+
151
+ const mockRED = {
148
152
  nodes: {
149
153
  createNode: function(node, config) {
154
+ nodeInstance = node; // Capture the node instance
155
+
150
156
  // Apply config properties to node
151
157
  Object.assign(node, {
152
158
  id: config.id || 'mock-node-id',
153
159
  type: config.type || 'email-receiver',
154
160
  name: config.name || 'Mock Node',
155
- on: options.onHandler || function() {},
161
+ on: function(event, callback) {
162
+ if (event === 'input') {
163
+ storedInputCallback = callback;
164
+ // Store the callback on the node instance for easy access
165
+ node.inputCallback = callback;
166
+ }
167
+ // Call the original onHandler if provided
168
+ if (options.onHandler) {
169
+ options.onHandler.call(node, event, callback);
170
+ }
171
+ },
156
172
  status: options.statusHandler || function() {},
157
173
  error: options.errorHandler || function() {},
158
174
  send: options.sendHandler || function() {},
@@ -166,6 +182,14 @@ function createMockNodeRED(options = {}) {
166
182
  // Store registration for verification in tests
167
183
  this.lastRegisteredType = type;
168
184
  this.lastRegisteredConstructor = constructor;
185
+ },
186
+ // Helper method to get the stored input callback
187
+ getInputCallback: function() {
188
+ return storedInputCallback;
189
+ },
190
+ // Helper method to get the node instance
191
+ getNodeInstance: function() {
192
+ return nodeInstance;
169
193
  }
170
194
  },
171
195
  util: {
@@ -181,7 +205,7 @@ function createMockNodeRED(options = {}) {
181
205
  return null;
182
206
  }
183
207
  }
184
-
208
+
185
209
  // Simple mock implementation
186
210
  if (callback) {
187
211
  callback(null, value);
@@ -202,6 +226,8 @@ function createMockNodeRED(options = {}) {
202
226
  debug: options.logDebug || function() {}
203
227
  }
204
228
  };
229
+
230
+ return mockRED;
205
231
  }
206
232
 
207
233
  /**
@@ -247,7 +273,7 @@ const testConfigs = {
247
273
  userType: 'str',
248
274
  password: 'testpass',
249
275
  passwordType: 'str',
250
- folder: 'INBOX',
276
+ folder: ['INBOX'],
251
277
  folderType: 'str',
252
278
  markseen: true,
253
279
  markseenType: 'bool'
@@ -271,6 +297,22 @@ const testConfigs = {
271
297
  markseenType: 'bool'
272
298
  },
273
299
 
300
+ invalidFolderType: {
301
+ id: 'test-node-4',
302
+ type: 'email-receiver',
303
+ name: 'Invalid Config Test',
304
+ host: '', // Missing host
305
+ hostType: 'str',
306
+ port: 993,
307
+ portType: 'num',
308
+ user: 'test@test.com',
309
+ userType: 'str',
310
+ password: '', // Missing password
311
+ passwordType: 'str',
312
+ folder: 123,
313
+ folderType: 'num'
314
+ },
315
+
274
316
  invalidConfig: {
275
317
  id: 'test-node-4',
276
318
  type: 'email-receiver',
@@ -283,7 +325,7 @@ const testConfigs = {
283
325
  userType: 'str',
284
326
  password: '', // Missing password
285
327
  passwordType: 'str',
286
- folder: 123, // Wrong type
328
+ folder: ["Inbox"],
287
329
  folderType: 'num'
288
330
  },
289
331
 
@@ -116,6 +116,11 @@ describe('Email Receiver Node - Unit Tests with Helpers', function() {
116
116
  it('should call node.error for invalid folder type', function(done) {
117
117
  // ARRANGE: Set up error tracking
118
118
  const mockRED = createMockNodeRED({
119
+ onHandler: function(event, callback) {
120
+ if (event === 'input') {
121
+ this.inputCallback = callback;
122
+ }
123
+ },
119
124
  errorHandler: function(err) {
120
125
  // ASSERT: Should receive appropriate error message
121
126
  err.should.containEql("The 'folders' property must be an array of strings.");
@@ -126,13 +131,28 @@ describe('Email Receiver Node - Unit Tests with Helpers', function() {
126
131
  // ACT: Register node and create instance with invalid config
127
132
  emailReceiverNode(mockRED);
128
133
  const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
129
- new nodeConstructor(testConfigs.invalidConfig);
134
+ const nodeInstance = new nodeConstructor(testConfigs.invalidFolderType);
135
+
136
+ // Trigger the error by sending an input message
137
+ // Use a small delay to ensure the constructor has completed
138
+ setTimeout(() => {
139
+ if (nodeInstance.inputCallback) {
140
+ nodeInstance.inputCallback({ payload: "test" });
141
+ } else {
142
+ done(new Error('inputCallback was not set on the node instance'));
143
+ }
144
+ }, 10);
130
145
  });
131
146
 
132
147
  it('should call node.error for missing config', function(done) {
133
148
  // ARRANGE: Set up error and status tracking
134
149
  let statusCalled = false;
135
150
  const mockRED = createMockNodeRED({
151
+ onHandler: function(event, callback) {
152
+ if (event === 'input') {
153
+ this.inputCallback = callback;
154
+ }
155
+ },
136
156
  statusHandler: function(status) {
137
157
  statusCalled = true;
138
158
  if (status.fill) {
@@ -150,7 +170,61 @@ describe('Email Receiver Node - Unit Tests with Helpers', function() {
150
170
  // ACT: Register node and create instance with invalid config
151
171
  emailReceiverNode(mockRED);
152
172
  const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
153
- new nodeConstructor(testConfigs.invalidConfig);
173
+ const nodeInstance = new nodeConstructor(testConfigs.invalidConfig);
174
+
175
+ // Trigger the error by sending an input message
176
+ // Use a small delay to ensure the constructor has completed
177
+ setTimeout(() => {
178
+ if (nodeInstance.inputCallback) {
179
+ nodeInstance.inputCallback({ payload: "test" });
180
+ } else {
181
+ done(new Error('inputCallback was not set on the node instance'));
182
+ }
183
+ }, 10);
184
+ });
185
+
186
+ it('should handle connection errors gracefully', function(done) {
187
+ // ARRANGE: Set up connection error scenario
188
+ const mockRED = createMockNodeRED({
189
+ onHandler: function(event, callback) {
190
+ if (event === 'input') {
191
+ this.inputCallback = callback;
192
+ }
193
+ },
194
+ statusHandler: function(status) {
195
+ if (status.fill === 'red' && status.text && status.text.includes('error')) {
196
+ done(); // Success - error status was set
197
+ }
198
+ },
199
+ errorHandler: function(err) {
200
+ // Also accept errors as valid completion
201
+ should.exist(err);
202
+ done();
203
+ }
204
+ });
205
+
206
+ // ACT: Create node and trigger connection attempt
207
+ emailReceiverNode(mockRED);
208
+ const nodeConstructor = mockRED.nodes.lastRegisteredConstructor;
209
+
210
+ // Use a config that should cause connection issues
211
+ const badConfig = {
212
+ ...testConfigs.valid,
213
+ host: 'nonexistent.invalid.host.com',
214
+ port: 12345 // Invalid port
215
+ };
216
+
217
+ const nodeInstance = new nodeConstructor(badConfig);
218
+
219
+ // Trigger the error by sending an input message
220
+ // Use a small delay to ensure the constructor has completed
221
+ setTimeout(() => {
222
+ if (nodeInstance.inputCallback) {
223
+ nodeInstance.inputCallback({ payload: "test" });
224
+ } else {
225
+ done(new Error('inputCallback was not set on the node instance'));
226
+ }
227
+ }, 10);
154
228
  });
155
229
  });
156
230