@azure/msal-angular 4.0.12 → 4.0.13

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 (88) hide show
  1. package/.beachballrc +3 -0
  2. package/.editorconfig +16 -0
  3. package/.eslintrc.json +3 -0
  4. package/CHANGELOG.json +2315 -0
  5. package/CHANGELOG.md +869 -0
  6. package/FAQ.md +182 -0
  7. package/angular.json +51 -0
  8. package/docs/angular-universal.md +64 -0
  9. package/docs/configuration.md +609 -0
  10. package/docs/errors.md +89 -0
  11. package/docs/events.md +262 -0
  12. package/docs/initialization.md +206 -0
  13. package/docs/known-issues.md +19 -0
  14. package/docs/logging.md +47 -0
  15. package/docs/msal-guard.md +208 -0
  16. package/docs/msal-interceptor.md +160 -0
  17. package/docs/multi-tenant.md +90 -0
  18. package/docs/performance.md +50 -0
  19. package/docs/public-apis.md +29 -0
  20. package/docs/redirects.md +257 -0
  21. package/docs/security.md +4 -0
  22. package/docs/ssosilent.md +84 -0
  23. package/docs/v0-v1-upgrade-guide.md +61 -0
  24. package/docs/v1-v2-upgrade-guide.md +70 -0
  25. package/docs/v2-v3-upgrade-guide.md +52 -0
  26. package/docs/v3-v4-upgrade-guide.md +36 -0
  27. package/karma.conf.js +44 -0
  28. package/ng-package.json +7 -0
  29. package/package.json +56 -26
  30. package/src/IMsalService.ts +34 -0
  31. package/src/constants.ts +20 -0
  32. package/src/msal.broadcast.config.ts +8 -0
  33. package/src/msal.broadcast.service.spec.ts +471 -0
  34. package/src/msal.broadcast.service.ts +84 -0
  35. package/src/msal.guard.config.ts +27 -0
  36. package/src/msal.guard.spec.ts +525 -0
  37. package/src/msal.guard.ts +290 -0
  38. package/src/msal.interceptor.config.ts +39 -0
  39. package/src/msal.interceptor.spec.ts +1168 -0
  40. package/src/msal.interceptor.ts +388 -0
  41. package/src/msal.module.ts +51 -0
  42. package/src/msal.navigation.client.spec.ts +96 -0
  43. package/src/msal.navigation.client.ts +59 -0
  44. package/src/msal.redirect.component.spec.ts +64 -0
  45. package/src/msal.redirect.component.ts +26 -0
  46. package/src/msal.service.spec.ts +468 -0
  47. package/src/msal.service.ts +104 -0
  48. package/src/packageMetadata.ts +3 -0
  49. package/{public-api.d.ts → src/public-api.ts} +35 -17
  50. package/src/test.ts +19 -0
  51. package/tsconfig.json +25 -0
  52. package/tsconfig.lib.json +27 -0
  53. package/tsconfig.lib.prod.json +10 -0
  54. package/tsconfig.spec.json +17 -0
  55. package/typedoc.json +10 -0
  56. package/IMsalService.d.ts +0 -17
  57. package/constants.d.ts +0 -5
  58. package/esm2020/IMsalService.mjs +0 -6
  59. package/esm2020/azure-msal-angular.mjs +0 -5
  60. package/esm2020/constants.mjs +0 -10
  61. package/esm2020/msal.broadcast.config.mjs +0 -6
  62. package/esm2020/msal.broadcast.service.mjs +0 -66
  63. package/esm2020/msal.guard.config.mjs +0 -6
  64. package/esm2020/msal.guard.mjs +0 -218
  65. package/esm2020/msal.interceptor.config.mjs +0 -6
  66. package/esm2020/msal.interceptor.mjs +0 -270
  67. package/esm2020/msal.module.mjs +0 -46
  68. package/esm2020/msal.navigation.client.mjs +0 -53
  69. package/esm2020/msal.redirect.component.mjs +0 -31
  70. package/esm2020/msal.service.mjs +0 -88
  71. package/esm2020/packageMetadata.mjs +0 -4
  72. package/esm2020/public-api.mjs +0 -18
  73. package/fesm2015/azure-msal-angular.mjs +0 -762
  74. package/fesm2015/azure-msal-angular.mjs.map +0 -1
  75. package/fesm2020/azure-msal-angular.mjs +0 -758
  76. package/fesm2020/azure-msal-angular.mjs.map +0 -1
  77. package/index.d.ts +0 -5
  78. package/msal.broadcast.config.d.ts +0 -3
  79. package/msal.broadcast.service.d.ts +0 -19
  80. package/msal.guard.config.d.ts +0 -9
  81. package/msal.guard.d.ts +0 -43
  82. package/msal.interceptor.config.d.ts +0 -13
  83. package/msal.interceptor.d.ts +0 -70
  84. package/msal.module.d.ts +0 -13
  85. package/msal.navigation.client.d.ts +0 -19
  86. package/msal.redirect.component.d.ts +0 -15
  87. package/msal.service.d.ts +0 -33
  88. package/packageMetadata.d.ts +0 -2
@@ -0,0 +1,84 @@
1
+ /*
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { Inject, Injectable, Optional } from "@angular/core";
7
+ import {
8
+ EventMessage,
9
+ EventMessageUtils,
10
+ IPublicClientApplication,
11
+ InteractionStatus,
12
+ } from "@azure/msal-browser";
13
+ import { BehaviorSubject, Observable, ReplaySubject, Subject } from "rxjs";
14
+ import { MsalBroadcastConfiguration } from "./msal.broadcast.config";
15
+ import { MSAL_BROADCAST_CONFIG, MSAL_INSTANCE } from "./constants";
16
+ import { name, version } from "./packageMetadata";
17
+
18
+ @Injectable()
19
+ export class MsalBroadcastService {
20
+ private _msalSubject: Subject<EventMessage>;
21
+ public msalSubject$: Observable<EventMessage>;
22
+ private _inProgress: BehaviorSubject<InteractionStatus>;
23
+ public inProgress$: Observable<InteractionStatus>;
24
+
25
+ constructor(
26
+ @Inject(MSAL_INSTANCE) private msalInstance: IPublicClientApplication,
27
+ @Optional()
28
+ @Inject(MSAL_BROADCAST_CONFIG)
29
+ private msalBroadcastConfig?: MsalBroadcastConfiguration
30
+ ) {
31
+ // Make _msalSubject a ReplaySubject if configured to replay past events
32
+ if (
33
+ this.msalBroadcastConfig &&
34
+ this.msalBroadcastConfig.eventsToReplay > 0
35
+ ) {
36
+ this.msalInstance
37
+ .getLogger()
38
+ .clone(name, version)
39
+ .verbose(
40
+ `BroadcastService - eventsToReplay set on BroadcastConfig, replaying the last ${this.msalBroadcastConfig.eventsToReplay} events`
41
+ );
42
+ this._msalSubject = new ReplaySubject<EventMessage>(
43
+ this.msalBroadcastConfig.eventsToReplay
44
+ );
45
+ } else {
46
+ // Defaults to _msalSubject being a Subject
47
+ this._msalSubject = new Subject<EventMessage>();
48
+ }
49
+
50
+ this.msalSubject$ = this._msalSubject.asObservable();
51
+
52
+ // InProgress as BehaviorSubject so most recent inProgress state will be available upon subscription
53
+ this._inProgress = new BehaviorSubject<InteractionStatus>(
54
+ InteractionStatus.Startup
55
+ );
56
+ this.inProgress$ = this._inProgress.asObservable();
57
+
58
+ this.msalInstance.addEventCallback((message: EventMessage) => {
59
+ this._msalSubject.next(message);
60
+ const status = EventMessageUtils.getInteractionStatusFromEvent(
61
+ message,
62
+ this._inProgress.value
63
+ );
64
+ if (status !== null) {
65
+ this.msalInstance
66
+ .getLogger()
67
+ .clone(name, version)
68
+ .verbose(
69
+ `BroadcastService - ${message.eventType} results in setting inProgress from ${this._inProgress.value} to ${status}`
70
+ );
71
+ this._inProgress.next(status);
72
+ }
73
+ });
74
+ }
75
+
76
+ /**
77
+ * Resets inProgress state to None
78
+ */
79
+ resetInProgressEvent(): void {
80
+ if (this._inProgress.value === InteractionStatus.Startup) {
81
+ this._inProgress.next(InteractionStatus.None);
82
+ }
83
+ }
84
+ }
@@ -0,0 +1,27 @@
1
+ /*
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { RouterStateSnapshot } from "@angular/router";
7
+ import {
8
+ PopupRequest,
9
+ RedirectRequest,
10
+ InteractionType,
11
+ } from "@azure/msal-browser";
12
+ import { MsalService } from "./msal.service";
13
+
14
+ export declare type MsalGuardAuthRequest =
15
+ | Partial<PopupRequest>
16
+ | Partial<Omit<RedirectRequest, "redirectStartPage">>;
17
+
18
+ export type MsalGuardConfiguration = {
19
+ interactionType: InteractionType.Popup | InteractionType.Redirect;
20
+ authRequest?:
21
+ | MsalGuardAuthRequest
22
+ | ((
23
+ authService: MsalService,
24
+ state: RouterStateSnapshot
25
+ ) => MsalGuardAuthRequest);
26
+ loginFailedRoute?: string;
27
+ };
@@ -0,0 +1,525 @@
1
+ import { HttpClientTestingModule } from "@angular/common/http/testing";
2
+ import { TestBed } from "@angular/core/testing";
3
+ import { UrlTree } from "@angular/router";
4
+ import { RouterTestingModule } from "@angular/router/testing";
5
+ import { Location } from "@angular/common";
6
+ import {
7
+ BrowserSystemOptions,
8
+ InteractionType,
9
+ IPublicClientApplication,
10
+ LogLevel,
11
+ PublicClientApplication,
12
+ UrlString,
13
+ } from "@azure/msal-browser";
14
+ import { of } from "rxjs";
15
+ import {
16
+ MsalModule,
17
+ MsalGuard,
18
+ MsalService,
19
+ MsalBroadcastService,
20
+ } from "./public-api";
21
+ import { MsalGuardConfiguration } from "./msal.guard.config";
22
+
23
+ let guard: MsalGuard;
24
+ let authService: MsalService;
25
+ let routeMock: any = { snapshot: {} };
26
+ let routeStateMock: any = { snapshot: {}, url: "/" };
27
+ let testInteractionType: InteractionType;
28
+ let testLoginFailedRoute: string;
29
+ let testConfiguration: Partial<MsalGuardConfiguration>;
30
+ let browserSystemOptions: BrowserSystemOptions;
31
+
32
+ function MSALInstanceFactory(): IPublicClientApplication {
33
+ return new PublicClientApplication({
34
+ auth: {
35
+ clientId: "b5c2e510-4a17-4feb-b219-e55aa5b74144",
36
+ redirectUri: "http://localhost:4200",
37
+ },
38
+ system: {
39
+ loggerOptions: {
40
+ loggerCallback: (level, message) => {
41
+ // console.log(message)
42
+ },
43
+ logLevel: LogLevel.Verbose,
44
+ piiLoggingEnabled: true,
45
+ },
46
+ },
47
+ });
48
+ }
49
+
50
+ function MSALGuardConfigFactory(): MsalGuardConfiguration {
51
+ return {
52
+ //@ts-ignore
53
+ interactionType: testInteractionType,
54
+ loginFailedRoute: testLoginFailedRoute,
55
+ authRequest: testConfiguration?.authRequest,
56
+ };
57
+ }
58
+
59
+ function initializeMsal(providers: any[] = []) {
60
+ TestBed.resetTestingModule();
61
+ TestBed.configureTestingModule({
62
+ imports: [
63
+ MsalModule.forRoot(MSALInstanceFactory(), MSALGuardConfigFactory(), {
64
+ interactionType: InteractionType.Popup,
65
+ protectedResourceMap: new Map(),
66
+ }),
67
+ HttpClientTestingModule,
68
+ RouterTestingModule.withRoutes([]),
69
+ ],
70
+ providers: [MsalGuard, MsalService, MsalBroadcastService, ...providers],
71
+ teardown: { destroyAfterEach: false },
72
+ });
73
+
74
+ authService = TestBed.inject(MsalService);
75
+ guard = TestBed.inject(MsalGuard);
76
+ }
77
+
78
+ describe("MsalGuard", () => {
79
+ beforeEach(() => {
80
+ testInteractionType = InteractionType.Popup;
81
+ testLoginFailedRoute = undefined;
82
+ testConfiguration = {};
83
+ browserSystemOptions = {};
84
+ routeStateMock = { snapshot: {}, url: "/" };
85
+ initializeMsal();
86
+ });
87
+
88
+ it("is created", () => {
89
+ expect(guard).toBeTruthy();
90
+ });
91
+
92
+ it("throws error for silent interaction type", (done) => {
93
+ testInteractionType = InteractionType.Silent;
94
+ initializeMsal();
95
+ try {
96
+ guard.canActivate(routeMock, routeStateMock).subscribe((result) => {});
97
+ } catch (err) {
98
+ expect(err.errorCode).toBe("invalid_interaction_type");
99
+ done();
100
+ }
101
+ });
102
+
103
+ it("returns false if page with MSAL Guard is set as redirectUri", (done) => {
104
+ spyOn(UrlString, "hashContainsKnownProperties").and.returnValue(true);
105
+ spyOnProperty(window, "parent", "get").and.returnValue({ ...window });
106
+
107
+ guard.canActivate(routeMock, routeStateMock).subscribe((result) => {
108
+ expect(result).toBeFalse();
109
+ done();
110
+ });
111
+ });
112
+
113
+ it("returns false if page contains known successful response (path routing)", (done) => {
114
+ initializeMsal([
115
+ {
116
+ provide: Location,
117
+ useValue: {
118
+ path: jasmine
119
+ .createSpy("path")
120
+ .and.callFake((hash: boolean) =>
121
+ hash ? "/path?code=123#code=456" : "/path"
122
+ ),
123
+ prepareExternalUrl: jasmine
124
+ .createSpy("prepareExternalUrl")
125
+ .and.callFake((url: string) => "/path"),
126
+ },
127
+ },
128
+ ]);
129
+
130
+ routeStateMock = {
131
+ snapshot: {},
132
+ url: "/path?code=123#code=456",
133
+ root: {
134
+ fragment: "code=456",
135
+ },
136
+ };
137
+
138
+ spyOn(MsalService.prototype, "handleRedirectObservable").and.returnValue(
139
+ //@ts-ignore
140
+ of("test")
141
+ );
142
+
143
+ spyOn(PublicClientApplication.prototype, "getAllAccounts").and.returnValue([
144
+ {
145
+ homeAccountId: "test",
146
+ localAccountId: "test",
147
+ environment: "test",
148
+ tenantId: "test",
149
+ username: "test",
150
+ },
151
+ ]);
152
+
153
+ guard
154
+ .canActivate(routeMock, routeStateMock)
155
+ .subscribe((result: UrlTree) => {
156
+ expect(result.toString()).toEqual("/path");
157
+ done();
158
+ });
159
+ });
160
+
161
+ it("returns true if page contains code= in query parameters only", (done) => {
162
+ initializeMsal([
163
+ {
164
+ provide: Location,
165
+ useValue: {
166
+ path: jasmine
167
+ .createSpy("path")
168
+ .and.callFake((hash: boolean) =>
169
+ hash ? "/path?code=123" : "/path"
170
+ ),
171
+ prepareExternalUrl: jasmine
172
+ .createSpy("prepareExternalUrl")
173
+ .and.callFake((url: string) => "/path"),
174
+ },
175
+ },
176
+ ]);
177
+
178
+ routeStateMock = {
179
+ snapshot: {},
180
+ url: "/path?code=123",
181
+ root: {
182
+ fragment: null,
183
+ },
184
+ };
185
+
186
+ spyOn(MsalService.prototype, "handleRedirectObservable").and.returnValue(
187
+ //@ts-ignore
188
+ of("test")
189
+ );
190
+
191
+ spyOn(PublicClientApplication.prototype, "getAllAccounts").and.returnValue([
192
+ {
193
+ homeAccountId: "test",
194
+ localAccountId: "test",
195
+ environment: "test",
196
+ tenantId: "test",
197
+ username: "test",
198
+ },
199
+ ]);
200
+
201
+ guard
202
+ .canActivate(routeMock, routeStateMock)
203
+ .subscribe((result: UrlTree) => {
204
+ expect(result).toBeTrue();
205
+ done();
206
+ });
207
+ });
208
+
209
+ it("returns true if page route doesnt end with /code", (done) => {
210
+ initializeMsal([
211
+ {
212
+ provide: Location,
213
+ useValue: {
214
+ path: jasmine
215
+ .createSpy("path")
216
+ .and.callFake((hash: boolean) => (hash ? "/codes" : "/")),
217
+ prepareExternalUrl: jasmine
218
+ .createSpy("prepareExternalUrl")
219
+ .and.callFake((url: string) => "#/codes"),
220
+ },
221
+ },
222
+ ]);
223
+
224
+ routeStateMock = {
225
+ snapshot: {},
226
+ url: "/codes",
227
+ root: {
228
+ fragment: null,
229
+ },
230
+ };
231
+
232
+ spyOn(MsalService.prototype, "handleRedirectObservable").and.returnValue(
233
+ //@ts-ignore
234
+ of("test")
235
+ );
236
+
237
+ spyOn(PublicClientApplication.prototype, "getAllAccounts").and.returnValue([
238
+ {
239
+ homeAccountId: "test",
240
+ localAccountId: "test",
241
+ environment: "test",
242
+ tenantId: "test",
243
+ username: "test",
244
+ },
245
+ ]);
246
+
247
+ guard
248
+ .canActivate(routeMock, routeStateMock)
249
+ .subscribe((result: UrlTree) => {
250
+ expect(result).toBeTrue();
251
+ done();
252
+ });
253
+ });
254
+
255
+ it("returns true if page route doesnt end with /code (short path)", (done) => {
256
+ initializeMsal([
257
+ {
258
+ provide: Location,
259
+ useValue: {
260
+ path: jasmine
261
+ .createSpy("path")
262
+ .and.callFake((hash: boolean) => (hash ? "/cod" : "/")),
263
+ prepareExternalUrl: jasmine
264
+ .createSpy("prepareExternalUrl")
265
+ .and.callFake((url: string) => "#/cod"),
266
+ },
267
+ },
268
+ ]);
269
+
270
+ routeStateMock = {
271
+ snapshot: {},
272
+ url: "/cod",
273
+ root: {
274
+ fragment: null,
275
+ },
276
+ };
277
+
278
+ spyOn(MsalService.prototype, "handleRedirectObservable").and.returnValue(
279
+ //@ts-ignore
280
+ of("test")
281
+ );
282
+
283
+ spyOn(PublicClientApplication.prototype, "getAllAccounts").and.returnValue([
284
+ {
285
+ homeAccountId: "test",
286
+ localAccountId: "test",
287
+ environment: "test",
288
+ tenantId: "test",
289
+ username: "test",
290
+ },
291
+ ]);
292
+
293
+ guard
294
+ .canActivate(routeMock, routeStateMock)
295
+ .subscribe((result: UrlTree) => {
296
+ expect(result).toBeTrue();
297
+ done();
298
+ });
299
+ });
300
+
301
+ it("returns false if page contains known successful response (hash routing)", (done) => {
302
+ initializeMsal([
303
+ {
304
+ provide: Location,
305
+ useValue: {
306
+ path: jasmine
307
+ .createSpy("path")
308
+ .and.callFake((hash: boolean) => (hash ? "/code=" : "/")),
309
+ prepareExternalUrl: jasmine
310
+ .createSpy("prepareExternalUrl")
311
+ .and.callFake((url: string) => "#/"),
312
+ },
313
+ },
314
+ ]);
315
+
316
+ routeStateMock = {
317
+ snapshot: {},
318
+ url: "/code",
319
+ root: {
320
+ fragment: null,
321
+ },
322
+ };
323
+
324
+ spyOn(MsalService.prototype, "handleRedirectObservable").and.returnValue(
325
+ //@ts-ignore
326
+ of("test")
327
+ );
328
+
329
+ spyOn(PublicClientApplication.prototype, "getAllAccounts").and.returnValue([
330
+ {
331
+ homeAccountId: "test",
332
+ localAccountId: "test",
333
+ environment: "test",
334
+ tenantId: "test",
335
+ username: "test",
336
+ },
337
+ ]);
338
+
339
+ guard
340
+ .canActivate(routeMock, routeStateMock)
341
+ .subscribe((result: UrlTree) => {
342
+ expect(result.toString()).toEqual("/");
343
+ done();
344
+ });
345
+ });
346
+
347
+ it("returns true for a logged in user", (done) => {
348
+ spyOn(MsalService.prototype, "handleRedirectObservable").and.returnValue(
349
+ //@ts-ignore
350
+ of("test")
351
+ );
352
+
353
+ spyOn(PublicClientApplication.prototype, "getAllAccounts").and.returnValue([
354
+ {
355
+ homeAccountId: "test",
356
+ localAccountId: "test",
357
+ environment: "test",
358
+ tenantId: "test",
359
+ username: "test",
360
+ },
361
+ ]);
362
+
363
+ guard.canActivate(routeMock, routeStateMock).subscribe((result) => {
364
+ expect(result).toBeTrue();
365
+ done();
366
+ });
367
+ });
368
+
369
+ it("should return true after logging in with popup", (done) => {
370
+ testConfiguration = {
371
+ authRequest: (authService, state) => {
372
+ expect(state).toBeDefined();
373
+ expect(authService).toBeDefined();
374
+ return {};
375
+ },
376
+ };
377
+ initializeMsal();
378
+ spyOn(MsalService.prototype, "handleRedirectObservable").and.returnValue(
379
+ //@ts-ignore
380
+ of("test")
381
+ );
382
+
383
+ spyOn(PublicClientApplication.prototype, "getAllAccounts").and.returnValue(
384
+ []
385
+ );
386
+
387
+ spyOn(MsalService.prototype, "loginPopup").and.returnValue(
388
+ //@ts-ignore
389
+ of(true)
390
+ );
391
+
392
+ guard.canActivate(routeMock, routeStateMock).subscribe((result) => {
393
+ expect(result).toBeTrue();
394
+ done();
395
+ });
396
+ });
397
+
398
+ it("should return false after login with popup fails and no loginFailedRoute set", (done) => {
399
+ spyOn(MsalService.prototype, "handleRedirectObservable").and.returnValue(
400
+ //@ts-ignore
401
+ of("test")
402
+ );
403
+
404
+ spyOn(PublicClientApplication.prototype, "getAllAccounts").and.returnValue(
405
+ []
406
+ );
407
+
408
+ spyOn(MsalService.prototype, "loginPopup").and.throwError("login error");
409
+
410
+ guard.canActivate(routeMock, routeStateMock).subscribe((result) => {
411
+ expect(result).toBeFalse();
412
+ done();
413
+ });
414
+ });
415
+
416
+ it("should return loginFailedRoute after login with popup fails and loginFailedRoute set", (done) => {
417
+ testLoginFailedRoute = "failed";
418
+ initializeMsal();
419
+
420
+ spyOn(guard, "parseUrl").and.returnValue(
421
+ testLoginFailedRoute as unknown as UrlTree
422
+ );
423
+
424
+ spyOn(MsalService.prototype, "handleRedirectObservable").and.returnValue(
425
+ //@ts-ignore
426
+ of("test")
427
+ );
428
+
429
+ spyOn(PublicClientApplication.prototype, "getAllAccounts").and.returnValue(
430
+ []
431
+ );
432
+
433
+ spyOn(MsalService.prototype, "loginPopup").and.throwError("login error");
434
+
435
+ guard.canActivate(routeMock, routeStateMock).subscribe((result) => {
436
+ expect(result).toBe("failed" as unknown as UrlTree);
437
+ done();
438
+ });
439
+ });
440
+
441
+ it("should return false after logging in with redirect", (done) => {
442
+ testInteractionType = InteractionType.Redirect;
443
+ initializeMsal();
444
+
445
+ spyOn(MsalService.prototype, "handleRedirectObservable").and.returnValue(
446
+ //@ts-ignore
447
+ of("test")
448
+ );
449
+
450
+ spyOn(PublicClientApplication.prototype, "getAllAccounts").and.returnValue(
451
+ []
452
+ );
453
+
454
+ spyOn(PublicClientApplication.prototype, "loginRedirect").and.returnValue(
455
+ new Promise((resolve) => {
456
+ resolve();
457
+ })
458
+ );
459
+
460
+ guard.canActivate(routeMock, routeStateMock).subscribe((result) => {
461
+ expect(result).toBeFalse();
462
+ done();
463
+ });
464
+ });
465
+
466
+ it("canActivateChild returns true with logged in user", (done) => {
467
+ spyOn(MsalService.prototype, "handleRedirectObservable").and.returnValue(
468
+ //@ts-ignore
469
+ of("test")
470
+ );
471
+
472
+ spyOn(PublicClientApplication.prototype, "getAllAccounts").and.returnValue([
473
+ {
474
+ homeAccountId: "test",
475
+ localAccountId: "test",
476
+ environment: "test",
477
+ tenantId: "test",
478
+ username: "test",
479
+ },
480
+ ]);
481
+
482
+ guard.canActivateChild(routeMock, routeStateMock).subscribe((result) => {
483
+ expect(result).toBeTrue();
484
+ done();
485
+ });
486
+ });
487
+
488
+ it("canLoad returns true with logged in user", (done) => {
489
+ spyOn(MsalService.prototype, "handleRedirectObservable").and.returnValue(
490
+ //@ts-ignore
491
+ of("test")
492
+ );
493
+
494
+ spyOn(PublicClientApplication.prototype, "getAllAccounts").and.returnValue([
495
+ {
496
+ homeAccountId: "test",
497
+ localAccountId: "test",
498
+ environment: "test",
499
+ tenantId: "test",
500
+ username: "test",
501
+ },
502
+ ]);
503
+
504
+ guard.canMatch().subscribe((result) => {
505
+ expect(result).toBeTrue();
506
+ done();
507
+ });
508
+ });
509
+
510
+ it("canLoad returns false with no users logged in", (done) => {
511
+ spyOn(MsalService.prototype, "handleRedirectObservable").and.returnValue(
512
+ //@ts-ignore
513
+ of("test")
514
+ );
515
+
516
+ spyOn(PublicClientApplication.prototype, "getAllAccounts").and.returnValue(
517
+ []
518
+ );
519
+
520
+ guard.canMatch().subscribe((result) => {
521
+ expect(result).toBeFalse();
522
+ done();
523
+ });
524
+ });
525
+ });