mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Fix stuff happening based on timers not being run correctly in unit tests (#5764)
* Introduce helper for advancing fake time Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Introduce reactive now to kludge around global shared state in library Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Replace all usages of "now" from mobx-utils with our own kludge to get rid of shared global state between unit tests Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Consolidate all usages of advanceTimersByTime to make sure things happening based on timers are run correctly Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Fix incorrect expect in test Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Enable skipped unit test since prerequisites are done Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
parent
3480b517c1
commit
5f57213179
@ -18,6 +18,7 @@ import downloadPlatformUpdateInjectable from "../../main/application-update/down
|
|||||||
import quitAndInstallUpdateInjectable from "../../main/application-update/quit-and-install-update.injectable";
|
import quitAndInstallUpdateInjectable from "../../main/application-update/quit-and-install-update.injectable";
|
||||||
import appVersionInjectable from "../../common/get-configuration-file-model/app-version/app-version.injectable";
|
import appVersionInjectable from "../../common/get-configuration-file-model/app-version/app-version.injectable";
|
||||||
import periodicalCheckForUpdatesInjectable from "../../main/application-update/periodical-check-for-updates/periodical-check-for-updates.injectable";
|
import periodicalCheckForUpdatesInjectable from "../../main/application-update/periodical-check-for-updates/periodical-check-for-updates.injectable";
|
||||||
|
import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time";
|
||||||
|
|
||||||
describe("analytics for installing update", () => {
|
describe("analytics for installing update", () => {
|
||||||
let applicationBuilder: ApplicationBuilder;
|
let applicationBuilder: ApplicationBuilder;
|
||||||
@ -27,9 +28,7 @@ describe("analytics for installing update", () => {
|
|||||||
let mainDi: DiContainer;
|
let mainDi: DiContainer;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
jest.useFakeTimers();
|
useFakeTime("2015-10-21T07:28:00Z");
|
||||||
|
|
||||||
global.Date.now = () => new Date("2015-10-21T07:28:00Z").getTime();
|
|
||||||
|
|
||||||
applicationBuilder = getApplicationBuilder();
|
applicationBuilder = getApplicationBuilder();
|
||||||
|
|
||||||
@ -84,14 +83,14 @@ describe("analytics for installing update", () => {
|
|||||||
it("when enough time passes to check for updates again, sends event to analytics for being checked periodically", () => {
|
it("when enough time passes to check for updates again, sends event to analytics for being checked periodically", () => {
|
||||||
analyticsListenerMock.mockClear();
|
analyticsListenerMock.mockClear();
|
||||||
|
|
||||||
jest.advanceTimersByTime(1000 * 60 * 60 * 2);
|
advanceFakeTime(1000 * 60 * 60 * 2);
|
||||||
|
|
||||||
expect(analyticsListenerMock).toHaveBeenCalledWith({
|
expect(analyticsListenerMock).toHaveBeenCalledWith({
|
||||||
name: "app",
|
name: "app",
|
||||||
action: "checking-for-updates",
|
action: "checking-for-updates",
|
||||||
|
|
||||||
params: {
|
params: {
|
||||||
currentDateTime: "2015-10-21T07:28:00Z",
|
currentDateTime: "2015-10-21T09:28:00Z",
|
||||||
source: "periodic",
|
source: "periodic",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/ge
|
|||||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||||
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
|
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
|
||||||
import quitAndInstallUpdateInjectable from "../../main/application-update/quit-and-install-update.injectable";
|
import quitAndInstallUpdateInjectable from "../../main/application-update/quit-and-install-update.injectable";
|
||||||
|
import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time";
|
||||||
|
|
||||||
function daysToMilliseconds(days: number) {
|
function daysToMilliseconds(days: number) {
|
||||||
return Math.round(days * 24 * 60 * 60 * 1000);
|
return Math.round(days * 24 * 60 * 60 * 1000);
|
||||||
@ -28,7 +29,7 @@ describe("encourage user to update when sufficient time passed since update was
|
|||||||
let quitAndInstallUpdateMock: jest.MockedFunction<() => void>;
|
let quitAndInstallUpdateMock: jest.MockedFunction<() => void>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.useFakeTimers();
|
useFakeTime("2015-10-21T07:28:00Z");
|
||||||
|
|
||||||
applicationBuilder = getApplicationBuilder();
|
applicationBuilder = getApplicationBuilder();
|
||||||
|
|
||||||
@ -128,13 +129,13 @@ describe("encourage user to update when sufficient time passed since update was
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("given just enough time passes for medium update encouragement, has medium emotional indication in the button", () => {
|
it("given just enough time passes for medium update encouragement, has medium emotional indication in the button", () => {
|
||||||
jest.advanceTimersByTime(daysToMilliseconds(22));
|
advanceFakeTime(daysToMilliseconds(22));
|
||||||
|
|
||||||
expect(button).toHaveAttribute("data-warning-level", "medium");
|
expect(button).toHaveAttribute("data-warning-level", "medium");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("given just enough time passes for severe update encouragement, has severe emotional indication in the button", () => {
|
it("given just enough time passes for severe update encouragement, has severe emotional indication in the button", () => {
|
||||||
jest.advanceTimersByTime(daysToMilliseconds(26));
|
advanceFakeTime(daysToMilliseconds(26));
|
||||||
|
|
||||||
expect(button).toHaveAttribute("data-warning-level", "high");
|
expect(button).toHaveAttribute("data-warning-level", "high");
|
||||||
});
|
});
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import type { DownloadPlatformUpdate } from "../../main/application-update/downl
|
|||||||
import downloadPlatformUpdateInjectable from "../../main/application-update/download-platform-update/download-platform-update.injectable";
|
import downloadPlatformUpdateInjectable from "../../main/application-update/download-platform-update/download-platform-update.injectable";
|
||||||
import setUpdateOnQuitInjectable from "../../main/electron-app/features/set-update-on-quit.injectable";
|
import setUpdateOnQuitInjectable from "../../main/electron-app/features/set-update-on-quit.injectable";
|
||||||
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
|
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
|
||||||
|
import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time";
|
||||||
|
|
||||||
describe("installing update", () => {
|
describe("installing update", () => {
|
||||||
let applicationBuilder: ApplicationBuilder;
|
let applicationBuilder: ApplicationBuilder;
|
||||||
@ -25,7 +26,7 @@ describe("installing update", () => {
|
|||||||
let setUpdateOnQuitMock: jest.Mock;
|
let setUpdateOnQuitMock: jest.Mock;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.useFakeTimers();
|
useFakeTime("2015-10-21T07:28:00Z");
|
||||||
|
|
||||||
applicationBuilder = getApplicationBuilder();
|
applicationBuilder = getApplicationBuilder();
|
||||||
|
|
||||||
@ -114,8 +115,8 @@ describe("installing update", () => {
|
|||||||
expect(rendered.baseElement).toMatchSnapshot();
|
expect(rendered.baseElement).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip("when 5 seconds elapses, clears the notification to the user", () => {
|
it("when 5 seconds elapses, clears the notification to the user", () => {
|
||||||
jest.advanceTimersByTime(6000);
|
advanceFakeTime(6000);
|
||||||
|
|
||||||
expect(rendered.getByTestId("app-update-idle")).toBeInTheDocument();
|
expect(rendered.getByTestId("app-update-idle")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import type { AsyncFnMock } from "@async-fn/jest";
|
|||||||
import asyncFn from "@async-fn/jest";
|
import asyncFn from "@async-fn/jest";
|
||||||
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
|
import processCheckingForUpdatesInjectable from "../../main/application-update/check-for-updates/process-checking-for-updates.injectable";
|
||||||
import periodicalCheckForUpdatesInjectable from "../../main/application-update/periodical-check-for-updates/periodical-check-for-updates.injectable";
|
import periodicalCheckForUpdatesInjectable from "../../main/application-update/periodical-check-for-updates/periodical-check-for-updates.injectable";
|
||||||
|
import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time";
|
||||||
|
|
||||||
const ENOUGH_TIME = 1000 * 60 * 60 * 2;
|
const ENOUGH_TIME = 1000 * 60 * 60 * 2;
|
||||||
|
|
||||||
@ -19,7 +20,7 @@ describe("periodical checking of updates", () => {
|
|||||||
let processCheckingForUpdatesMock: AsyncFnMock<() => Promise<void>>;
|
let processCheckingForUpdatesMock: AsyncFnMock<() => Promise<void>>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.useFakeTimers();
|
useFakeTime("2015-10-21T07:28:00Z");
|
||||||
|
|
||||||
applicationBuilder = getApplicationBuilder();
|
applicationBuilder = getApplicationBuilder();
|
||||||
|
|
||||||
@ -59,7 +60,7 @@ describe("periodical checking of updates", () => {
|
|||||||
it("when just not enough time passes, does not check for updates again automatically yet", () => {
|
it("when just not enough time passes, does not check for updates again automatically yet", () => {
|
||||||
processCheckingForUpdatesMock.mockClear();
|
processCheckingForUpdatesMock.mockClear();
|
||||||
|
|
||||||
jest.advanceTimersByTime(ENOUGH_TIME - 1);
|
advanceFakeTime(ENOUGH_TIME - 1);
|
||||||
|
|
||||||
expect(processCheckingForUpdatesMock).not.toHaveBeenCalled();
|
expect(processCheckingForUpdatesMock).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
@ -67,7 +68,7 @@ describe("periodical checking of updates", () => {
|
|||||||
it("when just enough time passes, checks for updates again automatically", () => {
|
it("when just enough time passes, checks for updates again automatically", () => {
|
||||||
processCheckingForUpdatesMock.mockClear();
|
processCheckingForUpdatesMock.mockClear();
|
||||||
|
|
||||||
jest.advanceTimersByTime(ENOUGH_TIME);
|
advanceFakeTime(ENOUGH_TIME);
|
||||||
|
|
||||||
expect(processCheckingForUpdatesMock).toHaveBeenCalled();
|
expect(processCheckingForUpdatesMock).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import pathExistsInjectable from "../../common/fs/path-exists.injectable";
|
|||||||
import readJsonFileInjectable from "../../common/fs/read-json-file.injectable";
|
import readJsonFileInjectable from "../../common/fs/read-json-file.injectable";
|
||||||
import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token";
|
import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token";
|
||||||
import sidebarStorageInjectable from "../../renderer/components/layout/sidebar-storage/sidebar-storage.injectable";
|
import sidebarStorageInjectable from "../../renderer/components/layout/sidebar-storage/sidebar-storage.injectable";
|
||||||
|
import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time";
|
||||||
|
|
||||||
describe("cluster - sidebar and tab navigation for core", () => {
|
describe("cluster - sidebar and tab navigation for core", () => {
|
||||||
let applicationBuilder: ApplicationBuilder;
|
let applicationBuilder: ApplicationBuilder;
|
||||||
@ -29,7 +30,7 @@ describe("cluster - sidebar and tab navigation for core", () => {
|
|||||||
let rendered: RenderResult;
|
let rendered: RenderResult;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.useFakeTimers();
|
useFakeTime("2015-10-21T07:28:00Z");
|
||||||
|
|
||||||
applicationBuilder = getApplicationBuilder();
|
applicationBuilder = getApplicationBuilder();
|
||||||
rendererDi = applicationBuilder.dis.rendererDi;
|
rendererDi = applicationBuilder.dis.rendererDi;
|
||||||
@ -262,7 +263,7 @@ describe("cluster - sidebar and tab navigation for core", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("when not enough time passes, does not store state for expanded sidebar items to file system yet", async () => {
|
it("when not enough time passes, does not store state for expanded sidebar items to file system yet", async () => {
|
||||||
jest.advanceTimersByTime(250 - 1);
|
advanceFakeTime(250 - 1);
|
||||||
|
|
||||||
const pathExistsFake = rendererDi.inject(pathExistsInjectable);
|
const pathExistsFake = rendererDi.inject(pathExistsInjectable);
|
||||||
|
|
||||||
@ -274,7 +275,7 @@ describe("cluster - sidebar and tab navigation for core", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("when enough time passes, stores state for expanded sidebar items to file system", async () => {
|
it("when enough time passes, stores state for expanded sidebar items to file system", async () => {
|
||||||
jest.advanceTimersByTime(250);
|
advanceFakeTime(250);
|
||||||
|
|
||||||
const readJsonFileFake = rendererDi.inject(readJsonFileInjectable);
|
const readJsonFileFake = rendererDi.inject(readJsonFileInjectable);
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import { navigateToRouteInjectionToken } from "../../common/front-end-routing/na
|
|||||||
import assert from "assert";
|
import assert from "assert";
|
||||||
import type { FakeExtensionData } from "../../renderer/components/test-utils/get-renderer-extension-fake";
|
import type { FakeExtensionData } from "../../renderer/components/test-utils/get-renderer-extension-fake";
|
||||||
import { getRendererExtensionFakeFor } from "../../renderer/components/test-utils/get-renderer-extension-fake";
|
import { getRendererExtensionFakeFor } from "../../renderer/components/test-utils/get-renderer-extension-fake";
|
||||||
|
import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time";
|
||||||
|
|
||||||
describe("cluster - sidebar and tab navigation for extensions", () => {
|
describe("cluster - sidebar and tab navigation for extensions", () => {
|
||||||
let applicationBuilder: ApplicationBuilder;
|
let applicationBuilder: ApplicationBuilder;
|
||||||
@ -25,7 +26,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
|
|||||||
let rendered: RenderResult;
|
let rendered: RenderResult;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.useFakeTimers();
|
useFakeTime("2015-10-21T07:28:00Z");
|
||||||
|
|
||||||
applicationBuilder = getApplicationBuilder();
|
applicationBuilder = getApplicationBuilder();
|
||||||
rendererDi = applicationBuilder.dis.rendererDi;
|
rendererDi = applicationBuilder.dis.rendererDi;
|
||||||
@ -278,7 +279,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("when not enough time passes, does not store state for expanded sidebar items to file system yet", async () => {
|
it("when not enough time passes, does not store state for expanded sidebar items to file system yet", async () => {
|
||||||
jest.advanceTimersByTime(250 - 1);
|
advanceFakeTime(250 - 1);
|
||||||
|
|
||||||
const pathExistsFake = rendererDi.inject(pathExistsInjectable);
|
const pathExistsFake = rendererDi.inject(pathExistsInjectable);
|
||||||
|
|
||||||
@ -290,7 +291,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("when enough time passes, stores state for expanded sidebar items to file system", async () => {
|
it("when enough time passes, stores state for expanded sidebar items to file system", async () => {
|
||||||
jest.advanceTimersByTime(250);
|
advanceFakeTime(250);
|
||||||
|
|
||||||
const readJsonFileFake = rendererDi.inject(readJsonFileInjectable);
|
const readJsonFileFake = rendererDi.inject(readJsonFileInjectable);
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { lensWindowInjectionToken } from "../../main/start-main-application/lens
|
|||||||
import exitAppInjectable from "../../main/electron-app/features/exit-app.injectable";
|
import exitAppInjectable from "../../main/electron-app/features/exit-app.injectable";
|
||||||
import clusterManagerInjectable from "../../main/cluster-manager.injectable";
|
import clusterManagerInjectable from "../../main/cluster-manager.injectable";
|
||||||
import stopServicesAndExitAppInjectable from "../../main/stop-services-and-exit-app.injectable";
|
import stopServicesAndExitAppInjectable from "../../main/stop-services-and-exit-app.injectable";
|
||||||
|
import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time";
|
||||||
|
|
||||||
describe("quitting the app using application menu", () => {
|
describe("quitting the app using application menu", () => {
|
||||||
describe("given application has started", () => {
|
describe("given application has started", () => {
|
||||||
@ -18,7 +19,7 @@ describe("quitting the app using application menu", () => {
|
|||||||
let exitAppMock: jest.Mock;
|
let exitAppMock: jest.Mock;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
jest.useFakeTimers();
|
useFakeTime("2015-10-21T07:28:00Z");
|
||||||
|
|
||||||
applicationBuilder = getApplicationBuilder().beforeApplicationStart(
|
applicationBuilder = getApplicationBuilder().beforeApplicationStart(
|
||||||
({ mainDi }) => {
|
({ mainDi }) => {
|
||||||
@ -71,14 +72,14 @@ describe("quitting the app using application menu", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("after insufficient time passes, does not terminate application yet", () => {
|
it("after insufficient time passes, does not terminate application yet", () => {
|
||||||
jest.advanceTimersByTime(999);
|
advanceFakeTime(999);
|
||||||
|
|
||||||
expect(exitAppMock).not.toHaveBeenCalled();
|
expect(exitAppMock).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("after sufficient time passes", () => {
|
describe("after sufficient time passes", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.advanceTimersByTime(1000);
|
advanceFakeTime(1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("terminates application", () => {
|
it("terminates application", () => {
|
||||||
|
|||||||
25
src/common/test-utils/use-fake-time.ts
Normal file
25
src/common/test-utils/use-fake-time.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { act } from "@testing-library/react";
|
||||||
|
|
||||||
|
let usingFakeTime = false;
|
||||||
|
|
||||||
|
export const advanceFakeTime = (milliseconds: number) => {
|
||||||
|
if (!usingFakeTime) {
|
||||||
|
throw new Error("Tried to advance fake time but it was not enabled. Call useFakeTime() first.");
|
||||||
|
}
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
jest.advanceTimersByTime(milliseconds);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useFakeTime = (dateTime: string) => {
|
||||||
|
usingFakeTime = true;
|
||||||
|
|
||||||
|
jest.useFakeTimers();
|
||||||
|
|
||||||
|
jest.setSystemTime(new Date(dateTime));
|
||||||
|
};
|
||||||
70
src/common/utils/reactive-now/reactive-now.test.tsx
Normal file
70
src/common/utils/reactive-now/reactive-now.test.tsx
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import type { RenderResult } from "@testing-library/react";
|
||||||
|
import { render } from "@testing-library/react";
|
||||||
|
import type { IComputedValue } from "mobx";
|
||||||
|
import { computed, observe } from "mobx";
|
||||||
|
import React from "react";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import { advanceFakeTime, useFakeTime } from "../../test-utils/use-fake-time";
|
||||||
|
import { reactiveNow } from "./reactive-now";
|
||||||
|
|
||||||
|
describe("reactiveNow", () => {
|
||||||
|
let someComputed: IComputedValue<boolean>;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
useFakeTime("2015-10-21T07:28:00Z");
|
||||||
|
|
||||||
|
someComputed = computed(() => {
|
||||||
|
const currentTimestamp = reactiveNow();
|
||||||
|
|
||||||
|
return currentTimestamp > new Date("2015-10-21T07:28:00Z").getTime();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("react-context", () => {
|
||||||
|
let rendered: RenderResult;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const TestComponent = observer(
|
||||||
|
({ someComputed }: { someComputed: IComputedValue<boolean> }) => (
|
||||||
|
<div>{someComputed.get() ? "true" : "false"}</div>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
rendered = render(<TestComponent someComputed={someComputed} />);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("given time passes, works", () => {
|
||||||
|
advanceFakeTime(1000);
|
||||||
|
|
||||||
|
expect(rendered.container.textContent).toBe("true");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not share the state from previous test", () => {
|
||||||
|
expect(rendered.container.textContent).toBe("false");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("non-react-context", () => {
|
||||||
|
let actual: boolean;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
observe(someComputed, (changed) => {
|
||||||
|
actual = changed.newValue as boolean;
|
||||||
|
}, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("given time passes, works", () => {
|
||||||
|
advanceFakeTime(1000);
|
||||||
|
|
||||||
|
expect(actual).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not share the state from previous test", () => {
|
||||||
|
expect(actual).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
60
src/common/utils/reactive-now/reactive-now.ts
Normal file
60
src/common/utils/reactive-now/reactive-now.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { _isComputingDerivation } from "mobx";
|
||||||
|
import type { IResource } from "mobx-utils";
|
||||||
|
import { fromResource } from "mobx-utils";
|
||||||
|
|
||||||
|
// Note: This file is copy-pasted from mobx-utils to fix very specific issue.
|
||||||
|
// TODO: Remove this file once https://github.com/mobxjs/mobx-utils/issues/306 is fixed.
|
||||||
|
const tickers: Record<number|string, IResource<number>> = {};
|
||||||
|
|
||||||
|
export function reactiveNow(interval?: number | "frame") {
|
||||||
|
if (interval === void 0) { interval = 1000; }
|
||||||
|
|
||||||
|
if (!_isComputingDerivation()) {
|
||||||
|
// See #40
|
||||||
|
return Date.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: This is the kludge until https://github.com/mobxjs/mobx-utils/issues/306 is fixed
|
||||||
|
const synchronizationIsEnabled = !process.env.JEST_WORKER_ID;
|
||||||
|
|
||||||
|
if (!tickers[interval] || !synchronizationIsEnabled) {
|
||||||
|
if (typeof interval === "number")
|
||||||
|
tickers[interval] = createIntervalTicker(interval);
|
||||||
|
else
|
||||||
|
tickers[interval] = createAnimationFrameTicker();
|
||||||
|
}
|
||||||
|
|
||||||
|
return tickers[interval].current();
|
||||||
|
}
|
||||||
|
|
||||||
|
function createIntervalTicker(interval: number) {
|
||||||
|
let subscriptionHandle: NodeJS.Timer;
|
||||||
|
|
||||||
|
return fromResource(function (sink) {
|
||||||
|
sink(Date.now());
|
||||||
|
subscriptionHandle = setInterval(function () { return sink(Date.now()); }, interval);
|
||||||
|
}, function () {
|
||||||
|
clearInterval(subscriptionHandle);
|
||||||
|
}, Date.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
function createAnimationFrameTicker() {
|
||||||
|
const frameBasedTicker = fromResource(function (sink) {
|
||||||
|
sink(Date.now());
|
||||||
|
|
||||||
|
function scheduleTick() {
|
||||||
|
window.requestAnimationFrame(function () {
|
||||||
|
sink(Date.now());
|
||||||
|
if (frameBasedTicker.isAlive())
|
||||||
|
scheduleTick();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
scheduleTick();
|
||||||
|
}, function () { }, Date.now());
|
||||||
|
|
||||||
|
return frameBasedTicker;
|
||||||
|
}
|
||||||
@ -4,9 +4,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { now } from "mobx-utils";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { formatDuration } from "../../utils";
|
import { formatDuration } from "../../utils";
|
||||||
|
import { reactiveNow } from "../../../common/utils/reactive-now/reactive-now";
|
||||||
|
|
||||||
export interface ReactiveDurationProps {
|
export interface ReactiveDurationProps {
|
||||||
timestamp: string | undefined;
|
timestamp: string | undefined;
|
||||||
@ -42,7 +42,7 @@ export const ReactiveDuration = observer(({ timestamp, compact = true }: Reactiv
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{formatDuration(now(computeUpdateInterval(timestampSeconds)) - timestampSeconds, compact)}
|
{formatDuration(reactiveNow(computeUpdateInterval(timestampSeconds)) - timestampSeconds, compact)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import type { UpdateIsBeingDownloaded } from "../../../common/application-update
|
|||||||
import updateIsBeingDownloadedInjectable from "../../../common/application-update/update-is-being-downloaded/update-is-being-downloaded.injectable";
|
import updateIsBeingDownloadedInjectable from "../../../common/application-update/update-is-being-downloaded/update-is-being-downloaded.injectable";
|
||||||
import type { UpdatesAreBeingDiscovered } from "../../../common/application-update/updates-are-being-discovered/updates-are-being-discovered.injectable";
|
import type { UpdatesAreBeingDiscovered } from "../../../common/application-update/updates-are-being-discovered/updates-are-being-discovered.injectable";
|
||||||
import updatesAreBeingDiscoveredInjectable from "../../../common/application-update/updates-are-being-discovered/updates-are-being-discovered.injectable";
|
import updatesAreBeingDiscoveredInjectable from "../../../common/application-update/updates-are-being-discovered/updates-are-being-discovered.injectable";
|
||||||
import { now as reactiveDateNow } from "mobx-utils";
|
import { reactiveNow } from "../../../common/utils/reactive-now/reactive-now";
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
progressOfUpdateDownload: ProgressOfUpdateDownload;
|
progressOfUpdateDownload: ProgressOfUpdateDownload;
|
||||||
@ -32,7 +32,7 @@ interface EndNoteProps {
|
|||||||
const EndNote = observer(({ version, note }: EndNoteProps) => {
|
const EndNote = observer(({ version, note }: EndNoteProps) => {
|
||||||
const [start] = useState(Date.now());
|
const [start] = useState(Date.now());
|
||||||
|
|
||||||
if (start + 5000 <= reactiveDateNow()) {
|
if (start + 5000 <= reactiveNow()) {
|
||||||
return idle();
|
return idle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
*/
|
*/
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import { computed } from "mobx";
|
import { computed } from "mobx";
|
||||||
import { now as reactiveDateNow } from "mobx-utils";
|
|
||||||
import updateDownloadedDateTimeInjectable from "../../../common/application-update/update-downloaded-date-time/update-downloaded-date-time.injectable";
|
import updateDownloadedDateTimeInjectable from "../../../common/application-update/update-downloaded-date-time/update-downloaded-date-time.injectable";
|
||||||
|
import { reactiveNow } from "../../../common/utils/reactive-now/reactive-now";
|
||||||
|
|
||||||
const updateWarningLevelInjectable = getInjectable({
|
const updateWarningLevelInjectable = getInjectable({
|
||||||
id: "update-warning-level",
|
id: "update-warning-level",
|
||||||
@ -23,7 +23,7 @@ const updateWarningLevelInjectable = getInjectable({
|
|||||||
const ONE_DAY = 1000 * 60 * 60 * 24;
|
const ONE_DAY = 1000 * 60 * 60 * 24;
|
||||||
|
|
||||||
const downloadedAtTimestamp = new Date(downloadedAt).getTime();
|
const downloadedAtTimestamp = new Date(downloadedAt).getTime();
|
||||||
const currentDateTimeTimestamp = reactiveDateNow(ONE_DAY);
|
const currentDateTimeTimestamp = reactiveNow(ONE_DAY);
|
||||||
|
|
||||||
const elapsedTime = currentDateTimeTimestamp - downloadedAtTimestamp;
|
const elapsedTime = currentDateTimeTimestamp - downloadedAtTimestamp;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user