mirror of
https://github.com/bitwarden/browser
synced 2026-02-10 13:40:06 +00:00
Add tests for autofill modal work
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
import { Router } from "@angular/router";
|
||||
import { mock } from "jest-mock-extended";
|
||||
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
|
||||
import { DesktopSettingsService } from "src/platform/services/desktop-settings.service";
|
||||
|
||||
import {
|
||||
DesktopFido2UserInterfaceService,
|
||||
DesktopFido2UserInterfaceSession,
|
||||
} from "./desktop-fido2-user-interface.service";
|
||||
import type { NativeWindowObject } from "./desktop-fido2-user-interface.service";
|
||||
|
||||
describe("Desktop Fido2 User Interface Service", () => {
|
||||
const accountService = mock<AccountService>();
|
||||
const authService = mock<AuthService>();
|
||||
const cipherService = mock<CipherService>();
|
||||
const desktopSettingsService = mock<DesktopSettingsService>();
|
||||
const logService = mock<LogService>();
|
||||
const messagingService = mock<MessagingService>();
|
||||
const router = mock<Router>();
|
||||
let desktopFido2UserInterfaceService: DesktopFido2UserInterfaceService;
|
||||
|
||||
beforeEach(() => {
|
||||
desktopFido2UserInterfaceService = new DesktopFido2UserInterfaceService(
|
||||
authService,
|
||||
cipherService,
|
||||
accountService,
|
||||
logService,
|
||||
messagingService,
|
||||
router,
|
||||
desktopSettingsService,
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
describe("newSession", () => {
|
||||
it("logs a warning", async () => {
|
||||
const fallbackSupported = false;
|
||||
const nativeWindowObject = {};
|
||||
await desktopFido2UserInterfaceService.newSession(fallbackSupported, nativeWindowObject);
|
||||
|
||||
expect(logService.warning).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Desktop Fido2 User Interface Session", () => {
|
||||
const accountService = mock<AccountService>();
|
||||
const authService = mock<AuthService>();
|
||||
const cipherService = mock<CipherService>();
|
||||
const desktopSettingsService = mock<DesktopSettingsService>();
|
||||
const logService = mock<LogService>();
|
||||
const router = mock<Router>();
|
||||
const windowObject = mock<NativeWindowObject>();
|
||||
let desktopFido2UserInterfaceSession: DesktopFido2UserInterfaceSession;
|
||||
|
||||
beforeEach(() => {
|
||||
desktopFido2UserInterfaceSession = new DesktopFido2UserInterfaceSession(
|
||||
authService,
|
||||
cipherService,
|
||||
accountService,
|
||||
logService,
|
||||
router,
|
||||
desktopSettingsService,
|
||||
windowObject,
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
describe("availableCipherId$", () => {
|
||||
it("returns available cipher ids", () => {
|
||||
desktopFido2UserInterfaceSession.availableCipherIds$.subscribe({
|
||||
next: (ids) => {
|
||||
expect(ids).toEqual(["id1", "id2"]);
|
||||
},
|
||||
});
|
||||
|
||||
desktopFido2UserInterfaceSession["availableCipherIdsSubject"].next(["id1", "id2"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("pickCredential", () => {
|
||||
it("returns a cipherId when one exists", async () => {
|
||||
const result = await desktopFido2UserInterfaceSession.pickCredential({
|
||||
cipherIds: ["id"],
|
||||
userVerification: false,
|
||||
assumeUserPresence: false,
|
||||
masterPasswordRepromptRequired: false,
|
||||
});
|
||||
|
||||
expect(result).toStrictEqual({ cipherId: "id", userVerified: false });
|
||||
});
|
||||
|
||||
it("returns a user chosen cipherId", async () => {
|
||||
jest
|
||||
.spyOn(desktopFido2UserInterfaceSession as any, "waitForUiChosenCipher")
|
||||
.mockResolvedValue("id2");
|
||||
|
||||
const result = await desktopFido2UserInterfaceSession.pickCredential({
|
||||
cipherIds: ["id", "id2"],
|
||||
userVerification: false,
|
||||
assumeUserPresence: false,
|
||||
masterPasswordRepromptRequired: false,
|
||||
});
|
||||
|
||||
expect(result).toStrictEqual({ cipherId: "id2", userVerified: true });
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,161 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { ComponentFixture, TestBed } from "@angular/core/testing";
|
||||
import { RouterModule, Router } from "@angular/router";
|
||||
import { MockProxy, mock } from "jest-mock-extended";
|
||||
import { of } from "rxjs";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import {
|
||||
BadgeModule,
|
||||
ButtonModule,
|
||||
DialogModule,
|
||||
IconModule,
|
||||
ItemModule,
|
||||
SectionComponent,
|
||||
TableModule,
|
||||
} from "@bitwarden/components";
|
||||
|
||||
import { BitIconButtonComponent } from "../../../../../../libs/components/src/icon-button/icon-button.component";
|
||||
import { SectionHeaderComponent } from "../../../../../../libs/components/src/section/section-header.component";
|
||||
import {
|
||||
DesktopFido2UserInterfaceService,
|
||||
DesktopFido2UserInterfaceSession,
|
||||
} from "../../../autofill/services/desktop-fido2-user-interface.service";
|
||||
import { DesktopSettingsService } from "../../../platform/services/desktop-settings.service";
|
||||
|
||||
import { Fido2CreateComponent } from "./fido2-create.component";
|
||||
|
||||
describe("Fido2CreateComponent", () => {
|
||||
let rpid: string;
|
||||
let component: Fido2CreateComponent;
|
||||
let fixture: ComponentFixture<Fido2CreateComponent>;
|
||||
let cipherService: MockProxy<CipherService>;
|
||||
let desktopSettingsService: MockProxy<DesktopSettingsService>;
|
||||
let domainSettingService: MockProxy<DomainSettingsService>;
|
||||
let interfaceService: MockProxy<DesktopFido2UserInterfaceService>;
|
||||
let session: MockProxy<DesktopFido2UserInterfaceSession>;
|
||||
let router: MockProxy<Router>;
|
||||
|
||||
beforeEach(async () => {
|
||||
rpid = "example.com";
|
||||
router = mock<Router>();
|
||||
session = mock<DesktopFido2UserInterfaceSession>({
|
||||
getRpId: jest.fn().mockResolvedValue(rpid),
|
||||
});
|
||||
cipherService = mock<CipherService>({
|
||||
getAllDecrypted: jest.fn().mockResolvedValue([
|
||||
{
|
||||
login: {
|
||||
hasUris: true,
|
||||
fido2Credentials: [],
|
||||
matchesUri: jest.fn().mockReturnValue(true),
|
||||
},
|
||||
},
|
||||
{
|
||||
login: {
|
||||
hasUris: false,
|
||||
fido2Credentials: [],
|
||||
matchesUri: jest.fn().mockReturnValue(false),
|
||||
},
|
||||
},
|
||||
]),
|
||||
});
|
||||
desktopSettingsService = mock<DesktopSettingsService>();
|
||||
domainSettingService = mock<DomainSettingsService>({
|
||||
getUrlEquivalentDomains: jest
|
||||
.fn()
|
||||
.mockReturnValue(of(new Set(["example.com", "example.org"]))),
|
||||
equivalentDomains$: of([
|
||||
["example.com", "example.org"],
|
||||
["example.net", "example.info"],
|
||||
]),
|
||||
});
|
||||
interfaceService = mock<DesktopFido2UserInterfaceService>({
|
||||
getCurrentSession: jest.fn().mockReturnValue(session),
|
||||
});
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterModule,
|
||||
SectionHeaderComponent,
|
||||
BitIconButtonComponent,
|
||||
TableModule,
|
||||
JslibModule,
|
||||
IconModule,
|
||||
ButtonModule,
|
||||
DialogModule,
|
||||
SectionComponent,
|
||||
ItemModule,
|
||||
BadgeModule,
|
||||
],
|
||||
providers: [
|
||||
{ provide: DesktopSettingsService, useValue: desktopSettingsService },
|
||||
{ provide: DesktopFido2UserInterfaceService, useValue: interfaceService },
|
||||
{ provide: DesktopFido2UserInterfaceSession, useValue: session },
|
||||
{ provide: CipherService, useValue: cipherService },
|
||||
{ provide: DomainSettingsService, useValue: domainSettingService },
|
||||
{ provide: I18nService, useValue: mock<I18nService>() },
|
||||
{ provide: Router, useValue: router },
|
||||
],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(Fido2CreateComponent);
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
|
||||
it("creates the component", () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it("ngOnInit", async () => {
|
||||
component.session = session;
|
||||
|
||||
await component.ngOnInit();
|
||||
|
||||
expect(session.getRpId).toHaveBeenCalledTimes(1);
|
||||
expect(domainSettingService.getUrlEquivalentDomains).toHaveBeenCalledWith(rpid);
|
||||
expect(cipherService.getAllDecrypted).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("adds pass key to cipher", async () => {
|
||||
component.session = session;
|
||||
const cipher = new CipherView();
|
||||
|
||||
await component.addPasskeyToCipher(cipher);
|
||||
|
||||
expect(session.notifyConfirmCredential).toHaveBeenCalledWith(true, cipher);
|
||||
});
|
||||
|
||||
describe("confirming the pass key", () => {
|
||||
// it("throws an error when no session exists", async () => {
|
||||
// component.session = undefined;
|
||||
|
||||
// await expect(component.confirmPasskey()).rejects.toThrow("No session found");
|
||||
// });
|
||||
it("confirms the pass key", async () => {
|
||||
component.session = session;
|
||||
|
||||
await component.confirmPasskey();
|
||||
|
||||
expect(router.navigate).toHaveBeenCalledWith(["/"]);
|
||||
expect(session.notifyConfirmCredential).toHaveBeenCalledWith(true);
|
||||
expect(desktopSettingsService.setModalMode).toHaveBeenCalledWith(false);
|
||||
});
|
||||
});
|
||||
|
||||
it("closes the modal", async () => {
|
||||
component.session = session;
|
||||
|
||||
await component.closeModal();
|
||||
|
||||
expect(router.navigate).toHaveBeenCalledWith(["/"]);
|
||||
expect(desktopSettingsService.setModalMode).toHaveBeenCalledWith(false);
|
||||
expect(session.notifyConfirmCredential).toHaveBeenCalledWith(false);
|
||||
expect(session.confirmChosenCipher).toHaveBeenCalledWith(null);
|
||||
});
|
||||
});
|
||||
@@ -36,6 +36,7 @@ import { CipherCreateRequest } from "../models/request/cipher-create.request";
|
||||
import { CipherPartialRequest } from "../models/request/cipher-partial.request";
|
||||
import { CipherRequest } from "../models/request/cipher.request";
|
||||
import { CipherView } from "../models/view/cipher.view";
|
||||
import { Fido2CredentialView } from "../models/view/fido2-credential.view";
|
||||
import { LoginUriView } from "../models/view/login-uri.view";
|
||||
|
||||
import { CipherService } from "./cipher.service";
|
||||
@@ -414,4 +415,41 @@ describe("Cipher Service", () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getAllDecryptedForIds", () => {
|
||||
it("returns ciphers for the given ids", async () => {
|
||||
const startingCiphers = [{ ...cipherObj }, { ...cipherObj, id: "id2" }];
|
||||
const expectedObj = [cipherObj];
|
||||
jest.spyOn(cipherService as any, "getAllDecrypted").mockResolvedValue(startingCiphers);
|
||||
|
||||
const result = await cipherService.getAllDecryptedForIds(["id"]);
|
||||
|
||||
expect(result).toEqual(expectedObj);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getPasskeyCiphers", () => {
|
||||
it("returns the fido2 ciphers when they are available", async () => {
|
||||
const passkeyDate = new Date();
|
||||
const cipherWithFido2 = [
|
||||
{
|
||||
...cipherObj,
|
||||
login: { fido2Credentials: [{ creationDate: passkeyDate } as Fido2CredentialView] },
|
||||
},
|
||||
];
|
||||
jest.spyOn(cipherService as any, "getAllDecrypted").mockResolvedValue(cipherWithFido2);
|
||||
|
||||
const result = await cipherService.getAllDecrypted();
|
||||
|
||||
expect(result).toBe(cipherWithFido2);
|
||||
});
|
||||
|
||||
it("returns null when there are no ciphers", async () => {
|
||||
jest.spyOn(cipherService as any, "getAllDecrypted").mockResolvedValue(null);
|
||||
|
||||
const result = await cipherService.getPasskeyCiphers();
|
||||
|
||||
expect(result).toBe(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user