@friggframework/admin-scripts 2.0.0--canary.545.b4ca16d.0 → 2.0.0--canary.517.8eaf5df.0
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/README.md +277 -0
- package/index.js +23 -6
- package/package.json +6 -6
- package/src/adapters/__tests__/aws-scheduler-adapter.test.js +106 -45
- package/src/adapters/__tests__/local-scheduler-adapter.test.js +24 -10
- package/src/adapters/__tests__/scheduler-adapter-factory.test.js +30 -9
- package/src/adapters/__tests__/scheduler-adapter.test.js +6 -2
- package/src/adapters/aws-scheduler-adapter.js +55 -28
- package/src/adapters/local-scheduler-adapter.js +2 -2
- package/src/adapters/scheduler-adapter-factory.js +3 -1
- package/src/adapters/scheduler-adapter.js +9 -3
- package/src/application/__tests__/admin-frigg-commands.test.js +73 -30
- package/src/application/__tests__/admin-script-base.test.js +23 -6
- package/src/application/__tests__/script-factory.test.js +30 -6
- package/src/application/__tests__/script-runner.test.js +113 -24
- package/src/application/__tests__/validate-script-input.test.js +54 -15
- package/src/application/admin-frigg-commands.js +21 -9
- package/src/application/admin-script-base.js +3 -2
- package/src/application/script-factory.js +3 -1
- package/src/application/script-runner.js +90 -48
- package/src/application/use-cases/__tests__/delete-schedule-use-case.test.js +16 -7
- package/src/application/use-cases/__tests__/get-effective-schedule-use-case.test.js +9 -4
- package/src/application/use-cases/__tests__/upsert-schedule-use-case.test.js +21 -10
- package/src/application/use-cases/delete-schedule-use-case.js +6 -4
- package/src/application/use-cases/get-effective-schedule-use-case.js +3 -1
- package/src/application/use-cases/index.js +3 -1
- package/src/application/use-cases/upsert-schedule-use-case.js +30 -11
- package/src/application/validate-script-input.js +10 -3
- package/src/builtins/__tests__/integration-health-check.test.js +232 -127
- package/src/builtins/__tests__/oauth-token-refresh.test.js +128 -75
- package/src/builtins/index.js +1 -4
- package/src/builtins/integration-health-check.js +63 -30
- package/src/builtins/oauth-token-refresh.js +64 -29
- package/src/infrastructure/__tests__/admin-auth-middleware.test.js +9 -3
- package/src/infrastructure/__tests__/admin-script-router.test.js +125 -52
- package/src/infrastructure/admin-auth-middleware.js +3 -1
- package/src/infrastructure/admin-script-router.js +129 -14
- package/src/infrastructure/bootstrap.js +87 -0
- package/src/infrastructure/script-executor-handler.js +119 -52
- package/src/application/__tests__/dry-run-http-interceptor.test.js +0 -313
- package/src/application/__tests__/dry-run-repository-wrapper.test.js +0 -257
- package/src/application/__tests__/schedule-management-use-case.test.js +0 -276
- package/src/application/dry-run-http-interceptor.js +0 -296
- package/src/application/dry-run-repository-wrapper.js +0 -261
- package/src/application/schedule-management-use-case.js +0 -230
|
@@ -3,10 +3,19 @@ const { IntegrationHealthCheckScript } = require('../integration-health-check');
|
|
|
3
3
|
describe('IntegrationHealthCheckScript', () => {
|
|
4
4
|
describe('Definition', () => {
|
|
5
5
|
it('should have correct name and metadata', () => {
|
|
6
|
-
expect(IntegrationHealthCheckScript.Definition.name).toBe(
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
expect(IntegrationHealthCheckScript.Definition.
|
|
6
|
+
expect(IntegrationHealthCheckScript.Definition.name).toBe(
|
|
7
|
+
'integration-health-check'
|
|
8
|
+
);
|
|
9
|
+
expect(IntegrationHealthCheckScript.Definition.version).toBe(
|
|
10
|
+
'1.0.0'
|
|
11
|
+
);
|
|
12
|
+
expect(IntegrationHealthCheckScript.Definition.source).toBe(
|
|
13
|
+
'BUILTIN'
|
|
14
|
+
);
|
|
15
|
+
expect(
|
|
16
|
+
IntegrationHealthCheckScript.Definition.config
|
|
17
|
+
.requireIntegrationInstance
|
|
18
|
+
).toBe(true);
|
|
10
19
|
});
|
|
11
20
|
|
|
12
21
|
it('should have valid input schema', () => {
|
|
@@ -35,12 +44,16 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
35
44
|
});
|
|
36
45
|
|
|
37
46
|
it('should have appropriate timeout configuration', () => {
|
|
38
|
-
expect(IntegrationHealthCheckScript.Definition.config.timeout).toBe(
|
|
47
|
+
expect(IntegrationHealthCheckScript.Definition.config.timeout).toBe(
|
|
48
|
+
900000
|
|
49
|
+
); // 15 minutes
|
|
39
50
|
});
|
|
40
51
|
|
|
41
52
|
it('should have clean display object', () => {
|
|
42
53
|
// Display should only have UI-specific fields
|
|
43
|
-
expect(
|
|
54
|
+
expect(
|
|
55
|
+
IntegrationHealthCheckScript.Definition.display.category
|
|
56
|
+
).toBe('maintenance');
|
|
44
57
|
// Should NOT have redundant label/description - they're derived from top-level
|
|
45
58
|
});
|
|
46
59
|
});
|
|
@@ -63,7 +76,9 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
63
76
|
});
|
|
64
77
|
|
|
65
78
|
it('should return empty results when no integrations found', async () => {
|
|
66
|
-
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
79
|
+
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
80
|
+
[]
|
|
81
|
+
);
|
|
67
82
|
|
|
68
83
|
const result = await script.execute({});
|
|
69
84
|
|
|
@@ -80,25 +95,31 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
80
95
|
type: 'hubspot',
|
|
81
96
|
credentials: {
|
|
82
97
|
access_token: 'token123',
|
|
83
|
-
expires_at: new Date(
|
|
84
|
-
|
|
85
|
-
|
|
98
|
+
expires_at: new Date(
|
|
99
|
+
Date.now() + 24 * 60 * 60 * 1000
|
|
100
|
+
).toISOString(),
|
|
101
|
+
},
|
|
102
|
+
},
|
|
86
103
|
};
|
|
87
104
|
|
|
88
105
|
const mockInstance = {
|
|
89
106
|
primary: {
|
|
90
107
|
api: {
|
|
91
|
-
getAuthenticationInfo: jest
|
|
92
|
-
|
|
93
|
-
|
|
108
|
+
getAuthenticationInfo: jest
|
|
109
|
+
.fn()
|
|
110
|
+
.mockResolvedValue({ user: 'test' }),
|
|
111
|
+
},
|
|
112
|
+
},
|
|
94
113
|
};
|
|
95
114
|
|
|
96
|
-
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
115
|
+
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
116
|
+
[integration]
|
|
117
|
+
);
|
|
97
118
|
mockContext.instantiate.mockResolvedValue(mockInstance);
|
|
98
119
|
|
|
99
120
|
const result = await script.execute({
|
|
100
121
|
checkCredentials: true,
|
|
101
|
-
checkConnectivity: true
|
|
122
|
+
checkConnectivity: true,
|
|
102
123
|
});
|
|
103
124
|
|
|
104
125
|
expect(result.healthy).toBe(1);
|
|
@@ -106,9 +127,11 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
106
127
|
expect(result.results[0]).toMatchObject({
|
|
107
128
|
integrationId: 'int-1',
|
|
108
129
|
status: 'healthy',
|
|
109
|
-
issues: []
|
|
130
|
+
issues: [],
|
|
110
131
|
});
|
|
111
|
-
expect(
|
|
132
|
+
expect(
|
|
133
|
+
mockInstance.primary.api.getAuthenticationInfo
|
|
134
|
+
).toHaveBeenCalled();
|
|
112
135
|
});
|
|
113
136
|
|
|
114
137
|
it('should return unhealthy for missing access token', async () => {
|
|
@@ -116,15 +139,17 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
116
139
|
id: 'int-1',
|
|
117
140
|
config: {
|
|
118
141
|
type: 'hubspot',
|
|
119
|
-
credentials: {} // No access_token
|
|
120
|
-
}
|
|
142
|
+
credentials: {}, // No access_token
|
|
143
|
+
},
|
|
121
144
|
};
|
|
122
145
|
|
|
123
|
-
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
146
|
+
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
147
|
+
[integration]
|
|
148
|
+
);
|
|
124
149
|
|
|
125
150
|
const result = await script.execute({
|
|
126
151
|
checkCredentials: true,
|
|
127
|
-
checkConnectivity: false
|
|
152
|
+
checkConnectivity: false,
|
|
128
153
|
});
|
|
129
154
|
|
|
130
155
|
expect(result.healthy).toBe(0);
|
|
@@ -132,7 +157,7 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
132
157
|
expect(result.results[0]).toMatchObject({
|
|
133
158
|
integrationId: 'int-1',
|
|
134
159
|
status: 'unhealthy',
|
|
135
|
-
issues: ['Missing access token']
|
|
160
|
+
issues: ['Missing access token'],
|
|
136
161
|
});
|
|
137
162
|
});
|
|
138
163
|
|
|
@@ -144,23 +169,25 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
144
169
|
type: 'hubspot',
|
|
145
170
|
credentials: {
|
|
146
171
|
access_token: 'token123',
|
|
147
|
-
expires_at: pastDate.toISOString()
|
|
148
|
-
}
|
|
149
|
-
}
|
|
172
|
+
expires_at: pastDate.toISOString(),
|
|
173
|
+
},
|
|
174
|
+
},
|
|
150
175
|
};
|
|
151
176
|
|
|
152
|
-
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
177
|
+
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
178
|
+
[integration]
|
|
179
|
+
);
|
|
153
180
|
|
|
154
181
|
const result = await script.execute({
|
|
155
182
|
checkCredentials: true,
|
|
156
|
-
checkConnectivity: false
|
|
183
|
+
checkConnectivity: false,
|
|
157
184
|
});
|
|
158
185
|
|
|
159
186
|
expect(result.unhealthy).toBe(1);
|
|
160
187
|
expect(result.results[0]).toMatchObject({
|
|
161
188
|
integrationId: 'int-1',
|
|
162
189
|
status: 'unhealthy',
|
|
163
|
-
issues: ['Access token expired']
|
|
190
|
+
issues: ['Access token expired'],
|
|
164
191
|
});
|
|
165
192
|
});
|
|
166
193
|
|
|
@@ -171,30 +198,38 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
171
198
|
type: 'hubspot',
|
|
172
199
|
credentials: {
|
|
173
200
|
access_token: 'token123',
|
|
174
|
-
expires_at: new Date(
|
|
175
|
-
|
|
176
|
-
|
|
201
|
+
expires_at: new Date(
|
|
202
|
+
Date.now() + 24 * 60 * 60 * 1000
|
|
203
|
+
).toISOString(),
|
|
204
|
+
},
|
|
205
|
+
},
|
|
177
206
|
};
|
|
178
207
|
|
|
179
208
|
const mockInstance = {
|
|
180
209
|
primary: {
|
|
181
210
|
api: {
|
|
182
|
-
getAuthenticationInfo: jest
|
|
183
|
-
|
|
184
|
-
|
|
211
|
+
getAuthenticationInfo: jest
|
|
212
|
+
.fn()
|
|
213
|
+
.mockRejectedValue(new Error('Network error')),
|
|
214
|
+
},
|
|
215
|
+
},
|
|
185
216
|
};
|
|
186
217
|
|
|
187
|
-
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
218
|
+
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
219
|
+
[integration]
|
|
220
|
+
);
|
|
188
221
|
mockContext.instantiate.mockResolvedValue(mockInstance);
|
|
189
222
|
|
|
190
223
|
const result = await script.execute({
|
|
191
224
|
checkCredentials: true,
|
|
192
|
-
checkConnectivity: true
|
|
225
|
+
checkConnectivity: true,
|
|
193
226
|
});
|
|
194
227
|
|
|
195
228
|
expect(result.unhealthy).toBe(1);
|
|
196
229
|
expect(result.results[0].status).toBe('unhealthy');
|
|
197
|
-
expect(result.results[0].issues).toContainEqual(
|
|
230
|
+
expect(result.results[0].issues).toContainEqual(
|
|
231
|
+
expect.stringContaining('API connectivity failed')
|
|
232
|
+
);
|
|
198
233
|
});
|
|
199
234
|
|
|
200
235
|
it('should update integration status when updateStatus is true', async () => {
|
|
@@ -204,31 +239,41 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
204
239
|
type: 'hubspot',
|
|
205
240
|
credentials: {
|
|
206
241
|
access_token: 'token123',
|
|
207
|
-
expires_at: new Date(
|
|
208
|
-
|
|
209
|
-
|
|
242
|
+
expires_at: new Date(
|
|
243
|
+
Date.now() + 24 * 60 * 60 * 1000
|
|
244
|
+
).toISOString(),
|
|
245
|
+
},
|
|
246
|
+
},
|
|
210
247
|
};
|
|
211
248
|
|
|
212
249
|
const mockInstance = {
|
|
213
250
|
primary: {
|
|
214
251
|
api: {
|
|
215
|
-
getAuthenticationInfo: jest
|
|
216
|
-
|
|
217
|
-
|
|
252
|
+
getAuthenticationInfo: jest
|
|
253
|
+
.fn()
|
|
254
|
+
.mockResolvedValue({ user: 'test' }),
|
|
255
|
+
},
|
|
256
|
+
},
|
|
218
257
|
};
|
|
219
258
|
|
|
220
|
-
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
259
|
+
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
260
|
+
[integration]
|
|
261
|
+
);
|
|
221
262
|
mockContext.instantiate.mockResolvedValue(mockInstance);
|
|
222
|
-
mockContext.integrationRepository.updateIntegrationStatus.mockResolvedValue(
|
|
263
|
+
mockContext.integrationRepository.updateIntegrationStatus.mockResolvedValue(
|
|
264
|
+
undefined
|
|
265
|
+
);
|
|
223
266
|
|
|
224
267
|
const result = await script.execute({
|
|
225
268
|
checkCredentials: true,
|
|
226
269
|
checkConnectivity: true,
|
|
227
|
-
updateStatus: true
|
|
270
|
+
updateStatus: true,
|
|
228
271
|
});
|
|
229
272
|
|
|
230
273
|
expect(result.healthy).toBe(1);
|
|
231
|
-
expect(
|
|
274
|
+
expect(
|
|
275
|
+
mockContext.integrationRepository.updateIntegrationStatus
|
|
276
|
+
).toHaveBeenCalledWith('int-1', 'ACTIVE');
|
|
232
277
|
});
|
|
233
278
|
|
|
234
279
|
it('should update integration status to ERROR for unhealthy integrations', async () => {
|
|
@@ -236,21 +281,27 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
236
281
|
id: 'int-1',
|
|
237
282
|
config: {
|
|
238
283
|
type: 'hubspot',
|
|
239
|
-
credentials: {} // Missing credentials
|
|
240
|
-
}
|
|
284
|
+
credentials: {}, // Missing credentials
|
|
285
|
+
},
|
|
241
286
|
};
|
|
242
287
|
|
|
243
|
-
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
244
|
-
|
|
288
|
+
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
289
|
+
[integration]
|
|
290
|
+
);
|
|
291
|
+
mockContext.integrationRepository.updateIntegrationStatus.mockResolvedValue(
|
|
292
|
+
undefined
|
|
293
|
+
);
|
|
245
294
|
|
|
246
295
|
const result = await script.execute({
|
|
247
296
|
checkCredentials: true,
|
|
248
297
|
checkConnectivity: false,
|
|
249
|
-
updateStatus: true
|
|
298
|
+
updateStatus: true,
|
|
250
299
|
});
|
|
251
300
|
|
|
252
301
|
expect(result.unhealthy).toBe(1);
|
|
253
|
-
expect(
|
|
302
|
+
expect(
|
|
303
|
+
mockContext.integrationRepository.updateIntegrationStatus
|
|
304
|
+
).toHaveBeenCalledWith('int-1', 'ERROR');
|
|
254
305
|
});
|
|
255
306
|
|
|
256
307
|
it('should not update status when updateStatus is false', async () => {
|
|
@@ -260,29 +311,37 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
260
311
|
type: 'hubspot',
|
|
261
312
|
credentials: {
|
|
262
313
|
access_token: 'token123',
|
|
263
|
-
expires_at: new Date(
|
|
264
|
-
|
|
265
|
-
|
|
314
|
+
expires_at: new Date(
|
|
315
|
+
Date.now() + 24 * 60 * 60 * 1000
|
|
316
|
+
).toISOString(),
|
|
317
|
+
},
|
|
318
|
+
},
|
|
266
319
|
};
|
|
267
320
|
|
|
268
321
|
const mockInstance = {
|
|
269
322
|
primary: {
|
|
270
323
|
api: {
|
|
271
|
-
getAuthenticationInfo: jest
|
|
272
|
-
|
|
273
|
-
|
|
324
|
+
getAuthenticationInfo: jest
|
|
325
|
+
.fn()
|
|
326
|
+
.mockResolvedValue({ user: 'test' }),
|
|
327
|
+
},
|
|
328
|
+
},
|
|
274
329
|
};
|
|
275
330
|
|
|
276
|
-
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
331
|
+
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
332
|
+
[integration]
|
|
333
|
+
);
|
|
277
334
|
mockContext.instantiate.mockResolvedValue(mockInstance);
|
|
278
335
|
|
|
279
336
|
await script.execute({
|
|
280
337
|
checkCredentials: true,
|
|
281
338
|
checkConnectivity: true,
|
|
282
|
-
updateStatus: false
|
|
339
|
+
updateStatus: false,
|
|
283
340
|
});
|
|
284
341
|
|
|
285
|
-
expect(
|
|
342
|
+
expect(
|
|
343
|
+
mockContext.integrationRepository.updateIntegrationStatus
|
|
344
|
+
).not.toHaveBeenCalled();
|
|
286
345
|
});
|
|
287
346
|
|
|
288
347
|
it('should handle status update failures gracefully', async () => {
|
|
@@ -292,27 +351,35 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
292
351
|
type: 'hubspot',
|
|
293
352
|
credentials: {
|
|
294
353
|
access_token: 'token123',
|
|
295
|
-
expires_at: new Date(
|
|
296
|
-
|
|
297
|
-
|
|
354
|
+
expires_at: new Date(
|
|
355
|
+
Date.now() + 24 * 60 * 60 * 1000
|
|
356
|
+
).toISOString(),
|
|
357
|
+
},
|
|
358
|
+
},
|
|
298
359
|
};
|
|
299
360
|
|
|
300
361
|
const mockInstance = {
|
|
301
362
|
primary: {
|
|
302
363
|
api: {
|
|
303
|
-
getAuthenticationInfo: jest
|
|
304
|
-
|
|
305
|
-
|
|
364
|
+
getAuthenticationInfo: jest
|
|
365
|
+
.fn()
|
|
366
|
+
.mockResolvedValue({ user: 'test' }),
|
|
367
|
+
},
|
|
368
|
+
},
|
|
306
369
|
};
|
|
307
370
|
|
|
308
|
-
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
371
|
+
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
372
|
+
[integration]
|
|
373
|
+
);
|
|
309
374
|
mockContext.instantiate.mockResolvedValue(mockInstance);
|
|
310
|
-
mockContext.integrationRepository.updateIntegrationStatus.mockRejectedValue(
|
|
375
|
+
mockContext.integrationRepository.updateIntegrationStatus.mockRejectedValue(
|
|
376
|
+
new Error('Update failed')
|
|
377
|
+
);
|
|
311
378
|
|
|
312
379
|
const result = await script.execute({
|
|
313
380
|
checkCredentials: true,
|
|
314
381
|
checkConnectivity: true,
|
|
315
|
-
updateStatus: true
|
|
382
|
+
updateStatus: true,
|
|
316
383
|
});
|
|
317
384
|
|
|
318
385
|
expect(result.healthy).toBe(1); // Should still report healthy
|
|
@@ -326,28 +393,42 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
326
393
|
it('should filter by specific integration IDs', async () => {
|
|
327
394
|
const integration1 = {
|
|
328
395
|
id: 'int-1',
|
|
329
|
-
config: {
|
|
396
|
+
config: {
|
|
397
|
+
type: 'hubspot',
|
|
398
|
+
credentials: { access_token: 'token1' },
|
|
399
|
+
},
|
|
330
400
|
};
|
|
331
401
|
const integration2 = {
|
|
332
402
|
id: 'int-2',
|
|
333
|
-
config: {
|
|
403
|
+
config: {
|
|
404
|
+
type: 'salesforce',
|
|
405
|
+
credentials: { access_token: 'token2' },
|
|
406
|
+
},
|
|
334
407
|
};
|
|
335
408
|
|
|
336
|
-
mockContext.integrationRepository.findIntegrationById.mockImplementation(
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
409
|
+
mockContext.integrationRepository.findIntegrationById.mockImplementation(
|
|
410
|
+
(id) => {
|
|
411
|
+
if (id === 'int-1') return Promise.resolve(integration1);
|
|
412
|
+
if (id === 'int-2') return Promise.resolve(integration2);
|
|
413
|
+
return Promise.reject(new Error('Not found'));
|
|
414
|
+
}
|
|
415
|
+
);
|
|
341
416
|
|
|
342
417
|
const result = await script.execute({
|
|
343
418
|
integrationIds: ['int-1', 'int-2'],
|
|
344
419
|
checkCredentials: true,
|
|
345
|
-
checkConnectivity: false
|
|
420
|
+
checkConnectivity: false,
|
|
346
421
|
});
|
|
347
422
|
|
|
348
|
-
expect(
|
|
349
|
-
|
|
350
|
-
|
|
423
|
+
expect(
|
|
424
|
+
mockContext.integrationRepository.findIntegrationById
|
|
425
|
+
).toHaveBeenCalledWith('int-1');
|
|
426
|
+
expect(
|
|
427
|
+
mockContext.integrationRepository.findIntegrationById
|
|
428
|
+
).toHaveBeenCalledWith('int-2');
|
|
429
|
+
expect(
|
|
430
|
+
mockContext.integrationRepository.findIntegrations
|
|
431
|
+
).not.toHaveBeenCalled();
|
|
351
432
|
expect(result.results).toHaveLength(2);
|
|
352
433
|
});
|
|
353
434
|
|
|
@@ -358,17 +439,23 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
358
439
|
type: 'hubspot',
|
|
359
440
|
credentials: {
|
|
360
441
|
access_token: 'token123',
|
|
361
|
-
expires_at: new Date(
|
|
362
|
-
|
|
363
|
-
|
|
442
|
+
expires_at: new Date(
|
|
443
|
+
Date.now() + 24 * 60 * 60 * 1000
|
|
444
|
+
).toISOString(),
|
|
445
|
+
},
|
|
446
|
+
},
|
|
364
447
|
};
|
|
365
448
|
|
|
366
|
-
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
367
|
-
|
|
449
|
+
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
450
|
+
[integration]
|
|
451
|
+
);
|
|
452
|
+
mockContext.instantiate.mockRejectedValue(
|
|
453
|
+
new Error('Instantiation failed')
|
|
454
|
+
);
|
|
368
455
|
|
|
369
456
|
const result = await script.execute({
|
|
370
457
|
checkCredentials: true,
|
|
371
|
-
checkConnectivity: true
|
|
458
|
+
checkConnectivity: true,
|
|
372
459
|
});
|
|
373
460
|
|
|
374
461
|
// Should still complete but mark as unknown or unhealthy
|
|
@@ -381,24 +468,28 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
381
468
|
id: 'int-1',
|
|
382
469
|
config: {
|
|
383
470
|
type: 'hubspot',
|
|
384
|
-
credentials: {} // Missing credentials, but check is disabled
|
|
385
|
-
}
|
|
471
|
+
credentials: {}, // Missing credentials, but check is disabled
|
|
472
|
+
},
|
|
386
473
|
};
|
|
387
474
|
|
|
388
475
|
const mockInstance = {
|
|
389
476
|
primary: {
|
|
390
477
|
api: {
|
|
391
|
-
getAuthenticationInfo: jest
|
|
392
|
-
|
|
393
|
-
|
|
478
|
+
getAuthenticationInfo: jest
|
|
479
|
+
.fn()
|
|
480
|
+
.mockResolvedValue({ user: 'test' }),
|
|
481
|
+
},
|
|
482
|
+
},
|
|
394
483
|
};
|
|
395
484
|
|
|
396
|
-
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
485
|
+
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
486
|
+
[integration]
|
|
487
|
+
);
|
|
397
488
|
mockContext.instantiate.mockResolvedValue(mockInstance);
|
|
398
489
|
|
|
399
490
|
const result = await script.execute({
|
|
400
491
|
checkCredentials: false,
|
|
401
|
-
checkConnectivity: true
|
|
492
|
+
checkConnectivity: true,
|
|
402
493
|
});
|
|
403
494
|
|
|
404
495
|
expect(result.results[0].checks.credentials).toBeUndefined();
|
|
@@ -412,16 +503,20 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
412
503
|
type: 'hubspot',
|
|
413
504
|
credentials: {
|
|
414
505
|
access_token: 'token123',
|
|
415
|
-
expires_at: new Date(
|
|
416
|
-
|
|
417
|
-
|
|
506
|
+
expires_at: new Date(
|
|
507
|
+
Date.now() + 24 * 60 * 60 * 1000
|
|
508
|
+
).toISOString(),
|
|
509
|
+
},
|
|
510
|
+
},
|
|
418
511
|
};
|
|
419
512
|
|
|
420
|
-
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
513
|
+
mockContext.integrationRepository.findIntegrations.mockResolvedValue(
|
|
514
|
+
[integration]
|
|
515
|
+
);
|
|
421
516
|
|
|
422
517
|
const result = await script.execute({
|
|
423
518
|
checkCredentials: true,
|
|
424
|
-
checkConnectivity: false
|
|
519
|
+
checkConnectivity: false,
|
|
425
520
|
});
|
|
426
521
|
|
|
427
522
|
expect(result.results[0].checks.credentials).toBeDefined();
|
|
@@ -434,7 +529,9 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
434
529
|
let script;
|
|
435
530
|
|
|
436
531
|
beforeEach(() => {
|
|
437
|
-
script = new IntegrationHealthCheckScript({
|
|
532
|
+
script = new IntegrationHealthCheckScript({
|
|
533
|
+
context: { log: jest.fn() },
|
|
534
|
+
});
|
|
438
535
|
});
|
|
439
536
|
|
|
440
537
|
it('should return valid for integrations with valid credentials', () => {
|
|
@@ -443,9 +540,11 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
443
540
|
config: {
|
|
444
541
|
credentials: {
|
|
445
542
|
access_token: 'token123',
|
|
446
|
-
expires_at: new Date(
|
|
447
|
-
|
|
448
|
-
|
|
543
|
+
expires_at: new Date(
|
|
544
|
+
Date.now() + 24 * 60 * 60 * 1000
|
|
545
|
+
).toISOString(),
|
|
546
|
+
},
|
|
547
|
+
},
|
|
449
548
|
};
|
|
450
549
|
|
|
451
550
|
const result = script.checkCredentialValidity(integration);
|
|
@@ -458,8 +557,8 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
458
557
|
const integration = {
|
|
459
558
|
id: 'int-1',
|
|
460
559
|
config: {
|
|
461
|
-
credentials: {}
|
|
462
|
-
}
|
|
560
|
+
credentials: {},
|
|
561
|
+
},
|
|
463
562
|
};
|
|
464
563
|
|
|
465
564
|
const result = script.checkCredentialValidity(integration);
|
|
@@ -474,9 +573,9 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
474
573
|
config: {
|
|
475
574
|
credentials: {
|
|
476
575
|
access_token: 'token123',
|
|
477
|
-
expires_at: new Date(Date.now() - 1000).toISOString() // Expired
|
|
478
|
-
}
|
|
479
|
-
}
|
|
576
|
+
expires_at: new Date(Date.now() - 1000).toISOString(), // Expired
|
|
577
|
+
},
|
|
578
|
+
},
|
|
480
579
|
};
|
|
481
580
|
|
|
482
581
|
const result = script.checkCredentialValidity(integration);
|
|
@@ -490,10 +589,10 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
490
589
|
id: 'int-1',
|
|
491
590
|
config: {
|
|
492
591
|
credentials: {
|
|
493
|
-
access_token: 'token123'
|
|
592
|
+
access_token: 'token123',
|
|
494
593
|
// No expires_at
|
|
495
|
-
}
|
|
496
|
-
}
|
|
594
|
+
},
|
|
595
|
+
},
|
|
497
596
|
};
|
|
498
597
|
|
|
499
598
|
const result = script.checkCredentialValidity(integration);
|
|
@@ -518,15 +617,17 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
518
617
|
it('should return valid for successful API calls', async () => {
|
|
519
618
|
const integration = {
|
|
520
619
|
id: 'int-1',
|
|
521
|
-
config: { type: 'hubspot' }
|
|
620
|
+
config: { type: 'hubspot' },
|
|
522
621
|
};
|
|
523
622
|
|
|
524
623
|
const mockInstance = {
|
|
525
624
|
primary: {
|
|
526
625
|
api: {
|
|
527
|
-
getAuthenticationInfo: jest
|
|
528
|
-
|
|
529
|
-
|
|
626
|
+
getAuthenticationInfo: jest
|
|
627
|
+
.fn()
|
|
628
|
+
.mockResolvedValue({ user: 'test' }),
|
|
629
|
+
},
|
|
630
|
+
},
|
|
530
631
|
};
|
|
531
632
|
|
|
532
633
|
mockContext.instantiate.mockResolvedValue(mockInstance);
|
|
@@ -541,15 +642,17 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
541
642
|
it('should try getCurrentUser if getAuthenticationInfo is not available', async () => {
|
|
542
643
|
const integration = {
|
|
543
644
|
id: 'int-1',
|
|
544
|
-
config: { type: 'hubspot' }
|
|
645
|
+
config: { type: 'hubspot' },
|
|
545
646
|
};
|
|
546
647
|
|
|
547
648
|
const mockInstance = {
|
|
548
649
|
primary: {
|
|
549
650
|
api: {
|
|
550
|
-
getCurrentUser: jest
|
|
551
|
-
|
|
552
|
-
|
|
651
|
+
getCurrentUser: jest
|
|
652
|
+
.fn()
|
|
653
|
+
.mockResolvedValue({ user: 'test' }),
|
|
654
|
+
},
|
|
655
|
+
},
|
|
553
656
|
};
|
|
554
657
|
|
|
555
658
|
mockContext.instantiate.mockResolvedValue(mockInstance);
|
|
@@ -563,13 +666,13 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
563
666
|
it('should return note when no health check endpoint is available', async () => {
|
|
564
667
|
const integration = {
|
|
565
668
|
id: 'int-1',
|
|
566
|
-
config: { type: 'hubspot' }
|
|
669
|
+
config: { type: 'hubspot' },
|
|
567
670
|
};
|
|
568
671
|
|
|
569
672
|
const mockInstance = {
|
|
570
673
|
primary: {
|
|
571
|
-
api: {} // No health check methods
|
|
572
|
-
}
|
|
674
|
+
api: {}, // No health check methods
|
|
675
|
+
},
|
|
573
676
|
};
|
|
574
677
|
|
|
575
678
|
mockContext.instantiate.mockResolvedValue(mockInstance);
|
|
@@ -584,15 +687,17 @@ describe('IntegrationHealthCheckScript', () => {
|
|
|
584
687
|
it('should return invalid for API failures', async () => {
|
|
585
688
|
const integration = {
|
|
586
689
|
id: 'int-1',
|
|
587
|
-
config: { type: 'hubspot' }
|
|
690
|
+
config: { type: 'hubspot' },
|
|
588
691
|
};
|
|
589
692
|
|
|
590
693
|
const mockInstance = {
|
|
591
694
|
primary: {
|
|
592
695
|
api: {
|
|
593
|
-
getAuthenticationInfo: jest
|
|
594
|
-
|
|
595
|
-
|
|
696
|
+
getAuthenticationInfo: jest
|
|
697
|
+
.fn()
|
|
698
|
+
.mockRejectedValue(new Error('Network error')),
|
|
699
|
+
},
|
|
700
|
+
},
|
|
596
701
|
};
|
|
597
702
|
|
|
598
703
|
mockContext.instantiate.mockResolvedValue(mockInstance);
|