1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Provide a way to unit test usages of storages

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
Janne Savolainen 2022-07-18 15:03:30 +03:00
parent 1fed6c4be0
commit 3c13fef3d4
No known key found for this signature in database
GPG Key ID: 8C6CFB2FFFE8F68A
7 changed files with 49 additions and 39 deletions

View File

@ -18,12 +18,10 @@ import { frontEndRouteInjectionToken } from "../../common/front-end-routing/fron
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import writeJsonFileInjectable from "../../common/fs/write-json-file.injectable"; import writeJsonFileInjectable from "../../common/fs/write-json-file.injectable";
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 hostedClusterIdInjectable from "../../renderer/cluster-frame-context/hosted-cluster-id.injectable"; import hostedClusterIdInjectable from "../../renderer/cluster-frame-context/hosted-cluster-id.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;
@ -31,8 +29,6 @@ describe("cluster - sidebar and tab navigation for core", () => {
let rendered: RenderResult; let rendered: RenderResult;
beforeEach(() => { beforeEach(() => {
useFakeTime("2015-10-21T07:28:00Z");
applicationBuilder = getApplicationBuilder(); applicationBuilder = getApplicationBuilder();
rendererDi = applicationBuilder.dis.rendererDi; rendererDi = applicationBuilder.dis.rendererDi;
@ -265,21 +261,7 @@ describe("cluster - sidebar and tab navigation for core", () => {
expect(rendered.getByTestId("some-child-page")).not.toBeNull(); expect(rendered.getByTestId("some-child-page")).not.toBeNull();
}); });
it("when not enough time passes, does not store state for expanded sidebar items to file system yet", async () => { it("stores state for expanded sidebar items to file system", async () => {
advanceFakeTime(250 - 1);
const pathExistsFake = rendererDi.inject(pathExistsInjectable);
const actual = await pathExistsFake(
"/some-directory-for-lens-local-storage/some-hosted-cluster-id.json",
);
expect(actual).toBe(false);
});
it("when enough time passes, stores state for expanded sidebar items to file system", async () => {
advanceFakeTime(250);
const readJsonFileFake = rendererDi.inject(readJsonFileInjectable); const readJsonFileFake = rendererDi.inject(readJsonFileInjectable);
const actual = await readJsonFileFake( const actual = await readJsonFileFake(

View File

@ -11,13 +11,11 @@ import { matches } from "lodash/fp";
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import writeJsonFileInjectable from "../../common/fs/write-json-file.injectable"; import writeJsonFileInjectable from "../../common/fs/write-json-file.injectable";
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 type { DiContainer } from "@ogre-tools/injectable"; import type { DiContainer } from "@ogre-tools/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 assert from "assert"; import assert from "assert";
import hostedClusterIdInjectable from "../../renderer/cluster-frame-context/hosted-cluster-id.injectable"; import hostedClusterIdInjectable from "../../renderer/cluster-frame-context/hosted-cluster-id.injectable";
import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time";
import { getExtensionFakeFor } from "../../renderer/components/test-utils/get-extension-fake"; import { getExtensionFakeFor } from "../../renderer/components/test-utils/get-extension-fake";
import type { IObservableValue } from "mobx"; import type { IObservableValue } from "mobx";
import { runInAction, computed, observable } from "mobx"; import { runInAction, computed, observable } from "mobx";
@ -33,8 +31,6 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
let rendered: RenderResult; let rendered: RenderResult;
beforeEach(() => { beforeEach(() => {
useFakeTime("2015-10-21T07:28:00Z");
applicationBuilder = getApplicationBuilder(); applicationBuilder = getApplicationBuilder();
rendererDi = applicationBuilder.dis.rendererDi; rendererDi = applicationBuilder.dis.rendererDi;
@ -386,21 +382,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
expect(tabLink.dataset.isActiveTest).toBe("false"); expect(tabLink.dataset.isActiveTest).toBe("false");
}); });
it("when not enough time passes, does not store state for expanded sidebar items to file system yet", async () => { it("stores state for expanded sidebar items to file system", async () => {
advanceFakeTime(250 - 1);
const pathExistsFake = rendererDi.inject(pathExistsInjectable);
const actual = await pathExistsFake(
"/some-directory-for-lens-local-storage/some-hosted-cluster-id.json",
);
expect(actual).toBe(false);
});
it("when enough time passes, stores state for expanded sidebar items to file system", async () => {
advanceFakeTime(250);
const readJsonFileFake = rendererDi.inject(readJsonFileInjectable); const readJsonFileFake = rendererDi.inject(readJsonFileInjectable);
const actual = await readJsonFileFake( const actual = await readJsonFileFake(

View File

@ -72,6 +72,7 @@ import { asyncComputed } from "@ogre-tools/injectable-react";
import forceUpdateModalRootFrameComponentInjectable from "./application-update/force-update-modal/force-update-modal-root-frame-component.injectable"; import forceUpdateModalRootFrameComponentInjectable from "./application-update/force-update-modal/force-update-modal-root-frame-component.injectable";
import legacyOnChannelListenInjectable from "./ipc/legacy-channel-listen.injectable"; import legacyOnChannelListenInjectable from "./ipc/legacy-channel-listen.injectable";
import getEntitySettingCommandsInjectable from "./components/command-palette/registered-commands/get-entity-setting-commands.injectable"; import getEntitySettingCommandsInjectable from "./components/command-palette/registered-commands/get-entity-setting-commands.injectable";
import storageSaveDelayInjectable from "./utils/create-storage/storage-save-delay.injectable";
export const getDiForUnitTesting = (opts: { doGeneralOverrides?: boolean } = {}) => { export const getDiForUnitTesting = (opts: { doGeneralOverrides?: boolean } = {}) => {
const { const {
@ -111,6 +112,9 @@ export const getDiForUnitTesting = (opts: { doGeneralOverrides?: boolean } = {})
di.override(historyInjectable, () => createMemoryHistory()); di.override(historyInjectable, () => createMemoryHistory());
di.override(legacyOnChannelListenInjectable, () => () => noop); di.override(legacyOnChannelListenInjectable, () => () => noop);
di.override(storageSaveDelayInjectable, () => 0);
di.override(requestAnimationFrameInjectable, () => (callback) => callback()); di.override(requestAnimationFrameInjectable, () => (callback) => callback());
di.override(lensResourcesDirInjectable, () => "/irrelevant"); di.override(lensResourcesDirInjectable, () => "/irrelevant");

View File

@ -11,6 +11,7 @@ import { observable } from "mobx";
import loggerInjectable from "../../../common/logger.injectable"; import loggerInjectable from "../../../common/logger.injectable";
import getAbsolutePathInjectable from "../../../common/path/get-absolute-path.injectable"; import getAbsolutePathInjectable from "../../../common/path/get-absolute-path.injectable";
import hostedClusterIdInjectable from "../../cluster-frame-context/hosted-cluster-id.injectable"; import hostedClusterIdInjectable from "../../cluster-frame-context/hosted-cluster-id.injectable";
import storageSaveDelayInjectable from "./storage-save-delay.injectable";
const createStorageInjectable = getInjectable({ const createStorageInjectable = getInjectable({
id: "create-storage", id: "create-storage",
@ -27,6 +28,7 @@ const createStorageInjectable = getInjectable({
directoryForLensLocalStorage: di.inject(directoryForLensLocalStorageInjectable), directoryForLensLocalStorage: di.inject(directoryForLensLocalStorageInjectable),
getAbsolutePath: di.inject(getAbsolutePathInjectable), getAbsolutePath: di.inject(getAbsolutePathInjectable),
hostedClusterId: di.inject(hostedClusterIdInjectable), hostedClusterId: di.inject(hostedClusterIdInjectable),
saveDelay: di.inject(storageSaveDelayInjectable),
}), }),
}); });

View File

@ -21,6 +21,7 @@ interface Dependencies {
writeJsonFile: (filePath: string, contentObject: JsonObject) => Promise<void>; writeJsonFile: (filePath: string, contentObject: JsonObject) => Promise<void>;
getAbsolutePath: GetAbsolutePath; getAbsolutePath: GetAbsolutePath;
hostedClusterId: string | undefined; hostedClusterId: string | undefined;
saveDelay: number;
} }
export type CreateStorage = <T>(key: string, defaultValue: T) => StorageLayer<T>; export type CreateStorage = <T>(key: string, defaultValue: T) => StorageLayer<T>;
@ -36,6 +37,7 @@ export const createStorage = ({
readJsonFile, readJsonFile,
writeJsonFile, writeJsonFile,
hostedClusterId, hostedClusterId,
saveDelay,
}: Dependencies): CreateStorage => (key, defaultValue) => { }: Dependencies): CreateStorage => (key, defaultValue) => {
const { logPrefix } = StorageHelper; const { logPrefix } = StorageHelper;
@ -59,7 +61,7 @@ export const createStorage = ({
// bind auto-saving data changes to %storage-file.json // bind auto-saving data changes to %storage-file.json
reaction(() => toJS(storage.data), saveFile, { reaction(() => toJS(storage.data), saveFile, {
delay: 250, // lazy, avoid excessive writes to fs delay: saveDelay, // lazy, avoid excessive writes to fs
equals: comparer.structural, // save only when something really changed equals: comparer.structural, // save only when something really changed
}); });

View File

@ -0,0 +1,12 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
const storageSaveDelayInjectable = getInjectable({
id: "storage-save-delay",
instantiate: () => 250,
});
export default storageSaveDelayInjectable;

View File

@ -0,0 +1,26 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { DiContainer } from "@ogre-tools/injectable";
import type { CreateStorage } from "./create-storage";
import createStorageInjectable from "./create-storage.injectable";
export const controlWhenStoragesAreReady = (di: DiContainer) => {
const storagesAreReady: Promise<void>[] = [];
const decorated =
(toBeDecorated: CreateStorage) =>
(key: string, defaultValue: any) => {
const storage = toBeDecorated(key, defaultValue);
storagesAreReady.push(storage.whenReady);
return storage;
};
// TODO: Remove when typing is added to the library
(di as any).decorateFunction(createStorageInjectable, decorated);
return async () => void await Promise.all(storagesAreReady);
};