1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-23 19:53:43 +00:00

[PM-4816] Create shared LoginApprovalComponent (#11982)

* Stub out dialog

* Genericize LoginApprovalComponent

* update ipc mocks

* Remove changes to account component

* Remove changes to account component

* Remove debug

* Remove test component

* Remove added translations

* Fix failing test

* Run lint and prettier

* Rename LoginApprovalServiceAbstraction to LoginApprovalComponentServiceAbstraction

* Add back missing "isVisible" check before calling loginRequest

* Rename classes to contain "Component" in the name

* Add missing space between "login attempt" and fingerprint phrase

* Require email
This commit is contained in:
Alec Rippberger
2024-11-22 12:55:26 -06:00
committed by GitHub
parent 13d4b6f2a6
commit 02ea368446
12 changed files with 307 additions and 12 deletions

View File

@@ -0,0 +1,122 @@
import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog";
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { mock, MockProxy } from "jest-mock-extended";
import { of } from "rxjs";
import {
AuthRequestServiceAbstraction,
LoginApprovalComponentServiceAbstraction,
} from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { UserId } from "@bitwarden/common/types/guid";
import { ToastService } from "@bitwarden/components";
import { KeyService } from "@bitwarden/key-management";
import { LoginApprovalComponent } from "./login-approval.component";
describe("LoginApprovalComponent", () => {
let component: LoginApprovalComponent;
let fixture: ComponentFixture<LoginApprovalComponent>;
let authRequestService: MockProxy<AuthRequestServiceAbstraction>;
let accountService: MockProxy<AccountService>;
let apiService: MockProxy<ApiService>;
let i18nService: MockProxy<I18nService>;
let dialogRef: MockProxy<DialogRef>;
let toastService: MockProxy<ToastService>;
const testNotificationId = "test-notification-id";
const testEmail = "test@bitwarden.com";
const testPublicKey = "test-public-key";
beforeEach(async () => {
authRequestService = mock<AuthRequestServiceAbstraction>();
accountService = mock<AccountService>();
apiService = mock<ApiService>();
i18nService = mock<I18nService>();
dialogRef = mock<DialogRef>();
toastService = mock<ToastService>();
accountService.activeAccount$ = of({
email: testEmail,
id: "test-user-id" as UserId,
emailVerified: true,
name: null,
});
await TestBed.configureTestingModule({
imports: [LoginApprovalComponent],
providers: [
{ provide: DIALOG_DATA, useValue: { notificationId: testNotificationId } },
{ provide: AuthRequestServiceAbstraction, useValue: authRequestService },
{ provide: AccountService, useValue: accountService },
{ provide: PlatformUtilsService, useValue: mock<PlatformUtilsService>() },
{ provide: I18nService, useValue: i18nService },
{ provide: ApiService, useValue: apiService },
{ provide: AppIdService, useValue: mock<AppIdService>() },
{ provide: KeyService, useValue: mock<KeyService>() },
{ provide: DialogRef, useValue: dialogRef },
{ provide: ToastService, useValue: toastService },
{
provide: LoginApprovalComponentServiceAbstraction,
useValue: mock<LoginApprovalComponentServiceAbstraction>(),
},
],
}).compileComponents();
fixture = TestBed.createComponent(LoginApprovalComponent);
component = fixture.componentInstance;
});
it("creates successfully", () => {
expect(component).toBeTruthy();
});
describe("ngOnInit", () => {
beforeEach(() => {
apiService.getAuthRequest.mockResolvedValue({
publicKey: testPublicKey,
creationDate: new Date().toISOString(),
} as AuthRequestResponse);
authRequestService.getFingerprintPhrase.mockResolvedValue("test-phrase");
});
it("retrieves and sets auth request data", async () => {
await component.ngOnInit();
expect(apiService.getAuthRequest).toHaveBeenCalledWith(testNotificationId);
expect(component.email).toBe(testEmail);
expect(component.fingerprintPhrase).toBeDefined();
});
it("updates time text initially", async () => {
i18nService.t.mockReturnValue("justNow");
await component.ngOnInit();
expect(component.requestTimeText).toBe("justNow");
});
});
describe("denyLogin", () => {
it("denies auth request and shows info toast", async () => {
const response = { requestApproved: false } as AuthRequestResponse;
apiService.getAuthRequest.mockResolvedValue(response);
authRequestService.approveOrDenyAuthRequest.mockResolvedValue(response);
i18nService.t.mockReturnValue("denied message");
await component.denyLogin();
expect(authRequestService.approveOrDenyAuthRequest).toHaveBeenCalledWith(false, response);
expect(toastService.showToast).toHaveBeenCalledWith({
variant: "info",
title: null,
message: "denied message",
});
});
});
});