diff --git a/src/common/k8s-api/api-manager.ts b/src/common/k8s-api/api-manager.ts
index 2480506d37..b2befc4771 100644
--- a/src/common/k8s-api/api-manager.ts
+++ b/src/common/k8s-api/api-manager.ts
@@ -27,11 +27,11 @@ import type { KubeApi } from "./kube-api";
import type { KubeObject } from "./kube-object";
import { IKubeObjectRef, parseKubeApi, createKubeApiURL } from "./kube-api-parse";
-export interface IGettableStore {
+export interface IApiManager {
getStore>(api: string | KubeApi): TKubeObjectStore | undefined;
}
-export class ApiManager implements IGettableStore {
+export class ApiManager implements IApiManager {
private apis = observable.map>();
private stores = observable.map>();
diff --git a/src/extensions/registries/kube-object-menu-registry.ts b/src/extensions/registries/kube-object-menu-registry.ts
index cfc198ee04..a6ce70322b 100644
--- a/src/extensions/registries/kube-object-menu-registry.ts
+++ b/src/extensions/registries/kube-object-menu-registry.ts
@@ -32,11 +32,11 @@ export interface KubeObjectMenuRegistration {
components: KubeObjectMenuComponents;
}
-export interface IHasGettableItemsForKind {
+export interface IKubeObjectMenuRegistry {
getItemsForKind(kind: string, apiVersion: string): any;
}
-export class KubeObjectMenuRegistry extends BaseRegistry implements IHasGettableItemsForKind {
+export class KubeObjectMenuRegistry extends BaseRegistry implements IKubeObjectMenuRegistry {
getItemsForKind = (kind: string, apiVersion: string) =>
this.getItems().filter((item) =>
item.kind === kind && item.apiVersions.includes(apiVersion),
diff --git a/src/main/cluster.ts b/src/main/cluster.ts
index 2ec97c792a..bb20a718db 100644
--- a/src/main/cluster.ts
+++ b/src/main/cluster.ts
@@ -37,12 +37,16 @@ import { ClusterMetadataKey, initialNodeShellImage, ClusterStatus } from "../com
import { disposer, storedKubeConfigFolder, toJS } from "../common/utils";
import type { Response } from "request";
+export interface ICluster {
+ name: string
+}
+
/**
* Cluster
*
* @beta
*/
-export class Cluster implements ClusterModel, ClusterState {
+export class Cluster implements ClusterModel, ClusterState, ICluster {
/** Unique id for a cluster */
public readonly id: ClusterId;
private kubeCtl: Kubectl;
diff --git a/src/renderer/components/+workloads-deployments/deployment-replicasets.tsx b/src/renderer/components/+workloads-deployments/deployment-replicasets.tsx
index eae0e10332..1ae8d20552 100644
--- a/src/renderer/components/+workloads-deployments/deployment-replicasets.tsx
+++ b/src/renderer/components/+workloads-deployments/deployment-replicasets.tsx
@@ -24,7 +24,7 @@ import "./deployment-replicasets.scss";
import React from "react";
import { observer } from "mobx-react";
import type { ReplicaSet } from "../../../common/k8s-api/endpoints";
-import { KubeObjectMenu, KubeObjectMenuProps } from "../kube-object-menu";
+import type { KubeObjectMenuProps } from "../kube-object-menu";
import { Spinner } from "../spinner";
import { prevDefault, stopPropagation } from "../../utils";
import { DrawerTitle } from "../drawer";
@@ -32,8 +32,8 @@ import { Table, TableCell, TableHead, TableRow } from "../table";
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
import { replicaSetStore } from "../+workloads-replicasets/replicasets.store";
import { showDetails } from "../kube-detail-params";
-import { InjectNaive } from "../kube-object-menu/inject-naive/inject-naive";
-
+import { Inject } from "@ogre-tools/injectable-react";
+import KubeObjectMenuInjectable from "../kube-object-menu/kube-object-menu.injectable";
enum sortBy {
name = "name",
@@ -115,7 +115,6 @@ export class DeploymentReplicaSets extends React.Component {
}
export function ReplicaSetMenu(props: KubeObjectMenuProps) {
- return (
-
- );
+ return ;
}
+
diff --git a/src/renderer/components/kube-object-details/kube-object-details.tsx b/src/renderer/components/kube-object-details/kube-object-details.tsx
index dacd0b61de..6c9cfa286d 100644
--- a/src/renderer/components/kube-object-details/kube-object-details.tsx
+++ b/src/renderer/components/kube-object-details/kube-object-details.tsx
@@ -29,14 +29,13 @@ import type { KubeObject } from "../../../common/k8s-api/kube-object";
import { Spinner } from "../spinner";
import { apiManager } from "../../../common/k8s-api/api-manager";
import { crdStore } from "../+custom-resources/crd.store";
-import { KubeObjectMenu } from "../kube-object-menu";
import { KubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import logger from "../../../main/logger";
import { CrdResourceDetails } from "../+custom-resources";
import { KubeObjectMeta } from "../kube-object-meta";
import { hideDetails, kubeDetailsUrlParam } from "../kube-detail-params";
-import { InjectNaive } from "../kube-object-menu/inject-naive/inject-naive";
-
+import { Inject } from "@ogre-tools/injectable-react";
+import KubeObjectMenuInjectable from "../kube-object-menu/kube-object-menu.injectable";
export interface KubeObjectDetailsProps {
className?: string;
@@ -105,7 +104,7 @@ export class KubeObjectDetails extends React.Component {
className="KubeObjectDetails flex column"
open={isOpen}
title=""
- toolbar={}
+ toolbar={}
onClose={hideDetails}
>
{isLoading && }
@@ -145,7 +144,7 @@ export class KubeObjectDetails extends React.Component {
className="KubeObjectDetails flex column"
open={isOpen}
title={title}
- toolbar={}
+ toolbar={}
onClose={hideDetails}
>
{isLoading && }
diff --git a/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx b/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx
index f0d9591e62..9dba0cd219 100644
--- a/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx
+++ b/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx
@@ -28,7 +28,6 @@ import { cssNames, Disposer } from "../../utils";
import type { KubeObject } from "../../../common/k8s-api/kube-object";
import { ItemListLayout, ItemListLayoutProps } from "../item-object-list/item-list-layout";
import type { KubeObjectStore } from "../../../common/k8s-api/kube-object.store";
-import { KubeObjectMenu } from "../kube-object-menu";
import { kubeWatchApi } from "../../../common/k8s-api/kube-watch-api";
import { NamespaceSelectFilter } from "../+namespaces/namespace-select-filter";
import { ResourceKindMap, ResourceNames } from "../../utils/rbac";
@@ -36,7 +35,8 @@ import { kubeSelectedUrlParam, toggleDetails } from "../kube-detail-params";
import { Icon } from "../icon";
import { TooltipPosition } from "../tooltip";
import type { ClusterContext } from "../../../common/k8s-api/cluster-context";
-import { InjectNaive } from "../kube-object-menu/inject-naive/inject-naive";
+import { Inject } from "@ogre-tools/injectable-react";
+import KubeObjectMenuInjectable from "../kube-object-menu/kube-object-menu.injectable";
export interface KubeObjectListLayoutProps extends ItemListLayoutProps {
store: KubeObjectStore;
@@ -141,7 +141,7 @@ export class KubeObjectListLayout extends React.Component<
}),
...[customizeHeader].flat(),
]}
- renderItemMenu={item => }
+ renderItemMenu={item => }
/>
);
}
diff --git a/src/renderer/components/kube-object-menu/__snapshots__/kube-object-menu.test.tsx.snap b/src/renderer/components/kube-object-menu/__snapshots__/kube-object-menu.test.tsx.snap
index 14844c43a9..8d173b079c 100644
--- a/src/renderer/components/kube-object-menu/__snapshots__/kube-object-menu.test.tsx.snap
+++ b/src/renderer/components/kube-object-menu/__snapshots__/kube-object-menu.test.tsx.snap
@@ -17,7 +17,7 @@ exports[`kube-object-menu given kube object renders 1`] = `
>
from
- Some cluster name
+ Some name
?
@@ -166,7 +166,7 @@ exports[`kube-object-menu given kube object with namespace when removing kube ob
>
from
- Some cluster name
+ Some name
?
@@ -267,7 +267,7 @@ exports[`kube-object-menu given kube object without namespace when removing kube
>
from
- Some cluster name
+ Some name
?
diff --git a/src/renderer/components/kube-object-menu/dependencies/apiManager.injectable.ts b/src/renderer/components/kube-object-menu/dependencies/apiManager.injectable.ts
new file mode 100644
index 0000000000..a8ab6a1bc6
--- /dev/null
+++ b/src/renderer/components/kube-object-menu/dependencies/apiManager.injectable.ts
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2021 OpenLens Authors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+import { IApiManager, apiManager } from "../../../../common/k8s-api/api-manager";
+import type { IInjectable } from "@ogre-tools/injectable";
+
+const apiManagerInjectable: IInjectable = {
+ getDependencies: () => ({}),
+ instantiate: () => apiManager,
+};
+
+export default apiManagerInjectable;
diff --git a/src/renderer/components/kube-object-menu/inject-naive/inject-naive.tsx b/src/renderer/components/kube-object-menu/dependencies/cluster.injectable.ts
similarity index 55%
rename from src/renderer/components/kube-object-menu/inject-naive/inject-naive.tsx
rename to src/renderer/components/kube-object-menu/dependencies/cluster.injectable.ts
index 43d682ac14..b3d7467121 100644
--- a/src/renderer/components/kube-object-menu/inject-naive/inject-naive.tsx
+++ b/src/renderer/components/kube-object-menu/dependencies/cluster.injectable.ts
@@ -18,37 +18,16 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-
-import React from "react";
-import { editResourceTab } from "../../dock/edit-resource.store";
-import { hideDetails } from "../../kube-detail-params";
-import { apiManager } from "../../../../common/k8s-api/api-manager";
-import { KubeObjectMenuRegistry } from "../../../../extensions/registries";
import { getActiveClusterEntity } from "../../../api/catalog-entity-registry";
-import type { KubeObjectMenuDependencies } from "../kube-object-menu";
-import type { KubeObject } from "../../../../common/k8s-api/kube-object";
-interface Props {
- Component: React.ElementType
- [key: string]: any,
-}
+import type { IInjectable } from "@ogre-tools/injectable";
+import { lifecycleEnum } from "@ogre-tools/injectable";
+import type { ICluster } from "../../../../main/cluster";
-export const InjectNaive = ({ Component, ...props }: Props) => {
- const kubeObjectMenuRegistry = KubeObjectMenuRegistry.getInstance();
- const cluster = getActiveClusterEntity();
-
- const dependencies: KubeObjectMenuDependencies = {
- clusterName: cluster.name,
- editResourceTab,
- hideDetails,
- apiManager,
- kubeObjectMenuRegistry,
- };
-
- return (
-
- );
+const clusterInjectable: IInjectable = {
+ getDependencies: () => ({}),
+ instantiate: () => getActiveClusterEntity(),
+ lifecycle: lifecycleEnum.transient,
};
+
+export default clusterInjectable;
diff --git a/src/renderer/components/kube-object-menu/dependencies/clusterName.injectable.ts b/src/renderer/components/kube-object-menu/dependencies/clusterName.injectable.ts
new file mode 100644
index 0000000000..1e1065f309
--- /dev/null
+++ b/src/renderer/components/kube-object-menu/dependencies/clusterName.injectable.ts
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2021 OpenLens Authors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+import { lifecycleEnum } from "@ogre-tools/injectable";
+import type { ICluster } from "../../../../main/cluster";
+import type { IInjectable } from "@ogre-tools/injectable";
+import clusterInjectable from "./cluster.injectable";
+
+interface IDependencies {
+ cluster: ICluster;
+}
+
+const clusterNameInjectable: IInjectable<
+ string | undefined,
+ IDependencies
+> = {
+ getDependencies: di => ({
+ cluster: di.inject(clusterInjectable),
+ }),
+
+ instantiate: ({ cluster }) => cluster?.name,
+
+ lifecycle: lifecycleEnum.transient,
+};
+
+export default clusterNameInjectable;
diff --git a/src/renderer/components/kube-object-menu/dependencies/editResourceTab.injectable.ts b/src/renderer/components/kube-object-menu/dependencies/editResourceTab.injectable.ts
new file mode 100644
index 0000000000..aa3ef38095
--- /dev/null
+++ b/src/renderer/components/kube-object-menu/dependencies/editResourceTab.injectable.ts
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2021 OpenLens Authors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+import { editResourceTab } from "../../dock/edit-resource.store";
+import type { IInjectable } from "@ogre-tools/injectable";
+
+const editResourceTabInjectable: IInjectable = {
+ getDependencies: () => ({}),
+ instantiate: () => editResourceTab,
+};
+
+export default editResourceTabInjectable;
diff --git a/src/renderer/components/kube-object-menu/dependencies/hideDetails.injectable.ts b/src/renderer/components/kube-object-menu/dependencies/hideDetails.injectable.ts
new file mode 100644
index 0000000000..fc25d7c178
--- /dev/null
+++ b/src/renderer/components/kube-object-menu/dependencies/hideDetails.injectable.ts
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2021 OpenLens Authors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+import { hideDetails } from "../../kube-detail-params";
+import type { IInjectable } from "@ogre-tools/injectable";
+
+export const hideDetailsInjectable: IInjectable = {
+ getDependencies: () => ({}),
+ instantiate: () => hideDetails,
+};
+
+export default hideDetailsInjectable;
diff --git a/src/renderer/components/kube-object-menu/dependencies/kubeObjectMenuRegistry.injectable.ts b/src/renderer/components/kube-object-menu/dependencies/kubeObjectMenuRegistry.injectable.ts
new file mode 100644
index 0000000000..9ee3ae70a2
--- /dev/null
+++ b/src/renderer/components/kube-object-menu/dependencies/kubeObjectMenuRegistry.injectable.ts
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2021 OpenLens Authors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+import { IKubeObjectMenuRegistry, KubeObjectMenuRegistry } from "../../../../extensions/registries";
+import type { IInjectable } from "@ogre-tools/injectable";
+
+const kubeObjectMenuRegistryInjectable: IInjectable = {
+ getDependencies: () => ({}),
+ instantiate: () => KubeObjectMenuRegistry.getInstance(),
+};
+
+export default kubeObjectMenuRegistryInjectable;
diff --git a/src/renderer/components/kube-object-menu/kube-object-menu.injectable.ts b/src/renderer/components/kube-object-menu/kube-object-menu.injectable.ts
new file mode 100644
index 0000000000..330e988932
--- /dev/null
+++ b/src/renderer/components/kube-object-menu/kube-object-menu.injectable.ts
@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) 2021 OpenLens Authors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+import { KubeObjectMenu, KubeObjectMenuDependencies } from "./kube-object-menu";
+import type { KubeObject } from "../../../common/k8s-api/kube-object";
+import type { IComponentInjectable } from "@ogre-tools/injectable";
+import apiManagerInjectable from "./dependencies/apiManager.injectable";
+import clusterNameInjectable from "./dependencies/clusterName.injectable";
+import kubeObjectMenuRegistryInjectable from "./dependencies/kubeObjectMenuRegistry.injectable";
+import editResourceTabInjectable from "./dependencies/editResourceTab.injectable";
+import hideDetailsInjectable from "./dependencies/hideDetails.injectable";
+
+const KubeObjectMenuInjectable: IComponentInjectable<
+ typeof KubeObjectMenu,
+ KubeObjectMenuDependencies
+> = {
+ getDependencies: di => ({
+ clusterName: di.inject(clusterNameInjectable),
+ apiManager: di.inject(apiManagerInjectable),
+ kubeObjectMenuRegistry: di.inject(kubeObjectMenuRegistryInjectable),
+ editResourceTab: di.inject(editResourceTabInjectable),
+ hideDetails: di.inject(hideDetailsInjectable),
+ }),
+
+ instantiate: KubeObjectMenu,
+};
+
+export default KubeObjectMenuInjectable;
diff --git a/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx b/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx
index 050e5c7a49..2d9ba02fe5 100644
--- a/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx
+++ b/src/renderer/components/kube-object-menu/kube-object-menu.test.tsx
@@ -20,28 +20,41 @@
*/
import React from "react";
-import { render, screen } from "@testing-library/react";
+import { screen } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";
-import { KubeObjectMenu, KubeObjectMenuDependencies } from "./kube-object-menu";
import { KubeObject } from "../../../common/k8s-api/kube-object";
import userEvent from "@testing-library/user-event";
-import type { KubeApi } from "../../../common/k8s-api/kube-api";
+import type { IConfigurableDependencyInjectionContainer } from "@ogre-tools/injectable";
import type { KubeObjectMenuRegistration } from "../../../extensions/registries";
-import type { IGettableStore } from "../../../common/k8s-api/api-manager";
-import type { KubeObjectStore } from "../../../common/k8s-api/kube-object.store";
+import { KubeObjectMenuRegistry } from "../../../extensions/registries";
import { ConfirmDialog } from "../confirm-dialog";
import asyncFn from "@async-fn/jest";
-import { KubeObjectMenuRegistry } from "../../../extensions/registries";
+import { getDiForUnitTesting } from "../getDiForUnitTesting";
+
+import { Inject } from "@ogre-tools/injectable-react";
+import clusterInjectable from "./dependencies/cluster.injectable";
+import apiManagerInjectable from "./dependencies/apiManager.injectable";
+import hideDetailsInjectable from "./dependencies/hideDetails.injectable";
+import editResourceTabInjectable from "./dependencies/editResourceTab.injectable";
+import { TabKind } from "../dock/dock.store";
+import KubeObjectMenuInjectable from "./kube-object-menu.injectable";
+import kubeObjectMenuRegistryInjectable from "./dependencies/kubeObjectMenuRegistry.injectable";
+import { renderFor, IDiRender } from "../test-utils/renderFor";
describe("kube-object-menu", () => {
- let hideDetailsStub: () => void;
- let editResourceTabStub: () => void;
- let apiManagerStub: IGettableStore;
- let kubeObjectMenuRegistry: KubeObjectMenuRegistry;
let objectStub: KubeObject | null;
- let dependencies: KubeObjectMenuDependencies;
+ let di: IConfigurableDependencyInjectionContainer;
+ let render: IDiRender;
beforeEach(() => {
+ di = getDiForUnitTesting();
+
+ // TODO: Remove global shared state
+ KubeObjectMenuRegistry.resetInstance();
+ KubeObjectMenuRegistry.createInstance();
+
+ render = renderFor(di);
+
// TODO: Remove illegal global overwrites for what should be a dependency somewhere.
// TODO: Remove usage of experimental browser API.
window.requestIdleCallback = (callback: IdleRequestCallback): number => {
@@ -52,62 +65,66 @@ describe("kube-object-menu", () => {
window.cancelIdleCallback = () => {};
- apiManagerStub = {
- getStore: >(
- // eslint-disable-next-line unused-imports/no-unused-vars-ts
- api: string | KubeApi,
- ): TKubeObjectStore | undefined => undefined,
- };
+ di.override(clusterInjectable, {
+ name: "Some name",
+ });
- // TODO: Remove global shared state
- KubeObjectMenuRegistry.resetInstance();
- KubeObjectMenuRegistry.createInstance();
- kubeObjectMenuRegistry = KubeObjectMenuRegistry.getInstance();
+ di.override(apiManagerInjectable, {
+ getStore: () => undefined,
+ });
- const MenuItemComponent: React.FC = () => Some menu item;
+ di.override(hideDetailsInjectable, () => {});
+
+ di.override(editResourceTabInjectable, () => ({
+ id: "irrelevant",
+ kind: TabKind.TERMINAL,
+ pinned: false,
+ title: "irrelevant",
+ }));
addDynamicMenuItem({
- kubeObjectMenuRegistry,
- MenuItemComponent,
+ di,
apiVersions: ["some-api-version"],
kind: "some-kind",
});
addDynamicMenuItem({
- kubeObjectMenuRegistry,
- MenuItemComponent,
+ di,
apiVersions: ["some-unrelated-api-version"],
kind: "some-kind",
});
addDynamicMenuItem({
- kubeObjectMenuRegistry,
- MenuItemComponent,
+ di,
apiVersions: ["some-api-version"],
kind: "some-unrelated-kind",
});
+ });
- hideDetailsStub = () => {};
+ it("given no cluster, does not crash", () => {
+ di.override(clusterInjectable, null);
- editResourceTabStub = () => {};
+ objectStub = null;
- dependencies = {
- clusterName: "Some cluster name",
- apiManager: apiManagerStub,
- kubeObjectMenuRegistry,
- hideDetails: hideDetailsStub,
- editResourceTab: editResourceTabStub,
- };
+ expect(() => {
+ render(
+ ,
+ );
+ }).not.toThrow();
});
it("given no kube object, renders", () => {
objectStub = null;
const { baseElement } = render(
- ,
);
@@ -136,9 +153,9 @@ describe("kube-object-menu", () => {
-
@@ -195,7 +212,6 @@ describe("kube-object-menu", () => {
describe("given kube object with namespace", () => {
let baseElement: Element;
- let getByTestId: (arg0: string) => any;
beforeEach(async () => {
objectStub = KubeObject.create({
@@ -209,13 +225,13 @@ describe("kube-object-menu", () => {
},
});
- ({ baseElement, getByTestId } = render(
+ ({ baseElement } = render(
-
{}}
/>
@@ -224,7 +240,7 @@ describe("kube-object-menu", () => {
});
it("when removing kube object, renders confirmation dialog with namespace", () => {
- const menuItem = getByTestId("menu-action-remove");
+ const menuItem = screen.getByTestId("menu-action-remove");
userEvent.click(menuItem);
@@ -234,7 +250,6 @@ describe("kube-object-menu", () => {
describe("given kube object without namespace", () => {
let baseElement: Element;
- let getByTestId: (arg0: string) => any;
beforeEach(async () => {
objectStub = KubeObject.create({
@@ -248,13 +263,13 @@ describe("kube-object-menu", () => {
},
});
- ({ baseElement, getByTestId } = render(
+ ({ baseElement } = render(
-
{}}
/>
@@ -263,7 +278,7 @@ describe("kube-object-menu", () => {
});
it("when removing kube object, renders confirmation dialog without namespace", () => {
- const menuItem = getByTestId("menu-action-remove");
+ const menuItem = screen.getByTestId("menu-action-remove");
userEvent.click(menuItem);
@@ -273,21 +288,25 @@ describe("kube-object-menu", () => {
});
const addDynamicMenuItem = ({
- kubeObjectMenuRegistry,
- MenuItemComponent,
+ di,
apiVersions,
kind,
}: {
- kubeObjectMenuRegistry: KubeObjectMenuRegistry;
- MenuItemComponent: React.ComponentType;
+ di: any;
apiVersions: string[];
kind: string;
}) => {
+ const MenuItemComponent: React.FC = () => Some menu item;
+
const dynamicMenuItemStub: KubeObjectMenuRegistration = {
apiVersions,
kind,
components: { MenuItem: MenuItemComponent },
};
+ const kubeObjectMenuRegistry: KubeObjectMenuRegistry = di.inject(
+ kubeObjectMenuRegistryInjectable,
+ );
+
kubeObjectMenuRegistry.add(dynamicMenuItemStub);
};
diff --git a/src/renderer/components/kube-object-menu/kube-object-menu.tsx b/src/renderer/components/kube-object-menu/kube-object-menu.tsx
index 4bb7e9ab99..27591ee790 100644
--- a/src/renderer/components/kube-object-menu/kube-object-menu.tsx
+++ b/src/renderer/components/kube-object-menu/kube-object-menu.tsx
@@ -22,16 +22,16 @@
import React from "react";
import { boundMethod, cssNames } from "../../utils";
import type { KubeObject } from "../../../common/k8s-api/kube-object";
-import { MenuActions, MenuActionsProps } from "../menu/menu-actions";
+import { MenuActions, MenuActionsProps } from "../menu";
import identity from "lodash/identity";
-import type { IHasGettableItemsForKind } from "../../../extensions/registries";
-import type { IGettableStore } from "../../../common/k8s-api/api-manager";
+import type { IKubeObjectMenuRegistry } from "../../../extensions/registries";
+import type { IApiManager } from "../../../common/k8s-api/api-manager";
-export interface KubeObjectMenuDependencies{
- apiManager: IGettableStore;
- kubeObjectMenuRegistry: IHasGettableItemsForKind;
- clusterName: string,
+export interface KubeObjectMenuDependencies {
+ apiManager: IApiManager;
+ kubeObjectMenuRegistry: IKubeObjectMenuRegistry;
+ clusterName: string;
hideDetails: () => void;
editResourceTab: (kubeObject: TKubeObject) => void;
}
@@ -40,22 +40,21 @@ export interface KubeObjectMenuProps extends MenuActionsProps {
object: TKubeObject | null | undefined;
editable?: boolean;
removable?: boolean;
- dependencies?: KubeObjectMenuDependencies
}
+export interface KubeObjectMenuPropsAndDependencies
+ extends KubeObjectMenuProps,
+ KubeObjectMenuDependencies {}
+
export class KubeObjectMenu<
TKubeObject extends KubeObject,
-> extends React.Component> {
- get dependencies() {
- return this.props.dependencies;
- }
-
+> extends React.Component> {
get store() {
const { object } = this.props;
if (!object) return null;
- return this.dependencies.apiManager.getStore(object.selfLink);
+ return this.props.apiManager.getStore(object.selfLink);
}
get isEditable() {
@@ -68,13 +67,13 @@ export class KubeObjectMenu<
@boundMethod
async update() {
- this.dependencies.hideDetails();
- this.dependencies.editResourceTab(this.props.object);
+ this.props.hideDetails();
+ this.props.editResourceTab(this.props.object);
}
@boundMethod
async remove() {
- this.dependencies.hideDetails();
+ this.props.hideDetails();
const { object, removeAction } = this.props;
// TODO: currently only branch for removeAction() is unit tested, and store.remove() is not.
@@ -90,16 +89,13 @@ export class KubeObjectMenu<
return null;
}
- const breadcrumbParts = [
- object.getNs(),
- object.getName(),
- ];
+ const breadcrumbParts = [object.getNs(), object.getName()];
const breadcrumb = breadcrumbParts.filter(identity).join("/");
return (
- Remove {object.kind} {breadcrumb} from {this.dependencies.clusterName}?
+ Remove {object.kind} {breadcrumb} from {this.props.clusterName}?
);
}
@@ -111,16 +107,22 @@ export class KubeObjectMenu<
return [];
}
- return this.dependencies.kubeObjectMenuRegistry
+ return this.props.kubeObjectMenuRegistry
.getItemsForKind(object.kind, object.apiVersion)
- .map(({ components: { MenuItem }}: { components: { MenuItem: React.ReactType }}, index: number) => (
-
- ),
+ .map(
+ (
+ {
+ components: { MenuItem },
+ }: { components: { MenuItem: React.ReactType }},
+ index: number,
+ ) => (
+
+ ),
);
}
diff --git a/src/renderer/components/test-utils/renderFor.tsx b/src/renderer/components/test-utils/renderFor.tsx
new file mode 100644
index 0000000000..690d3d8332
--- /dev/null
+++ b/src/renderer/components/test-utils/renderFor.tsx
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2021 OpenLens Authors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+import React from "react";
+
+import {
+ render as testingLibraryRender,
+ RenderResult,
+} from "@testing-library/react";
+
+import type { IConfigurableDependencyInjectionContainer } from "@ogre-tools/injectable";
+
+import { DiContextProvider } from "@ogre-tools/injectable-react";
+
+export type IDiRender = (ui: React.ReactElement) => RenderResult;
+
+type IDiRenderFor = (
+ di: IConfigurableDependencyInjectionContainer,
+) => IDiRender;
+
+export const renderFor: IDiRenderFor = di => ui =>
+ testingLibraryRender(
+ {ui},
+ );
+