@friggframework/core 2.0.0--canary.461.bb7fcba.0 → 2.0.0--canary.461.5767fa4.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.
Files changed (118) hide show
  1. package/generated/prisma-mongodb/client.d.ts +1 -0
  2. package/generated/prisma-mongodb/client.js +4 -0
  3. package/generated/prisma-mongodb/default.d.ts +1 -0
  4. package/generated/prisma-mongodb/default.js +4 -0
  5. package/generated/prisma-mongodb/edge.d.ts +1 -0
  6. package/generated/prisma-mongodb/edge.js +336 -0
  7. package/generated/prisma-mongodb/index-browser.js +318 -0
  8. package/generated/prisma-mongodb/index.d.ts +22993 -0
  9. package/generated/prisma-mongodb/index.js +361 -0
  10. package/generated/prisma-mongodb/package.json +183 -0
  11. package/generated/prisma-mongodb/query-engine-debian-openssl-3.0.x +0 -0
  12. package/generated/prisma-mongodb/query-engine-rhel-openssl-3.0.x +0 -0
  13. package/generated/prisma-mongodb/runtime/binary.d.ts +1 -0
  14. package/generated/prisma-mongodb/runtime/binary.js +289 -0
  15. package/generated/prisma-mongodb/runtime/edge-esm.js +34 -0
  16. package/generated/prisma-mongodb/runtime/edge.js +34 -0
  17. package/generated/prisma-mongodb/runtime/index-browser.d.ts +370 -0
  18. package/generated/prisma-mongodb/runtime/index-browser.js +16 -0
  19. package/generated/prisma-mongodb/runtime/library.d.ts +3977 -0
  20. package/generated/prisma-mongodb/runtime/react-native.js +83 -0
  21. package/generated/prisma-mongodb/runtime/wasm-compiler-edge.js +84 -0
  22. package/generated/prisma-mongodb/runtime/wasm-engine-edge.js +36 -0
  23. package/generated/prisma-mongodb/schema.prisma +364 -0
  24. package/generated/prisma-mongodb/wasm-edge-light-loader.mjs +4 -0
  25. package/generated/prisma-mongodb/wasm-worker-loader.mjs +4 -0
  26. package/generated/prisma-mongodb/wasm.d.ts +1 -0
  27. package/generated/prisma-mongodb/wasm.js +343 -0
  28. package/generated/prisma-postgresql/client.d.ts +1 -0
  29. package/generated/prisma-postgresql/client.js +4 -0
  30. package/generated/prisma-postgresql/default.d.ts +1 -0
  31. package/generated/prisma-postgresql/default.js +4 -0
  32. package/generated/prisma-postgresql/edge.d.ts +1 -0
  33. package/generated/prisma-postgresql/edge.js +358 -0
  34. package/generated/prisma-postgresql/index-browser.js +340 -0
  35. package/generated/prisma-postgresql/index.d.ts +25171 -0
  36. package/generated/prisma-postgresql/index.js +383 -0
  37. package/generated/prisma-postgresql/package.json +183 -0
  38. package/generated/prisma-postgresql/query-engine-debian-openssl-3.0.x +0 -0
  39. package/generated/prisma-postgresql/query-engine-rhel-openssl-3.0.x +0 -0
  40. package/generated/prisma-postgresql/query_engine_bg.js +2 -0
  41. package/generated/prisma-postgresql/query_engine_bg.wasm +0 -0
  42. package/generated/prisma-postgresql/runtime/binary.d.ts +1 -0
  43. package/generated/prisma-postgresql/runtime/binary.js +289 -0
  44. package/generated/prisma-postgresql/runtime/edge-esm.js +34 -0
  45. package/generated/prisma-postgresql/runtime/edge.js +34 -0
  46. package/generated/prisma-postgresql/runtime/index-browser.d.ts +370 -0
  47. package/generated/prisma-postgresql/runtime/index-browser.js +16 -0
  48. package/generated/prisma-postgresql/runtime/library.d.ts +3977 -0
  49. package/generated/prisma-postgresql/runtime/react-native.js +83 -0
  50. package/generated/prisma-postgresql/runtime/wasm-compiler-edge.js +84 -0
  51. package/generated/prisma-postgresql/runtime/wasm-engine-edge.js +36 -0
  52. package/generated/prisma-postgresql/schema.prisma +347 -0
  53. package/generated/prisma-postgresql/wasm-edge-light-loader.mjs +4 -0
  54. package/generated/prisma-postgresql/wasm-worker-loader.mjs +4 -0
  55. package/generated/prisma-postgresql/wasm.d.ts +1 -0
  56. package/generated/prisma-postgresql/wasm.js +365 -0
  57. package/package.json +5 -5
  58. package/application/commands/integration-commands.test.js +0 -123
  59. package/core/Worker.test.js +0 -159
  60. package/database/encryption/encryption-integration.test.js +0 -553
  61. package/database/encryption/encryption-schema-registry.test.js +0 -392
  62. package/database/encryption/field-encryption-service.test.js +0 -525
  63. package/database/encryption/mongo-decryption-fix-verification.test.js +0 -348
  64. package/database/encryption/postgres-decryption-fix-verification.test.js +0 -371
  65. package/database/encryption/postgres-relation-decryption.test.js +0 -245
  66. package/database/encryption/prisma-encryption-extension.test.js +0 -439
  67. package/database/repositories/migration-status-repository-s3.test.js +0 -158
  68. package/database/use-cases/check-encryption-health-use-case.test.js +0 -192
  69. package/database/use-cases/get-migration-status-use-case.test.js +0 -171
  70. package/database/use-cases/run-database-migration-use-case.test.js +0 -310
  71. package/database/use-cases/trigger-database-migration-use-case.test.js +0 -250
  72. package/database/utils/prisma-runner.test.js +0 -486
  73. package/encrypt/Cryptor.test.js +0 -144
  74. package/errors/base-error.test.js +0 -32
  75. package/errors/fetch-error.test.js +0 -79
  76. package/errors/halt-error.test.js +0 -11
  77. package/errors/validation-errors.test.js +0 -120
  78. package/handlers/auth-flow.integration.test.js +0 -147
  79. package/handlers/integration-event-dispatcher.test.js +0 -209
  80. package/handlers/routers/db-migration.test.js +0 -51
  81. package/handlers/routers/health.test.js +0 -210
  82. package/handlers/routers/integration-webhook-routers.test.js +0 -126
  83. package/handlers/use-cases/check-integrations-health-use-case.test.js +0 -125
  84. package/handlers/webhook-flow.integration.test.js +0 -356
  85. package/handlers/workers/db-migration.test.js +0 -50
  86. package/handlers/workers/integration-defined-workers.test.js +0 -184
  87. package/integrations/tests/integration-router-multi-auth.test.js +0 -369
  88. package/integrations/tests/use-cases/create-integration.test.js +0 -131
  89. package/integrations/tests/use-cases/delete-integration-for-user.test.js +0 -150
  90. package/integrations/tests/use-cases/find-integration-context-by-external-entity-id.test.js +0 -92
  91. package/integrations/tests/use-cases/get-integration-for-user.test.js +0 -150
  92. package/integrations/tests/use-cases/get-integration-instance.test.js +0 -176
  93. package/integrations/tests/use-cases/get-integrations-for-user.test.js +0 -176
  94. package/integrations/tests/use-cases/get-possible-integrations.test.js +0 -188
  95. package/integrations/tests/use-cases/update-integration-messages.test.js +0 -142
  96. package/integrations/tests/use-cases/update-integration-status.test.js +0 -103
  97. package/integrations/tests/use-cases/update-integration.test.js +0 -141
  98. package/integrations/use-cases/create-process.test.js +0 -178
  99. package/integrations/use-cases/get-process.test.js +0 -190
  100. package/integrations/use-cases/load-integration-context-full.test.js +0 -329
  101. package/integrations/use-cases/load-integration-context.test.js +0 -114
  102. package/integrations/use-cases/update-process-metrics.test.js +0 -308
  103. package/integrations/use-cases/update-process-state.test.js +0 -256
  104. package/lambda/TimeoutCatcher.test.js +0 -68
  105. package/logs/logger.test.js +0 -76
  106. package/modules/module-hydration.test.js +0 -205
  107. package/modules/requester/requester.test.js +0 -28
  108. package/queues/queuer-util.test.js +0 -132
  109. package/user/tests/use-cases/create-individual-user.test.js +0 -24
  110. package/user/tests/use-cases/create-organization-user.test.js +0 -28
  111. package/user/tests/use-cases/create-token-for-user-id.test.js +0 -19
  112. package/user/tests/use-cases/get-user-from-adopter-jwt.test.js +0 -113
  113. package/user/tests/use-cases/get-user-from-bearer-token.test.js +0 -64
  114. package/user/tests/use-cases/get-user-from-x-frigg-headers.test.js +0 -346
  115. package/user/tests/use-cases/login-user.test.js +0 -220
  116. package/user/tests/user-password-encryption-isolation.test.js +0 -237
  117. package/user/tests/user-password-hashing.test.js +0 -235
  118. package/websocket/repositories/websocket-connection-repository.test.js +0 -227
@@ -1,369 +0,0 @@
1
- const { AuthenticateUser } = require('../../user/use-cases/authenticate-user');
2
- const { GetUserFromBearerToken } = require('../../user/use-cases/get-user-from-bearer-token');
3
- const { GetUserFromXFriggHeaders } = require('../../user/use-cases/get-user-from-x-frigg-headers');
4
- const { GetUserFromAdopterJwt } = require('../../user/use-cases/get-user-from-adopter-jwt');
5
- const { User } = require('../../user/user');
6
- const Boom = require('@hapi/boom');
7
-
8
- describe('AuthenticateUser - Multi-Mode Authentication', () => {
9
- let authenticateUser;
10
- let mockGetUserFromBearerToken;
11
- let mockGetUserFromXFriggHeaders;
12
- let mockGetUserFromAdopterJwt;
13
- let mockUserConfig;
14
- let mockUser;
15
-
16
- beforeEach(() => {
17
- mockUser = new User(
18
- { id: 'user-123', username: 'testuser' },
19
- null,
20
- false,
21
- 'individual',
22
- true,
23
- false
24
- );
25
-
26
- mockGetUserFromBearerToken = {
27
- execute: jest.fn().mockResolvedValue(mockUser),
28
- };
29
-
30
- mockGetUserFromXFriggHeaders = {
31
- execute: jest.fn().mockResolvedValue(mockUser),
32
- };
33
-
34
- mockGetUserFromAdopterJwt = {
35
- execute: jest.fn().mockResolvedValue(mockUser),
36
- };
37
-
38
- mockUserConfig = {
39
- authModes: {
40
- friggToken: true,
41
- xFriggHeaders: true,
42
- adopterJwt: false,
43
- },
44
- };
45
-
46
- authenticateUser = new AuthenticateUser({
47
- getUserFromBearerToken: mockGetUserFromBearerToken,
48
- getUserFromXFriggHeaders: mockGetUserFromXFriggHeaders,
49
- getUserFromAdopterJwt: mockGetUserFromAdopterJwt,
50
- userConfig: mockUserConfig,
51
- });
52
- });
53
-
54
- describe('Priority 1: X-Frigg Headers (Backend-to-Backend)', () => {
55
- it('should authenticate with x-frigg-appUserId header', async () => {
56
- const mockReq = {
57
- headers: {
58
- 'x-frigg-appuserid': 'app-user-123',
59
- },
60
- };
61
-
62
- const result = await authenticateUser.execute(mockReq);
63
-
64
- expect(result).toBe(mockUser);
65
- expect(mockGetUserFromXFriggHeaders.execute).toHaveBeenCalledWith(
66
- 'app-user-123',
67
- undefined
68
- );
69
- expect(mockGetUserFromBearerToken.execute).not.toHaveBeenCalled();
70
- });
71
-
72
- it('should authenticate with x-frigg-appOrgId header', async () => {
73
- const mockReq = {
74
- headers: {
75
- 'x-frigg-apporgid': 'app-org-456',
76
- },
77
- };
78
-
79
- const result = await authenticateUser.execute(mockReq);
80
-
81
- expect(result).toBe(mockUser);
82
- expect(mockGetUserFromXFriggHeaders.execute).toHaveBeenCalledWith(
83
- undefined,
84
- 'app-org-456'
85
- );
86
- expect(mockGetUserFromBearerToken.execute).not.toHaveBeenCalled();
87
- });
88
-
89
- it('should authenticate with both x-frigg headers when they match', async () => {
90
- const mockReq = {
91
- headers: {
92
- 'x-frigg-appuserid': 'app-user-123',
93
- 'x-frigg-apporgid': 'app-org-456',
94
- },
95
- };
96
-
97
- const result = await authenticateUser.execute(mockReq);
98
-
99
- expect(result).toBe(mockUser);
100
- expect(mockGetUserFromXFriggHeaders.execute).toHaveBeenCalledWith(
101
- 'app-user-123',
102
- 'app-org-456'
103
- );
104
- });
105
-
106
- it('should reject conflicting x-frigg headers (delegated to use case)', async () => {
107
- const mockReq = {
108
- headers: {
109
- 'x-frigg-appuserid': 'app-user-123',
110
- 'x-frigg-apporgid': 'app-org-999',
111
- },
112
- };
113
-
114
- const conflictError = Boom.badRequest('User ID mismatch');
115
- mockGetUserFromXFriggHeaders.execute.mockRejectedValue(conflictError);
116
-
117
- await expect(authenticateUser.execute(mockReq)).rejects.toThrow(
118
- conflictError
119
- );
120
- });
121
-
122
- it('should skip x-frigg headers when authModes.xFriggHeaders is false', async () => {
123
- mockUserConfig.authModes.xFriggHeaders = false;
124
-
125
- const mockReq = {
126
- headers: {
127
- 'x-frigg-appuserid': 'app-user-123',
128
- authorization: 'Bearer frigg-token-xyz',
129
- },
130
- };
131
-
132
- await authenticateUser.execute(mockReq);
133
-
134
- expect(mockGetUserFromXFriggHeaders.execute).not.toHaveBeenCalled();
135
- expect(mockGetUserFromBearerToken.execute).toHaveBeenCalledWith(
136
- 'Bearer frigg-token-xyz'
137
- );
138
- });
139
- });
140
-
141
- describe('Priority 2: Adopter JWT', () => {
142
- beforeEach(() => {
143
- mockUserConfig.authModes.adopterJwt = true;
144
- });
145
-
146
- it('should try JWT when enabled and Bearer token is 3-part format', async () => {
147
- const mockReq = {
148
- headers: {
149
- authorization: 'Bearer eyJhbGci.eyJzdWIi.signature',
150
- },
151
- };
152
-
153
- await authenticateUser.execute(mockReq);
154
-
155
- expect(mockGetUserFromAdopterJwt.execute).toHaveBeenCalledWith(
156
- 'eyJhbGci.eyJzdWIi.signature'
157
- );
158
- expect(mockGetUserFromBearerToken.execute).not.toHaveBeenCalled();
159
- });
160
-
161
- it('should fall back to Frigg token when Bearer token is not JWT format', async () => {
162
- const mockReq = {
163
- headers: {
164
- authorization: 'Bearer simple-token',
165
- },
166
- };
167
-
168
- await authenticateUser.execute(mockReq);
169
-
170
- expect(mockGetUserFromAdopterJwt.execute).not.toHaveBeenCalled();
171
- expect(mockGetUserFromBearerToken.execute).toHaveBeenCalledWith(
172
- 'Bearer simple-token'
173
- );
174
- });
175
-
176
- it('should not try JWT when authModes.adopterJwt is false', async () => {
177
- mockUserConfig.authModes.adopterJwt = false;
178
-
179
- const mockReq = {
180
- headers: {
181
- authorization: 'Bearer eyJhbGci.eyJzdWIi.signature',
182
- },
183
- };
184
-
185
- await authenticateUser.execute(mockReq);
186
-
187
- expect(mockGetUserFromAdopterJwt.execute).not.toHaveBeenCalled();
188
- expect(mockGetUserFromBearerToken.execute).toHaveBeenCalledWith(
189
- 'Bearer eyJhbGci.eyJzdWIi.signature'
190
- );
191
- });
192
- });
193
-
194
- describe('Priority 3: Frigg Native Token (Fallback)', () => {
195
- it('should fall back to Frigg token when no x-frigg headers', async () => {
196
- const mockReq = {
197
- headers: {
198
- authorization: 'Bearer frigg-token-123',
199
- },
200
- };
201
-
202
- const result = await authenticateUser.execute(mockReq);
203
-
204
- expect(result).toBe(mockUser);
205
- expect(mockGetUserFromBearerToken.execute).toHaveBeenCalledWith(
206
- 'Bearer frigg-token-123'
207
- );
208
- expect(mockGetUserFromXFriggHeaders.execute).not.toHaveBeenCalled();
209
- });
210
-
211
- it('should skip Frigg token when authModes.friggToken is false', async () => {
212
- mockUserConfig.authModes.friggToken = false;
213
-
214
- const mockReq = {
215
- headers: {
216
- authorization: 'Bearer frigg-token-123',
217
- },
218
- };
219
-
220
- await expect(authenticateUser.execute(mockReq)).rejects.toThrow(
221
- Boom.unauthorized().message
222
- );
223
-
224
- expect(mockGetUserFromBearerToken.execute).not.toHaveBeenCalled();
225
- });
226
- });
227
-
228
- describe('Priority Ordering', () => {
229
- it('should prioritize x-frigg headers over bearer token', async () => {
230
- const mockReq = {
231
- headers: {
232
- 'x-frigg-appuserid': 'app-user-123',
233
- authorization: 'Bearer frigg-token-xyz',
234
- },
235
- };
236
-
237
- await authenticateUser.execute(mockReq);
238
-
239
- expect(mockGetUserFromXFriggHeaders.execute).toHaveBeenCalledWith(
240
- 'app-user-123',
241
- undefined
242
- );
243
- expect(mockGetUserFromBearerToken.execute).not.toHaveBeenCalled();
244
- });
245
-
246
- it('should try JWT before Frigg token when JWT enabled', async () => {
247
- mockUserConfig.authModes.adopterJwt = true;
248
-
249
- const mockReq = {
250
- headers: {
251
- authorization: 'Bearer part1.part2.part3',
252
- },
253
- };
254
-
255
- await authenticateUser.execute(mockReq);
256
-
257
- expect(mockGetUserFromAdopterJwt.execute).toHaveBeenCalledWith(
258
- 'part1.part2.part3'
259
- );
260
- expect(mockGetUserFromBearerToken.execute).not.toHaveBeenCalled();
261
- });
262
- });
263
-
264
- describe('Auth Mode Configuration', () => {
265
- it('should use default friggToken mode when authModes not configured', () => {
266
- const authWithDefaults = new AuthenticateUser({
267
- getUserFromBearerToken: mockGetUserFromBearerToken,
268
- getUserFromXFriggHeaders: mockGetUserFromXFriggHeaders,
269
- getUserFromAdopterJwt: mockGetUserFromAdopterJwt,
270
- userConfig: {}, // No authModes
271
- });
272
-
273
- const mockReq = {
274
- headers: {
275
- authorization: 'Bearer token',
276
- },
277
- };
278
-
279
- authWithDefaults.execute(mockReq);
280
-
281
- expect(mockGetUserFromBearerToken.execute).toHaveBeenCalled();
282
- });
283
-
284
- it('should throw unauthorized when no valid authentication provided', async () => {
285
- const mockReq = {
286
- headers: {},
287
- };
288
-
289
- await expect(authenticateUser.execute(mockReq)).rejects.toThrow(
290
- Boom.unauthorized().message
291
- );
292
-
293
- await expect(authenticateUser.execute(mockReq)).rejects.toThrow(
294
- 'No valid authentication provided'
295
- );
296
- });
297
-
298
- it('should throw unauthorized when all auth modes disabled', async () => {
299
- mockUserConfig.authModes = {
300
- friggToken: false,
301
- xFriggHeaders: false,
302
- adopterJwt: false,
303
- };
304
-
305
- const mockReq = {
306
- headers: {
307
- authorization: 'Bearer token',
308
- },
309
- };
310
-
311
- await expect(authenticateUser.execute(mockReq)).rejects.toThrow(
312
- 'No valid authentication provided'
313
- );
314
- });
315
- });
316
-
317
- describe('Error Handling', () => {
318
- it('should propagate authentication errors from x-frigg headers', async () => {
319
- const mockReq = {
320
- headers: {
321
- 'x-frigg-appuserid': 'invalid-user',
322
- },
323
- };
324
-
325
- const customError = Boom.badRequest('Invalid user ID');
326
- mockGetUserFromXFriggHeaders.execute.mockRejectedValue(customError);
327
-
328
- await expect(authenticateUser.execute(mockReq)).rejects.toThrow(
329
- customError
330
- );
331
- });
332
-
333
- it('should propagate authentication errors from bearer token', async () => {
334
- const mockReq = {
335
- headers: {
336
- authorization: 'Bearer invalid-token',
337
- },
338
- };
339
-
340
- const customError = Boom.unauthorized('Invalid token');
341
- mockGetUserFromBearerToken.execute.mockRejectedValue(customError);
342
-
343
- await expect(authenticateUser.execute(mockReq)).rejects.toThrow(
344
- customError
345
- );
346
- });
347
-
348
- it('should propagate not implemented error from JWT', async () => {
349
- mockUserConfig.authModes.adopterJwt = true;
350
-
351
- const mockReq = {
352
- headers: {
353
- authorization: 'Bearer part1.part2.part3',
354
- },
355
- };
356
-
357
- const notImplementedError = Boom.notImplemented('JWT not implemented');
358
- mockGetUserFromAdopterJwt.execute.mockRejectedValue(
359
- notImplementedError
360
- );
361
-
362
- await expect(authenticateUser.execute(mockReq)).rejects.toThrow(
363
- notImplementedError
364
- );
365
- });
366
- });
367
- });
368
-
369
-
@@ -1,131 +0,0 @@
1
- jest.mock('../../../database/config', () => ({
2
- DB_TYPE: 'mongodb',
3
- getDatabaseType: jest.fn(() => 'mongodb'),
4
- PRISMA_LOG_LEVEL: 'error,warn',
5
- PRISMA_QUERY_LOGGING: false,
6
- }));
7
-
8
- const { CreateIntegration } = require('../../use-cases/create-integration');
9
- const { TestIntegrationRepository } = require('../doubles/test-integration-repository');
10
- const { TestModuleFactory } = require('../../../modules/tests/doubles/test-module-factory');
11
- const { DummyIntegration } = require('../doubles/dummy-integration-class');
12
-
13
- describe('CreateIntegration Use-Case', () => {
14
- let integrationRepository;
15
- let moduleFactory;
16
- let useCase;
17
-
18
- beforeEach(() => {
19
- integrationRepository = new TestIntegrationRepository();
20
- moduleFactory = new TestModuleFactory();
21
- useCase = new CreateIntegration({
22
- integrationRepository,
23
- integrationClasses: [DummyIntegration],
24
- moduleFactory,
25
- });
26
- });
27
-
28
- describe('happy path', () => {
29
- it('creates an integration and returns DTO', async () => {
30
- const entities = ['entity-1'];
31
- const userId = 'user-1';
32
- const config = { type: 'dummy', foo: 'bar' };
33
-
34
- const dto = await useCase.execute(entities, userId, config);
35
-
36
- expect(dto.id).toBeDefined();
37
- expect(dto.config).toEqual(config);
38
- expect(dto.userId).toBe(userId);
39
- expect(dto.entities).toEqual(entities);
40
- expect(dto.status).toBe('NEW');
41
- });
42
-
43
- it('triggers ON_CREATE event with correct payload', async () => {
44
- const entities = ['entity-1'];
45
- const userId = 'user-1';
46
- const config = { type: 'dummy', foo: 'bar' };
47
-
48
- const dto = await useCase.execute(entities, userId, config);
49
-
50
- const record = await integrationRepository.findIntegrationById(dto.id);
51
- expect(record).toBeTruthy();
52
-
53
- const history = integrationRepository.getOperationHistory();
54
- const createOperation = history.find(op => op.operation === 'create');
55
- expect(createOperation).toEqual({
56
- operation: 'create',
57
- id: dto.id,
58
- userId,
59
- config
60
- });
61
- });
62
-
63
- it('loads modules for each entity', async () => {
64
- const entities = ['entity-1', 'entity-2'];
65
- const userId = 'user-1';
66
- const config = { type: 'dummy' };
67
-
68
- const dto = await useCase.execute(entities, userId, config);
69
-
70
- expect(dto.entities).toEqual(entities);
71
- });
72
- });
73
-
74
- describe('error cases', () => {
75
- it('throws error when integration class is not found', async () => {
76
- const entities = ['entity-1'];
77
- const userId = 'user-1';
78
- const config = { type: 'unknown-type' };
79
-
80
- await expect(useCase.execute(entities, userId, config))
81
- .rejects
82
- .toThrow('No integration class found for type: unknown-type');
83
- });
84
-
85
- it('throws error when no integration classes provided', async () => {
86
- const useCaseWithoutClasses = new CreateIntegration({
87
- integrationRepository,
88
- integrationClasses: [],
89
- moduleFactory,
90
- });
91
-
92
- const entities = ['entity-1'];
93
- const userId = 'user-1';
94
- const config = { type: 'dummy' };
95
-
96
- await expect(useCaseWithoutClasses.execute(entities, userId, config))
97
- .rejects
98
- .toThrow('No integration class found for type: dummy');
99
- });
100
- });
101
-
102
- describe('edge cases', () => {
103
- it('handles empty entities array', async () => {
104
- const entities = [];
105
- const userId = 'user-1';
106
- const config = { type: 'dummy' };
107
-
108
- const dto = await useCase.execute(entities, userId, config);
109
-
110
- expect(dto.entities).toEqual([]);
111
- expect(dto.id).toBeDefined();
112
- });
113
-
114
- it('handles complex config objects', async () => {
115
- const entities = ['entity-1'];
116
- const userId = 'user-1';
117
- const config = {
118
- type: 'dummy',
119
- nested: {
120
- value: 123,
121
- array: [1, 2, 3],
122
- bool: true
123
- }
124
- };
125
-
126
- const dto = await useCase.execute(entities, userId, config);
127
-
128
- expect(dto.config).toEqual(config);
129
- });
130
- });
131
- });
@@ -1,150 +0,0 @@
1
- jest.mock('../../../database/config', () => ({
2
- DB_TYPE: 'mongodb',
3
- getDatabaseType: jest.fn(() => 'mongodb'),
4
- PRISMA_LOG_LEVEL: 'error,warn',
5
- PRISMA_QUERY_LOGGING: false,
6
- }));
7
-
8
- const { DeleteIntegrationForUser } = require('../../use-cases/delete-integration-for-user');
9
- const { TestIntegrationRepository } = require('../doubles/test-integration-repository');
10
- const { DummyIntegration } = require('../doubles/dummy-integration-class');
11
-
12
- describe('DeleteIntegrationForUser Use-Case', () => {
13
- let integrationRepository;
14
- let useCase;
15
-
16
- beforeEach(() => {
17
- integrationRepository = new TestIntegrationRepository();
18
- useCase = new DeleteIntegrationForUser({
19
- integrationRepository,
20
- integrationClasses: [DummyIntegration],
21
- });
22
- });
23
-
24
- describe('happy path', () => {
25
- it('deletes integration successfully', async () => {
26
- const record = await integrationRepository.createIntegration(['e1'], 'user-1', { type: 'dummy' });
27
-
28
- await useCase.execute(record.id, 'user-1');
29
-
30
- const found = await integrationRepository.findIntegrationById(record.id);
31
- expect(found).toBeNull();
32
- });
33
-
34
- it('tracks delete operation', async () => {
35
- const record = await integrationRepository.createIntegration(['e1'], 'user-1', { type: 'dummy' });
36
- integrationRepository.clearHistory();
37
-
38
- await useCase.execute(record.id, 'user-1');
39
-
40
- const history = integrationRepository.getOperationHistory();
41
- const deleteOperation = history.find(op => op.operation === 'delete');
42
- expect(deleteOperation).toEqual({
43
- operation: 'delete',
44
- id: record.id,
45
- existed: true,
46
- success: true
47
- });
48
- });
49
-
50
- it('deletes integration with multiple entities', async () => {
51
- const record = await integrationRepository.createIntegration(['e1', 'e2', 'e3'], 'user-1', { type: 'dummy' });
52
-
53
- await useCase.execute(record.id, 'user-1');
54
-
55
- const found = await integrationRepository.findIntegrationById(record.id);
56
- expect(found).toBeNull();
57
- });
58
- });
59
-
60
- describe('error cases', () => {
61
- it('throws error when integration not found', async () => {
62
- const nonExistentId = 'non-existent-id';
63
-
64
- await expect(useCase.execute(nonExistentId, 'user-1'))
65
- .rejects
66
- .toThrow(`Integration with id of ${nonExistentId} does not exist`);
67
- });
68
-
69
- it('throws error when user does not own integration', async () => {
70
- const record = await integrationRepository.createIntegration(['e1'], 'user-1', { type: 'dummy' });
71
-
72
- await expect(useCase.execute(record.id, 'different-user'))
73
- .rejects
74
- .toThrow(`Integration ${record.id} does not belong to User different-user`);
75
- });
76
-
77
- it('throws error when integration class not found', async () => {
78
- const useCaseWithoutClasses = new DeleteIntegrationForUser({
79
- integrationRepository,
80
- integrationClasses: [],
81
- });
82
-
83
- const record = await integrationRepository.createIntegration(['e1'], 'user-1', { type: 'dummy' });
84
-
85
- await expect(useCaseWithoutClasses.execute(record.id, 'user-1'))
86
- .rejects
87
- .toThrow();
88
- });
89
-
90
- it('tracks failed delete operation for non-existent integration', async () => {
91
- const nonExistentId = 'non-existent-id';
92
- integrationRepository.clearHistory();
93
-
94
- try {
95
- await useCase.execute(nonExistentId, 'user-1');
96
- } catch (error) {
97
- const history = integrationRepository.getOperationHistory();
98
- const findOperation = history.find(op => op.operation === 'findById');
99
- expect(findOperation).toEqual({
100
- operation: 'findById',
101
- id: nonExistentId,
102
- found: false
103
- });
104
- }
105
- });
106
- });
107
-
108
- describe('edge cases', () => {
109
- it('handles deletion of already deleted integration', async () => {
110
- const record = await integrationRepository.createIntegration(['e1'], 'user-1', { type: 'dummy' });
111
-
112
- await useCase.execute(record.id, 'user-1');
113
-
114
- await expect(useCase.execute(record.id, 'user-1'))
115
- .rejects
116
- .toThrow(`Integration with id of ${record.id} does not exist`);
117
- });
118
-
119
- it('handles integration with complex config during deletion', async () => {
120
- const complexConfig = {
121
- type: 'dummy',
122
- settings: { nested: { deep: 'value' } },
123
- credentials: { encrypted: true }
124
- };
125
-
126
- const record = await integrationRepository.createIntegration(['e1'], 'user-1', complexConfig);
127
-
128
- await useCase.execute(record.id, 'user-1');
129
-
130
- const found = await integrationRepository.findIntegrationById(record.id);
131
- expect(found).toBeNull();
132
- });
133
-
134
- it('handles null userId gracefully', async () => {
135
- const record = await integrationRepository.createIntegration(['e1'], 'user-1', { type: 'dummy' });
136
-
137
- await expect(useCase.execute(record.id, null))
138
- .rejects
139
- .toThrow(`Integration ${record.id} does not belong to User null`);
140
- });
141
-
142
- it('handles undefined userId gracefully', async () => {
143
- const record = await integrationRepository.createIntegration(['e1'], 'user-1', { type: 'dummy' });
144
-
145
- await expect(useCase.execute(record.id, undefined))
146
- .rejects
147
- .toThrow(`Integration ${record.id} does not belong to User undefined`);
148
- });
149
- });
150
- });