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

try and fix behavioural tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-04-20 17:09:11 -04:00
parent 6a93ef0358
commit 27ec0573a3
13 changed files with 141 additions and 176 deletions

View File

@ -21,6 +21,9 @@ 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 { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token";
import { getSidebarItem } from "../utils";
import createStoresAndApisInjectable from "../../renderer/create-stores-apis.injectable";
import sidebarStorageInjectable from "../../renderer/components/layout/sidebar-storage/sidebar-storage.injectable";
describe("cluster - sidebar and tab navigation for core", () => {
let applicationBuilder: ApplicationBuilder;
@ -33,8 +36,8 @@ describe("cluster - sidebar and tab navigation for core", () => {
applicationBuilder = getApplicationBuilder();
rendererDi = applicationBuilder.dis.rendererDi;
rendererDi.override(createStoresAndApisInjectable, () => true);
applicationBuilder.setEnvironmentToClusterFrame();
applicationBuilder.beforeSetups(({ rendererDi }) => {
rendererDi.override(
directoryForLensLocalStorageInjectable,
@ -72,13 +75,13 @@ describe("cluster - sidebar and tab navigation for core", () => {
it("parent is highlighted", () => {
const parent = getSidebarItem(rendered, "some-parent-id");
expect(parent.dataset.isActiveTest).toBe("true");
expect(parent?.dataset.isActiveTest).toBe("true");
});
it("parent sidebar item is not expanded", () => {
const child = getSidebarItem(rendered, "some-child-id");
expect(child).toBe(null);
expect(child).toBeUndefined();
});
it("child page is shown", () => {
@ -101,6 +104,12 @@ describe("cluster - sidebar and tab navigation for core", () => {
},
);
});
applicationBuilder.beforeRender(async ({ rendererDi }) => {
const sidebarStorage = rendererDi.inject(sidebarStorageInjectable);
await sidebarStorage.whenReady;
console.log({ ...sidebarStorage.get() });
});
rendered = await applicationBuilder.render();
});
@ -112,13 +121,13 @@ describe("cluster - sidebar and tab navigation for core", () => {
it("parent sidebar item is not highlighted", () => {
const parent = getSidebarItem(rendered, "some-parent-id");
expect(parent.dataset.isActiveTest).toBe("false");
expect(parent?.dataset.isActiveTest).toBe("false");
});
it("parent sidebar item is expanded", () => {
const child = getSidebarItem(rendered, "some-child-id");
expect(child).not.toBe(null);
expect(child).not.toBeUndefined();
});
});
@ -148,7 +157,7 @@ describe("cluster - sidebar and tab navigation for core", () => {
it("parent sidebar item is not expanded", () => {
const child = getSidebarItem(rendered, "some-child-id");
expect(child).toBe(null);
expect(child).toBeUndefined();
});
});
@ -175,7 +184,7 @@ describe("cluster - sidebar and tab navigation for core", () => {
it("parent sidebar item is not expanded", () => {
const child = getSidebarItem(rendered, "some-child-id");
expect(child).toBe(null);
expect(child).toBeUndefined();
});
});
@ -191,13 +200,13 @@ describe("cluster - sidebar and tab navigation for core", () => {
it("parent sidebar item is not highlighted", () => {
const parent = getSidebarItem(rendered, "some-parent-id");
expect(parent.dataset.isActiveTest).toBe("false");
expect(parent?.dataset.isActiveTest).toBe("false");
});
it("parent sidebar item is not expanded", () => {
const child = getSidebarItem(rendered, "some-child-id");
expect(child).toBe(null);
expect(child).toBeUndefined();
});
describe("when a parent sidebar item is expanded", () => {
@ -216,13 +225,13 @@ describe("cluster - sidebar and tab navigation for core", () => {
it("parent sidebar item is not highlighted", () => {
const parent = getSidebarItem(rendered, "some-parent-id");
expect(parent.dataset.isActiveTest).toBe("false");
expect(parent?.dataset.isActiveTest).toBe("false");
});
it("parent sidebar item is expanded", () => {
const child = getSidebarItem(rendered, "some-child-id");
expect(child).not.toBe(null);
expect(child).not.toBeUndefined();
});
describe("when a child of the parent is selected", () => {
@ -241,13 +250,13 @@ describe("cluster - sidebar and tab navigation for core", () => {
it("parent is highlighted", () => {
const parent = getSidebarItem(rendered, "some-parent-id");
expect(parent.dataset.isActiveTest).toBe("true");
expect(parent?.dataset.isActiveTest).toBe("true");
});
it("child is highlighted", () => {
const child = getSidebarItem(rendered, "some-child-id");
expect(child.dataset.isActiveTest).toBe("true");
expect(child?.dataset.isActiveTest).toBe("true");
});
it("child page is shown", () => {
@ -288,11 +297,6 @@ describe("cluster - sidebar and tab navigation for core", () => {
});
});
const getSidebarItem = (rendered: RenderResult, itemId: string) =>
rendered
.queryAllByTestId("sidebar-item")
.find((x) => x.dataset.idTest === itemId) || null;
const testSidebarItemsInjectable = getInjectable({
id: "some-sidebar-items-injectable",
@ -325,7 +329,7 @@ const testSidebarItemsInjectable = getInjectable({
injectionToken: sidebarItemsInjectionToken,
});
const testRouteInjectable = getInjectable({
const testRouteInjectable = getInjectable({
id: "some-route-injectable-id",
instantiate: () => ({

View File

@ -6,7 +6,7 @@ import React from "react";
import type { RenderResult } from "@testing-library/react";
import { fireEvent } from "@testing-library/react";
import { getRendererExtensionFake } from "../../renderer/components/test-utils/get-renderer-extension-fake";
import type { LensRendererExtension } from "../../extensions/lens-renderer-extension";
import { LensRendererExtension } from "../../extensions/lens-renderer-extension";
import directoryForLensLocalStorageInjectable from "../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable";
import routesInjectable from "../../renderer/routes/routes.injectable";
import { matches } from "lodash/fp";
@ -17,6 +17,8 @@ import pathExistsInjectable from "../../common/fs/path-exists.injectable";
import readJsonFileInjectable from "../../common/fs/read-json-file.injectable";
import type { DiContainer } from "@ogre-tools/injectable";
import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token";
import assert from "assert";
import { getSidebarItem } from "../utils";
describe("cluster - sidebar and tab navigation for extensions", () => {
let applicationBuilder: ApplicationBuilder;
@ -41,9 +43,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
describe("given extension with cluster pages and cluster page menus", () => {
beforeEach(async () => {
const testExtension = getRendererExtensionFake(
extensionStubWithSidebarItems,
);
const testExtension = getRendererExtensionFake(extensionStubWithSidebarItems);
await applicationBuilder.addExtensions(testExtension);
});
@ -51,9 +51,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
describe("given no state for expanded sidebar items exists, and navigated to child sidebar item, when rendered", () => {
beforeEach(async () => {
applicationBuilder.beforeRender(({ rendererDi }) => {
const navigateToRoute = rendererDi.inject(
navigateToRouteInjectionToken,
);
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
const route = rendererDi
.inject(routesInjectable)
@ -64,6 +62,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
}),
);
assert(route);
navigateToRoute(route);
});
@ -80,7 +79,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
"some-extension-id-some-parent-id",
);
expect(parent.dataset.isActiveTest).toBe("true");
expect(parent?.dataset.isActiveTest).toBe("true");
});
it("parent sidebar item is not expanded", () => {
@ -89,7 +88,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
"some-extension-id-some-child-id",
);
expect(child).toBe(null);
expect(child).toBeUndefined();
});
it("child page is shown", () => {
@ -126,7 +125,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
"some-extension-id-some-parent-id",
);
expect(parent.dataset.isActiveTest).toBe("false");
expect(parent?.dataset.isActiveTest).toBe("false");
});
it("parent sidebar item is expanded", () => {
@ -135,7 +134,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
"some-extension-id-some-child-id",
);
expect(child).not.toBe(null);
expect(child).not.toBeUndefined();
});
});
@ -168,7 +167,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
"some-extension-id-some-child-id",
);
expect(child).toBe(null);
expect(child).toBeUndefined();
});
});
@ -198,7 +197,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
"some-extension-id-some-child-id",
);
expect(child).toBe(null);
expect(child).toBeUndefined();
});
});
@ -217,7 +216,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
"some-extension-id-some-parent-id",
);
expect(parent.dataset.isActiveTest).toBe("false");
expect(parent?.dataset.isActiveTest).toBe("false");
});
it("parent sidebar item is not expanded", () => {
@ -226,7 +225,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
"some-extension-id-some-child-id",
);
expect(child).toBe(null);
expect(child).toBeUndefined();
});
describe("when a parent sidebar item is expanded", () => {
@ -248,7 +247,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
"some-extension-id-some-parent-id",
);
expect(parent.dataset.isActiveTest).toBe("false");
expect(parent?.dataset.isActiveTest).toBe("false");
});
it("parent sidebar item is expanded", () => {
@ -257,7 +256,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
"some-extension-id-some-child-id",
);
expect(child).not.toBe(null);
expect(child).not.toBeUndefined();
});
describe("when a child of the parent is selected", () => {
@ -279,7 +278,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
"some-extension-id-some-parent-id",
);
expect(parent.dataset.isActiveTest).toBe("true");
expect(parent?.dataset.isActiveTest).toBe("true");
});
it("child is highlighted", () => {
@ -288,7 +287,7 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
"some-extension-id-some-child-id",
);
expect(child.dataset.isActiveTest).toBe("true");
expect(child?.dataset.isActiveTest).toBe("true");
});
it("child page is shown", () => {
@ -385,10 +384,8 @@ describe("cluster - sidebar and tab navigation for extensions", () => {
});
});
const extensionStubWithSidebarItems: Partial<LensRendererExtension> = {
id: "some-extension-id",
clusterPages: [
const extensionStubWithSidebarItems = new (class extends LensRendererExtension {
clusterPages = [
{
components: {
Page: () => {
@ -396,7 +393,6 @@ const extensionStubWithSidebarItems: Partial<LensRendererExtension> = {
},
},
},
{
id: "some-child-page-id",
@ -404,7 +400,6 @@ const extensionStubWithSidebarItems: Partial<LensRendererExtension> = {
Page: () => <div data-testid="some-child-page">Some child page</div>,
},
},
{
id: "some-other-child-page-id",
@ -414,9 +409,9 @@ const extensionStubWithSidebarItems: Partial<LensRendererExtension> = {
),
},
},
],
];
clusterPageMenus: [
clusterPageMenus = [
{
id: "some-parent-id",
title: "Parent",
@ -433,7 +428,7 @@ const extensionStubWithSidebarItems: Partial<LensRendererExtension> = {
title: "Child 1",
components: {
Icon: null,
Icon: null as never,
},
},
@ -444,13 +439,16 @@ const extensionStubWithSidebarItems: Partial<LensRendererExtension> = {
title: "Child 2",
components: {
Icon: null,
Icon: null as never,
},
},
],
};
const getSidebarItem = (rendered: RenderResult, itemId: string) =>
rendered
.queryAllByTestId("sidebar-item")
.find((x) => x.dataset.idTest === itemId) || null;
];
})({
absolutePath: "/some/absolute/path",
id: "some-extension-id",
isBundled: true,
isCompatible: true,
isEnabled: true,
manifest: null as never,
manifestPath: "/some/manifest/path",
});

View File

@ -14,6 +14,7 @@ import { routeInjectionToken } from "../../common/front-end-routing/route-inject
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
import { navigateToRouteInjectionToken } from "../../common/front-end-routing/navigate-to-route-injection-token";
import { getSidebarItem } from "../utils";
describe("cluster - visibility of sidebar items", () => {
let applicationBuilder: ApplicationBuilder;
@ -43,7 +44,7 @@ describe("cluster - visibility of sidebar items", () => {
it("related sidebar item does not exist", () => {
const item = getSidebarItem(rendered, "some-item-id");
expect(item).toBeNull();
expect(item).toBeUndefined();
});
describe("when kube resource becomes allowed", () => {
@ -58,17 +59,12 @@ describe("cluster - visibility of sidebar items", () => {
it("related sidebar item exists", () => {
const item = getSidebarItem(rendered, "some-item-id");
expect(item).not.toBeNull();
expect(item).not.toBeUndefined();
});
});
});
});
const getSidebarItem = (rendered: RenderResult, itemId: string) =>
rendered
.queryAllByTestId("sidebar-item")
.find((x) => x.dataset.idTest === itemId) || null;
const testRouteInjectable = getInjectable({
id: "some-route-injectable-id",

12
src/behaviours/utils.ts Normal file
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 type { RenderResult } from "@testing-library/react";
export function getSidebarItem(rendered: RenderResult, itemId: string) {
return rendered
.queryAllByTestId("sidebar-item")
.find((x) => x.dataset.idTest === itemId);
}

View File

@ -26,9 +26,7 @@ import { Agent } from "https";
import type { Patch } from "rfc6902";
import assert from "assert";
import type { PartialDeep } from "type-fest";
import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api";
import loggerInjectable from "../logger.injectable";
import type { Logger } from "../logger";
import logger from "../logger";
/**
* The options used for creating a `KubeApi`
@ -330,7 +328,6 @@ export class KubeApi<
protected readonly doCheckPreferredVersion: boolean;
protected readonly fullApiPathname: string;
protected readonly fallbackApiBases: string[] | undefined;
protected readonly logger: Logger;
constructor({
objectConstructor,
@ -345,12 +342,10 @@ export class KubeApi<
assert(request, "request MUST be provided if not in a cluster page frame context");
const { apiBase, apiPrefix, apiGroup, apiVersion, resource } = parseKubeApi(fullApiPathname);
const di = getLegacyGlobalDiForExtensionApi();
assert(kind, "kind MUST be provied either via KubeApiOptions.kind or KubeApiOptions.objectConstructor.kind");
assert(apiPrefix, "apiBase MUST be parsable as a kubeApi selfLink style string");
this.logger = di.inject(loggerInjectable);
this.doCheckPreferredVersion = doCheckPreferredVersion;
this.fallbackApiBases = fallbackApiBases;
this.fullApiPathname = fullApiPathname;
@ -414,7 +409,7 @@ export class KubeApi<
return await this.getLatestApiPrefixGroup();
} catch (error) {
// If valid API wasn't found, log the error and return defaults below
this.logger.error(`[KUBE-API]: ${error}`);
logger.error(`[KUBE-API]: ${error}`);
}
}
@ -679,7 +674,7 @@ export class KubeApi<
const abortController = new WrappedAbortController(opts.abortController);
abortController.signal.addEventListener("abort", () => {
this.logger.info(`[KUBE-API] watch (${watchId}) aborted ${watchUrl}`);
logger.info(`[KUBE-API] watch (${watchId}) aborted ${watchUrl}`);
clearTimeout(timedRetry);
});
@ -690,7 +685,7 @@ export class KubeApi<
timeout: 600_000,
});
this.logger.info(`[KUBE-API] watch (${watchId}) ${retry === true ? "retried" : "started"} ${watchUrl}`);
logger.info(`[KUBE-API] watch (${watchId}) ${retry === true ? "retried" : "started"} ${watchUrl}`);
responsePromise
.then(response => {
@ -698,7 +693,7 @@ export class KubeApi<
let requestRetried = false;
if (!response.ok) {
this.logger.warn(`[KUBE-API] watch (${watchId}) error response ${watchUrl}`, { status: response.status });
logger.warn(`[KUBE-API] watch (${watchId}) error response ${watchUrl}`, { status: response.status });
return callback(null, response);
}
@ -715,7 +710,7 @@ export class KubeApi<
// Close current request
abortController.abort();
this.logger.info(`[KUBE-API] Watch timeout set, but not retried, retrying now`);
logger.info(`[KUBE-API] Watch timeout set, but not retried, retrying now`);
requestRetried = true;
@ -734,7 +729,7 @@ export class KubeApi<
return;
}
this.logger.info(`[KUBE-API] watch (${watchId}) ${eventName} ${watchUrl}`);
logger.info(`[KUBE-API] watch (${watchId}) ${eventName} ${watchUrl}`);
requestRetried = true;
@ -763,7 +758,7 @@ export class KubeApi<
});
})
.catch(error => {
this.logger.error(`[KUBE-API] watch (${watchId}) throwed ${watchUrl}`, error);
logger.error(`[KUBE-API] watch (${watchId}) throwed ${watchUrl}`, error);
callback(null, error);
});

View File

@ -8,7 +8,10 @@
// and to `Renderer`
export { ResourceStack } from "../../common/k8s/resource-stack";
export { apiManager } from "../../common/k8s-api/api-manager";
import apiManagerInjectable from "../../common/k8s-api/api-manager/manager.injectable";
import { asLegacyGlobalForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
export const apiManager = asLegacyGlobalForExtensionApi(apiManagerInjectable);
export {
KubeApi,

View File

@ -5,15 +5,10 @@
import { getInjectable } from "@ogre-tools/injectable";
import { noop } from "lodash/fp";
import { computed } from "mobx";
import type {
SidebarItemRegistration } from "../layout/sidebar-items.injectable";
import {
sidebarItemsInjectionToken,
} from "../layout/sidebar-items.injectable";
import type { SidebarItemRegistration } from "../layout/sidebar-items.injectable";
import { sidebarItemsInjectionToken } from "../layout/sidebar-items.injectable";
import { Icon } from "../icon";
import React from "react";
import crdListRouteInjectable from "../../../common/front-end-routing/routes/cluster/custom-resources/crd-list/crd-list-route.injectable";
import sidebarItemsForDefinitionGroupsInjectable from "./sidebar-items-for-definition-groups.injectable";
import routeIsActiveInjectable from "../../routes/route-is-active.injectable";
@ -26,10 +21,7 @@ const customResourceSidebarItemsInjectable = getInjectable({
const navigateToCrdList = di.inject(navigateToCrdListInjectable);
const crdListRoute = di.inject(crdListRouteInjectable);
const crdListRouteIsActive = di.inject(routeIsActiveInjectable, crdListRoute);
const definitionGroupSidebarItems = di.inject(
sidebarItemsForDefinitionGroupsInjectable,
);
const definitionGroupSidebarItems = di.inject(sidebarItemsForDefinitionGroupsInjectable);
return computed((): SidebarItemRegistration[] => {
const definitionsItem = {
@ -42,12 +34,10 @@ const customResourceSidebarItemsInjectable = getInjectable({
orderNumber: 10,
};
const definitionGroupItems = definitionGroupSidebarItems.get();
const childrenAndGrandChildren = [
const childrenAndGrandChildren = computed(() => [
definitionsItem,
...definitionGroupItems,
];
...definitionGroupSidebarItems.get(),
]);
const parentItem: SidebarItemRegistration = {
id: "custom-resources",
@ -55,11 +45,11 @@ const customResourceSidebarItemsInjectable = getInjectable({
title: "Custom Resources",
getIcon: () => <Icon material="extension" />,
onClick: noop,
isVisible: computed(() => childrenAndGrandChildren.some(item => item.isVisible?.get())),
isVisible: computed(() => childrenAndGrandChildren.get().some(item => item.isVisible?.get())),
orderNumber: 110,
};
return [parentItem, definitionsItem, ...definitionGroupItems];
return [parentItem, definitionsItem, ...definitionGroupSidebarItems.get()];
});
},

View File

@ -69,15 +69,10 @@ class NonInjectedMainLayout extends React.Component<MainLayoutProps & Dependenci
}
}
export const MainLayout = withInjectables<Dependencies, MainLayoutProps>(
NonInjectedMainLayout,
{
getProps: (di, props) => ({
sidebarStorage: di.inject(sidebarStorageInjectable),
...props,
}),
},
);
export const MainLayout = withInjectables<Dependencies, MainLayoutProps>(NonInjectedMainLayout, {
getProps: (di, props) => ({
...props,
sidebarStorage: di.inject(sidebarStorageInjectable),
}),
});

View File

@ -123,13 +123,9 @@ class NonInjectedSidebarItem extends React.Component<
}
}
export const SidebarItem = withInjectables<Dependencies, SidebarItemProps>(
NonInjectedSidebarItem,
{
getProps: (di, props) => ({
sidebarStorage: di.inject(sidebarStorageInjectable),
...props,
}),
},
);
export const SidebarItem = withInjectables<Dependencies, SidebarItemProps>(NonInjectedSidebarItem, {
getProps: (di, props) => ({
...props,
sidebarStorage: di.inject(sidebarStorageInjectable),
}),
});

View File

@ -25,7 +25,6 @@ import type { DiContainer } from "@ogre-tools/injectable";
import clusterStoreInjectable from "../../../common/cluster-store/cluster-store.injectable";
import type { ClusterStore } from "../../../common/cluster-store/cluster-store";
import mainExtensionsInjectable from "../../../extensions/main-extensions.injectable";
import type { LensMainExtension } from "../../../extensions/lens-main-extension";
import currentRouteComponentInjectable from "../../routes/current-route-component.injectable";
import { pipeline } from "@ogre-tools/fp";
import { flatMap, compact, join, get, filter } from "lodash/fp";
@ -91,7 +90,7 @@ export const getApplicationBuilder = () => {
rendererDi.override(subscribeStoresInjectable, () => () => () => {});
const environments: Record<string, Environment> = {
const environments = {
application: {
renderSidebar: () => null,
@ -100,12 +99,12 @@ export const getApplicationBuilder = () => {
"Tried to allow kube resource when environment is not cluster frame.",
);
},
},
} as Environment,
clusterFrame: {
renderSidebar: () => <Sidebar />,
onAllowKubeResource: () => {},
},
} as Environment,
};
let environment = environments.application;
@ -120,7 +119,7 @@ export const getApplicationBuilder = () => {
);
mainDi.override(mainExtensionsInjectable, () =>
computed((): LensMainExtension[] => []),
computed(() => []),
);
let allowedResourcesState: IObservableArray<KubeResource>;
@ -182,9 +181,7 @@ export const getApplicationBuilder = () => {
.map(get("id"));
throw new Error(
`Tried to click navigation item "${id}" which does not exist in preferences. Available IDs are "${availableIds.join(
'", "',
)}"`,
`Tried to click navigation item "${id}" which does not exist in preferences. Available IDs are "${availableIds.join('", "')}"`,
);
}
@ -268,12 +265,8 @@ export const getApplicationBuilder = () => {
await runSetups();
const render = renderFor(rendererDi);
const history = rendererDi.inject(observableHistoryInjectable);
const currentRouteComponent = rendererDi.inject(
currentRouteComponentInjectable,
);
const currentRouteComponent = rendererDi.inject(currentRouteComponentInjectable);
for (const callback of beforeRenderCallbacks) {
await callback(dis);

View File

@ -39,20 +39,21 @@ export const createStorage = ({
}: Dependencies): CreateStorage => (key, defaultValue) => {
const { logPrefix } = StorageHelper;
console.log("createStorage", { key, defaultValue });
if (!storage.initialized) {
storage.initialized = true;
(async () => {
const filePath = getAbsolutePath(directoryForLensLocalStorage, `${hostedClusterId || "app"}.json`);
console.log("reading from", filePath);
try {
storage.data = (await readJsonFile(filePath)) as JsonObject;
}
// eslint-disable-next-line no-empty
catch {}
finally {
} catch {
// do nothing
} finally {
if (!isTestEnv) {
logger.info(`${logPrefix} loading finished for ${filePath}`);
}

View File

@ -4,18 +4,24 @@
*/
// Helper for working with storages (e.g. window.localStorage, NodeJS/file-system, etc.)
import { action, comparer, computed, makeObservable, observable, toJS, when } from "mobx";
import { action, comparer, computed, makeObservable, observable, observe, toJS, when } from "mobx";
import type { Draft } from "immer";
import { produce, isDraft } from "immer";
import { isEqual, isPlainObject } from "lodash";
import logger from "../../main/logger";
export interface StorageChange<T> {
key: string;
value: T | undefined;
oldValue: T | undefined;
}
export interface StorageAdapter<T> {
[metadata: string]: any;
[metadata: string]: unknown;
getItem(key: string): T | Promise<T>;
setItem(key: string, value: T): void;
removeItem(key: string): void;
onChange?(change: { key: string; value: T; oldValue?: T }): void;
onChange?(change: StorageChange<T>): void;
}
export interface StorageHelperOptions<T> {
@ -61,9 +67,8 @@ export class StorageHelper<T> implements StorageLayer<T> {
this.storage = storage;
// TODO: This code uses undocumented MobX internal to criminally permit exotic mutations without encapsulation.
this.data.observe_(({ newValue, oldValue }) => {
this.onChange(newValue as T, oldValue as T);
observe(this.data, (change) => {
this.onChange(change.newValue as T | undefined, change.oldValue as T | undefined);
});
if (autoInit) {
@ -109,7 +114,7 @@ export class StorageHelper<T> implements StorageLayer<T> {
return isEqual(value, this.defaultValue);
}
protected onChange(value: T, oldValue?: T) {
protected onChange(value: T | undefined, oldValue: T | undefined) {
if (!this.initialized) return;
try {

View File

@ -8,46 +8,23 @@ import writeJsonFileInjectable from "../common/fs/write-json-file.injectable";
import readJsonFileInjectable from "../common/fs/read-json-file.injectable";
import pathExistsInjectable from "../common/fs/path-exists.injectable";
type Override = (di: DiContainer) => void;
export const overrideFsWithFakes = (di: DiContainer) => {
const state = new Map();
const readFile = readFileFor(state);
const overrides: Override[] = [
(di) => {
di.override(readFileInjectable, () => readFile);
},
(di) => {
di.override(
writeJsonFileInjectable,
() => (filePath, contents) => {
state.set(filePath, JSON.stringify(contents));
return Promise.resolve();
},
);
},
(di) => {
di.override(readJsonFileInjectable, () => async (filePath: string) => {
const fileContent = await readFile(filePath);
return JSON.parse(fileContent.toString());
});
},
(di) => {
di.override(
pathExistsInjectable,
() => async (filePath: string) => Promise.resolve(state.has(filePath)),
);
},
];
overrides.forEach(callback => callback(di));
di.override(readFileInjectable, () => readFile);
di.override(writeJsonFileInjectable, () => (
async (filePath, contents) => {
state.set(filePath, JSON.stringify(contents));
}
));
di.override(readJsonFileInjectable, () => (
async (filePath: string) => JSON.parse(await readFile(filePath))
));
di.override(pathExistsInjectable, () => (
(filePath: string) => Promise.resolve(state.has(filePath))
));
};
const readFileFor = (state: Map<string, string>) => (filePath: string) => {