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:
parent
1fed6c4be0
commit
3c13fef3d4
@ -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(
|
||||||
|
|||||||
@ -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(
|
||||||
|
|||||||
@ -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");
|
||||||
|
|
||||||
|
|||||||
@ -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),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
26
src/renderer/utils/create-storage/storages-are-ready.ts
Normal file
26
src/renderer/utils/create-storage/storages-are-ready.ts
Normal 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);
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user