1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-03 02:03:53 +00:00

update desktop service tests

This commit is contained in:
rr-bw
2025-11-01 21:44:44 -07:00
parent d503f17dab
commit ed3dea293a
2 changed files with 164 additions and 74 deletions

View File

@@ -85,86 +85,178 @@ describe("DesktopAuthRequestAnsweringService", () => {
expect(pendingAuthRequestsState.add).toHaveBeenCalledWith(userId);
});
it("should send an 'openLoginApproval' message if the desktop window is visible and the user is Unlocked, active, and not required to set/change their master password", async () => {
// Arrange
(global as any).ipc.platform.isWindowVisible.mockResolvedValue(true);
authService.activeAccountStatus$ = of(AuthenticationStatus.Unlocked);
describe("given the user is Unlocked, active, and not required to set/change their master password", () => {
describe("given the Desktop window is visible", () => {
it("should send an 'openLoginApproval' message", async () => {
// Arrange
(global as any).ipc.platform.isWindowVisible.mockResolvedValue(true);
authService.activeAccountStatus$ = of(AuthenticationStatus.Unlocked);
// Act
await sut.receivedPendingAuthRequest(userId, authRequestId);
// Act
await sut.receivedPendingAuthRequest(userId, authRequestId);
// Assert
expect(messagingService.send).toHaveBeenCalledTimes(1);
expect(messagingService.send).toHaveBeenCalledWith("openLoginApproval");
// Assert
expect(messagingService.send).toHaveBeenCalledTimes(1);
expect(messagingService.send).toHaveBeenCalledWith("openLoginApproval");
});
it("should NOT create a system notification", async () => {
// Arrange
(global as any).ipc.platform.isWindowVisible.mockResolvedValue(true);
authService.activeAccountStatus$ = of(AuthenticationStatus.Unlocked);
// Act
await sut.receivedPendingAuthRequest(userId, authRequestId);
// Assert
expect((global as any).ipc.auth.loginRequest).not.toHaveBeenCalled();
});
});
describe("given the Desktop window is NOT visible", () => {
it("should STILL send an 'openLoginApproval' message", async () => {
// Arrange
(global as any).ipc.platform.isWindowVisible.mockResolvedValue(false);
authService.activeAccountStatus$ = of(AuthenticationStatus.Unlocked);
// Act
await sut.receivedPendingAuthRequest(userId, authRequestId);
// Assert
expect(messagingService.send).toHaveBeenCalledTimes(1);
expect(messagingService.send).toHaveBeenCalledWith("openLoginApproval");
});
it("should create a system notification", async () => {
// Arrange
(global as any).ipc.platform.isWindowVisible.mockResolvedValue(false);
authService.activeAccountStatus$ = of(AuthenticationStatus.Unlocked);
// Act
await sut.receivedPendingAuthRequest(userId, authRequestId);
// Assert
expect(i18nService.t).toHaveBeenCalledWith("accountAccessRequested");
expect(i18nService.t).toHaveBeenCalledWith("confirmAccessAttempt", "user@example.com");
expect(i18nService.t).toHaveBeenCalledWith("close");
expect((global as any).ipc.auth.loginRequest).toHaveBeenCalledWith(
"accountAccessRequested",
"confirmAccessAttempt:user@example.com",
"close",
);
});
});
});
it("should not send an 'openLoginApproval' message if the desktop window is not visible", async () => {
(global as any).ipc.platform.isWindowVisible.mockResolvedValue(false);
authService.activeAccountStatus$ = of(AuthenticationStatus.Unlocked);
describe("given the user is Locked", () => {
it("should NOT send an 'openLoginApproval' message", async () => {
// Arrange
(global as any).ipc.platform.isWindowVisible.mockResolvedValue(true);
authService.activeAccountStatus$ = of(AuthenticationStatus.Locked);
// Act
await sut.receivedPendingAuthRequest(userId, authRequestId);
// Act
await sut.receivedPendingAuthRequest(userId, authRequestId);
// Assert
expect(messagingService.send).not.toHaveBeenCalled();
// Assert
expect(messagingService.send).not.toHaveBeenCalled();
});
it("should create a system notification", async () => {
// Arrange
(global as any).ipc.platform.isWindowVisible.mockResolvedValue(true);
authService.activeAccountStatus$ = of(AuthenticationStatus.Locked);
// Act
await sut.receivedPendingAuthRequest(userId, authRequestId);
// Assert
expect((global as any).ipc.auth.loginRequest).toHaveBeenCalledWith(
"accountAccessRequested",
"confirmAccessAttempt:user@example.com",
"close",
);
});
});
it("should create a system notification if the desktop window is not visible", async () => {
// Arrange
(global as any).ipc.platform.isWindowVisible.mockResolvedValue(false);
authService.activeAccountStatus$ = of(AuthenticationStatus.Unlocked);
describe("given the user is NOT the active user", () => {
it("should NOT send an 'openLoginApproval' message", async () => {
// Arrange
const differentUserId = "different-user-id" as UserId;
(global as any).ipc.platform.isWindowVisible.mockResolvedValue(true);
authService.activeAccountStatus$ = of(AuthenticationStatus.Unlocked);
accountService.activeAccount$ = of({
id: differentUserId,
email: "different@example.com",
emailVerified: true,
name: "Different User",
});
// Act
await sut.receivedPendingAuthRequest(userId, authRequestId);
// Act
await sut.receivedPendingAuthRequest(userId, authRequestId);
// Assert
expect(i18nService.t).toHaveBeenCalledWith("accountAccessRequested");
expect(i18nService.t).toHaveBeenCalledWith("confirmAccessAttempt", "user@example.com");
expect(i18nService.t).toHaveBeenCalledWith("close");
// Assert
expect(messagingService.send).not.toHaveBeenCalled();
});
expect((global as any).ipc.auth.loginRequest).toHaveBeenCalledWith(
"accountAccessRequested",
"confirmAccessAttempt:user@example.com",
"close",
);
it("should create a system notification", async () => {
// Arrange
const differentUserId = "different-user-id" as UserId;
(global as any).ipc.platform.isWindowVisible.mockResolvedValue(true);
authService.activeAccountStatus$ = of(AuthenticationStatus.Unlocked);
accountService.activeAccount$ = of({
id: differentUserId,
email: "different@example.com",
emailVerified: true,
name: "Different User",
});
// Act
await sut.receivedPendingAuthRequest(userId, authRequestId);
// Assert
expect((global as any).ipc.auth.loginRequest).toHaveBeenCalledWith(
"accountAccessRequested",
"confirmAccessAttempt:user@example.com",
"close",
);
});
});
it("should not create a system notification if the desktop window is visible and the user is Unlocked, active, and not required to set/change their master password", async () => {
// Arrange
(global as any).ipc.platform.isWindowVisible.mockResolvedValue(true);
authService.activeAccountStatus$ = of(AuthenticationStatus.Unlocked);
describe("given the user is required to set/change their master password", () => {
it("should NOT send an 'openLoginApproval' message", async () => {
// Arrange
(global as any).ipc.platform.isWindowVisible.mockResolvedValue(true);
authService.activeAccountStatus$ = of(AuthenticationStatus.Unlocked);
masterPasswordService.forceSetPasswordReason$ = jest
.fn()
.mockReturnValue(of(ForceSetPasswordReason.WeakMasterPassword));
// Act
await sut.receivedPendingAuthRequest(userId, authRequestId);
// Act
await sut.receivedPendingAuthRequest(userId, authRequestId);
// Assert
expect((global as any).ipc.auth.loginRequest).not.toHaveBeenCalled();
});
});
// Assert
expect(messagingService.send).not.toHaveBeenCalled();
});
describe("userMeetsConditionsToShowApprovalDialog()", () => {
it("should return true if desktop window is visible and user is Unlocked, active, and not required to set/change their master password", async () => {
// Arrange
(global as any).ipc.platform.isWindowVisible.mockResolvedValue(true);
authService.activeAccountStatus$ = of(AuthenticationStatus.Unlocked);
it("should create a system notification", async () => {
// Arrange
(global as any).ipc.platform.isWindowVisible.mockResolvedValue(true);
authService.activeAccountStatus$ = of(AuthenticationStatus.Unlocked);
masterPasswordService.forceSetPasswordReason$ = jest
.fn()
.mockReturnValue(of(ForceSetPasswordReason.WeakMasterPassword));
// Act
const result = await sut.userMeetsConditionsToShowApprovalDialog(userId);
// Act
await sut.receivedPendingAuthRequest(userId, authRequestId);
// Assert
expect(result).toBe(true);
});
it("should return false if desktop window is not visible", async () => {
// Arrange
(global as any).ipc.platform.isWindowVisible.mockResolvedValue(false);
authService.activeAccountStatus$ = of(AuthenticationStatus.Unlocked);
// Act
const result = await sut.userMeetsConditionsToShowApprovalDialog(userId);
// Assert
expect(result).toBe(false);
// Assert
expect((global as any).ipc.auth.loginRequest).toHaveBeenCalledWith(
"accountAccessRequested",
"confirmAccessAttempt:user@example.com",
"close",
);
});
});
});

View File

@@ -47,8 +47,16 @@ export class DesktopAuthRequestAnsweringService
if (userIsAvailableToViewDialog) {
// Send message to open dialog immediately for this request
this.messagingService.send("openLoginApproval");
} else {
// Create a system notification
}
const isWindowVisible = await ipc.platform.isWindowVisible();
// Create a system notification if either of the following are true:
// - User does NOT meet conditions to show dialog
// - User does meet conditions, but the Desktop window is not visible
// - In this second case, we both send the "openLoginApproval" message (above) AND
// also create the system notification to notify the user that the dialog is there.
if (!userIsAvailableToViewDialog || !isWindowVisible) {
const accounts = await firstValueFrom(this.accountService.accounts$);
const emailForUser = accounts[userId].email;
await ipc.auth.loginRequest(
@@ -59,16 +67,6 @@ export class DesktopAuthRequestAnsweringService
}
}
async userMeetsConditionsToShowApprovalDialog(userId: UserId): Promise<boolean> {
const meetsBasicConditions = await super.userMeetsConditionsToShowApprovalDialog(userId);
// To show an approval dialog immediately on Desktop, the window must be open.
const isWindowVisible = await ipc.platform.isWindowVisible();
const meetsDesktopConditions = meetsBasicConditions && isWindowVisible;
return meetsDesktopConditions;
}
async handleAuthRequestNotificationClicked(event: SystemNotificationEvent) {
// Not implemented for Desktop because click handling is already setup in electron-main-messaging.service.ts.
// See click handler in ipcMain.handle("loginRequest"...