1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-05 03:03:26 +00:00
Files
browser/libs/auth/src/angular/two-factor-auth/two-factor-auth.guard.spec.ts
Dave daf7b7d2ce fix(two-factor) [PM-21204]: Users without premium cannot disable premium 2FA (#17134)
* refactor(two-factor-service) [PM-21204]: Stub API methods in TwoFactorService (domain).

* refactor(two-factor-service) [PM-21204]: Build out stubs and add documentation.

* refactor(two-factor-service) [PM-21204]: Update TwoFactorApiService call sites to use TwoFactorService.

* refactor(two-fatcor) [PM-21204]: Remove deprecated and unused formPromise methods.

* refactor(two-factor) [PM-21204]: Move 2FA-supporting services into common/auth/two-factor feature namespace.

* refactor(two-factor) [PM-21204]: Update imports for service/init containers.

* feat(two-factor) [PM-21204]: Add a disabling flow for Premium 2FA when enabled on a non-Premium account.

* fix(two-factor-service) [PM-21204]: Fix type-safety of module constants.

* fix(multiple) [PM-21204]: Prettier.

* fix(user-verification-dialog) [PM-21204]: Remove bodyText configuration for this use.

* fix(user-verification-dialog) [PM-21204]: Improve the error message displayed to the user.
2025-11-21 10:35:34 -05:00

77 lines
2.7 KiB
TypeScript

import { Component } from "@angular/core";
import { TestBed } from "@angular/core/testing";
import { provideRouter, Router } from "@angular/router";
import { mock, MockProxy } from "jest-mock-extended";
import { BehaviorSubject } from "rxjs";
import { AuthenticationType } from "@bitwarden/common/auth/enums/authentication-type";
import { TwoFactorService } from "@bitwarden/common/auth/two-factor";
import { LoginStrategyServiceAbstraction } from "../../common";
import { TwoFactorAuthGuard } from "./two-factor-auth.guard";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({ template: "", standalone: true })
export class EmptyComponent {}
describe("TwoFactorAuthGuard", () => {
let loginStrategyService: MockProxy<LoginStrategyServiceAbstraction>;
const currentAuthTypesSubject = new BehaviorSubject<AuthenticationType | null>(null);
let twoFactorService: MockProxy<TwoFactorService>;
let router: Router;
beforeEach(() => {
loginStrategyService = mock<LoginStrategyServiceAbstraction>();
loginStrategyService.currentAuthType$ = currentAuthTypesSubject.asObservable();
twoFactorService = mock<TwoFactorService>();
TestBed.configureTestingModule({
providers: [
provideRouter([
{ path: "login", component: EmptyComponent },
{ path: "protected", component: EmptyComponent, canActivate: [TwoFactorAuthGuard] },
]),
{ provide: LoginStrategyServiceAbstraction, useValue: loginStrategyService },
{ provide: TwoFactorService, useValue: twoFactorService },
],
});
router = TestBed.inject(Router);
});
it("should redirect to /login if the user is not authenticating", async () => {
// Arrange
currentAuthTypesSubject.next(null);
twoFactorService.getProviders.mockResolvedValue(null);
// Act
await router.navigateByUrl("/protected");
// Assert
expect(router.url).toBe("/login");
});
const authenticationTypes = Object.entries(AuthenticationType)
// filter out reverse mappings (e.g., "0": "Password")
.filter(([key, value]) => typeof value === "number")
.map(([key, value]) => [value, key]) as [AuthenticationType, string][];
authenticationTypes.forEach(([authType, authTypeName]) => {
it(`should redirect to /login if the user is authenticating with ${authTypeName} but no two-factor providers exist`, async () => {
// Arrange
currentAuthTypesSubject.next(authType);
twoFactorService.getProviders.mockResolvedValue(null);
// Act
await router.navigateByUrl("/protected");
// Assert
expect(router.url).toBe("/login");
});
});
});