@friggframework/core 2.0.0--canary.461.61382d8.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,113 +0,0 @@
1
- const Boom = require('@hapi/boom');
2
- const { GetUserFromAdopterJwt } = require('../../use-cases/get-user-from-adopter-jwt');
3
-
4
- describe('GetUserFromAdopterJwt', () => {
5
- let getUserFromAdopterJwt;
6
- let mockUserRepository;
7
- let mockUserConfig;
8
-
9
- beforeEach(() => {
10
- mockUserRepository = {
11
- findIndividualUserByAppUserId: jest.fn(),
12
- findOrganizationUserByAppOrgId: jest.fn(),
13
- createIndividualUser: jest.fn(),
14
- createOrganizationUser: jest.fn(),
15
- };
16
-
17
- mockUserConfig = {
18
- usePassword: false,
19
- primary: 'individual',
20
- individualUserRequired: true,
21
- organizationUserRequired: false,
22
- authModes: {
23
- adopterJwt: true,
24
- },
25
- jwtConfig: {
26
- secret: 'test-secret',
27
- userIdClaim: 'sub',
28
- orgIdClaim: 'org_id',
29
- algorithm: 'HS256',
30
- },
31
- };
32
-
33
- getUserFromAdopterJwt = new GetUserFromAdopterJwt({
34
- userRepository: mockUserRepository,
35
- userConfig: mockUserConfig,
36
- });
37
- });
38
-
39
- describe('Stub Behavior', () => {
40
- it('should throw 501 Not Implemented error', async () => {
41
- const jwtToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyMTIzIiwib3JnX2lkIjoib3JnNDU2In0.signature';
42
-
43
- await expect(
44
- getUserFromAdopterJwt.execute(jwtToken)
45
- ).rejects.toThrow(Boom.notImplemented().message);
46
- });
47
-
48
- it('should provide helpful error message about alternative auth modes', async () => {
49
- const jwtToken = 'test.jwt.token';
50
-
51
- try {
52
- await getUserFromAdopterJwt.execute(jwtToken);
53
- fail('Should have thrown error');
54
- } catch (error) {
55
- expect(error.message).toContain('not yet implemented');
56
- expect(error.message).toContain('friggToken');
57
- expect(error.message).toContain('xFriggHeaders');
58
- }
59
- });
60
-
61
- it('should throw 501 error with any token format', async () => {
62
- await expect(
63
- getUserFromAdopterJwt.execute('simple-token')
64
- ).rejects.toThrow(Boom.notImplemented().message);
65
-
66
- await expect(
67
- getUserFromAdopterJwt.execute('part1.part2.part3')
68
- ).rejects.toThrow(Boom.notImplemented().message);
69
-
70
- await expect(getUserFromAdopterJwt.execute('')).rejects.toThrow(
71
- Boom.notImplemented().message
72
- );
73
- });
74
- });
75
-
76
- describe('Initialization', () => {
77
- it('should initialize successfully with valid configuration', () => {
78
- expect(getUserFromAdopterJwt).toBeDefined();
79
- expect(getUserFromAdopterJwt.userRepository).toBe(
80
- mockUserRepository
81
- );
82
- expect(getUserFromAdopterJwt.userConfig).toBe(mockUserConfig);
83
- });
84
-
85
- it('should initialize without jwtConfig (will fail on execute)', () => {
86
- const configWithoutJwt = {
87
- usePassword: false,
88
- primary: 'individual',
89
- };
90
-
91
- const instance = new GetUserFromAdopterJwt({
92
- userRepository: mockUserRepository,
93
- userConfig: configWithoutJwt,
94
- });
95
-
96
- expect(instance).toBeDefined();
97
- });
98
- });
99
-
100
- describe('Future Implementation Notes', () => {
101
- it('should have documented todos for JWT implementation', () => {
102
- const useCaseFileContent = require('fs').readFileSync(
103
- require.resolve('../../use-cases/get-user-from-adopter-jwt.js'),
104
- 'utf-8'
105
- );
106
-
107
- expect(useCaseFileContent).toContain('@todo');
108
- expect(useCaseFileContent).toContain('jsonwebtoken');
109
- expect(useCaseFileContent).toContain('FUTURE IMPLEMENTATION');
110
- });
111
- });
112
- });
113
-
@@ -1,64 +0,0 @@
1
- const {
2
- GetUserFromBearerToken,
3
- } = require('../../use-cases/get-user-from-bearer-token');
4
- const { TestUserRepository } = require('../doubles/test-user-repository');
5
-
6
- describe('GetUserFromBearerToken Use Case', () => {
7
- let userRepository;
8
- let getUserFromBearerToken;
9
- let userConfig;
10
-
11
- beforeEach(() => {
12
- userConfig = {
13
- usePassword: true,
14
- primary: 'individual',
15
- individualUserRequired: true,
16
- organizationUserRequired: false,
17
- };
18
- userRepository = new TestUserRepository({ userConfig });
19
- getUserFromBearerToken = new GetUserFromBearerToken({
20
- userRepository,
21
- userConfig
22
- });
23
- });
24
-
25
- it('should retrieve a user for a valid bearer token', async () => {
26
- const userId = 'user-123';
27
- const token = await userRepository.createToken(userId);
28
- const createdUserData = await userRepository.createIndividualUser({
29
- id: userId,
30
- });
31
-
32
- const user = await getUserFromBearerToken.execute(`Bearer ${token}`);
33
-
34
- expect(user).toBeDefined();
35
- expect(user.getId()).toBe(createdUserData.id);
36
- });
37
-
38
- it('should throw an unauthorized error if the bearer token is missing', async () => {
39
- await expect(getUserFromBearerToken.execute(null)).rejects.toThrow(
40
- 'Missing Authorization Header'
41
- );
42
- });
43
-
44
- it('should throw an unauthorized error for an invalid token format', async () => {
45
- await expect(
46
- getUserFromBearerToken.execute('InvalidToken')
47
- ).rejects.toThrow('Invalid Token Format');
48
- });
49
-
50
- it('should throw an unauthorized error if the Session Token is not found', async () => {
51
- userRepository.getSessionToken = jest.fn().mockResolvedValue(null);
52
- await expect(
53
- getUserFromBearerToken.execute('Bearer invalid-token')
54
- ).rejects.toThrow('Session Token Not Found');
55
- });
56
-
57
- it('should throw an unauthorized error if the token is valid but finds no user', async () => {
58
- userRepository.getSessionToken = jest.fn().mockResolvedValue(null);
59
- const token = await userRepository.createToken('user-dne');
60
- await expect(
61
- getUserFromBearerToken.execute(`Bearer ${token}`)
62
- ).rejects.toThrow('Session Token Not Found');
63
- });
64
- });
@@ -1,346 +0,0 @@
1
- const Boom = require('@hapi/boom');
2
- const { GetUserFromXFriggHeaders } = require('../../use-cases/get-user-from-x-frigg-headers');
3
- const { User } = require('../../user');
4
-
5
- describe('GetUserFromXFriggHeaders', () => {
6
- let getUserFromXFriggHeaders;
7
- let mockUserRepository;
8
- let mockUserConfig;
9
-
10
- beforeEach(() => {
11
- mockUserRepository = {
12
- findIndividualUserByAppUserId: jest.fn(),
13
- findOrganizationUserByAppOrgId: jest.fn(),
14
- createIndividualUser: jest.fn(),
15
- createOrganizationUser: jest.fn(),
16
- };
17
-
18
- mockUserConfig = {
19
- usePassword: false,
20
- primary: 'individual',
21
- individualUserRequired: true,
22
- organizationUserRequired: false,
23
- };
24
-
25
- getUserFromXFriggHeaders = new GetUserFromXFriggHeaders({
26
- userRepository: mockUserRepository,
27
- userConfig: mockUserConfig,
28
- });
29
- });
30
-
31
- describe('Validation', () => {
32
- it('should throw 400 error when neither appUserId nor appOrgId provided', async () => {
33
- await expect(
34
- getUserFromXFriggHeaders.execute(null, null)
35
- ).rejects.toThrow(Boom.badRequest().message);
36
-
37
- await expect(
38
- getUserFromXFriggHeaders.execute(undefined, undefined)
39
- ).rejects.toThrow();
40
- });
41
- });
42
-
43
- describe('Find Existing User', () => {
44
- it('should find existing individual user by appUserId', async () => {
45
- const mockIndividualUser = {
46
- id: 'user-123',
47
- appUserId: 'app-user-456',
48
- username: 'testuser',
49
- };
50
-
51
- mockUserRepository.findIndividualUserByAppUserId.mockResolvedValue(
52
- mockIndividualUser
53
- );
54
-
55
- const result = await getUserFromXFriggHeaders.execute(
56
- 'app-user-456',
57
- null
58
- );
59
-
60
- expect(result).toBeInstanceOf(User);
61
- expect(
62
- mockUserRepository.findIndividualUserByAppUserId
63
- ).toHaveBeenCalledWith('app-user-456');
64
- expect(
65
- mockUserRepository.createIndividualUser
66
- ).not.toHaveBeenCalled();
67
- });
68
-
69
- it('should find existing organization user by appOrgId', async () => {
70
- mockUserConfig.organizationUserRequired = true;
71
- mockUserConfig.primary = 'organization';
72
-
73
- const mockOrgUser = {
74
- id: 'org-123',
75
- appOrgId: 'app-org-456',
76
- };
77
-
78
- mockUserRepository.findOrganizationUserByAppOrgId.mockResolvedValue(
79
- mockOrgUser
80
- );
81
-
82
- const result = await getUserFromXFriggHeaders.execute(
83
- null,
84
- 'app-org-456'
85
- );
86
-
87
- expect(result).toBeInstanceOf(User);
88
- expect(
89
- mockUserRepository.findOrganizationUserByAppOrgId
90
- ).toHaveBeenCalledWith('app-org-456');
91
- expect(
92
- mockUserRepository.createOrganizationUser
93
- ).not.toHaveBeenCalled();
94
- });
95
- });
96
-
97
- describe('Auto-create User', () => {
98
- it('should create new individual user when appUserId not found', async () => {
99
- mockUserRepository.findIndividualUserByAppUserId.mockResolvedValue(
100
- null
101
- );
102
-
103
- const mockCreatedUser = {
104
- id: 'user-new',
105
- appUserId: 'new-app-user',
106
- username: 'app-user-new-app-user',
107
- email: 'new-app-user@app.local',
108
- };
109
-
110
- mockUserRepository.createIndividualUser.mockResolvedValue(
111
- mockCreatedUser
112
- );
113
-
114
- const result = await getUserFromXFriggHeaders.execute(
115
- 'new-app-user',
116
- null
117
- );
118
-
119
- expect(result).toBeInstanceOf(User);
120
- expect(
121
- mockUserRepository.createIndividualUser
122
- ).toHaveBeenCalledWith({
123
- appUserId: 'new-app-user',
124
- username: 'app-user-new-app-user',
125
- email: 'new-app-user@app.local',
126
- });
127
- });
128
-
129
- it('should create new organization user when appOrgId not found', async () => {
130
- mockUserConfig.organizationUserRequired = true;
131
- mockUserConfig.primary = 'organization';
132
- mockUserConfig.individualUserRequired = false;
133
-
134
- mockUserRepository.findOrganizationUserByAppOrgId.mockResolvedValue(
135
- null
136
- );
137
-
138
- const mockCreatedOrgUser = {
139
- id: 'org-new',
140
- appOrgId: 'new-app-org',
141
- };
142
-
143
- mockUserRepository.createOrganizationUser.mockResolvedValue(
144
- mockCreatedOrgUser
145
- );
146
-
147
- const result = await getUserFromXFriggHeaders.execute(
148
- null,
149
- 'new-app-org'
150
- );
151
-
152
- expect(result).toBeInstanceOf(User);
153
- expect(
154
- mockUserRepository.createOrganizationUser
155
- ).toHaveBeenCalledWith({
156
- appOrgId: 'new-app-org',
157
- });
158
- });
159
- });
160
-
161
- describe('User ID Conflict Detection', () => {
162
- it('should throw 400 error when both IDs provided but belong to different users', async () => {
163
- const mockIndividualUser = {
164
- id: 'user-123',
165
- appUserId: 'app-user-456',
166
- organizationUser: 'org-999', // Different org
167
- };
168
-
169
- const mockOrgUser = {
170
- id: 'org-888', // Different ID
171
- appOrgId: 'app-org-789',
172
- };
173
-
174
- mockUserConfig.organizationUserRequired = true;
175
-
176
- mockUserRepository.findIndividualUserByAppUserId.mockResolvedValue(
177
- mockIndividualUser
178
- );
179
- mockUserRepository.findOrganizationUserByAppOrgId.mockResolvedValue(
180
- mockOrgUser
181
- );
182
-
183
- await expect(
184
- getUserFromXFriggHeaders.execute('app-user-456', 'app-org-789')
185
- ).rejects.toThrow(Boom.badRequest().message);
186
-
187
- await expect(
188
- getUserFromXFriggHeaders.execute('app-user-456', 'app-org-789')
189
- ).rejects.toThrow('User ID mismatch');
190
- });
191
-
192
- it('should succeed when both IDs provided and belong to same user', async () => {
193
- const mockOrgUser = {
194
- id: 'org-123',
195
- appOrgId: 'app-org-789',
196
- };
197
-
198
- const mockIndividualUser = {
199
- id: 'user-456',
200
- appUserId: 'app-user-456',
201
- organizationUser: 'org-123', // Matches org user
202
- };
203
-
204
- mockUserConfig.organizationUserRequired = true;
205
-
206
- mockUserRepository.findIndividualUserByAppUserId.mockResolvedValue(
207
- mockIndividualUser
208
- );
209
- mockUserRepository.findOrganizationUserByAppOrgId.mockResolvedValue(
210
- mockOrgUser
211
- );
212
-
213
- const result = await getUserFromXFriggHeaders.execute(
214
- 'app-user-456',
215
- 'app-org-789'
216
- );
217
-
218
- expect(result).toBeInstanceOf(User);
219
- expect(
220
- mockUserRepository.createIndividualUser
221
- ).not.toHaveBeenCalled();
222
- expect(
223
- mockUserRepository.createOrganizationUser
224
- ).not.toHaveBeenCalled();
225
- });
226
-
227
- it('should not validate conflict when only one ID provided', async () => {
228
- const mockIndividualUser = {
229
- id: 'user-123',
230
- appUserId: 'app-user-456',
231
- };
232
-
233
- mockUserRepository.findIndividualUserByAppUserId.mockResolvedValue(
234
- mockIndividualUser
235
- );
236
-
237
- const result = await getUserFromXFriggHeaders.execute(
238
- 'app-user-456',
239
- null
240
- );
241
-
242
- expect(result).toBeInstanceOf(User);
243
- expect(
244
- mockUserRepository.findOrganizationUserByAppOrgId
245
- ).not.toHaveBeenCalled();
246
- });
247
- });
248
-
249
- describe('User Config Respect', () => {
250
- it('should respect individualUserRequired setting', async () => {
251
- mockUserConfig.individualUserRequired = false;
252
-
253
- mockUserRepository.findIndividualUserByAppUserId.mockResolvedValue(
254
- null
255
- );
256
-
257
- await getUserFromXFriggHeaders.execute('app-user-test', null);
258
-
259
- // Should not attempt to query or create individual user if not required
260
- expect(
261
- mockUserRepository.findIndividualUserByAppUserId
262
- ).not.toHaveBeenCalled();
263
- });
264
-
265
- it('should respect organizationUserRequired setting', async () => {
266
- mockUserConfig.organizationUserRequired = false;
267
-
268
- mockUserRepository.findOrganizationUserByAppOrgId.mockResolvedValue(
269
- null
270
- );
271
-
272
- const mockIndividualUser = {
273
- id: 'user-123',
274
- appUserId: 'app-user-456',
275
- };
276
-
277
- mockUserRepository.findIndividualUserByAppUserId.mockResolvedValue(
278
- mockIndividualUser
279
- );
280
-
281
- await getUserFromXFriggHeaders.execute('app-user-456', 'app-org-789');
282
-
283
- // Should not query org user if not required
284
- expect(
285
- mockUserRepository.findOrganizationUserByAppOrgId
286
- ).not.toHaveBeenCalled();
287
- });
288
-
289
- it('should respect primary user setting', async () => {
290
- mockUserConfig.primary = 'organization';
291
- mockUserConfig.organizationUserRequired = true;
292
-
293
- const mockOrgUser = {
294
- id: 'org-123',
295
- appOrgId: 'app-org-789',
296
- };
297
-
298
- mockUserRepository.findOrganizationUserByAppOrgId.mockResolvedValue(
299
- mockOrgUser
300
- );
301
-
302
- const result = await getUserFromXFriggHeaders.execute(
303
- null,
304
- 'app-org-789'
305
- );
306
-
307
- expect(result).toBeInstanceOf(User);
308
- // Verify User is constructed with org as primary
309
- expect(result.config.primary).toBe('organization');
310
- });
311
- });
312
-
313
- describe('Edge Cases', () => {
314
- it('should handle both IDs when only one user exists', async () => {
315
- const mockIndividualUser = {
316
- id: 'user-123',
317
- appUserId: 'app-user-456',
318
- };
319
-
320
- mockUserConfig.organizationUserRequired = true;
321
-
322
- mockUserRepository.findIndividualUserByAppUserId.mockResolvedValue(
323
- mockIndividualUser
324
- );
325
- mockUserRepository.findOrganizationUserByAppOrgId.mockResolvedValue(
326
- null
327
- );
328
-
329
- const result = await getUserFromXFriggHeaders.execute(
330
- 'app-user-456',
331
- 'app-org-789'
332
- );
333
-
334
- expect(result).toBeInstanceOf(User);
335
- // Should not throw conflict error when only one user found
336
- });
337
-
338
- it('should handle empty string IDs as falsy', async () => {
339
- await expect(
340
- getUserFromXFriggHeaders.execute('', '')
341
- ).rejects.toThrow();
342
- });
343
- });
344
- });
345
-
346
-