diff --git a/src/features/entity-settings/__snapshots__/showing-settings-for-correct-entity.test.tsx.snap b/src/features/entity-settings/__snapshots__/showing-settings-for-correct-entity.test.tsx.snap new file mode 100644 index 0000000000..695cd7ba77 --- /dev/null +++ b/src/features/entity-settings/__snapshots__/showing-settings-for-correct-entity.test.tsx.snap @@ -0,0 +1,1056 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Showing correct entity settings renders 1`] = ` + +
+
+
+
+
+ + + home + + +
+
+
+ + + arrow_back + + +
+
+
+ + + arrow_forward + + +
+
+
+
+
+
+
+
+ +
+
+

+ Welcome to some-product-name! +

+

+ To get you started we have auto-detected your clusters in your + + kubeconfig file and added them to the catalog, your centralized + + view for managing all your cloud-native resources. +
+
+ If you have any questions or feedback, please join our + + Lens Community slack channel + + . +

+ +
+
+
+
+
+
+
+
+ + + arrow_left + + +
+
+ 0 +
+
+ + + arrow_right + + +
+
+
+
+
+
+
+
+
+ +`; + +exports[`Showing correct entity settings when navigating to local cluster entity settings renders 1`] = ` + +
+
+
+
+
+ + + home + + +
+
+
+ + + arrow_back + + +
+
+
+ + + arrow_forward + + +
+
+
+
+
+
+
+ +
+
+
+

+ General +

+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+
+
+
+ + + arrow_left + + +
+
+ 0 +
+
+ + + arrow_right + + +
+
+
+
+
+
+
+
+
+ +`; + +exports[`Showing correct entity settings when navigating to non-local cluster entity settings renders 1`] = ` + +
+
+
+
+
+ + + home + + +
+
+
+ + + arrow_back + + +
+
+
+ + + arrow_forward + + +
+
+
+
+
+
+
+ +
+
+
+

+ Proxy +

+
+
+
+ HTTP Proxy + +
+
+ +
+
+ + HTTP Proxy server. Used for communicating with Kubernetes API. + +
+
+
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+
+
+
+ + + arrow_left + + +
+
+ 0 +
+
+ + + arrow_right + + +
+
+
+
+
+
+
+
+
+ +`; + +exports[`Showing correct entity settings when navigating to weblink entity settings renders 1`] = ` + +
+
+
+
+
+ + + home + + +
+
+
+ + + arrow_back + + +
+
+
+ + + arrow_forward + + +
+
+
+
+
+
+
+ +
+
+
+ No settings found for + + entity.k8slens.dev/v1alpha1 + / + WebLink +
+
+
+
+
+
+ + + close + + +
+ +
+
+
+
+
+
+
+
+
+ + + arrow_left + + +
+
+ 0 +
+
+ + + arrow_right + + +
+
+
+
+
+
+
+
+
+ +`; diff --git a/src/features/entity-settings/showing-settings-for-correct-entity.test.tsx b/src/features/entity-settings/showing-settings-for-correct-entity.test.tsx new file mode 100644 index 0000000000..306582a188 --- /dev/null +++ b/src/features/entity-settings/showing-settings-for-correct-entity.test.tsx @@ -0,0 +1,226 @@ +/** + * 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 { RenderResult } from "@testing-library/react"; +import { KubernetesCluster, WebLink } from "../../common/catalog-entities"; +import getClusterByIdInjectable from "../../common/cluster-store/get-by-id.injectable"; +import type { Cluster } from "../../common/cluster/cluster"; +import navigateToEntitySettingsInjectable from "../../common/front-end-routing/routes/entity-settings/navigate-to-entity-settings.injectable"; +import catalogEntityRegistryInjectable from "../../renderer/api/catalog/entity/registry.injectable"; +import { type ApplicationBuilder, getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; +import createClusterInjectable from "../../renderer/create-cluster/create-cluster.injectable"; + +describe("Showing correct entity settings", () => { + let builder: ApplicationBuilder; + let rendered: RenderResult; + let windowDi: DiContainer; + let clusterEntity: KubernetesCluster; + let localClusterEntity: KubernetesCluster; + let otherEntity: WebLink; + let cluster: Cluster; + + beforeEach(async () => { + builder = getApplicationBuilder(); + + builder.afterWindowStart((windowDi) => { + const createCluster = windowDi.inject(createClusterInjectable); + + clusterEntity = new KubernetesCluster({ + metadata: { + labels: {}, + name: "some-kubernetes-cluster", + uid: "some-entity-id", + }, + spec: { + kubeconfigContext: "some-context", + kubeconfigPath: "/some/path/to/kubeconfig", + }, + status: { + phase: "connecting", + }, + }); + localClusterEntity = new KubernetesCluster({ + metadata: { + labels: {}, + name: "some-local-kubernetes-cluster", + uid: "some-entity-id-2", + source: "local", + }, + spec: { + kubeconfigContext: "some-context", + kubeconfigPath: "/some/path/to/local/kubeconfig", + }, + status: { + phase: "connecting", + }, + }); + otherEntity = new WebLink({ + metadata: { + labels: {}, + name: "some-weblink", + uid: "some-weblink-id", + }, + spec: { + url: "https://my-websome.com", + }, + status: { + phase: "available", + }, + }); + cluster = createCluster({ + contextName: clusterEntity.spec.kubeconfigContext, + id: clusterEntity.getId(), + kubeConfigPath: clusterEntity.spec.kubeconfigPath, + }, { + clusterServerUrl: "https://localhost:9999", + }); + + // TODO: remove once ClusterStore can be used without overriding it + windowDi.override(getClusterByIdInjectable, () => (clusterId) => { + if (clusterId === cluster.id) { + return cluster; + } + + return undefined; + }); + + // TODO: replace with proper entity source once syncing entities between main and windows is injectable + const catalogEntityRegistry = windowDi.inject(catalogEntityRegistryInjectable); + + catalogEntityRegistry.updateItems([clusterEntity, otherEntity, localClusterEntity]); + }); + + rendered = await builder.render(); + windowDi = builder.applicationWindow.only.di; + }); + + it("renders", () => { + expect(rendered.baseElement).toMatchSnapshot(); + }); + + it("does not show entity settings page yet", () => { + expect(rendered.queryByTestId("entity-settings")).not.toBeInTheDocument(); + }); + + describe("when navigating to non-local cluster entity settings", () => { + beforeEach(() => { + const navigateToEntitySettings = windowDi.inject(navigateToEntitySettingsInjectable); + + navigateToEntitySettings(clusterEntity.getId()); + }); + + it("renders", () => { + expect(rendered.baseElement).toMatchSnapshot(); + }); + + it("shows entity settings page", () => { + expect(rendered.queryByTestId("entity-settings")).toBeInTheDocument(); + }); + + it("does not show the General setting tab header for non-local cluster", () => { + expect(rendered.queryByTestId("general-tab")).not.toBeInTheDocument(); + }); + + it("shows Proxy setting tab header", () => { + expect(rendered.queryByTestId("proxy-tab")).toBeInTheDocument(); + }); + + it("shows Terminal setting tab header", () => { + expect(rendered.queryByTestId("terminal-tab")).toBeInTheDocument(); + }); + + it("shows Namespaces setting tab header", () => { + expect(rendered.queryByTestId("namespace-tab")).toBeInTheDocument(); + }); + + it("shows Metrics setting tab header", () => { + expect(rendered.queryByTestId("metrics-tab")).toBeInTheDocument(); + }); + + it("shows Node Shell setting tab header", () => { + expect(rendered.queryByTestId("node-shell-tab")).toBeInTheDocument(); + }); + + it("shows the setting tabs in the correct order", () => { + expect(rendered.getByTestId("proxy-tab").nextSibling).toHaveAttribute("data-testid", "terminal-tab"); + expect(rendered.getByTestId("terminal-tab").nextSibling).toHaveAttribute("data-testid", "namespace-tab"); + expect(rendered.getByTestId("namespace-tab").nextSibling).toHaveAttribute("data-testid", "metrics-tab"); + expect(rendered.getByTestId("metrics-tab").nextSibling).toHaveAttribute("data-testid", "node-shell-tab"); + }); + }); + + describe("when navigating to local cluster entity settings", () => { + beforeEach(() => { + const navigateToEntitySettings = windowDi.inject(navigateToEntitySettingsInjectable); + + navigateToEntitySettings(localClusterEntity.getId()); + }); + + it("renders", () => { + expect(rendered.baseElement).toMatchSnapshot(); + }); + + it("shows entity settings page", () => { + expect(rendered.queryByTestId("entity-settings")).toBeInTheDocument(); + }); + + it("shows the General setting tab header", () => { + expect(rendered.queryByTestId("general-tab")).toBeInTheDocument(); + }); + + it("shows Proxy setting tab header", () => { + expect(rendered.queryByTestId("proxy-tab")).toBeInTheDocument(); + }); + + it("shows Terminal setting tab header", () => { + expect(rendered.queryByTestId("terminal-tab")).toBeInTheDocument(); + }); + + it("shows Namespaces setting tab header", () => { + expect(rendered.queryByTestId("namespace-tab")).toBeInTheDocument(); + }); + + it("shows Metrics setting tab header", () => { + expect(rendered.queryByTestId("metrics-tab")).toBeInTheDocument(); + }); + + it("shows Node Shell setting tab header", () => { + expect(rendered.queryByTestId("node-shell-tab")).toBeInTheDocument(); + }); + + it("shows the setting tabs in the correct order", () => { + expect(rendered.getByTestId("general-tab").nextSibling).toHaveAttribute("data-testid", "proxy-tab"); + expect(rendered.getByTestId("proxy-tab").nextSibling).toHaveAttribute("data-testid", "terminal-tab"); + expect(rendered.getByTestId("terminal-tab").nextSibling).toHaveAttribute("data-testid", "namespace-tab"); + expect(rendered.getByTestId("namespace-tab").nextSibling).toHaveAttribute("data-testid", "metrics-tab"); + expect(rendered.getByTestId("metrics-tab").nextSibling).toHaveAttribute("data-testid", "node-shell-tab"); + }); + }); + + describe("when navigating to weblink entity settings", () => { + beforeEach(() => { + const navigateToEntitySettings = windowDi.inject(navigateToEntitySettingsInjectable); + + navigateToEntitySettings(otherEntity.getId()); + }); + + it("renders", () => { + expect(rendered.baseElement).toMatchSnapshot(); + }); + + it("shows entity settings page", () => { + expect(rendered.queryByTestId("entity-settings")).toBeInTheDocument(); + }); + + it("does not show the unrelated settings", () => { + expect(rendered.queryByTestId("general-tab")).not.toBeInTheDocument(); + }); + + it("shows no settings page info", () => { + expect(rendered.baseElement.querySelector("[data-preference-page-does-not-exist-test='true']")).toBeInTheDocument(); + }); + }); +}); diff --git a/src/renderer/components/+entity-settings/entity-settings.tsx b/src/renderer/components/+entity-settings/entity-settings.tsx index 994ad0aefd..8b7fd9f4ce 100644 --- a/src/renderer/components/+entity-settings/entity-settings.tsx +++ b/src/renderer/components/+entity-settings/entity-settings.tsx @@ -98,16 +98,30 @@ const NonInjectedCatalogEntitySettings = observer((props: CatalogEntitySettingsP { - (tabId && setting) && ( -
-

{setting.title}

+ tabId && setting + ? (
- +

{setting.title}

+
+ +
-
- ) + ) + : ( +
+ No settings found for + {" "} + {entity.apiVersion} + / + {entity.kind} +
+ ) }
); diff --git a/src/renderer/components/+entity-settings/internal-kubernetes-cluster/general-settings.injectable.tsx b/src/renderer/components/+entity-settings/internal-kubernetes-cluster/general-settings.injectable.tsx index 737e0db5c4..059f8c15eb 100644 --- a/src/renderer/components/+entity-settings/internal-kubernetes-cluster/general-settings.injectable.tsx +++ b/src/renderer/components/+entity-settings/internal-kubernetes-cluster/general-settings.injectable.tsx @@ -54,13 +54,13 @@ const GeneralKubernetesClusterSettings = withInjectables ({ - apiVersions: ["entity.k8slens.dev/v1alpha1"], + apiVersions: new Set(["entity.k8slens.dev/v1alpha1"]), kind: "KubernetesCluster", source: "local", title: "General", group: "Settings", id: "general", - priority: 40, + orderNumber: 0, components: { View: GeneralKubernetesClusterSettings, }, diff --git a/src/renderer/components/+entity-settings/internal-kubernetes-cluster/metrics-settings.injectable.tsx b/src/renderer/components/+entity-settings/internal-kubernetes-cluster/metrics-settings.injectable.tsx index e5afa9fba1..1be5f7e78a 100644 --- a/src/renderer/components/+entity-settings/internal-kubernetes-cluster/metrics-settings.injectable.tsx +++ b/src/renderer/components/+entity-settings/internal-kubernetes-cluster/metrics-settings.injectable.tsx @@ -48,12 +48,12 @@ const MetricsKubernetesClusterSettings = withInjectables ({ - apiVersions: ["entity.k8slens.dev/v1alpha1"], + apiVersions: new Set(["entity.k8slens.dev/v1alpha1"]), kind: "KubernetesCluster", title: "Metrics", group: "Settings", id: "metrics", - priority: 40, + orderNumber: 40, components: { View: MetricsKubernetesClusterSettings, }, diff --git a/src/renderer/components/+entity-settings/internal-kubernetes-cluster/namespace-settings.injectable.tsx b/src/renderer/components/+entity-settings/internal-kubernetes-cluster/namespace-settings.injectable.tsx index 9e0f404ad0..9f599bc188 100644 --- a/src/renderer/components/+entity-settings/internal-kubernetes-cluster/namespace-settings.injectable.tsx +++ b/src/renderer/components/+entity-settings/internal-kubernetes-cluster/namespace-settings.injectable.tsx @@ -39,12 +39,12 @@ const NamespaceKubernetesClusterSettings = withInjectables ({ - apiVersions: ["entity.k8slens.dev/v1alpha1"], + apiVersions: new Set(["entity.k8slens.dev/v1alpha1"]), kind: "KubernetesCluster", title: "Namespace", group: "Settings", id: "namespace", - priority: 40, + orderNumber: 30, components: { View: NamespaceKubernetesClusterSettings, }, diff --git a/src/renderer/components/+entity-settings/internal-kubernetes-cluster/node-shell-settings.injectable.tsx b/src/renderer/components/+entity-settings/internal-kubernetes-cluster/node-shell-settings.injectable.tsx index b013d5ea5e..ff899095d6 100644 --- a/src/renderer/components/+entity-settings/internal-kubernetes-cluster/node-shell-settings.injectable.tsx +++ b/src/renderer/components/+entity-settings/internal-kubernetes-cluster/node-shell-settings.injectable.tsx @@ -39,12 +39,12 @@ const NodeShellKubernetesClusterSettings = withInjectables ({ - apiVersions: ["entity.k8slens.dev/v1alpha1"], + apiVersions: new Set(["entity.k8slens.dev/v1alpha1"]), kind: "KubernetesCluster", title: "Node Shell", group: "Settings", id: "node-shell", - priority: 40, + orderNumber: 45, components: { View: NodeShellKubernetesClusterSettings, }, diff --git a/src/renderer/components/+entity-settings/internal-kubernetes-cluster/proxy-settings.injectable.tsx b/src/renderer/components/+entity-settings/internal-kubernetes-cluster/proxy-settings.injectable.tsx index 7db969b504..4479a04c2a 100644 --- a/src/renderer/components/+entity-settings/internal-kubernetes-cluster/proxy-settings.injectable.tsx +++ b/src/renderer/components/+entity-settings/internal-kubernetes-cluster/proxy-settings.injectable.tsx @@ -39,12 +39,12 @@ const ProxyKubernetesClusterSettings = withInjectables ({ - apiVersions: ["entity.k8slens.dev/v1alpha1"], + apiVersions: new Set(["entity.k8slens.dev/v1alpha1"]), kind: "KubernetesCluster", title: "Proxy", group: "Settings", id: "proxy", - priority: 40, + orderNumber: 10, components: { View: ProxyKubernetesClusterSettings, }, diff --git a/src/renderer/components/+entity-settings/internal-kubernetes-cluster/terminal-settings.injectable.tsx b/src/renderer/components/+entity-settings/internal-kubernetes-cluster/terminal-settings.injectable.tsx index da6ddb7aa1..e778c97728 100644 --- a/src/renderer/components/+entity-settings/internal-kubernetes-cluster/terminal-settings.injectable.tsx +++ b/src/renderer/components/+entity-settings/internal-kubernetes-cluster/terminal-settings.injectable.tsx @@ -39,12 +39,12 @@ const TerminalKubernetesClusterSettings = withInjectables ({ - apiVersions: ["entity.k8slens.dev/v1alpha1"], + apiVersions: new Set(["entity.k8slens.dev/v1alpha1"]), kind: "KubernetesCluster", title: "Terminal", group: "Settings", id: "terminal", - priority: 40, + orderNumber: 20, components: { View: TerminalKubernetesClusterSettings, }, diff --git a/src/renderer/components/cluster-settings/icon-settings.tsx b/src/renderer/components/cluster-settings/icon-settings.tsx index 4f5c6abd78..55e4b21828 100644 --- a/src/renderer/components/cluster-settings/icon-settings.tsx +++ b/src/renderer/components/cluster-settings/icon-settings.tsx @@ -4,14 +4,14 @@ */ import React from "react"; -import type { Cluster } from "../../../../common/cluster/cluster"; -import { autoBind } from "../../../utils"; +import type { Cluster } from "../../../common/cluster/cluster"; +import { autoBind } from "../../utils"; import { observable } from "mobx"; import { observer } from "mobx-react"; -import type { KubernetesCluster } from "../../../../common/catalog-entities"; -import { FilePicker, OverSizeLimitStyle } from "../../file-picker"; -import { MenuActions, MenuItem } from "../../menu"; -import { Avatar } from "../../avatar"; +import type { KubernetesCluster } from "../../../common/catalog-entities"; +import { FilePicker, OverSizeLimitStyle } from "../file-picker"; +import { MenuActions, MenuItem } from "../menu"; +import { Avatar } from "../avatar"; enum GeneralInputStatus { CLEAN = "clean", diff --git a/src/renderer/components/cluster-settings/kubeconfig.tsx b/src/renderer/components/cluster-settings/kubeconfig.tsx index cc94ab4548..251185ba89 100644 --- a/src/renderer/components/cluster-settings/kubeconfig.tsx +++ b/src/renderer/components/cluster-settings/kubeconfig.tsx @@ -4,11 +4,11 @@ */ import React from "react"; -import type { Cluster } from "../../../../common/cluster/cluster"; +import type { Cluster } from "../../../common/cluster/cluster"; import { observer } from "mobx-react"; -import { SubTitle } from "../../layout/sub-title"; +import { SubTitle } from "../layout/sub-title"; import { shell } from "electron"; -import { Notice } from "../../+extensions/notice"; +import { Notice } from "../+extensions/notice"; export interface ClusterKubeconfigProps { cluster: Cluster; diff --git a/src/renderer/components/cluster-settings/local-terminal-settings.tsx b/src/renderer/components/cluster-settings/local-terminal-settings.tsx index 639623e08f..9a37381b15 100644 --- a/src/renderer/components/cluster-settings/local-terminal-settings.tsx +++ b/src/renderer/components/cluster-settings/local-terminal-settings.tsx @@ -5,20 +5,20 @@ import React, { useEffect, useState } from "react"; import { observer } from "mobx-react"; -import type { Cluster } from "../../../../common/cluster/cluster"; -import { Input } from "../../input"; -import { SubTitle } from "../../layout/sub-title"; -import type { ShowNotification } from "../../notifications"; -import { Icon } from "../../icon"; -import { PathPicker } from "../../path-picker"; -import { isWindows } from "../../../../common/vars"; +import type { Cluster } from "../../../common/cluster/cluster"; +import { Input } from "../input"; +import { SubTitle } from "../layout/sub-title"; +import type { ShowNotification } from "../notifications"; +import { Icon } from "../icon"; +import { PathPicker } from "../path-picker"; import { withInjectables } from "@ogre-tools/injectable-react"; -import showErrorNotificationInjectable from "../../notifications/show-error-notification.injectable"; -import type { ValidateDirectory } from "../../../../common/fs/validate-directory.injectable"; -import validateDirectoryInjectable from "../../../../common/fs/validate-directory.injectable"; -import type { ResolveTilde } from "../../../../common/path/resolve-tilde.injectable"; -import resolveTildeInjectable from "../../../../common/path/resolve-tilde.injectable"; -import Gutter from "../../gutter/gutter"; +import showErrorNotificationInjectable from "../notifications/show-error-notification.injectable"; +import type { ValidateDirectory } from "../../../common/fs/validate-directory.injectable"; +import validateDirectoryInjectable from "../../../common/fs/validate-directory.injectable"; +import type { ResolveTilde } from "../../../common/path/resolve-tilde.injectable"; +import resolveTildeInjectable from "../../../common/path/resolve-tilde.injectable"; +import Gutter from "../gutter/gutter"; +import isWindowsInjectable from "../../../common/vars/is-windows.injectable"; export interface ClusterLocalTerminalSettingProps { cluster: Cluster; @@ -27,6 +27,7 @@ interface Dependencies { showErrorNotification: ShowNotification; validateDirectory: ValidateDirectory; resolveTilde: ResolveTilde; + isWindows: boolean; } const NonInjectedClusterLocalTerminalSetting = observer(({ @@ -34,6 +35,7 @@ const NonInjectedClusterLocalTerminalSetting = observer(({ showErrorNotification, validateDirectory, resolveTilde, + isWindows, }: Dependencies & ClusterLocalTerminalSettingProps) => { if (!cluster) { return null; @@ -165,5 +167,6 @@ export const ClusterLocalTerminalSetting = withInjectables (callback) => callback()); di.override(lensResourcesDirInjectable, () => "/irrelevant"); - // TODO: remove when entity settings registry is refactored - di.override(getEntitySettingCommandsInjectable, () => () => []); - // TODO: Remove after "LensRendererExtension.isEnabledForCluster" is removed di.override(extensionShouldBeEnabledForClusterFrameInjectable, () => asyncComputed({ getValueFromObservedPromise: async () => true, valueWhenPending: true }),