From 0da1f216fbee39f4b31d31f7a414a716857ae93a Mon Sep 17 00:00:00 2001 From: Janne Savolainen Date: Thu, 7 Jul 2022 15:26:17 +0300 Subject: [PATCH] Expose reactive way to disable pages in Extension API Signed-off-by: Janne Savolainen --- .../reactively-disable-cluster-pages.test.tsx | 70 +++++++++++++++++++ ...tively-hide-kube-object-menu-item.test.tsx | 3 - .../reactively-disable-global-pages.test.tsx | 68 ++++++++++++++++++ src/extensions/registries/page-registry.ts | 2 + ...extension-route-registrator.injectable.tsx | 22 +++--- 5 files changed, 154 insertions(+), 11 deletions(-) create mode 100644 src/behaviours/cluster/extension-api/reactively-disable-cluster-pages.test.tsx create mode 100644 src/behaviours/routes/extension-api/reactively-disable-global-pages.test.tsx diff --git a/src/behaviours/cluster/extension-api/reactively-disable-cluster-pages.test.tsx b/src/behaviours/cluster/extension-api/reactively-disable-cluster-pages.test.tsx new file mode 100644 index 0000000000..4cc5e45576 --- /dev/null +++ b/src/behaviours/cluster/extension-api/reactively-disable-cluster-pages.test.tsx @@ -0,0 +1,70 @@ +/** + * 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 type { IObservableValue } from "mobx"; +import { observable, runInAction, computed } from "mobx"; +import React from "react"; +import type { TestExtensionRenderer } from "../../../renderer/components/test-utils/get-extension-fake"; +import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; +import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; +import { getExtensionFakeFor } from "../../../renderer/components/test-utils/get-extension-fake"; + +describe("reactively disable cluster pages", () => { + let builder: ApplicationBuilder; + let rendered: RenderResult; + let someObservable: IObservableValue; + let rendererTestExtension: TestExtensionRenderer; + + beforeEach(async () => { + builder = getApplicationBuilder(); + + builder.setEnvironmentToClusterFrame(); + + const getExtensionFake = getExtensionFakeFor(builder); + + someObservable = observable.box(false); + + const testExtension = getExtensionFake({ + id: "test-extension-id", + name: "test-extension", + + rendererOptions: { + clusterPages: [{ + components: { + Page: () =>
Some page
, + }, + + enabled: computed(() => someObservable.get()), + }], + }, + }); + + rendered = await builder.render(); + + builder.extensions.enable(testExtension); + + rendererTestExtension = testExtension.renderer; + }); + + it("when navigating to the page, does not show the page", () => { + rendererTestExtension.navigate(); + + const actual = rendered.queryByTestId("some-test-page"); + + expect(actual).not.toBeInTheDocument(); + }); + + it("given page becomes enabled, when navigating to the page, shows the page", () => { + runInAction(() => { + someObservable.set(true); + }); + + rendererTestExtension.navigate(); + + const actual = rendered.queryByTestId("some-test-page"); + + expect(actual).toBeInTheDocument(); + }); +}); diff --git a/src/behaviours/cluster/kube-object-menu/extension-api/reactively-hide-kube-object-menu-item.test.tsx b/src/behaviours/cluster/kube-object-menu/extension-api/reactively-hide-kube-object-menu-item.test.tsx index 5fc637f845..74f33a657a 100644 --- a/src/behaviours/cluster/kube-object-menu/extension-api/reactively-hide-kube-object-menu-item.test.tsx +++ b/src/behaviours/cluster/kube-object-menu/extension-api/reactively-hide-kube-object-menu-item.test.tsx @@ -13,7 +13,6 @@ import { observable, runInAction, computed } from "mobx"; import React from "react"; import { navigateToRouteInjectionToken } from "../../../../common/front-end-routing/navigate-to-route-injection-token"; import { routeSpecificComponentInjectionToken } from "../../../../renderer/routes/route-specific-component-injection-token"; -import extensionShouldBeEnabledForClusterFrameInjectable from "../../../../renderer/extension-loader/extension-should-be-enabled-for-cluster-frame.injectable"; import { KubeObject } from "../../../../common/k8s-api/kube-object"; import { KubeObjectMenu } from "../../../../renderer/components/kube-object-menu"; @@ -27,8 +26,6 @@ describe("reactively hide kube object menu item", () => { const rendererDi = builder.dis.rendererDi; - rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable); - rendererDi.register(testRouteInjectable, testRouteComponentInjectable); builder.setEnvironmentToClusterFrame(); diff --git a/src/behaviours/routes/extension-api/reactively-disable-global-pages.test.tsx b/src/behaviours/routes/extension-api/reactively-disable-global-pages.test.tsx new file mode 100644 index 0000000000..523a56cf79 --- /dev/null +++ b/src/behaviours/routes/extension-api/reactively-disable-global-pages.test.tsx @@ -0,0 +1,68 @@ +/** + * 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 type { IObservableValue } from "mobx"; +import { observable, runInAction, computed } from "mobx"; +import React from "react"; +import type { TestExtensionRenderer } from "../../../renderer/components/test-utils/get-extension-fake"; +import type { ApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; +import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; +import { getExtensionFakeFor } from "../../../renderer/components/test-utils/get-extension-fake"; + +describe("reactively disable global pages", () => { + let builder: ApplicationBuilder; + let rendered: RenderResult; + let someObservable: IObservableValue; + let rendererTestExtension: TestExtensionRenderer; + + beforeEach(async () => { + builder = getApplicationBuilder(); + + const getExtensionFake = getExtensionFakeFor(builder); + + someObservable = observable.box(false); + + const testExtension = getExtensionFake({ + id: "test-extension-id", + name: "test-extension", + + rendererOptions: { + globalPages: [{ + components: { + Page: () =>
Some page
, + }, + + enabled: computed(() => someObservable.get()), + }], + }, + }); + + rendered = await builder.render(); + + builder.extensions.enable(testExtension); + + rendererTestExtension = testExtension.renderer; + }); + + it("when navigating to the page, does not show the page", () => { + rendererTestExtension.navigate(); + + const actual = rendered.queryByTestId("some-test-page"); + + expect(actual).not.toBeInTheDocument(); + }); + + it("given page becomes enabled, when navigating to the page, shows the page", () => { + runInAction(() => { + someObservable.set(true); + }); + + rendererTestExtension.navigate(); + + const actual = rendered.queryByTestId("some-test-page"); + + expect(actual).toBeInTheDocument(); + }); +}); diff --git a/src/extensions/registries/page-registry.ts b/src/extensions/registries/page-registry.ts index b698460a54..6584b3aa9b 100644 --- a/src/extensions/registries/page-registry.ts +++ b/src/extensions/registries/page-registry.ts @@ -2,6 +2,7 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ +import type { IComputedValue } from "mobx"; import type { PageParamInit, PageParam } from "../../renderer/navigation"; // Extensions-api -> Custom page registration @@ -14,6 +15,7 @@ export interface PageRegistration { id?: string; params?: PageParams, "name" | "prefix">>; components: PageComponents; + enabled?: IComputedValue; } export interface PageComponents { diff --git a/src/renderer/routes/extension-route-registrator.injectable.tsx b/src/renderer/routes/extension-route-registrator.injectable.tsx index 241e6950a5..d36c17cdad 100644 --- a/src/renderer/routes/extension-route-registrator.injectable.tsx +++ b/src/renderer/routes/extension-route-registrator.injectable.tsx @@ -35,16 +35,22 @@ const extensionRouteRegistratorInjectable = getInjectable({ return [ ...extension.globalPages.map( - toRouteInjectable( - false, - computed(() => true), + toRouteInjectable(false, (registration) => + computed(() => + registration.enabled ? registration.enabled.get() : true, + ), ), ), ...extension.clusterPages.map( - toRouteInjectable( - true, - computed(() => extensionShouldBeEnabledForClusterFrame.value.get()), + toRouteInjectable(true, (registration) => + computed(() => { + if (!extensionShouldBeEnabledForClusterFrame.value.get()) { + return false; + } + + return registration.enabled ? registration.enabled.get() : true; + }), ), ), ].flat(); @@ -61,7 +67,7 @@ const toRouteInjectableFor = di: DiContainerForInjection, extension: LensRendererExtension, ) => - (clusterFrame: boolean, isEnabled: IComputedValue) => + (clusterFrame: boolean, getIsEnabled: (registration: PageRegistration) => IComputedValue) => (registration: PageRegistration) => { const routeInjectable = getInjectable({ id: `route-${registration.id}-for-extension-${extension.sanitizedExtensionId}`, @@ -69,7 +75,7 @@ const toRouteInjectableFor = instantiate: () => ({ path: getExtensionRoutePath(extension, registration.id), clusterFrame, - isEnabled, + isEnabled: getIsEnabled(registration), extension, }),