From 823cab8170548ebfc41d70b4f7e82a163b592647 Mon Sep 17 00:00:00 2001 From: Iku-turso Date: Tue, 26 Apr 2022 10:39:00 +0300 Subject: [PATCH] Make navigating to Helm Charts not blow up Co-authored-by: Janne Savolainen Signed-off-by: Iku-turso --- .../navigation-to-helm-charts.test.ts.snap | 454 ++++++++++++++++++ .../navigation-to-helm-charts.test.ts | 51 ++ src/main/getDiForUnitTesting.ts | 4 + src/main/helm/__tests__/helm-service.test.ts | 16 +- src/main/helm/helm-repo-manager.injectable.ts | 157 +++++- src/main/helm/helm-repo-manager.ts | 154 +----- .../components/+helm-charts/helm-charts.tsx | 2 + .../release-details/release-details.tsx | 10 +- .../components/item-object-list/content.tsx | 44 +- src/renderer/components/select/select.tsx | 25 +- .../test-utils/get-application-builder.tsx | 27 ++ src/renderer/getDiForUnitTesting.tsx | 21 +- 12 files changed, 779 insertions(+), 186 deletions(-) create mode 100644 src/behaviours/helm-charts/__snapshots__/navigation-to-helm-charts.test.ts.snap create mode 100644 src/behaviours/helm-charts/navigation-to-helm-charts.test.ts diff --git a/src/behaviours/helm-charts/__snapshots__/navigation-to-helm-charts.test.ts.snap b/src/behaviours/helm-charts/__snapshots__/navigation-to-helm-charts.test.ts.snap new file mode 100644 index 0000000000..f9aeaeac9c --- /dev/null +++ b/src/behaviours/helm-charts/__snapshots__/navigation-to-helm-charts.test.ts.snap @@ -0,0 +1,454 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`helm-charts - navigation to Helm charts when navigating to Helm charts renders 1`] = ` +
+
+ +
+
+ + +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ Name +
+ + + arrow_drop_down + + +
+
+
+ Description +
+
+
+
+ Version +
+
+
+
+ App Version +
+
+
+
+ Repository +
+ + + arrow_drop_down + + +
+ +
+
+
+
+
+
+
+
+
+`; diff --git a/src/behaviours/helm-charts/navigation-to-helm-charts.test.ts b/src/behaviours/helm-charts/navigation-to-helm-charts.test.ts new file mode 100644 index 0000000000..b6e496381c --- /dev/null +++ b/src/behaviours/helm-charts/navigation-to-helm-charts.test.ts @@ -0,0 +1,51 @@ +/** + * 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 { + ApplicationBuilder, + getApplicationBuilder, +} from "../../renderer/components/test-utils/get-application-builder"; + +describe("helm-charts - navigation to Helm charts", () => { + let applicationBuilder: ApplicationBuilder; + + beforeEach(() => { + applicationBuilder = getApplicationBuilder(); + + // applicationBuilder.beforeSetups(({ rendererDi }) => { + // const userStoreStub = { + // extensionRegistryUrl: { customUrl: "some-custom-url" }, + // } as unknown as UserStore; + // + // rendererDi.override(userStoreInjectable, () => userStoreStub); + // + // const themeStoreStub = ({ themeOptions: [] }) as unknown as ThemeStore; + // + // rendererDi.override(themeStoreInjectable, () => themeStoreStub); + // }); + }); + + describe("when navigating to Helm charts", () => { + let rendered: RenderResult; + + beforeEach(async () => { + applicationBuilder.setEnvironmentToClusterFrame(); + + rendered = await applicationBuilder.render(); + + applicationBuilder.helmCharts.navigate(); + }); + + it("renders", () => { + expect(rendered.container).toMatchSnapshot(); + }); + + it("shows page for Helm charts", () => { + const page = rendered.getByTestId("page-for-helm-charts"); + + expect(page).not.toBeNull(); + }); + }); +}); diff --git a/src/main/getDiForUnitTesting.ts b/src/main/getDiForUnitTesting.ts index 63addb3bbf..7e1a0fa94d 100644 --- a/src/main/getDiForUnitTesting.ts +++ b/src/main/getDiForUnitTesting.ts @@ -66,6 +66,8 @@ import getElectronAppPathInjectable from "./app-paths/get-electron-app-path/get- import setElectronAppPathInjectable from "./app-paths/set-electron-app-path/set-electron-app-path.injectable"; import setupMainWindowVisibilityAfterActivationInjectable from "./electron-app/after-application-is-ready/setup-main-window-visibility-after-activation.injectable"; import setupDeviceShutdownInjectable from "./electron-app/after-application-is-ready/setup-device-shutdown.injectable"; +import setupApplicationNameInjectable from "./electron-app/before-application-is-ready/setup-application-name.injectable"; +import setupRunnablesBeforeClosingOfApplicationInjectable from "./electron-app/before-application-is-ready/setup-runnables-before-closing-of-application.injectable"; export const getDiForUnitTesting = ( { doGeneralOverrides } = { doGeneralOverrides: false }, @@ -195,6 +197,8 @@ const overrideElectronFeatures = (di: DiContainer) => { di.override(setupDeepLinkingInjectable, () => ({ run: () => {} })); di.override(exitAppInjectable, () => () => {}); + di.override(setupApplicationNameInjectable, () => ({ run: () => {} })); + di.override(setupRunnablesBeforeClosingOfApplicationInjectable, () => ({ run: () => {} })); di.override(getCommandLineSwitchInjectable, () => () => "irrelevant"); di.override(requestSingleInstanceLockInjectable, () => () => true); di.override(disableHardwareAccelerationInjectable, () => () => {}); diff --git a/src/main/helm/__tests__/helm-service.test.ts b/src/main/helm/__tests__/helm-service.test.ts index 42c548c4be..d9e6532e5c 100644 --- a/src/main/helm/__tests__/helm-service.test.ts +++ b/src/main/helm/__tests__/helm-service.test.ts @@ -17,14 +17,11 @@ describe("Helm Service tests", () => { it("list charts with deprecated entries", async () => { mockHelmRepoManager.mockReturnValue({ - init: jest.fn(), - repositories: jest.fn().mockImplementation(async () => { - return [ - { name: "stable", url: "stableurl" }, - { name: "experiment", url: "experimenturl" }, - ]; - }), - }); + repositories: jest.fn().mockImplementation(async () => [ + { name: "stable", url: "stableurl" }, + { name: "experiment", url: "experimenturl" }, + ]), + } as any); const charts = await helmService.listCharts(); @@ -127,13 +124,12 @@ describe("Helm Service tests", () => { it("list charts sorted by version in descending order", async () => { mockHelmRepoManager.mockReturnValue({ - init: jest.fn(), repositories: jest.fn().mockImplementation(async () => { return [ { name: "bitnami", url: "bitnamiurl" }, ]; }), - }); + } as any); const charts = await helmService.listCharts(); diff --git a/src/main/helm/helm-repo-manager.injectable.ts b/src/main/helm/helm-repo-manager.injectable.ts index 5b5c5738a3..fa6075e438 100644 --- a/src/main/helm/helm-repo-manager.injectable.ts +++ b/src/main/helm/helm-repo-manager.injectable.ts @@ -3,16 +3,161 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { HelmRepoManager } from "./helm-repo-manager"; + +import yaml from "js-yaml"; +import { readFile } from "fs-extra"; +import { customRequestPromise } from "../../common/request"; +import orderBy from "lodash/orderBy"; +import logger from "../logger"; +import { execHelm } from "./exec"; +import type { HelmEnv, HelmRepo, HelmRepoConfig } from "./helm-repo-manager"; + +class HelmRepoManager { + protected repos: HelmRepo[]; + protected helmEnv: HelmEnv; + protected didUpdateOnce: boolean; + + public async loadAvailableRepos(): Promise { + const res = await customRequestPromise({ + uri: "https://github.com/lensapp/artifact-hub-repositories/releases/download/latest/repositories.json", + json: true, + resolveWithFullResponse: true, + timeout: 10000, + }); + + return orderBy(res.body as HelmRepo[], (repo) => repo.name); + } + + private async ensureInitialized() { + this.helmEnv ??= await this.parseHelmEnv(); + + const repos = await this.list(); + + if (repos.length === 0) { + await this.addRepo({ + name: "bitnami", + url: "https://charts.bitnami.com/bitnami", + }); + } + + if (!this.didUpdateOnce) { + await this.update(); + this.didUpdateOnce = true; + } + } + + protected async parseHelmEnv() { + const output = await execHelm(["env"]); + const lines = output.split(/\r?\n/); // split by new line feed + const env: HelmEnv = {}; + + lines.forEach((line: string) => { + const [key, value] = line.split("="); + + if (key && value) { + env[key] = value.replace(/"/g, ""); // strip quotas + } + }); + + return env; + } + + public async repo(name: string): Promise { + const repos = await this.repositories(); + + return repos.find((repo) => repo.name === name); + } + + private async list(): Promise { + try { + const rawConfig = await readFile( + this.helmEnv.HELM_REPOSITORY_CONFIG, + "utf8", + ); + const parsedConfig = yaml.load(rawConfig) as HelmRepoConfig; + + if (typeof parsedConfig === "object" && parsedConfig) { + return parsedConfig.repositories; + } + } catch { + // ignore error + } + + return []; + } + + public async repositories(): Promise { + try { + await this.ensureInitialized(); + + const repos = await this.list(); + + return repos.map((repo) => ({ + ...repo, + cacheFilePath: `${this.helmEnv.HELM_REPOSITORY_CACHE}/${repo.name}-index.yaml`, + })); + } catch (error) { + logger.error(`[HELM]: repositories listing error`, error); + + return []; + } + } + + public async update() { + return execHelm(["repo", "update"]); + } + + public async addRepo({ + name, + url, + insecureSkipTlsVerify, + username, + password, + caFile, + keyFile, + certFile, + }: HelmRepo) { + logger.info(`[HELM]: adding repo ${name} from ${url}`); + const args = ["repo", "add", name, url]; + + if (insecureSkipTlsVerify) { + args.push("--insecure-skip-tls-verify"); + } + + if (username) { + args.push("--username", username); + } + + if (password) { + args.push("--password", password); + } + + if (caFile) { + args.push("--ca-file", caFile); + } + + if (keyFile) { + args.push("--key-file", keyFile); + } + + if (certFile) { + args.push("--cert-file", certFile); + } + + return execHelm(args); + } + + public async removeRepo({ name, url }: HelmRepo): Promise { + logger.info(`[HELM]: removing repo ${name} (${url})`); + + return execHelm(["repo", "remove", name]); + } +} const helmRepoManagerInjectable = getInjectable({ id: "helm-repo-manager", - instantiate: () => { - HelmRepoManager.resetInstance(); - - return HelmRepoManager.createInstance(); - }, + instantiate: () => new HelmRepoManager(), }); export default helmRepoManagerInjectable; diff --git a/src/main/helm/helm-repo-manager.ts b/src/main/helm/helm-repo-manager.ts index 7f174cfa8e..e7775e5bf0 100644 --- a/src/main/helm/helm-repo-manager.ts +++ b/src/main/helm/helm-repo-manager.ts @@ -3,13 +3,11 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import yaml from "js-yaml"; -import { readFile } from "fs-extra"; -import { Singleton } from "../../common/utils/singleton"; -import { customRequestPromise } from "../../common/request"; -import orderBy from "lodash/orderBy"; -import logger from "../logger"; -import { execHelm } from "./exec"; +import { + asLegacyGlobalSingletonForExtensionApi, +} from "../../extensions/as-legacy-globals-for-extension-api/as-legacy-global-singleton-object-for-extension-api"; + +import helmRepoManagerInjectable from "./helm-repo-manager.injectable"; export type HelmEnv = Record & { HELM_REPOSITORY_CACHE?: string; @@ -32,144 +30,4 @@ export interface HelmRepo { password?: string; } -export class HelmRepoManager extends Singleton { - protected repos: HelmRepo[]; - protected helmEnv: HelmEnv; - protected didUpdateOnce: boolean; - - public async loadAvailableRepos(): Promise { - const res = await customRequestPromise({ - uri: "https://github.com/lensapp/artifact-hub-repositories/releases/download/latest/repositories.json", - json: true, - resolveWithFullResponse: true, - timeout: 10000, - }); - - return orderBy(res.body as HelmRepo[], repo => repo.name); - } - - private async ensureInitialized() { - this.helmEnv ??= await this.parseHelmEnv(); - - const repos = await this.list(); - - if (repos.length === 0) { - await this.addRepo({ - name: "bitnami", - url: "https://charts.bitnami.com/bitnami", - }); - } - - if (!this.didUpdateOnce) { - await this.update(); - this.didUpdateOnce = true; - } - } - - protected async parseHelmEnv() { - const output = await execHelm(["env"]); - const lines = output.split(/\r?\n/); // split by new line feed - const env: HelmEnv = {}; - - lines.forEach((line: string) => { - const [key, value] = line.split("="); - - if (key && value) { - env[key] = value.replace(/"/g, ""); // strip quotas - } - }); - - return env; - } - - public async repo(name: string): Promise { - const repos = await this.repositories(); - - return repos.find(repo => repo.name === name); - } - - private async list(): Promise { - try { - const rawConfig = await readFile(this.helmEnv.HELM_REPOSITORY_CONFIG, "utf8"); - const parsedConfig = yaml.load(rawConfig) as HelmRepoConfig; - - if (typeof parsedConfig === "object" && parsedConfig) { - return parsedConfig.repositories; - } - } catch { - // ignore error - } - - return []; - } - - public async repositories(): Promise { - try { - await this.ensureInitialized(); - - const repos = await this.list(); - - return repos.map(repo => ({ - ...repo, - cacheFilePath: `${this.helmEnv.HELM_REPOSITORY_CACHE}/${repo.name}-index.yaml`, - })); - } catch (error) { - logger.error(`[HELM]: repositories listing error`, error); - - return []; - } - } - - public async update() { - return execHelm([ - "repo", - "update", - ]); - } - - public async addRepo({ name, url, insecureSkipTlsVerify, username, password, caFile, keyFile, certFile }: HelmRepo) { - logger.info(`[HELM]: adding repo ${name} from ${url}`); - const args = [ - "repo", - "add", - name, - url, - ]; - - if (insecureSkipTlsVerify) { - args.push("--insecure-skip-tls-verify"); - } - - if (username) { - args.push("--username", username); - } - - if (password) { - args.push("--password", password); - } - - if (caFile) { - args.push("--ca-file", caFile); - } - - if (keyFile) { - args.push("--key-file", keyFile); - } - - if (certFile) { - args.push("--cert-file", certFile); - } - - return execHelm(args); - } - - public async removeRepo({ name, url }: HelmRepo): Promise { - logger.info(`[HELM]: removing repo ${name} (${url})`); - - return execHelm([ - "repo", - "remove", - name, - ]); - } -} +export const HelmRepoManager = asLegacyGlobalSingletonForExtensionApi(helmRepoManagerInjectable); diff --git a/src/renderer/components/+helm-charts/helm-charts.tsx b/src/renderer/components/+helm-charts/helm-charts.tsx index 50ca0ccb88..027b4fd019 100644 --- a/src/renderer/components/+helm-charts/helm-charts.tsx +++ b/src/renderer/components/+helm-charts/helm-charts.tsx @@ -74,6 +74,8 @@ class NonInjectedHelmCharts extends Component { render() { return ( +
+ Promise; createUpgradeChartTab: (release: HelmRelease) => void; userSuppliedValuesAreShown: { toggle: () => void; value: boolean }; + themeStore: ThemeStore; } @observer @@ -249,13 +251,13 @@ class NonInjectedReleaseDetails extends Component; return ( updateRelease: di.inject(updateReleaseInjectable), createUpgradeChartTab: di.inject(createUpgradeChartTabInjectable), + themeStore: di.inject(themeStoreInjectable), + ...props, }), }, diff --git a/src/renderer/components/item-object-list/content.tsx b/src/renderer/components/item-object-list/content.tsx index 97a05ab219..af98e8c1dc 100644 --- a/src/renderer/components/item-object-list/content.tsx +++ b/src/renderer/components/item-object-list/content.tsx @@ -21,13 +21,16 @@ import { Spinner } from "../spinner"; import type { ItemObject, ItemStore } from "../../../common/item.store"; import type { Filter } from "./page-filters.store"; import { pageFilters } from "./page-filters.store"; -import { ThemeStore } from "../../theme.store"; +import type { ThemeStore } from "../../theme.store"; import { MenuActions } from "../menu/menu-actions"; import { MenuItem } from "../menu"; import { Checkbox } from "../checkbox"; -import { UserStore } from "../../../common/user-store"; -import type { OpenConfirmDialog } from "../confirm-dialog/open.injectable"; +import type { UserStore } from "../../../common/user-store"; import { withInjectables } from "@ogre-tools/injectable-react"; +import type { OpenConfirmDialog } from "../confirm-dialog/open.injectable"; + +import themeStoreInjectable from "../../theme-store.injectable"; +import userStoreInjectable from "../../../common/user-store/user-store.injectable"; import openConfirmDialogInjectable from "../confirm-dialog/open.injectable"; export interface ItemListLayoutContentProps { @@ -66,12 +69,14 @@ export interface ItemListLayoutContentProps { } interface Dependencies { + themeStore: ThemeStore; + userStore: UserStore; openConfirmDialog: OpenConfirmDialog; } @observer -class NonInjectedItemListLayoutContent extends React.Component & Dependencies> { - constructor(props: ItemListLayoutContentProps & Dependencies) { +class NonInjectedItemListLayoutContent extends React.Component> { + constructor(props: Dependencies & ItemListLayoutContentProps) { super(props); makeObservable(this); autoBind(this); @@ -255,7 +260,7 @@ class NonInjectedItemListLayoutContent extends React.Compo detailsItem, className, tableProps = {}, tableId, getItems, } = this.props; const selectedItemId = detailsItem && detailsItem.getId(); - const classNames = cssNames(className, "box", "grow", ThemeStore.getInstance().activeTheme.type); + const classNames = cssNames(className, "box", "grow", this.props.themeStore.activeTheme.type); const items = getItems(); const selectedItems = store.pickOnlySelected(items); @@ -298,7 +303,7 @@ class NonInjectedItemListLayoutContent extends React.Compo showColumn({ id: columnId, showWithColumn }: TableCellProps): boolean { const { tableId, isConfigurable } = this.props; - return !isConfigurable || !UserStore.getInstance().isTableColumnHidden(tableId, columnId, showWithColumn); + return !isConfigurable || !this.props.userStore.isTableColumnHidden(tableId, columnId, showWithColumn); } renderColumnVisibilityMenu() { @@ -312,7 +317,7 @@ class NonInjectedItemListLayoutContent extends React.Compo `} value={this.showColumn(cellProps)} - onChange={() => UserStore.getInstance().toggleTableColumnVisibility(tableId, cellProps.id)} + onChange={() => this.props.userStore.toggleTableColumnVisibility(tableId, cellProps.id)} /> ) @@ -322,9 +327,20 @@ class NonInjectedItemListLayoutContent extends React.Compo } } -export const ItemListLayoutContent = withInjectables>(NonInjectedItemListLayoutContent, { - getProps: (di, props) => ({ - ...props, - openConfirmDialog: di.inject(openConfirmDialogInjectable), - }), -}) as (props: ItemListLayoutContentProps) => React.ReactElement; +const InjectedItemListLayoutContent = withInjectables>( + NonInjectedItemListLayoutContent, + { + getProps: (di, props) => ({ + themeStore: di.inject(themeStoreInjectable), + userStore: di.inject(userStoreInjectable), + openConfirmDialog: di.inject(openConfirmDialogInjectable), + ...props, + }), + }, +); + +export function ItemListLayoutContent( + props: ItemListLayoutContentProps, +) { + return ; +} diff --git a/src/renderer/components/select/select.tsx b/src/renderer/components/select/select.tsx index 46c99f34cc..df37885ff3 100644 --- a/src/renderer/components/select/select.tsx +++ b/src/renderer/components/select/select.tsx @@ -18,9 +18,11 @@ import ReactSelect, { type StylesConfig, } from "react-select"; import ReactSelectCreatable, { type CreatableProps } from "react-select/creatable"; -import { ThemeStore } from "../../theme.store"; +import type { ThemeStore } from "../../theme.store"; import { autoBind, cssNames } from "../../utils"; import { merge } from "lodash"; +import { withInjectables } from "@ogre-tools/injectable-react"; +import themeStoreInjectable from "../../theme-store.injectable"; const { Menu } = components; @@ -34,6 +36,10 @@ export interface SelectOption { label?: React.ReactNode; } +interface Dependencies { + themeStore: ThemeStore; +} + export interface SelectProps extends ReactSelectProps, CreatableProps> { id?: string; // Optional only because of Extension API. Required to make Select deterministic in unit tests value?: T; @@ -45,21 +51,21 @@ export interface SelectProps extends ReactSelectProps, Crea } @observer -export class Select extends React.Component { +class NonInjectedSelect extends React.Component { static defaultProps: Omit = { autoConvertOptions: true, menuPortalTarget: document.body, menuPlacement: "auto", }; - constructor(props: SelectProps) { + constructor(props: SelectProps & Dependencies) { super(props); makeObservable(this); autoBind(this); } @computed get themeClass() { - const themeName = this.props.themeName || ThemeStore.getInstance().activeTheme.type; + const themeName = this.props.themeName || this.props.themeStore.activeTheme.type; return `theme-${themeName}`; } @@ -153,3 +159,14 @@ export class Select extends React.Component { : ; } } + +export const Select = withInjectables( + NonInjectedSelect, + + { + getProps: (di, props) => ({ + themeStore: di.inject(themeStoreInjectable), + ...props, + }), + }, +); diff --git a/src/renderer/components/test-utils/get-application-builder.tsx b/src/renderer/components/test-utils/get-application-builder.tsx index ee6dcda7ba..a17a9cc0c5 100644 --- a/src/renderer/components/test-utils/get-application-builder.tsx +++ b/src/renderer/components/test-utils/get-application-builder.tsx @@ -33,6 +33,10 @@ import preferenceNavigationItemsInjectable from "../+preferences/preferences-nav import navigateToPreferencesInjectable from "../../../common/front-end-routing/routes/preferences/navigate-to-preferences.injectable"; import type { MenuItemOpts } from "../../../main/menu/application-menu-items.injectable"; import applicationMenuItemsInjectable from "../../../main/menu/application-menu-items.injectable"; +import navigateToHelmChartsInjectable from "../../../common/front-end-routing/routes/cluster/helm/charts/navigate-to-helm-charts.injectable"; +import clusterFrameContextInjectable from "../../cluster-frame-context/cluster-frame-context.injectable"; +import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store"; +import hostedClusterInjectable from "../../../common/cluster-store/hosted-cluster.injectable"; type Callback = (dis: DiContainers) => void | Promise; @@ -56,6 +60,10 @@ export interface ApplicationBuilder { click: (id: string) => void; }; }; + + helmCharts: { + navigate: () => void; + }; } interface DiContainers { @@ -192,6 +200,14 @@ export const getApplicationBuilder = () => { }, }, + helmCharts: { + navigate: () => { + const navigateToHelmCharts = rendererDi.inject(navigateToHelmChartsInjectable); + + navigateToHelmCharts(); + }, + }, + setEnvironmentToClusterFrame: () => { environment = environments.clusterFrame; @@ -206,6 +222,17 @@ export const getApplicationBuilder = () => { () => "/irrelevant", ); + rendererDi.override(hostedClusterInjectable, () => ({ + accessibleNamespaces: [], + })); + + const clusterFrameContext = rendererDi.inject( + clusterFrameContextInjectable, + ); + + // Todo: get rid of global state. + KubeObjectStore.defaultContext.set(clusterFrameContext); + return builder; }, diff --git a/src/renderer/getDiForUnitTesting.tsx b/src/renderer/getDiForUnitTesting.tsx index 6a752dfd85..db8c2e830f 100644 --- a/src/renderer/getDiForUnitTesting.tsx +++ b/src/renderer/getDiForUnitTesting.tsx @@ -33,6 +33,9 @@ import { getAbsolutePathFake } from "../common/test-utils/get-absolute-path-fake import joinPathsInjectable from "../common/path/join-paths.injectable"; import { joinPathsFake } from "../common/test-utils/join-paths-fake"; import hotbarStoreInjectable from "../common/hotbar-store.injectable"; +import themeStoreInjectable from "./theme-store.injectable"; +import apiManagerInjectable from "./components/kube-object-menu/dependencies/api-manager.injectable"; +import { ApiManager } from "../common/k8s-api/api-manager"; export const getDiForUnitTesting = ( { doGeneralOverrides } = { doGeneralOverrides: false }, @@ -69,7 +72,16 @@ export const getDiForUnitTesting = ( // eslint-disable-next-line unused-imports/no-unused-vars-ts di.override(clusterStoreInjectable, () => ({ getById: (id): Cluster => ({}) as Cluster }) as ClusterStore); - di.override(userStoreInjectable, () => ({}) as UserStore); + + di.override( + userStoreInjectable, + () => + ({ + isTableColumnHidden: () => false, + } as unknown as UserStore), + ); + + di.override(apiManagerInjectable, () => new ApiManager()); di.override(getValueFromRegisteredChannelInjectable, () => () => undefined); di.override(registerIpcChannelListenerInjectable, () => () => undefined); @@ -92,6 +104,13 @@ export const getDiForUnitTesting = ( error: (message: string, ...args: any) => console.error(message, ...args), info: noop, })); + + di.override(themeStoreInjectable, () => ({ + activeTheme: { + type: "some-active-theme-type", + }, + })); + } return di;