@equinor/fusion-framework-module-msal 10.0.2 → 11.0.0-next.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 (73) hide show
  1. package/CHANGELOG.md +163 -0
  2. package/README.md +17 -368
  3. package/dist/esm/MsalConfigurator.js +176 -88
  4. package/dist/esm/MsalConfigurator.js.map +1 -1
  5. package/dist/esm/__tests__/MsalConfigurator.test.js +75 -0
  6. package/dist/esm/__tests__/MsalConfigurator.test.js.map +1 -1
  7. package/dist/esm/__tests__/create-proxy-provider.test.js +53 -0
  8. package/dist/esm/__tests__/create-proxy-provider.test.js.map +1 -0
  9. package/dist/esm/__tests__/mock/msal-mock.test.js +399 -0
  10. package/dist/esm/__tests__/mock/msal-mock.test.js.map +1 -0
  11. package/dist/esm/index.js +5 -0
  12. package/dist/esm/index.js.map +1 -1
  13. package/dist/esm/mock/MsalMockClient.js +467 -0
  14. package/dist/esm/mock/MsalMockClient.js.map +1 -0
  15. package/dist/esm/mock/MsalMockConfigurator.js +187 -0
  16. package/dist/esm/mock/MsalMockConfigurator.js.map +1 -0
  17. package/dist/esm/mock/create-mock-token.js +60 -0
  18. package/dist/esm/mock/create-mock-token.js.map +1 -0
  19. package/dist/esm/mock/create-msal-mock-client.js +20 -0
  20. package/dist/esm/mock/create-msal-mock-client.js.map +1 -0
  21. package/dist/esm/mock/decode-jwt-segment.js +22 -0
  22. package/dist/esm/mock/decode-jwt-segment.js.map +1 -0
  23. package/dist/esm/mock/index.js +30 -0
  24. package/dist/esm/mock/index.js.map +1 -0
  25. package/dist/esm/mock/module.js +38 -0
  26. package/dist/esm/mock/module.js.map +1 -0
  27. package/dist/esm/msal-config-schema.js +37 -0
  28. package/dist/esm/msal-config-schema.js.map +1 -0
  29. package/dist/esm/telemetry-config-schema.js +16 -0
  30. package/dist/esm/telemetry-config-schema.js.map +1 -0
  31. package/dist/esm/version.js +1 -1
  32. package/dist/esm/version.js.map +1 -1
  33. package/dist/esm/versioning/resolve-version.js +0 -1
  34. package/dist/esm/versioning/resolve-version.js.map +1 -1
  35. package/dist/tsconfig.tsbuildinfo +1 -1
  36. package/dist/types/MsalConfigurator.d.ts +96 -20
  37. package/dist/types/__tests__/create-proxy-provider.test.d.ts +1 -0
  38. package/dist/types/__tests__/mock/msal-mock.test.d.ts +1 -0
  39. package/dist/types/index.d.ts +5 -0
  40. package/dist/types/mock/MsalMockClient.d.ts +270 -0
  41. package/dist/types/mock/MsalMockConfigurator.d.ts +156 -0
  42. package/dist/types/mock/create-mock-token.d.ts +54 -0
  43. package/dist/types/mock/create-msal-mock-client.d.ts +14 -0
  44. package/dist/types/mock/decode-jwt-segment.d.ts +13 -0
  45. package/dist/types/mock/index.d.ts +29 -0
  46. package/dist/types/mock/module.d.ts +35 -0
  47. package/dist/types/msal-config-schema.d.ts +64 -0
  48. package/dist/types/telemetry-config-schema.d.ts +8 -0
  49. package/dist/types/version.d.ts +1 -1
  50. package/docs/api-reference.md +85 -0
  51. package/docs/auth-code-flow.md +86 -0
  52. package/docs/migration-v2-to-v4.md +115 -0
  53. package/docs/testing.md +167 -0
  54. package/docs/troubleshooting.md +17 -0
  55. package/docs/version-management.md +67 -0
  56. package/package.json +12 -5
  57. package/src/MsalConfigurator.ts +202 -115
  58. package/src/__tests__/MsalConfigurator.test.ts +106 -0
  59. package/src/__tests__/create-proxy-provider.test.ts +77 -0
  60. package/src/__tests__/mock/msal-mock.test.ts +544 -0
  61. package/src/index.ts +6 -0
  62. package/src/mock/MsalMockClient.ts +599 -0
  63. package/src/mock/MsalMockConfigurator.ts +241 -0
  64. package/src/mock/create-mock-token.ts +92 -0
  65. package/src/mock/create-msal-mock-client.ts +25 -0
  66. package/src/mock/decode-jwt-segment.ts +22 -0
  67. package/src/mock/index.ts +29 -0
  68. package/src/mock/module.ts +54 -0
  69. package/src/msal-config-schema.ts +81 -0
  70. package/src/telemetry-config-schema.ts +25 -0
  71. package/src/version.ts +1 -1
  72. package/src/versioning/resolve-version.ts +0 -1
  73. package/vitest.config.ts +1 -1
@@ -0,0 +1,467 @@
1
+ import { createMockToken } from './create-mock-token';
2
+ /**
3
+ * A stand-in for the MSAL client that resolves tokens in-process.
4
+ *
5
+ * @remarks
6
+ * Constructed from {@link MsalClientConfig} — the very same argument
7
+ * {@link MsalClient} takes — so it is a drop-in substitute rather than a second
8
+ * API to learn. `setClientConfig` therefore means the same thing whether a test
9
+ * runs against Entra ID or against this client.
10
+ *
11
+ * Only the boundary that would contact Entra ID is replaced. The real
12
+ * `MsalProvider` runs on top of it unchanged, so account handling, silent-token
13
+ * preference, scope resolution, proxy providers and telemetry behave as they do in
14
+ * production — the test exercises the framework rather than the mock.
15
+ *
16
+ * Tokens are structurally valid, unsigned JWTs and are byte-identical between runs.
17
+ * They are **not** cryptographically valid and are rejected by any real service.
18
+ */
19
+ export class MsalMockClient {
20
+ #user;
21
+ #cache = new Map();
22
+ #activeAccountId = null;
23
+ /**
24
+ * The account currently signed in, or `null`.
25
+ *
26
+ * @remarks
27
+ * Reads through the cache rather than holding an account of its own, so an
28
+ * account removed by a sign-out cannot linger as the active one.
29
+ *
30
+ * @returns The cached active account, or `null` when none is active.
31
+ */
32
+ get #account() {
33
+ return this.#activeAccountId ? (this.#cache.get(this.#activeAccountId) ?? null) : null;
34
+ }
35
+ /**
36
+ * Signs an account in, adding it to the cache and making it active.
37
+ *
38
+ * @param account - The account to sign in.
39
+ * @returns The signed-in account.
40
+ */
41
+ #signIn(account) {
42
+ this.#cache.set(account.homeAccountId, account);
43
+ this.#activeAccountId = account.homeAccountId;
44
+ return account;
45
+ }
46
+ /**
47
+ * Signs the active account out, as MSAL does — the account leaves the cache.
48
+ */
49
+ #signOut() {
50
+ // Only clear the cache entry when a session is active; this preserves an already signed-out state.
51
+ if (this.#activeAccountId) {
52
+ this.#cache.delete(this.#activeAccountId);
53
+ this.#activeAccountId = null;
54
+ }
55
+ }
56
+ /**
57
+ * Mirrors MSAL's redirect completion, which is a no-op for this in-process mock.
58
+ * @returns Always `null`, because the mock performs no redirect.
59
+ */
60
+ async handleRedirectPromise() {
61
+ return null;
62
+ }
63
+ /**
64
+ * Mirrors silent SSO and returns a token for the cached mock account.
65
+ * @param request - Silent SSO options and requested scopes.
66
+ * @returns A mock authentication result.
67
+ * @throws When no account is cached.
68
+ */
69
+ async ssoSilent(request) {
70
+ // Silent SSO must fail without a session so providers exercise their login path.
71
+ if (!this.#account) {
72
+ throw new Error('MsalMockClient: no cached account for silent sign-in');
73
+ }
74
+ return this.#createResult(request.scopes);
75
+ }
76
+ /**
77
+ * Mirrors popup login by signing in the configured mock user immediately.
78
+ * @param request - Optional popup options and requested scopes.
79
+ * @returns A mock authentication result.
80
+ */
81
+ async loginPopup(request) {
82
+ this.#signIn(this.#createAccount());
83
+ return this.#createResult(request?.scopes);
84
+ }
85
+ /**
86
+ * Mirrors redirect login without navigating, because the mock has no browser boundary.
87
+ * @param _request - Redirect options, accepted for interface compatibility.
88
+ */
89
+ async loginRedirect(_request) {
90
+ this.#signIn(this.#createAccount());
91
+ }
92
+ /**
93
+ * Mirrors the framework login entry point with an immediate mock sign-in.
94
+ * @param options - Login options including the requested scopes.
95
+ * @returns A mock login result.
96
+ */
97
+ async login(options) {
98
+ this.#signIn(this.#createAccount());
99
+ return this.#createResult(options.request?.scopes);
100
+ }
101
+ /** Mirrors logout by removing the active mock account from the cache. */
102
+ async logout() {
103
+ this.#signOut();
104
+ }
105
+ /**
106
+ * Mirrors MSAL initialization without performing a network handshake.
107
+ * @param _request - Initialization options, accepted for interface compatibility.
108
+ */
109
+ async initialize(_request) {
110
+ // No network handshake to perform
111
+ }
112
+ /**
113
+ * Mirrors popup token acquisition using the mock login flow.
114
+ * @param request - Popup token request.
115
+ * @returns A mock authentication result.
116
+ */
117
+ async acquireTokenPopup(request) {
118
+ return this.loginPopup(request);
119
+ }
120
+ /**
121
+ * Mirrors redirect token acquisition without browser navigation.
122
+ * @param request - Redirect token request.
123
+ */
124
+ async acquireTokenRedirect(request) {
125
+ return this.loginRedirect(request);
126
+ }
127
+ /**
128
+ * Mirrors silent token acquisition for the cached mock account.
129
+ * @param request - Silent token request.
130
+ * @returns A mock authentication result.
131
+ * @throws When no account is cached.
132
+ */
133
+ async acquireTokenSilent(request) {
134
+ // Silent acquisition must fail without a session, matching the real MSAL boundary.
135
+ if (!this.#account) {
136
+ throw new Error('MsalMockClient: no cached account for silent sign-in');
137
+ }
138
+ return this.#createResult(request.scopes);
139
+ }
140
+ /**
141
+ * Mirrors MSAL event registration; events are intentionally not emitted by the mock.
142
+ * @param _callback - Event handler, accepted for interface compatibility.
143
+ * @param _eventTypes - Event types, accepted for interface compatibility.
144
+ * @returns Always `null`, because the mock registers no callback.
145
+ */
146
+ addEventCallback(_callback, _eventTypes) {
147
+ return null;
148
+ }
149
+ /**
150
+ * Mirrors event removal as a no-op because this mock registers no callbacks.
151
+ * @param _callbackId - Callback identifier, accepted for interface compatibility.
152
+ */
153
+ removeEventCallback(_callbackId) {
154
+ // No-op for mock
155
+ }
156
+ /**
157
+ * Mirrors performance callback registration with a stable mock identifier.
158
+ * @param _callback - Performance handler, accepted for interface compatibility.
159
+ * @returns A stable mock callback identifier.
160
+ */
161
+ addPerformanceCallback(_callback) {
162
+ return 'mock-performance-callback';
163
+ }
164
+ /**
165
+ * Mirrors performance callback removal and reports successful mock removal.
166
+ * @param _callbackId - Callback identifier, accepted for interface compatibility.
167
+ * @returns Always `true` because no callback state is retained.
168
+ */
169
+ removePerformanceCallback(_callbackId) {
170
+ return true;
171
+ }
172
+ /**
173
+ * Mirrors MSAL account lookup against the mock cache.
174
+ * @param accountFilter - Account fields to match.
175
+ * @returns The first matching account, or `null`.
176
+ */
177
+ getAccount(accountFilter) {
178
+ const filter = (accountFilter ?? {});
179
+ // Filter the cache so callers observe the same account-selection semantics as MSAL.
180
+ const matches = this.getAllAccounts().filter((account) => (filter.homeAccountId === undefined || filter.homeAccountId === account.homeAccountId) &&
181
+ (filter.localAccountId === undefined || filter.localAccountId === account.localAccountId) &&
182
+ (filter.username === undefined || filter.username === account.username) &&
183
+ (filter.tenantId === undefined || filter.tenantId === account.tenantId));
184
+ return matches[0] ?? null;
185
+ }
186
+ /**
187
+ * Mirrors MSAL account enumeration using the mock cache.
188
+ * @param _accountFilter - Account filter, accepted for interface compatibility.
189
+ * @returns All accounts currently in the mock cache.
190
+ */
191
+ getAllAccounts(_accountFilter) {
192
+ return [...this.#cache.values()];
193
+ }
194
+ /**
195
+ * Mirrors redirect logout without navigating in the mock environment.
196
+ * @param _request - Logout options, accepted for interface compatibility.
197
+ */
198
+ async logoutRedirect(_request) {
199
+ this.#signOut();
200
+ }
201
+ /**
202
+ * Mirrors popup logout without opening a browser window.
203
+ * @param _request - Logout options, accepted for interface compatibility.
204
+ */
205
+ async logoutPopup(_request) {
206
+ this.#signOut();
207
+ }
208
+ /**
209
+ * Mirrors MSAL logger access; the mock does not retain a logger.
210
+ * @returns An interface-compatible empty logger value.
211
+ */
212
+ getLogger() {
213
+ // MSAL's Logger has a large internal surface with no mock consumers depend on; callers only pass it through
214
+ return undefined;
215
+ }
216
+ /**
217
+ * Mirrors logger configuration as a no-op for the mock.
218
+ * @param _logger - Logger, accepted for interface compatibility.
219
+ */
220
+ setLogger(_logger) {
221
+ // No-op for mock
222
+ }
223
+ /**
224
+ * Mirrors wrapper metadata initialization as a no-op for the mock.
225
+ * @param _sku - Wrapper identifier, accepted for interface compatibility.
226
+ * @param _version - Wrapper version, accepted for interface compatibility.
227
+ */
228
+ initializeWrapperLibrary(_sku, _version) {
229
+ // No-op for mock wrapper
230
+ }
231
+ /**
232
+ * Mirrors navigation-client configuration as a no-op because no navigation occurs.
233
+ * @param _navigationClient - Navigation client, accepted for interface compatibility.
234
+ */
235
+ setNavigationClient(_navigationClient) {
236
+ // No-op for mock
237
+ }
238
+ /**
239
+ * Mirrors configuration access and rejects it because the mock has no browser config.
240
+ * @returns Never; this mock does not expose browser configuration.
241
+ * @throws Always, because browser configuration is unsupported.
242
+ */
243
+ getConfiguration() {
244
+ throw new Error('MsalMockClient: getConfiguration is not supported in the mock client');
245
+ }
246
+ /**
247
+ * Mirrors cache hydration as a no-op because mock tokens are created in-process.
248
+ * @param _result - Authentication result, accepted for interface compatibility.
249
+ * @param _request - Original token request, accepted for interface compatibility.
250
+ */
251
+ async hydrateCache(_result, _request) {
252
+ // No-op for mock
253
+ }
254
+ /**
255
+ * Mirrors MSAL cache clearing by removing every mock account.
256
+ * @param _request - Cache-clear options, accepted for interface compatibility.
257
+ */
258
+ async clearCache(_request) {
259
+ this.#cache.clear();
260
+ this.#activeAccountId = null;
261
+ }
262
+ /**
263
+ * Mirrors the generic token acquisition entry point for the active mock account.
264
+ * @param options - Token acquisition options.
265
+ * @returns A mock result, or `null` without an active account.
266
+ */
267
+ async acquireToken(options) {
268
+ // Generic acquisition returns no result when no account is active, matching MSAL's nullable result.
269
+ if (!this.#account) {
270
+ return null;
271
+ }
272
+ return this.#createResult(options.request?.scopes);
273
+ }
274
+ /**
275
+ * Mirrors authorization-code exchange by signing in and returning a mock result.
276
+ * @param request - Authorization-code request.
277
+ * @returns A mock authentication result.
278
+ */
279
+ async acquireTokenByCode(request) {
280
+ this.#signIn(this.#createAccount());
281
+ return this.#createResult(request?.scopes);
282
+ }
283
+ /**
284
+ * Creates a mock client for the services the given configuration points at.
285
+ *
286
+ * @remarks
287
+ * Takes the same argument as {@link MsalClient}. A user named `Test User` is
288
+ * already in the account cache, so a provider built on this client boots the
289
+ * way one does for a returning user with a live session — no sign-in runs, and
290
+ * the provider's start-up path sees the state it would see in production. Use
291
+ * {@link MsalMockClient.setUser | setUser} to say who that user is.
292
+ *
293
+ * @param config - The same client configuration the real client is built from.
294
+ */
295
+ constructor(config) {
296
+ const tenantId = config.auth.tenantId ?? MsalMockClient.#tenantFromAuthority(config.auth);
297
+ this.#user = {
298
+ name: 'Test User',
299
+ username: 'test.user@equinor.com',
300
+ userId: 'fusion-mock-user',
301
+ tenantId: tenantId ?? 'fusion-mock-tenant',
302
+ scopes: ['fusion-mock-scope'],
303
+ clientId: config.auth.clientId,
304
+ };
305
+ this.#signIn(this.#createAccount());
306
+ }
307
+ /**
308
+ * Reads the tenant out of an authority URL.
309
+ *
310
+ * @remarks
311
+ * A configuration may carry only `authority`, in which case the tenant still
312
+ * has to end up on the tokens this client mints for the account to look like
313
+ * the one a real sign-in would have produced.
314
+ *
315
+ * @param auth - The auth section of the client configuration.
316
+ * @returns The tenant, or `undefined` when the authority carries none.
317
+ */
318
+ static #tenantFromAuthority(auth) {
319
+ // An explicit tenant takes precedence; only parse authority when configuration omitted it.
320
+ if (!auth.authority) {
321
+ return undefined;
322
+ }
323
+ try {
324
+ // Remove empty URL path segments to identify the authority's tenant consistently.
325
+ const segments = new URL(auth.authority).pathname.split('/').filter(Boolean);
326
+ return segments.at(-1);
327
+ }
328
+ catch {
329
+ return undefined;
330
+ }
331
+ }
332
+ /**
333
+ * Returns the client identifier used by tokens minted by this mock.
334
+ * @returns The configured client identifier.
335
+ */
336
+ get clientId() {
337
+ return this.#user.clientId;
338
+ }
339
+ /**
340
+ * Returns the tenant identifier used by tokens minted by this mock.
341
+ * @returns The configured tenant identifier.
342
+ */
343
+ get tenantId() {
344
+ return this.#user.tenantId;
345
+ }
346
+ /**
347
+ * Reports whether the mock currently has an active account.
348
+ * @returns Whether an account is active.
349
+ */
350
+ get hasValidClaims() {
351
+ return this.#account !== null;
352
+ }
353
+ /**
354
+ * Mirrors MSAL active-account access using the mock's single active account.
355
+ * @returns The active account, or `null`.
356
+ */
357
+ getActiveAccount() {
358
+ return this.#account;
359
+ }
360
+ /**
361
+ * Makes an account the active one, adding it to the cache if it is unknown.
362
+ *
363
+ * @remarks
364
+ * Real MSAL requires the account to already be cached. Accepting an unknown
365
+ * one is a deliberate concession to tests: it is the shortest way to swap the
366
+ * signed-in user between runs, without reconstructing the framework.
367
+ *
368
+ * @param next - The account to make active, or `null` to sign out.
369
+ */
370
+ setActiveAccount(next) {
371
+ // A null account is the MSAL sign-out signal, so clear the active mock session.
372
+ if (!next) {
373
+ this.#signOut();
374
+ return;
375
+ }
376
+ this.#signIn(next);
377
+ }
378
+ /**
379
+ * Declares who is signed in, replacing whoever was.
380
+ *
381
+ * @remarks
382
+ * This is the counterpart to a real sign-in: the client is configured with
383
+ * what it talks to, and learns the user separately. `MsalMockConfigurator`
384
+ * applies it as the configuration is assembled, so the account is in the cache
385
+ * before `MsalProvider.initialize` runs — the provider then behaves as it does
386
+ * for a returning user with a live session.
387
+ *
388
+ * Values left out keep whatever they were. Passing `null` signs out and
389
+ * forgets the identity, so the provider follows its unauthenticated path;
390
+ * `{ signedOut: true }` does the same but keeps the identity, so a later login
391
+ * resolves as that user.
392
+ *
393
+ * @param user - The user to sign in, or `null` when nobody is.
394
+ */
395
+ setUser(user) {
396
+ // Declaring a user replaces the session rather than adding to it, so a test
397
+ // that names a second user does not silently end up with two cached accounts
398
+ this.#cache.clear();
399
+ this.#activeAccountId = null;
400
+ // A null user explicitly clears the session and identity supplied to the mock.
401
+ if (!user) {
402
+ return;
403
+ }
404
+ const { account, signedOut, ...rest } = user;
405
+ // Merge overrides while retaining defaults for fields omitted by the test.
406
+ this.#user = {
407
+ ...this.#user,
408
+ ...rest,
409
+ name: rest.name ?? account?.name ?? this.#user.name,
410
+ username: rest.username ?? account?.username ?? this.#user.username,
411
+ userId: rest.userId ?? account?.localAccountId ?? this.#user.userId,
412
+ tenantId: rest.tenantId ?? account?.tenantId ?? this.#user.tenantId,
413
+ scopes: rest.scopes ?? this.#user.scopes,
414
+ };
415
+ // Keep identity data without caching an account when the test starts signed out.
416
+ if (signedOut) {
417
+ return;
418
+ }
419
+ this.#signIn(account ?? this.#createAccount());
420
+ }
421
+ /**
422
+ * Creates the one account represented by this mock's configured identity.
423
+ * @returns An MSAL-shaped account for the configured user.
424
+ */
425
+ #createAccount() {
426
+ return {
427
+ homeAccountId: `${this.#user.userId}.${this.#user.tenantId}`,
428
+ localAccountId: this.#user.userId,
429
+ environment: 'login.microsoftonline.com',
430
+ tenantId: this.#user.tenantId,
431
+ username: this.#user.username,
432
+ name: this.#user.name,
433
+ };
434
+ }
435
+ /**
436
+ * Creates an MSAL-shaped token result for the requested or default scopes.
437
+ * @param scopes - Requested scopes, or the user's configured defaults.
438
+ * @returns An MSAL-shaped mock authentication result.
439
+ */
440
+ #createResult(scopes) {
441
+ const granted = scopes?.length ? scopes : this.#user.scopes;
442
+ const token = createMockToken({
443
+ name: this.#user.name,
444
+ preferred_username: this.#user.username,
445
+ oid: this.#user.userId,
446
+ tid: this.#user.tenantId,
447
+ aud: this.#user.clientId,
448
+ scp: granted.join(' '),
449
+ });
450
+ // Object shape matches AuthenticationResult's fields consumers rely on; the real
451
+ // type also carries browser-only fields (e.g. `familyId`) this mock intentionally omits
452
+ return {
453
+ account: this.#account ?? this.#createAccount(),
454
+ accessToken: token,
455
+ idToken: token,
456
+ scopes: granted,
457
+ tokenType: 'Bearer',
458
+ expiresOn: new Date('2033-11-14T22:13:20.000Z'),
459
+ authority: `https://login.microsoftonline.com/${this.#user.tenantId}`,
460
+ uniqueId: this.#user.userId,
461
+ tenantId: this.#user.tenantId,
462
+ fromCache: false,
463
+ correlationId: 'fusion-mock-correlation',
464
+ };
465
+ }
466
+ }
467
+ //# sourceMappingURL=MsalMockClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MsalMockClient.js","sourceRoot":"","sources":["../../../src/mock/MsalMockClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,187 @@
1
+ import { MsalConfigurator } from '../MsalConfigurator';
2
+ import { MsalMockClient } from './MsalMockClient';
3
+ /**
4
+ * The client configuration used when a test declares none.
5
+ *
6
+ * @remarks
7
+ * `MsalClientConfig.auth.clientId` is required, so a mock still needs a client
8
+ * configuration to exist. Supplying a default is what lets an application boot
9
+ * under test without declaring credentials it does not have.
10
+ */
11
+ const defaultMockClientConfig = {
12
+ auth: {
13
+ clientId: 'fusion-mock-client',
14
+ tenantId: 'fusion-mock-tenant',
15
+ },
16
+ };
17
+ /**
18
+ * The real MSAL configurator, backed by an in-process client.
19
+ *
20
+ * @remarks
21
+ * Nothing else changes: the same builder API, the same validation and the same
22
+ * `MsalProvider` are used. Only the boundary that would contact Entra ID is
23
+ * substituted, through the same
24
+ * {@link MsalConfigurator._createClient | _createClient} seam the real
25
+ * configurator builds its own client from — and from the same
26
+ * {@link MsalConfigurator._createClientConfig | _createClientConfig}, so
27
+ * `setClientConfig` means exactly what it means in production.
28
+ *
29
+ * A user named `Test User` is signed in by default, so an application boots
30
+ * without declaring anything.
31
+ *
32
+ * @example Name the signed-in user
33
+ * ```typescript
34
+ * enableMsalMock(configurator, (builder) => {
35
+ * builder.setAccount({ name: 'Ada Lovelace', username: 'ada@equinor.com' });
36
+ * });
37
+ * ```
38
+ *
39
+ * @example Configure the client exactly as in production
40
+ * ```typescript
41
+ * enableMsalMock(configurator, (builder) => {
42
+ * builder.setClientConfig({ auth: { clientId: 'my-app', tenantId: 'my-tenant' } });
43
+ * });
44
+ * ```
45
+ *
46
+ * @example Take full control of authentication
47
+ * ```typescript
48
+ * enableMsalMock(configurator, (builder) => {
49
+ * builder.setClient(new MyOwnMsalClient());
50
+ * });
51
+ * ```
52
+ */
53
+ export class MsalMockConfigurator extends MsalConfigurator {
54
+ /**
55
+ * Declares the user to sign in.
56
+ *
57
+ * @remarks
58
+ * Who is signed in is session state, not client configuration — which is what
59
+ * lets {@link MsalMockClient} take the same argument the real client takes: a
60
+ * client is configured with *what it talks to*, never with *who is signed in*.
61
+ *
62
+ * The user is therefore recorded on the configuration as `mock.account`, not
63
+ * on this builder, and is signed in on whichever client the module ends up
64
+ * authenticating through — wherever that client was built:
65
+ *
66
+ * - The client this builder builds, normally. The user is in place before
67
+ * `MsalProvider.initialize` runs, which is what makes the provider's own
68
+ * start-up path observable: with `signedOut` and `setRequiresAuth(true)`, a
69
+ * test sees the real automatic login run.
70
+ * - The **host's** client when the module is hoisted onto a host
71
+ * application's provider, because none is built here. An application inside
72
+ * a portal shares the portal's session, so this changes who the host sees
73
+ * signed in too, as it would in production.
74
+ * - A client supplied through {@link MsalConfigurator.setClient | setClient},
75
+ * when that client is a {@link MsalMockClient}.
76
+ *
77
+ * Throws when that client cannot represent a declared user, rather than
78
+ * failing quietly — a silent no-op is the whole failure mode this exists to
79
+ * prevent.
80
+ *
81
+ * Pass `null` when nobody is signed in, or `{ signedOut: true }` to keep an
82
+ * identity without a session — a later login then resolves as that user.
83
+ *
84
+ * @param account - The user, or an ordinary config-builder callback resolving it.
85
+ * @returns The builder, for chaining.
86
+ *
87
+ * @example Derive the user from the modules in scope
88
+ * ```typescript
89
+ * builder.setAccount(async ({ hasModule }) => ({
90
+ * name: hasModule('app') ? 'App User' : 'Portal User',
91
+ * }));
92
+ * ```
93
+ */
94
+ setAccount(account) {
95
+ this._set('mock.account', account);
96
+ return this;
97
+ }
98
+ /**
99
+ * Signs the declared user in on the client the module authenticates through.
100
+ *
101
+ * @remarks
102
+ * Deliberately not done while the client is built: that would assume the scope
103
+ * declaring the user is the scope building the client, which is exactly what
104
+ * is not true when an application is tested inside a portal. The host built
105
+ * that client, in a scope this builder never sees, so the client has to be
106
+ * located rather than assumed.
107
+ *
108
+ * @param account - The user to sign in, or `null` when nobody is.
109
+ * @param config - The validated configuration, carrying the client when one was built.
110
+ * @param init - The builder arguments, carrying the host reference when hoisted.
111
+ * @throws When the resolved client is not a {@link MsalMockClient}.
112
+ */
113
+ #signIn(account, config, init) {
114
+ const host = init?.ref?.auth;
115
+ const client = config.client ?? host?.client;
116
+ // Reject a real client because mock account state cannot be applied to it.
117
+ if (!(client instanceof MsalMockClient)) {
118
+ throw new Error('MsalMockConfigurator: cannot sign a user in, because this module does not authenticate through a mock client. Declare the user where that client is configured instead.');
119
+ }
120
+ client.setUser(account);
121
+ }
122
+ /**
123
+ * Assembles the configuration, then signs the declared user in.
124
+ *
125
+ * @remarks
126
+ * Stands a client configuration in first when this builder is the one that
127
+ * will build a client: `MsalClientConfig.auth.clientId` is required to build
128
+ * any client at all and a test has no real credentials to declare. It then
129
+ * flows through the very same
130
+ * {@link MsalConfigurator._createClientConfig | _createClientConfig}
131
+ * enrichment the real client is built from, and anything declared through
132
+ * {@link MsalConfigurator.setClientConfig | setClientConfig} wins — exactly as
133
+ * in production.
134
+ *
135
+ * Doing that here rather than in the constructor is deliberate: a hoisted
136
+ * module authenticates through the host and builds no client, so it must not
137
+ * look configured either.
138
+ *
139
+ * The user is read from `rawConfig`, because the schema strips `mock` when it
140
+ * validates — the key exists to carry a test's declaration through the
141
+ * builder, never to reach the provider.
142
+ *
143
+ * @param rawConfig - The raw configuration to process.
144
+ * @param init - The builder arguments, carrying the host reference when hoisted.
145
+ * @returns The processed and validated configuration.
146
+ */
147
+ async _processConfig(rawConfig, init) {
148
+ // Supply mock credentials only when this builder owns client construction.
149
+ if (!this._isHoisted(init) && !this.getClientConfig()) {
150
+ this.setClientConfig(defaultMockClientConfig);
151
+ }
152
+ const config = await super._processConfig(rawConfig, init);
153
+ // `null` is a declaration in its own right — nobody is signed in — so only
154
+ // an absent one means the test said nothing about the user
155
+ const account = rawConfig.mock?.account;
156
+ // Apply even null because null explicitly requests a signed-out mock state.
157
+ if (account !== undefined) {
158
+ this.#signIn(account, config, init);
159
+ }
160
+ return config;
161
+ }
162
+ /**
163
+ * Builds an in-process client.
164
+ *
165
+ * @remarks
166
+ * Called only when no client was set, so
167
+ * {@link MsalConfigurator.setClient | setClient} still replaces authentication
168
+ * outright.
169
+ *
170
+ * Deliberately does not delegate to `super`, which would build a real
171
+ * `MsalClient` and contact Entra ID. It is never reached when the module is
172
+ * hoisted onto a host application's provider, because the base configurator
173
+ * gates client creation on {@link MsalConfigurator._isHoisted | _isHoisted} —
174
+ * a mock client built there would shadow the host's client, the exact scenario
175
+ * an application-inside-a-portal test exists to cover.
176
+ *
177
+ * Knows nothing about who is signed in: a client is built from what it talks
178
+ * to, and the declared user is applied to it afterwards.
179
+ *
180
+ * @param config - The validated configuration the client is built from.
181
+ * @returns A client resolving tokens in-process.
182
+ */
183
+ async _createClient(config) {
184
+ return new MsalMockClient(this._createClientConfig(config) ?? defaultMockClientConfig);
185
+ }
186
+ }
187
+ //# sourceMappingURL=MsalMockConfigurator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MsalMockConfigurator.js","sourceRoot":"","sources":["../../../src/mock/MsalMockConfigurator.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,gBAAgB,EAAmB,MAAM,qBAAqB,CAAC;AAExE,OAAO,EAAE,cAAc,EAAqB,MAAM,kBAAkB,CAAC;AA2BrE;;;;;;;GAOG;AACH,MAAM,uBAAuB,GAAqB;IAChD,IAAI,EAAE;QACJ,QAAQ,EAAE,oBAAoB;QAC9B,QAAQ,EAAE,oBAAoB;KAC/B;CACF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,OAAO,oBAAqB,SAAQ,gBAAgB;IACxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;IACI,UAAU,CACf,OAAyE;QAEzE,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,OAAO,CACL,OAA4B,EAC5B,MAAkB,EAClB,IAAgC;QAEhC,MAAM,IAAI,GAAI,IAAI,EAAE,GAA4C,EAAE,IAAI,CAAC;QACvE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,IAAI,EAAE,MAAM,CAAC;QAE7C,2EAA2E;QAC3E,IAAI,CAAC,CAAC,MAAM,YAAY,cAAc,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CACb,yKAAyK,CAC1K,CAAC;QACJ,CAAC;QAED,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACM,KAAK,CAAC,cAAc,CAC3B,SAAqB,EACrB,IAAgC;QAEhC,2EAA2E;QAC3E,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;YACtD,IAAI,CAAC,eAAe,CAAC,uBAAuB,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAE3D,2EAA2E;QAC3E,2DAA2D;QAC3D,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC;QACxC,4EAA4E;QAC5E,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QACtC,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACgB,KAAK,CAAC,aAAa,CAAC,MAAkB;QACvD,OAAO,IAAI,cAAc,CAAC,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,IAAI,uBAAuB,CAAC,CAAC;IACzF,CAAC;CACF"}