mirror of
https://github.com/bitwarden/browser.git
synced 2024-09-18 02:41:15 +02:00
[PM-6426] Working through jest tests
This commit is contained in:
parent
e82a52961b
commit
8117068379
@ -6,6 +6,8 @@ import { ConsoleLogService } from "@bitwarden/common/platform/services/console-l
|
|||||||
import { GlobalState, StateProvider } from "@bitwarden/common/platform/state";
|
import { GlobalState, StateProvider } from "@bitwarden/common/platform/state";
|
||||||
import { UserId } from "@bitwarden/common/types/guid";
|
import { UserId } from "@bitwarden/common/types/guid";
|
||||||
|
|
||||||
|
import { flushPromises } from "../../autofill/spec/testing-utils";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ActiveAlarm,
|
ActiveAlarm,
|
||||||
BrowserTaskSchedulerService,
|
BrowserTaskSchedulerService,
|
||||||
@ -20,10 +22,29 @@ jest.mock("rxjs", () => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function setupGlobalBrowserMock(overrides: Partial<chrome.alarms.Alarm> = {}) {
|
||||||
|
globalThis.browser.alarms = {
|
||||||
|
create: jest.fn(),
|
||||||
|
clear: jest.fn(),
|
||||||
|
get: jest.fn(),
|
||||||
|
getAll: jest.fn(),
|
||||||
|
clearAll: jest.fn(),
|
||||||
|
onAlarm: {
|
||||||
|
addListener: jest.fn(),
|
||||||
|
removeListener: jest.fn(),
|
||||||
|
hasListener: jest.fn(),
|
||||||
|
},
|
||||||
|
...overrides,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const userUuid = "user-uuid" as UserId;
|
||||||
|
function getAlarmNameMock(taskName: string) {
|
||||||
|
return `${userUuid}__${taskName}`;
|
||||||
|
}
|
||||||
|
|
||||||
describe("BrowserTaskSchedulerService", () => {
|
describe("BrowserTaskSchedulerService", () => {
|
||||||
const callback = jest.fn();
|
const callback = jest.fn();
|
||||||
const delayInMinutes = 2;
|
const delayInMinutes = 2;
|
||||||
const userUuid = "user-uuid" as UserId;
|
|
||||||
let activeUserIdMock$: BehaviorSubject<UserId>;
|
let activeUserIdMock$: BehaviorSubject<UserId>;
|
||||||
let activeAlarmsMock$: BehaviorSubject<ActiveAlarm[]>;
|
let activeAlarmsMock$: BehaviorSubject<ActiveAlarm[]>;
|
||||||
let logService: MockProxy<ConsoleLogService>;
|
let logService: MockProxy<ConsoleLogService>;
|
||||||
@ -71,12 +92,17 @@ describe("BrowserTaskSchedulerService", () => {
|
|||||||
ScheduledTaskNames.loginStrategySessionTimeout,
|
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||||
callback,
|
callback,
|
||||||
);
|
);
|
||||||
|
// @ts-expect-error mocking global browser object
|
||||||
|
// eslint-disable-next-line no-global-assign
|
||||||
|
globalThis.browser = {};
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
jest.clearAllTimers();
|
jest.clearAllTimers();
|
||||||
jest.useRealTimers();
|
jest.useRealTimers();
|
||||||
|
// eslint-disable-next-line no-global-assign
|
||||||
|
globalThis.browser = undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("setTimeout", () => {
|
describe("setTimeout", () => {
|
||||||
@ -87,7 +113,7 @@ describe("BrowserTaskSchedulerService", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(chrome.alarms.create).toHaveBeenCalledWith(
|
expect(chrome.alarms.create).toHaveBeenCalledWith(
|
||||||
`${userUuid}__${ScheduledTaskNames.loginStrategySessionTimeout}`,
|
getAlarmNameMock(ScheduledTaskNames.loginStrategySessionTimeout),
|
||||||
{ delayInMinutes },
|
{ delayInMinutes },
|
||||||
expect.any(Function),
|
expect.any(Function),
|
||||||
);
|
);
|
||||||
@ -126,19 +152,100 @@ describe("BrowserTaskSchedulerService", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("uses the global setTimeout API if the delay is less than 1000ms", async () => {
|
it("creates an alarm that is not associated with a user", async () => {
|
||||||
const delayInMs = 15000;
|
activeUserIdMock$.next(undefined);
|
||||||
jest.spyOn(globalThis, "setTimeout");
|
chrome.alarms.get = jest.fn().mockImplementation((_name, callback) => callback(undefined));
|
||||||
|
|
||||||
|
await browserTaskSchedulerService.setTimeout(
|
||||||
|
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||||
|
delayInMinutes * 60 * 1000,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(chrome.alarms.create).toHaveBeenCalledWith(
|
||||||
|
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||||
|
{ delayInMinutes },
|
||||||
|
expect.any(Function),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when the task is scheduled to be triggered in less than 1 minute", () => {
|
||||||
|
const delayInMs = 45000;
|
||||||
|
|
||||||
|
it("sets a timeout using the global setTimeout API", async () => {
|
||||||
|
jest.spyOn(globalThis, "setTimeout");
|
||||||
|
|
||||||
|
await browserTaskSchedulerService.setTimeout(
|
||||||
|
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||||
|
delayInMs,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(globalThis.setTimeout).toHaveBeenCalledWith(expect.any(Function), delayInMs);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sets a fallback alarm", async () => {
|
||||||
|
const delayInMs = 15000;
|
||||||
|
await browserTaskSchedulerService.setTimeout(
|
||||||
|
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||||
|
delayInMs,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(chrome.alarms.create).toHaveBeenCalledWith(
|
||||||
|
getAlarmNameMock(ScheduledTaskNames.loginStrategySessionTimeout),
|
||||||
|
{ delayInMinutes: 0.5 },
|
||||||
|
expect.any(Function),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sets the fallback for a minimum of 1 minute if the environment not for Chrome", async () => {
|
||||||
|
setupGlobalBrowserMock();
|
||||||
|
|
||||||
|
await browserTaskSchedulerService.setTimeout(
|
||||||
|
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||||
|
delayInMs,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(browser.alarms.create).toHaveBeenCalledWith(
|
||||||
|
getAlarmNameMock(ScheduledTaskNames.loginStrategySessionTimeout),
|
||||||
|
{ delayInMinutes: 1 },
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("clears the fallback alarm when the setTimeout is triggered", async () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
|
||||||
|
await browserTaskSchedulerService.setTimeout(
|
||||||
|
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||||
|
delayInMs,
|
||||||
|
);
|
||||||
|
jest.advanceTimersByTime(delayInMs);
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(chrome.alarms.clear).toHaveBeenCalledWith(
|
||||||
|
getAlarmNameMock(ScheduledTaskNames.loginStrategySessionTimeout),
|
||||||
|
expect.any(Function),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("triggering a task", () => {
|
||||||
|
it("clears an non user-based alarm if a separate user-based alarm has been set up", async () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
activeUserIdMock$.next(undefined);
|
||||||
|
const delayInMs = 10000;
|
||||||
|
chrome.alarms.get = jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation((_name, callback) => callback(mock<chrome.alarms.Alarm>()));
|
||||||
|
|
||||||
await browserTaskSchedulerService.setTimeout(
|
await browserTaskSchedulerService.setTimeout(
|
||||||
ScheduledTaskNames.loginStrategySessionTimeout,
|
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||||
delayInMs,
|
delayInMs,
|
||||||
);
|
);
|
||||||
|
jest.advanceTimersByTime(delayInMs);
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
expect(globalThis.setTimeout).toHaveBeenCalledWith(expect.any(Function), delayInMs);
|
expect(chrome.alarms.clear).toHaveBeenCalledWith(
|
||||||
expect(chrome.alarms.create).toHaveBeenCalledWith(
|
ScheduledTaskNames.loginStrategySessionTimeout,
|
||||||
`${userUuid}__${ScheduledTaskNames.loginStrategySessionTimeout}`,
|
|
||||||
{ delayInMinutes: 0.5 },
|
|
||||||
expect.any(Function),
|
expect.any(Function),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -152,7 +152,7 @@ export class BrowserTaskSchedulerServiceImplementation
|
|||||||
createInfo.delayInMinutes &&
|
createInfo.delayInMinutes &&
|
||||||
startTime + createInfo.delayInMinutes * 60 * 1000 < currentTime;
|
startTime + createInfo.delayInMinutes * 60 * 1000 < currentTime;
|
||||||
if (shouldAlarmHaveBeenTriggered || hasSetTimeoutAlarmExceededDelay) {
|
if (shouldAlarmHaveBeenTriggered || hasSetTimeoutAlarmExceededDelay) {
|
||||||
await this.triggerRecoveredAlarm(alarmName);
|
await this.triggerTask(alarmName);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,16 +247,6 @@ export class BrowserTaskSchedulerServiceImplementation
|
|||||||
await this.activeAlarmsState.update(() => alarms);
|
await this.activeAlarmsState.update(() => alarms);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Triggers a recovered alarm by deleting it from the recovered alarms set
|
|
||||||
*
|
|
||||||
* @param alarmName - The name of the recovered alarm to trigger.
|
|
||||||
* @param periodInMinutes - The period in minutes of the recovered alarm.
|
|
||||||
*/
|
|
||||||
private async triggerRecoveredAlarm(alarmName: string, periodInMinutes?: number): Promise<void> {
|
|
||||||
await this.triggerTask(alarmName, periodInMinutes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the on alarm listener to handle alarms.
|
* Sets up the on alarm listener to handle alarms.
|
||||||
*/
|
*/
|
||||||
@ -398,7 +388,9 @@ export class BrowserTaskSchedulerServiceImplementation
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the environment is a non-Chrome environment. This is used to determine
|
* Checks if the environment is a non-Chrome environment. This is used to determine
|
||||||
* if the browser alarms API should be used in place of the chrome alarms API.
|
* if the browser alarms API should be used in place of the chrome alarms API. This
|
||||||
|
* is necessary because the `chrome` polyfill that Mozilla implements does not allow
|
||||||
|
* passing the callback parameter in the same way most `chrome.alarm` api calls allow.
|
||||||
*/
|
*/
|
||||||
private isNonChromeEnvironment(): boolean {
|
private isNonChromeEnvironment(): boolean {
|
||||||
return typeof browser !== "undefined" && !!browser.alarms;
|
return typeof browser !== "undefined" && !!browser.alarms;
|
||||||
|
Loading…
Reference in New Issue
Block a user