bitwarden-estensione-browser/apps/desktop/src/auth/lock.component.spec.ts

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

428 lines
18 KiB
TypeScript
Raw Normal View History

import { NO_ERRORS_SCHEMA } from "@angular/core";
import { ComponentFixture, TestBed, fakeAsync, tick } from "@angular/core/testing";
import { ActivatedRoute } from "@angular/router";
import { MockProxy, mock } from "jest-mock-extended";
import { of } from "rxjs";
import { LockComponent as BaseLockComponent } from "@bitwarden/angular/auth/components/lock.component";
import { I18nPipe } from "@bitwarden/angular/platform/pipes/i18n.pipe";
Auth/PM-4596 - Extract PIN and Biometrics unlock method logic into re-useable services for user verification (#7107) * PM-4596 - PinCryptoService first draft * PM-4596 - PinCryptoService - Refactor pinKeyEncryptedKey retrievals out into own method getPinKeyEncryptedKeys * PM-4596 - npm ci + npm run prettier to fix lint issues * PM-4596 - PinCryptoService - Add kdf types * PM-4596 - PinCryptoService - Refactor pin validation into own helper method. * PM-4596 - Rename pin-crypto.service.ts to pin-crypto.service.implementation.ts * PM-4596 - PinCryptoService - add additional logging for error states. * PM-4596 - JslibServicesModule - register new PinCryptoService and PinCryptoServiceAbstraction * PM-4596 - PinCryptoService - modify decryptUserKeyWithPin signature to not require email to match MP verification process in user verification service. * PM-4596 - Lock components - use new PinCryptoService.decryptUserKeyWithPin(...) to get user key + refactor base comp unlock with pin method to improve * PM-4596 - Lock component - if too many invalid attempts, added toast explaining that we were logging the user out due to excess PIN entry attempts * PM-4596 - UserVerificationService - (1) Refactor verifyUser(...) to use switch + separate methods for a cleaner parent method + better extensibility for PIN & biometrics which are TBD (2) Add PIN support to validateInput(...) * PM-4596 - UserVerificationService - add PIN and biometrics functions to verifyUser(...) * PM-4596 - PinCryptoService Spec - start test file - instantiates properly * PM-4596 - PinCryptoService tests - WIP * PM-4596 - PinCryptoService tests - WIP - got success cases working * PM-4596 - pin-crypto.service.implementation.spec.ts renamed to pin-crypto.service.spec.ts * PM-4596 - PinCryptoService.getPinKeyEncryptedKeys(...) - add comment + var name change for clarity * PM-4596 - PinCryptoService tests - test invalid, null return scenarios * PM-4596 - CLI - bw.ts - update UserVerificationService instantiation to include new pinCryptoService * PM-4596 - PinCryptoService - import VaultTimeoutSettingsServiceAbstraction instead of implementation for factory creation to get browser building * PM-4596 - (1) Create pinCryptoServiceFactory for browser background (2) Add it to the existing userVerificationServiceFactory * PM-4596 - Browser - Main.background.ts - Add pinCryptoService and add to userVerificationService dependencies * PM-4596 - UserVerificationService - per PR feedback simplify returns of verifyUserByPIN(...) and verifyUserByBiometrics(...) * PM-4596 - Messages.json on desktop & browser - per PR feedback, adjust tooManyInvalidPinEntryAttemptsLoggingOut translation text to remove "you" * PM-4596 - VerificationType enum - fix line copy mistake and give BIOMETRICS own, unique value. * PM-4596 - VerificationType - rename BIOMETRICS to Biometrics to match existing MasterPassword value case. * PM-4596 - Update verification type to consider whether or not a secret exists as we have added a new verification which doesn't have a type. Add new server and client side verification types. Update all relevant code to pass compilation checks. * PM-4596 - More verification type tweaking * PM-4596 - Verification - verificationHasSecret - tweak logic to be more dynamic and flexible for future verification types * PM-4596 - UpdateTempPasswordComp - use new MasterPasswordVerification * PM-4596 - Desktop - DeleteAcctComp - use VerificationWithSecret to solve compile error w/ accessing secret * PM-4596 - Per discussions with Andreas & Will, move new Pin Crypto services into libs/auth + added @bitwarden/auth path to CLI tsconfig + added new, required index.ts files for exporting service abstractions & implementations * PM-4596 - Fixed missed import fixes for lock components across clients for pin crypto service after moving into @bitwarden/auth * PM-4596 - More PinCryptoService import fixes to get browser & desktop building * PM-4596 - Update desktop lock comp tests to pass by providing new pin crypto service. * PM-4596 - User verification service -update todo * PM-4596 - PinCryptoService - per PR feedback, fix auto import wrong paths. * PM-4596 - PinCryptoService tests - fix imports per PR feedback * PM-4596 - UserVerificationSvc - rename method to validateSecretInput per PR feedback * Fix imports * PM-4596 - PinCryptoService - Refactor naming for clarity and move test cases into describes per PR feedback * reorg libs/auth; expose only libs/auth/core to cli app * PM-4596 - UserVerification - Resolve import issue with importing from libs/auth. Can't use @bitwarden/auth for whatever reason. * PM-4596 - Fix desktop build by fixing import * PM-4596 - Provide PinCryptoService to UserVerificationService * PM-4596 - PinCryptoServiceFactory - you cannot import services from @bitwarden/auth in the background b/c it brings along the libs/auth/components and introduces angular into the background context which doesn't have access to angular which causes random test failures. So, we must separate out the core services just like the CLI to only bring along the angular agnostic services from core. * PM-4596 - Refactor libs/auth to have angular / common + update all imports per discussion with Matt & Will. Introduced circular dep between PinCryptoService + VaultTimeoutSettingsService + UserVerificationService * PM-4596 - VaultTimeoutSettingsService - Refactor UserVerificationService out of the service and update all service instantiations and tests. The use of the UserVerificationService.hasMasterPassword method no longer needs to be used for backwards compatibility. This resolves the circular dependency between the PinCryptoService, the UserVerificationService, and the VaultTimeoutSettingsService. We will likely refactor the hasMasterPassword method out of the UserVerificationService in the future. * PM-4596 - Update CL tsconfig.libs.json to add new auth/common and auth/angular paths for jslib-services.module imports of pin crypto service to work and for test code coverage to run successfully. * PM-4596 - Address PR feedback * PM-4596 - Update root tsconfig (only used by storybook) to add new libs/auth paths to fix chromatic build pipeline. * PM-4596 - Actually update tsconfig with proper routes to fix storybook * PM-4596 - UserVerificationService - verifyUserByBiometrics - add error handling logic to convert failed or cancelled biometrics verification to a usable boolean * PM-4596 - Add missing await * PM-4596 - (1) Add log service and log to user verification service biometric flow to ensure errors are at least revealed to the console (2) Fix factory missing PinCryptoServiceInitOptions * PM-4596 - Use the correct log service abstraction * PM-4596 - Remove unused types per PR review --------- Co-authored-by: William Martin <contact@willmartian.com>
2024-01-16 20:52:06 +01:00
import { PinCryptoServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
import { VaultTimeoutService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout.service";
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { BiometricStateService } from "@bitwarden/common/platform/biometrics/biometric-state.service";
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
import { DialogService } from "@bitwarden/components";
import { LockComponent } from "./lock.component";
// ipc mock global
const isWindowVisibleMock = jest.fn();
(global as any).ipc = {
platform: {
biometric: {
enabled: jest.fn(),
},
isWindowVisible: isWindowVisibleMock,
},
};
describe("LockComponent", () => {
let component: LockComponent;
let fixture: ComponentFixture<LockComponent>;
let stateServiceMock: MockProxy<StateService>;
const biometricStateService = mock<BiometricStateService>();
let messagingServiceMock: MockProxy<MessagingService>;
let broadcasterServiceMock: MockProxy<BroadcasterService>;
let platformUtilsServiceMock: MockProxy<PlatformUtilsService>;
let activatedRouteMock: MockProxy<ActivatedRoute>;
beforeEach(async () => {
stateServiceMock = mock<StateService>();
stateServiceMock.activeAccount$ = of(null);
messagingServiceMock = mock<MessagingService>();
broadcasterServiceMock = mock<BroadcasterService>();
platformUtilsServiceMock = mock<PlatformUtilsService>();
activatedRouteMock = mock<ActivatedRoute>();
activatedRouteMock.queryParams = mock<ActivatedRoute["queryParams"]>();
biometricStateService.dismissedRequirePasswordOnStartCallout$ = of(false);
biometricStateService.promptAutomatically$ = of(false);
biometricStateService.promptCancelled$ = of(false);
await TestBed.configureTestingModule({
declarations: [LockComponent, I18nPipe],
providers: [
{
provide: I18nService,
useValue: mock<I18nService>(),
},
{
provide: PlatformUtilsService,
useValue: platformUtilsServiceMock,
},
{
provide: MessagingService,
useValue: messagingServiceMock,
},
{
provide: CryptoService,
useValue: mock<CryptoService>(),
},
{
provide: VaultTimeoutService,
useValue: mock<VaultTimeoutService>(),
},
{
provide: VaultTimeoutSettingsService,
useValue: mock<VaultTimeoutSettingsService>(),
},
{
provide: EnvironmentService,
useValue: mock<EnvironmentService>(),
},
{
provide: StateService,
useValue: stateServiceMock,
},
{
provide: ApiService,
useValue: mock<ApiService>(),
},
{
provide: ActivatedRoute,
useValue: activatedRouteMock,
},
{
provide: BroadcasterService,
useValue: broadcasterServiceMock,
},
{
provide: PolicyApiServiceAbstraction,
useValue: mock<PolicyApiServiceAbstraction>(),
},
{
provide: InternalPolicyService,
useValue: mock<InternalPolicyService>(),
},
{
provide: PasswordStrengthServiceAbstraction,
useValue: mock<PasswordStrengthServiceAbstraction>(),
},
{
provide: LogService,
useValue: mock<LogService>(),
},
{
provide: DialogService,
useValue: mock<DialogService>(),
},
{
provide: DeviceTrustCryptoServiceAbstraction,
useValue: mock<DeviceTrustCryptoServiceAbstraction>(),
},
{
provide: UserVerificationService,
useValue: mock<UserVerificationService>(),
},
Auth/PM-4596 - Extract PIN and Biometrics unlock method logic into re-useable services for user verification (#7107) * PM-4596 - PinCryptoService first draft * PM-4596 - PinCryptoService - Refactor pinKeyEncryptedKey retrievals out into own method getPinKeyEncryptedKeys * PM-4596 - npm ci + npm run prettier to fix lint issues * PM-4596 - PinCryptoService - Add kdf types * PM-4596 - PinCryptoService - Refactor pin validation into own helper method. * PM-4596 - Rename pin-crypto.service.ts to pin-crypto.service.implementation.ts * PM-4596 - PinCryptoService - add additional logging for error states. * PM-4596 - JslibServicesModule - register new PinCryptoService and PinCryptoServiceAbstraction * PM-4596 - PinCryptoService - modify decryptUserKeyWithPin signature to not require email to match MP verification process in user verification service. * PM-4596 - Lock components - use new PinCryptoService.decryptUserKeyWithPin(...) to get user key + refactor base comp unlock with pin method to improve * PM-4596 - Lock component - if too many invalid attempts, added toast explaining that we were logging the user out due to excess PIN entry attempts * PM-4596 - UserVerificationService - (1) Refactor verifyUser(...) to use switch + separate methods for a cleaner parent method + better extensibility for PIN & biometrics which are TBD (2) Add PIN support to validateInput(...) * PM-4596 - UserVerificationService - add PIN and biometrics functions to verifyUser(...) * PM-4596 - PinCryptoService Spec - start test file - instantiates properly * PM-4596 - PinCryptoService tests - WIP * PM-4596 - PinCryptoService tests - WIP - got success cases working * PM-4596 - pin-crypto.service.implementation.spec.ts renamed to pin-crypto.service.spec.ts * PM-4596 - PinCryptoService.getPinKeyEncryptedKeys(...) - add comment + var name change for clarity * PM-4596 - PinCryptoService tests - test invalid, null return scenarios * PM-4596 - CLI - bw.ts - update UserVerificationService instantiation to include new pinCryptoService * PM-4596 - PinCryptoService - import VaultTimeoutSettingsServiceAbstraction instead of implementation for factory creation to get browser building * PM-4596 - (1) Create pinCryptoServiceFactory for browser background (2) Add it to the existing userVerificationServiceFactory * PM-4596 - Browser - Main.background.ts - Add pinCryptoService and add to userVerificationService dependencies * PM-4596 - UserVerificationService - per PR feedback simplify returns of verifyUserByPIN(...) and verifyUserByBiometrics(...) * PM-4596 - Messages.json on desktop & browser - per PR feedback, adjust tooManyInvalidPinEntryAttemptsLoggingOut translation text to remove "you" * PM-4596 - VerificationType enum - fix line copy mistake and give BIOMETRICS own, unique value. * PM-4596 - VerificationType - rename BIOMETRICS to Biometrics to match existing MasterPassword value case. * PM-4596 - Update verification type to consider whether or not a secret exists as we have added a new verification which doesn't have a type. Add new server and client side verification types. Update all relevant code to pass compilation checks. * PM-4596 - More verification type tweaking * PM-4596 - Verification - verificationHasSecret - tweak logic to be more dynamic and flexible for future verification types * PM-4596 - UpdateTempPasswordComp - use new MasterPasswordVerification * PM-4596 - Desktop - DeleteAcctComp - use VerificationWithSecret to solve compile error w/ accessing secret * PM-4596 - Per discussions with Andreas & Will, move new Pin Crypto services into libs/auth + added @bitwarden/auth path to CLI tsconfig + added new, required index.ts files for exporting service abstractions & implementations * PM-4596 - Fixed missed import fixes for lock components across clients for pin crypto service after moving into @bitwarden/auth * PM-4596 - More PinCryptoService import fixes to get browser & desktop building * PM-4596 - Update desktop lock comp tests to pass by providing new pin crypto service. * PM-4596 - User verification service -update todo * PM-4596 - PinCryptoService - per PR feedback, fix auto import wrong paths. * PM-4596 - PinCryptoService tests - fix imports per PR feedback * PM-4596 - UserVerificationSvc - rename method to validateSecretInput per PR feedback * Fix imports * PM-4596 - PinCryptoService - Refactor naming for clarity and move test cases into describes per PR feedback * reorg libs/auth; expose only libs/auth/core to cli app * PM-4596 - UserVerification - Resolve import issue with importing from libs/auth. Can't use @bitwarden/auth for whatever reason. * PM-4596 - Fix desktop build by fixing import * PM-4596 - Provide PinCryptoService to UserVerificationService * PM-4596 - PinCryptoServiceFactory - you cannot import services from @bitwarden/auth in the background b/c it brings along the libs/auth/components and introduces angular into the background context which doesn't have access to angular which causes random test failures. So, we must separate out the core services just like the CLI to only bring along the angular agnostic services from core. * PM-4596 - Refactor libs/auth to have angular / common + update all imports per discussion with Matt & Will. Introduced circular dep between PinCryptoService + VaultTimeoutSettingsService + UserVerificationService * PM-4596 - VaultTimeoutSettingsService - Refactor UserVerificationService out of the service and update all service instantiations and tests. The use of the UserVerificationService.hasMasterPassword method no longer needs to be used for backwards compatibility. This resolves the circular dependency between the PinCryptoService, the UserVerificationService, and the VaultTimeoutSettingsService. We will likely refactor the hasMasterPassword method out of the UserVerificationService in the future. * PM-4596 - Update CL tsconfig.libs.json to add new auth/common and auth/angular paths for jslib-services.module imports of pin crypto service to work and for test code coverage to run successfully. * PM-4596 - Address PR feedback * PM-4596 - Update root tsconfig (only used by storybook) to add new libs/auth paths to fix chromatic build pipeline. * PM-4596 - Actually update tsconfig with proper routes to fix storybook * PM-4596 - UserVerificationService - verifyUserByBiometrics - add error handling logic to convert failed or cancelled biometrics verification to a usable boolean * PM-4596 - Add missing await * PM-4596 - (1) Add log service and log to user verification service biometric flow to ensure errors are at least revealed to the console (2) Fix factory missing PinCryptoServiceInitOptions * PM-4596 - Use the correct log service abstraction * PM-4596 - Remove unused types per PR review --------- Co-authored-by: William Martin <contact@willmartian.com>
2024-01-16 20:52:06 +01:00
{
provide: PinCryptoServiceAbstraction,
useValue: mock<PinCryptoServiceAbstraction>(),
},
{
provide: BiometricStateService,
useValue: biometricStateService,
},
],
schemas: [NO_ERRORS_SCHEMA],
}).compileComponents();
fixture = TestBed.createComponent(LockComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
afterEach(() => {
jest.resetAllMocks();
});
describe("ngOnInit", () => {
it("should call super.ngOnInit() once", async () => {
const superNgOnInitSpy = jest.spyOn(BaseLockComponent.prototype, "ngOnInit");
await component.ngOnInit();
expect(superNgOnInitSpy).toHaveBeenCalledTimes(1);
});
it('should set "autoPromptBiometric" to true if "biometricState.promptAutomatically$" resolves to true', async () => {
biometricStateService.promptAutomatically$ = of(true);
await component.ngOnInit();
expect(component["autoPromptBiometric"]).toBe(true);
});
it('should set "autoPromptBiometric" to false if "biometricState.promptAutomatically$" resolves to false', async () => {
biometricStateService.promptAutomatically$ = of(false);
await component.ngOnInit();
expect(component["autoPromptBiometric"]).toBe(false);
});
it('should set "biometricReady" to true if "stateService.getBiometricReady()" resolves to true', async () => {
component["canUseBiometric"] = jest.fn().mockResolvedValue(true);
await component.ngOnInit();
expect(component["biometricReady"]).toBe(true);
});
it('should set "biometricReady" to false if "stateService.getBiometricReady()" resolves to false', async () => {
component["canUseBiometric"] = jest.fn().mockResolvedValue(false);
await component.ngOnInit();
expect(component["biometricReady"]).toBe(false);
});
it("should call displayBiometricUpdateWarning", async () => {
component["displayBiometricUpdateWarning"] = jest.fn();
await component.ngOnInit();
expect(component["displayBiometricUpdateWarning"]).toHaveBeenCalledTimes(1);
});
it("should call delayedAskForBiometric", async () => {
component["delayedAskForBiometric"] = jest.fn();
await component.ngOnInit();
expect(component["delayedAskForBiometric"]).toHaveBeenCalledTimes(1);
expect(component["delayedAskForBiometric"]).toHaveBeenCalledWith(500);
});
it("should call delayedAskForBiometric when queryParams change", async () => {
activatedRouteMock.queryParams = of({ promptBiometric: true });
component["delayedAskForBiometric"] = jest.fn();
await component.ngOnInit();
expect(component["delayedAskForBiometric"]).toHaveBeenCalledTimes(1);
expect(component["delayedAskForBiometric"]).toHaveBeenCalledWith(500);
});
it("should call messagingService.send", async () => {
await component.ngOnInit();
expect(messagingServiceMock.send).toHaveBeenCalledWith("getWindowIsFocused");
});
describe("broadcasterService.subscribe", () => {
it('should call onWindowHidden() when "broadcasterService.subscribe" is called with "windowHidden"', async () => {
component["onWindowHidden"] = jest.fn();
await component.ngOnInit();
broadcasterServiceMock.subscribe.mock.calls[0][1]({ command: "windowHidden" });
expect(component["onWindowHidden"]).toHaveBeenCalledTimes(1);
});
it('should call focusInput() when "broadcasterService.subscribe" is called with "windowIsFocused" is true and deferFocus is false', async () => {
component["focusInput"] = jest.fn();
component["deferFocus"] = null;
await component.ngOnInit();
broadcasterServiceMock.subscribe.mock.calls[0][1]({
command: "windowIsFocused",
windowIsFocused: true,
} as any);
expect(component["deferFocus"]).toBe(false);
expect(component["focusInput"]).toHaveBeenCalledTimes(1);
});
it('should not call focusInput() when "broadcasterService.subscribe" is called with "windowIsFocused" is true and deferFocus is true', async () => {
component["focusInput"] = jest.fn();
component["deferFocus"] = null;
await component.ngOnInit();
broadcasterServiceMock.subscribe.mock.calls[0][1]({
command: "windowIsFocused",
windowIsFocused: false,
} as any);
expect(component["deferFocus"]).toBe(true);
expect(component["focusInput"]).toHaveBeenCalledTimes(0);
});
it('should call focusInput() when "broadcasterService.subscribe" is called with "windowIsFocused" is true and deferFocus is true', async () => {
component["focusInput"] = jest.fn();
component["deferFocus"] = true;
await component.ngOnInit();
broadcasterServiceMock.subscribe.mock.calls[0][1]({
command: "windowIsFocused",
windowIsFocused: true,
} as any);
expect(component["deferFocus"]).toBe(false);
expect(component["focusInput"]).toHaveBeenCalledTimes(1);
});
it('should not call focusInput() when "broadcasterService.subscribe" is called with "windowIsFocused" is false and deferFocus is true', async () => {
component["focusInput"] = jest.fn();
component["deferFocus"] = true;
await component.ngOnInit();
broadcasterServiceMock.subscribe.mock.calls[0][1]({
command: "windowIsFocused",
windowIsFocused: false,
} as any);
expect(component["deferFocus"]).toBe(true);
expect(component["focusInput"]).toHaveBeenCalledTimes(0);
});
});
});
describe("ngOnDestroy", () => {
it("should call super.ngOnDestroy()", () => {
const superNgOnDestroySpy = jest.spyOn(BaseLockComponent.prototype, "ngOnDestroy");
component.ngOnDestroy();
expect(superNgOnDestroySpy).toHaveBeenCalledTimes(1);
});
it("should call broadcasterService.unsubscribe()", () => {
component.ngOnDestroy();
expect(broadcasterServiceMock.unsubscribe).toHaveBeenCalledTimes(1);
});
});
describe("focusInput", () => {
it('should call "focus" on #pin input if pinEnabled is true', () => {
component["pinEnabled"] = true;
global.document.getElementById = jest.fn().mockReturnValue({ focus: jest.fn() });
component["focusInput"]();
expect(global.document.getElementById).toHaveBeenCalledWith("pin");
});
it('should call "focus" on #masterPassword input if pinEnabled is false', () => {
component["pinEnabled"] = false;
global.document.getElementById = jest.fn().mockReturnValue({ focus: jest.fn() });
component["focusInput"]();
expect(global.document.getElementById).toHaveBeenCalledWith("masterPassword");
});
});
describe("delayedAskForBiometric", () => {
beforeEach(() => {
component["supportsBiometric"] = true;
component["autoPromptBiometric"] = true;
});
it('should wait for "delay" milliseconds', fakeAsync(async () => {
const delaySpy = jest.spyOn(global, "setTimeout");
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
component["delayedAskForBiometric"](5000);
tick(4000);
component["biometricAsked"] = false;
tick(1000);
component["biometricAsked"] = true;
expect(delaySpy).toHaveBeenCalledWith(expect.any(Function), 5000);
}));
it('should return; if "params" is defined and "params.promptBiometric" is false', fakeAsync(async () => {
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
component["delayedAskForBiometric"](5000, { promptBiometric: false });
tick(5000);
expect(component["biometricAsked"]).toBe(false);
}));
it('should not return; if "params" is defined and "params.promptBiometric" is true', fakeAsync(async () => {
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
component["delayedAskForBiometric"](5000, { promptBiometric: true });
tick(5000);
expect(component["biometricAsked"]).toBe(true);
}));
it('should not return; if "params" is undefined', fakeAsync(async () => {
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
component["delayedAskForBiometric"](5000);
tick(5000);
expect(component["biometricAsked"]).toBe(true);
}));
it('should return; if "supportsBiometric" is false', fakeAsync(async () => {
component["supportsBiometric"] = false;
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
component["delayedAskForBiometric"](5000);
tick(5000);
expect(component["biometricAsked"]).toBe(false);
}));
it('should return; if "autoPromptBiometric" is false', fakeAsync(async () => {
component["autoPromptBiometric"] = false;
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
component["delayedAskForBiometric"](5000);
tick(5000);
expect(component["biometricAsked"]).toBe(false);
}));
it("should call unlockBiometric() if biometricAsked is false and window is visible", fakeAsync(async () => {
isWindowVisibleMock.mockResolvedValue(true);
component["unlockBiometric"] = jest.fn();
component["biometricAsked"] = false;
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
component["delayedAskForBiometric"](5000);
tick(5000);
expect(component["unlockBiometric"]).toHaveBeenCalledTimes(1);
}));
it("should not call unlockBiometric() if biometricAsked is false and window is not visible", fakeAsync(async () => {
isWindowVisibleMock.mockResolvedValue(false);
component["unlockBiometric"] = jest.fn();
component["biometricAsked"] = false;
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
component["delayedAskForBiometric"](5000);
tick(5000);
expect(component["unlockBiometric"]).toHaveBeenCalledTimes(0);
}));
it("should not call unlockBiometric() if biometricAsked is true", fakeAsync(async () => {
isWindowVisibleMock.mockResolvedValue(true);
component["unlockBiometric"] = jest.fn();
component["biometricAsked"] = true;
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
component["delayedAskForBiometric"](5000);
tick(5000);
expect(component["unlockBiometric"]).toHaveBeenCalledTimes(0);
}));
});
describe("canUseBiometric", () => {
it("should call getUserId() on stateService", async () => {
stateServiceMock.getUserId.mockResolvedValue("userId");
await component["canUseBiometric"]();
expect(ipc.platform.biometric.enabled).toHaveBeenCalledWith("userId");
});
});
it('onWindowHidden() should set "showPassword" to false', () => {
component["showPassword"] = true;
component["onWindowHidden"]();
expect(component["showPassword"]).toBe(false);
});
});