diff --git a/src/behaviours/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx b/src/behaviours/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx index 26a2d17c8d..ff0bc402a8 100644 --- a/src/behaviours/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx +++ b/src/behaviours/cluster/sidebar-and-tab-navigation-for-extensions.test.tsx @@ -19,6 +19,8 @@ import assert from "assert"; import hostedClusterIdInjectable from "../../renderer/cluster-frame-context/hosted-cluster-id.injectable"; import { advanceFakeTime, useFakeTime } from "../../common/test-utils/use-fake-time"; import { getExtensionFakeFor } from "../../renderer/components/test-utils/get-extension-fake"; +import type { IObservableValue } from "mobx"; +import { runInAction, computed, observable } from "mobx"; // TODO: Make tooltips free of side effects by making it deterministic jest.mock("../../renderer/components/tooltip/withTooltip", () => ({ @@ -49,7 +51,11 @@ describe("cluster - sidebar and tab navigation for extensions", () => { }); describe("given extension with cluster pages and cluster page menus", () => { + let someObservable: IObservableValue; + beforeEach(() => { + someObservable = observable.box(false); + const getExtensionFake = getExtensionFakeFor(applicationBuilder); const testExtension = getExtensionFake({ @@ -114,6 +120,16 @@ describe("cluster - sidebar and tab navigation for extensions", () => { Icon: null as never, }, }, + + { + id: "some-menu-with-controlled-visibility", + title: "Some menu with controlled visibility", + visible: computed(() => someObservable.get()), + + components: { + Icon: () =>
Some icon
, + }, + }, ], }, }); @@ -276,6 +292,26 @@ describe("cluster - sidebar and tab navigation for extensions", () => { expect(child).toBeNull(); }); + it("does not show the sidebar item that should be hidden", () => { + const child = rendered.queryByTestId( + "sidebar-item-some-extension-name-some-menu-with-controlled-visibility", + ); + + expect(child).not.toBeInTheDocument(); + }); + + it("when sidebar item becomes visible, shows the sidebar item", () => { + runInAction(() => { + someObservable.set(true); + }); + + const child = rendered.queryByTestId( + "sidebar-item-some-extension-name-some-menu-with-controlled-visibility", + ); + + expect(child).toBeInTheDocument(); + }); + describe("when a parent sidebar item is expanded", () => { beforeEach(() => { const parentLink = rendered.getByTestId( diff --git a/src/extensions/registries/page-menu-registry.ts b/src/extensions/registries/page-menu-registry.ts index d69bcfadfa..d083d729c4 100644 --- a/src/extensions/registries/page-menu-registry.ts +++ b/src/extensions/registries/page-menu-registry.ts @@ -7,6 +7,7 @@ import type { IconProps } from "../../renderer/components/icon"; import type React from "react"; import type { PageTarget } from "./page-registry"; +import type { IComputedValue } from "mobx"; export interface ClusterPageMenuRegistration { id?: string; @@ -14,6 +15,7 @@ export interface ClusterPageMenuRegistration { target?: PageTarget; title: React.ReactNode; components: ClusterPageMenuComponents; + visible?: IComputedValue; } export interface ClusterPageMenuComponents { diff --git a/src/renderer/components/layout/extension-sidebar-item-registrator.injectable.tsx b/src/renderer/components/layout/extension-sidebar-item-registrator.injectable.tsx index 1a1a8515d9..28c0ed89ed 100644 --- a/src/renderer/components/layout/extension-sidebar-item-registrator.injectable.tsx +++ b/src/renderer/components/layout/extension-sidebar-item-registrator.injectable.tsx @@ -49,6 +49,8 @@ const extensionSidebarItemRegistratorInjectable = getInjectable({ ? `${extension.sanitizedExtensionId}-${registration.parentId}` : null, + ...(registration.visible ? { isVisible: registration.visible } : {}), + title: registration.title, getIcon: registration.components.Icon ? () =>