mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Expose reactive ways to hide items in cluster frame using Extension API - PART 7 (#5824)
* Kludge "isEnabledForCluster" work again for cluster pages Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Kludge "isEnabledForCluster" work again for kube object details Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Expose reactive way to hide kube object detail items in Extension API Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Expose reactive way to hide kube object menu items in Extension API Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Expose reactive way to hide kube object status items in Extension API Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Expose reactive way to hide workload overview detail items in Extension API Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Expose reactive way to disable pages in Extension API Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Expose a way to access active cluster from Extension API Signed-off-by: Janne Savolainen <janne.savolainen@live.fi> * Deprecate "isEnabledForCluster" in favor of individual enabled or visible properties for each registration Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
parent
ca40c51117
commit
d66e6c23c5
@ -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<boolean>;
|
||||
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: () => <div data-testid="some-test-page">Some page</div>,
|
||||
},
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,138 @@
|
||||
/**
|
||||
* 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 { 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";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token";
|
||||
import type { IObservableValue } from "mobx";
|
||||
import { runInAction, computed, observable } 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 { KubeObject } from "../../../../common/k8s-api/kube-object";
|
||||
import apiManagerInjectable from "../../../../common/k8s-api/api-manager/manager.injectable";
|
||||
import { KubeObjectDetails } from "../../../../renderer/components/kube-object-details";
|
||||
import type { ApiManager } from "../../../../common/k8s-api/api-manager";
|
||||
|
||||
describe("reactively hide kube object detail item", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
let rendered: RenderResult;
|
||||
let someObservable: IObservableValue<boolean>;
|
||||
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
builder.beforeApplicationStart(({ rendererDi }) => {
|
||||
rendererDi.override(
|
||||
apiManagerInjectable,
|
||||
() =>
|
||||
({
|
||||
getStore: () => ({
|
||||
getByPath: () =>
|
||||
getKubeObjectStub("some-kind", "some-api-version"),
|
||||
}),
|
||||
} as unknown as ApiManager),
|
||||
);
|
||||
});
|
||||
|
||||
const rendererDi = builder.dis.rendererDi;
|
||||
|
||||
rendererDi.register(testRouteInjectable, testRouteComponentInjectable);
|
||||
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
const getExtensionFake = getExtensionFakeFor(builder);
|
||||
|
||||
someObservable = observable.box(false);
|
||||
|
||||
const testExtension = getExtensionFake({
|
||||
id: "test-extension-id",
|
||||
name: "test-extension",
|
||||
|
||||
rendererOptions: {
|
||||
kubeObjectDetailItems: [
|
||||
{
|
||||
kind: "some-kind",
|
||||
apiVersions: ["some-api-version"],
|
||||
|
||||
components: {
|
||||
Details: () => (
|
||||
<div data-testid="some-kube-object-detail-item">
|
||||
Some detail
|
||||
</div>
|
||||
),
|
||||
},
|
||||
|
||||
visible: computed(() => someObservable.get()),
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
|
||||
const testRoute = rendererDi.inject(testRouteInjectable);
|
||||
|
||||
navigateToRoute(testRoute);
|
||||
|
||||
builder.extensions.enable(testExtension);
|
||||
});
|
||||
|
||||
it("does not show the kube object detail item", () => {
|
||||
const actual = rendered.queryByTestId("some-kube-object-detail-item");
|
||||
|
||||
expect(actual).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("given item should be shown, shows the kube object detail item", () => {
|
||||
runInAction(() => {
|
||||
someObservable.set(true);
|
||||
});
|
||||
|
||||
const actual = rendered.queryByTestId("some-kube-object-detail-item");
|
||||
|
||||
expect(actual).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
const testRouteInjectable = getInjectable({
|
||||
id: "test-route",
|
||||
|
||||
instantiate: () => ({
|
||||
path: "/test-route",
|
||||
clusterFrame: true,
|
||||
isEnabled: computed(() => true),
|
||||
}),
|
||||
|
||||
injectionToken: frontEndRouteInjectionToken,
|
||||
});
|
||||
|
||||
const testRouteComponentInjectable = getInjectable({
|
||||
id: "test-route-component",
|
||||
|
||||
instantiate: (di) => ({
|
||||
route: di.inject(testRouteInjectable),
|
||||
|
||||
Component: () => <KubeObjectDetails />,
|
||||
}),
|
||||
|
||||
injectionToken: routeSpecificComponentInjectionToken,
|
||||
});
|
||||
|
||||
const getKubeObjectStub = (kind: string, apiVersion: string) =>
|
||||
KubeObject.create({
|
||||
apiVersion,
|
||||
kind,
|
||||
metadata: {
|
||||
uid: "some-uid",
|
||||
name: "some-name",
|
||||
resourceVersion: "some-resource-version",
|
||||
namespace: "some-namespace",
|
||||
selfLink: "",
|
||||
},
|
||||
});
|
||||
@ -18,7 +18,6 @@ import { routeSpecificComponentInjectionToken } from "../../../../renderer/route
|
||||
import { KubeObject } from "../../../../common/k8s-api/kube-object";
|
||||
import extensionShouldBeEnabledForClusterFrameInjectable from "../../../../renderer/extension-loader/extension-should-be-enabled-for-cluster-frame.injectable";
|
||||
import { KubeObjectMenu } from "../../../../renderer/components/kube-object-menu";
|
||||
import apiManagerInjectable from "../../../../common/k8s-api/api-manager/manager.injectable";
|
||||
|
||||
describe("disable kube object menu items when cluster is not relevant", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
@ -30,10 +29,6 @@ describe("disable kube object menu items when cluster is not relevant", () => {
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
builder.beforeApplicationStart(({ mainDi }) => {
|
||||
mainDi.override(apiManagerInjectable, () => ({}));
|
||||
});
|
||||
|
||||
const rendererDi = builder.dis.rendererDi;
|
||||
|
||||
rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
|
||||
|
||||
@ -0,0 +1,126 @@
|
||||
/**
|
||||
* 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 { 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";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token";
|
||||
import type { IObservableValue } from "mobx";
|
||||
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 { KubeObject } from "../../../../common/k8s-api/kube-object";
|
||||
import { KubeObjectMenu } from "../../../../renderer/components/kube-object-menu";
|
||||
|
||||
describe("reactively hide kube object menu item", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
let rendered: RenderResult;
|
||||
let someObservable: IObservableValue<boolean>;
|
||||
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
const rendererDi = builder.dis.rendererDi;
|
||||
|
||||
rendererDi.register(testRouteInjectable, testRouteComponentInjectable);
|
||||
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
const getExtensionFake = getExtensionFakeFor(builder);
|
||||
|
||||
someObservable = observable.box(false);
|
||||
|
||||
const testExtension = getExtensionFake({
|
||||
id: "test-extension-id",
|
||||
name: "test-extension",
|
||||
|
||||
rendererOptions: {
|
||||
kubeObjectMenuItems: [
|
||||
{
|
||||
kind: "some-kind",
|
||||
apiVersions: ["some-api-version"],
|
||||
components: {
|
||||
MenuItem: () => (
|
||||
<div data-testid="some-kube-object-menu-item">Some menu item</div>
|
||||
),
|
||||
},
|
||||
|
||||
visible: computed(() => someObservable.get()),
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
|
||||
const testRoute = rendererDi.inject(testRouteInjectable);
|
||||
|
||||
navigateToRoute(testRoute);
|
||||
|
||||
builder.extensions.enable(testExtension);
|
||||
});
|
||||
|
||||
it("does not show the kube object menu item", () => {
|
||||
const actual = rendered.queryByTestId("some-kube-object-menu-item");
|
||||
|
||||
expect(actual).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("given item should be shown, shows the kube object menu item", () => {
|
||||
runInAction(() => {
|
||||
someObservable.set(true);
|
||||
});
|
||||
|
||||
const actual = rendered.queryByTestId("some-kube-object-menu-item");
|
||||
|
||||
expect(actual).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
const testRouteInjectable = getInjectable({
|
||||
id: "test-route",
|
||||
|
||||
instantiate: () => ({
|
||||
path: "/test-route",
|
||||
clusterFrame: true,
|
||||
isEnabled: computed(() => true),
|
||||
}),
|
||||
|
||||
injectionToken: frontEndRouteInjectionToken,
|
||||
});
|
||||
|
||||
const testRouteComponentInjectable = getInjectable({
|
||||
id: "test-route-component",
|
||||
|
||||
instantiate: (di) => ({
|
||||
route: di.inject(testRouteInjectable),
|
||||
|
||||
Component: () => (
|
||||
<KubeObjectMenu
|
||||
toolbar={true}
|
||||
object={getKubeObjectStub("some-kind", "some-api-version")}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
|
||||
injectionToken: routeSpecificComponentInjectionToken,
|
||||
});
|
||||
|
||||
const getKubeObjectStub = (kind: string, apiVersion: string) =>
|
||||
KubeObject.create({
|
||||
apiVersion,
|
||||
kind,
|
||||
metadata: {
|
||||
uid: "some-uid",
|
||||
name: "some-name",
|
||||
resourceVersion: "some-resource-version",
|
||||
namespace: "some-namespace",
|
||||
selfLink: "",
|
||||
},
|
||||
});
|
||||
|
||||
@ -0,0 +1,132 @@
|
||||
/**
|
||||
* 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 { 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";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token";
|
||||
import type { IObservableValue } from "mobx";
|
||||
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 { KubeObjectStatusLevel } from "../../../../common/k8s-api/kube-object-status";
|
||||
import { KubeObjectStatusIcon } from "../../../../renderer/components/kube-object-status-icon";
|
||||
|
||||
describe("reactively hide kube object status", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
let rendered: RenderResult;
|
||||
let someObservable: IObservableValue<boolean>;
|
||||
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
const rendererDi = builder.dis.rendererDi;
|
||||
|
||||
rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
|
||||
|
||||
rendererDi.register(testRouteInjectable, testRouteComponentInjectable);
|
||||
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
const getExtensionFake = getExtensionFakeFor(builder);
|
||||
|
||||
someObservable = observable.box(false);
|
||||
|
||||
const testExtension = getExtensionFake({
|
||||
id: "test-extension-id",
|
||||
name: "test-extension",
|
||||
|
||||
rendererOptions: {
|
||||
kubeObjectStatusTexts: [
|
||||
{
|
||||
kind: "some-kind",
|
||||
apiVersions: ["some-api-version"],
|
||||
|
||||
resolve: () => ({
|
||||
level: KubeObjectStatusLevel.CRITICAL,
|
||||
text: "some-kube-object-status-text",
|
||||
}),
|
||||
|
||||
visible: computed(() => someObservable.get()),
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
|
||||
const testRoute = rendererDi.inject(testRouteInjectable);
|
||||
|
||||
navigateToRoute(testRoute);
|
||||
|
||||
builder.extensions.enable(testExtension);
|
||||
});
|
||||
|
||||
it("does not show the kube object status", () => {
|
||||
const actual = rendered.baseElement.querySelectorAll(
|
||||
".KubeObjectStatusIcon",
|
||||
);
|
||||
|
||||
expect(actual).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("given item should be shown, shows the kube object status", () => {
|
||||
runInAction(() => {
|
||||
someObservable.set(true);
|
||||
});
|
||||
|
||||
const actual = rendered.baseElement.querySelectorAll(
|
||||
".KubeObjectStatusIcon",
|
||||
);
|
||||
|
||||
expect(actual).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
const testRouteInjectable = getInjectable({
|
||||
id: "test-route",
|
||||
|
||||
instantiate: () => ({
|
||||
path: "/test-route",
|
||||
clusterFrame: true,
|
||||
isEnabled: computed(() => true),
|
||||
}),
|
||||
|
||||
injectionToken: frontEndRouteInjectionToken,
|
||||
});
|
||||
|
||||
const testRouteComponentInjectable = getInjectable({
|
||||
id: "test-route-component",
|
||||
|
||||
instantiate: (di) => ({
|
||||
route: di.inject(testRouteInjectable),
|
||||
|
||||
Component: () => (
|
||||
<KubeObjectStatusIcon
|
||||
object={getKubeObjectStub("some-kind", "some-api-version")}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
|
||||
injectionToken: routeSpecificComponentInjectionToken,
|
||||
});
|
||||
|
||||
const getKubeObjectStub = (kind: string, apiVersion: string) =>
|
||||
KubeObject.create({
|
||||
apiVersion,
|
||||
kind,
|
||||
metadata: {
|
||||
uid: "some-uid",
|
||||
name: "some-name",
|
||||
resourceVersion: "some-resource-version",
|
||||
namespace: "some-namespace",
|
||||
selfLink: "",
|
||||
},
|
||||
});
|
||||
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* 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 { computed, observable, runInAction } from "mobx";
|
||||
import React from "react";
|
||||
import navigateToWorkloadsOverviewInjectable from "../../../../../common/front-end-routing/routes/cluster/workloads/overview/navigate-to-workloads-overview.injectable";
|
||||
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 hide workloads overview details item", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
let rendered: RenderResult;
|
||||
let someObservable: IObservableValue<boolean>;
|
||||
|
||||
beforeEach(async () => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
const rendererDi = builder.dis.rendererDi;
|
||||
|
||||
builder.setEnvironmentToClusterFrame();
|
||||
|
||||
const getExtensionFake = getExtensionFakeFor(builder);
|
||||
|
||||
someObservable = observable.box(false);
|
||||
|
||||
const testExtension = getExtensionFake({
|
||||
id: "test-extension-id",
|
||||
name: "test-extension",
|
||||
|
||||
rendererOptions: {
|
||||
kubeWorkloadsOverviewItems: [
|
||||
{
|
||||
components: {
|
||||
Details: () => (
|
||||
<div data-testid="some-workload-overview-detail-item">Some detail component</div>
|
||||
),
|
||||
},
|
||||
|
||||
visible: computed(() => someObservable.get()),
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
rendered = await builder.render();
|
||||
|
||||
const navigateToWorkloadsOverview = rendererDi.inject(
|
||||
navigateToWorkloadsOverviewInjectable,
|
||||
);
|
||||
|
||||
navigateToWorkloadsOverview();
|
||||
|
||||
builder.extensions.enable(testExtension);
|
||||
});
|
||||
|
||||
it("does not show the workload overview detail item", () => {
|
||||
const actual = rendered.queryByTestId("some-workload-overview-detail-item");
|
||||
|
||||
expect(actual).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("given item should be shown, shows the workload overview detail item", () => {
|
||||
runInAction(() => {
|
||||
someObservable.set(true);
|
||||
});
|
||||
|
||||
const actual = rendered.queryByTestId("some-workload-overview-detail-item");
|
||||
|
||||
expect(actual).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@ -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<boolean>;
|
||||
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: () => <div data-testid="some-test-page">Some page</div>,
|
||||
},
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
@ -90,6 +90,8 @@ export class LensRendererExtension extends LensExtension<LensRendererExtensionDe
|
||||
* called when the extension is created within a cluster frame.
|
||||
*
|
||||
* The default implementation is to return `true`
|
||||
*
|
||||
* @deprecated Switch to using "enabled" or "visible" properties in each registration together with `activeCluster`
|
||||
*/
|
||||
async isEnabledForCluster(cluster: KubernetesCluster): Promise<Boolean> {
|
||||
return (void cluster) || true;
|
||||
|
||||
@ -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<string | Omit<PageParamInit<any>, "name" | "prefix">>;
|
||||
components: PageComponents;
|
||||
enabled?: IComputedValue<boolean>;
|
||||
}
|
||||
|
||||
export interface PageComponents {
|
||||
|
||||
@ -10,6 +10,7 @@ import type { Disposer } from "../../common/utils";
|
||||
import catalogCategoryRegistryInjectable from "../../common/catalog/category-registry.injectable";
|
||||
import { asLegacyGlobalForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
|
||||
import catalogEntityRegistryInjectable from "../../renderer/api/catalog/entity/registry.injectable";
|
||||
import activeKubernetesClusterInjectable from "../../renderer/cluster-frame-context/active-kubernetes-cluster.injectable";
|
||||
|
||||
export const catalogCategories = asLegacyGlobalForExtensionApi(catalogCategoryRegistryInjectable);
|
||||
|
||||
@ -53,3 +54,7 @@ export class CatalogEntityRegistry {
|
||||
}
|
||||
|
||||
export const catalogEntities = new CatalogEntityRegistry();
|
||||
|
||||
export const activeCluster = asLegacyGlobalForExtensionApi(
|
||||
activeKubernetesClusterInjectable,
|
||||
);
|
||||
|
||||
@ -38,9 +38,13 @@ const workloadOverviewDetailRegistratorInjectable = getInjectable({
|
||||
instantiate: () => ({
|
||||
Component: registration.components.Details,
|
||||
|
||||
enabled: computed(() =>
|
||||
extensionShouldBeEnabledForClusterFrame.value.get(),
|
||||
),
|
||||
enabled: computed(() => {
|
||||
if (!extensionShouldBeEnabledForClusterFrame.value.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return registration.visible ? registration.visible.get() : true;
|
||||
}),
|
||||
|
||||
orderNumber:
|
||||
0.5 + (registration.priority ? 100 - registration.priority : 50),
|
||||
|
||||
@ -1,3 +1,9 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { IComputedValue } from "mobx";
|
||||
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
@ -9,4 +15,5 @@ interface WorkloadsOverviewDetailComponents {
|
||||
export interface WorkloadsOverviewDetailRegistration {
|
||||
components: WorkloadsOverviewDetailComponents;
|
||||
priority?: number;
|
||||
visible?: IComputedValue<boolean>;
|
||||
}
|
||||
|
||||
@ -10,9 +10,7 @@ import extensionShouldBeEnabledForClusterFrameInjectable from "../../../extensio
|
||||
import { kubeObjectDetailItemInjectionToken } from "./kube-object-detail-item-injection-token";
|
||||
import { extensionRegistratorInjectionToken } from "../../../../extensions/extension-loader/extension-registrator-injection-token";
|
||||
import currentKubeObjectInDetailsInjectable from "../current-kube-object-in-details.injectable";
|
||||
import {
|
||||
kubeObjectMatchesToKindAndApiVersion,
|
||||
} from "./kube-object-matches-to-kind-and-api-version";
|
||||
import { kubeObjectMatchesToKindAndApiVersion } from "./kube-object-matches-to-kind-and-api-version";
|
||||
|
||||
const kubeObjectDetailItemRegistratorInjectable = getInjectable({
|
||||
id: "kube-object-detail-item-registrator",
|
||||
@ -45,20 +43,24 @@ const kubeObjectDetailItemRegistratorInjectable = getInjectable({
|
||||
id,
|
||||
|
||||
instantiate: (di) => {
|
||||
const kubeObject = di.inject(
|
||||
currentKubeObjectInDetailsInjectable,
|
||||
);
|
||||
const kubeObject = di.inject(currentKubeObjectInDetailsInjectable);
|
||||
|
||||
return {
|
||||
kind: registration.kind,
|
||||
apiVersions: registration.apiVersions,
|
||||
Component: registration.components.Details,
|
||||
|
||||
enabled: computed(
|
||||
() =>
|
||||
extensionShouldBeEnabledForClusterFrame.value.get() &&
|
||||
isRelevantKubeObject(kubeObject.get()),
|
||||
),
|
||||
enabled: computed(() => {
|
||||
if (!extensionShouldBeEnabledForClusterFrame.value.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isRelevantKubeObject(kubeObject.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return registration.visible ? registration.visible.get() : true;
|
||||
}),
|
||||
|
||||
orderNumber: 300 - (registration.priority || 50),
|
||||
};
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
import type { KubeObject } from "../../../common/k8s-api/kube-object";
|
||||
import type { KubeObjectDetailsProps } from "./kube-object-details";
|
||||
import type React from "react";
|
||||
import type { IComputedValue } from "mobx";
|
||||
|
||||
export interface KubeObjectDetailComponents<T extends KubeObject = KubeObject> {
|
||||
Details: React.ComponentType<KubeObjectDetailsProps<T>>;
|
||||
@ -15,4 +16,5 @@ export interface KubeObjectDetailRegistration<T extends KubeObject = KubeObject>
|
||||
apiVersions: string[];
|
||||
components: KubeObjectDetailComponents<T>;
|
||||
priority?: number;
|
||||
visible?: IComputedValue<boolean>;
|
||||
}
|
||||
|
||||
@ -40,9 +40,13 @@ const kubeObjectMenuItemRegistratorInjectable = getInjectable({
|
||||
apiVersions: registration.apiVersions,
|
||||
Component: registration.components.MenuItem,
|
||||
|
||||
enabled: computed(() =>
|
||||
extensionShouldBeEnabledForClusterFrame.value.get(),
|
||||
),
|
||||
enabled: computed(() => {
|
||||
if (!extensionShouldBeEnabledForClusterFrame.value.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return registration.visible ? registration.visible.get() : true;
|
||||
}),
|
||||
|
||||
orderNumber: 100,
|
||||
}),
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { IComputedValue } from "mobx";
|
||||
import type React from "react";
|
||||
import type { KubeObject } from "../../../common/k8s-api/kube-object";
|
||||
|
||||
@ -19,4 +20,5 @@ export interface KubeObjectMenuRegistration {
|
||||
kind: string;
|
||||
apiVersions: string[];
|
||||
components: KubeObjectMenuComponents;
|
||||
visible?: IComputedValue<boolean>;
|
||||
}
|
||||
|
||||
@ -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 { KubeObject } from "../../../common/k8s-api/kube-object";
|
||||
import type { KubeObjectStatus } from "../../../common/k8s-api/kube-object-status";
|
||||
|
||||
@ -9,4 +10,5 @@ export interface KubeObjectStatusRegistration {
|
||||
kind: string;
|
||||
apiVersions: string[];
|
||||
resolve: (object: KubeObject) => KubeObjectStatus;
|
||||
visible?: IComputedValue<boolean>;
|
||||
}
|
||||
|
||||
@ -38,9 +38,13 @@ const kubeObjectStatusTextRegistratorInjectable = getInjectable({
|
||||
instantiate: () => ({
|
||||
...registration,
|
||||
|
||||
enabled: computed(() =>
|
||||
extensionShouldBeEnabledForClusterFrame.value.get(),
|
||||
),
|
||||
enabled: computed(() => {
|
||||
if (!extensionShouldBeEnabledForClusterFrame.value.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return registration.visible ? registration.visible.get() : true;
|
||||
}),
|
||||
}),
|
||||
|
||||
injectionToken: kubeObjectStatusTextInjectionToken,
|
||||
|
||||
@ -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<boolean>) =>
|
||||
(clusterFrame: boolean, getIsEnabled: (registration: PageRegistration) => IComputedValue<boolean>) =>
|
||||
(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,
|
||||
}),
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user