diff --git a/src/behaviours/cluster/kube-object-status-icon/__snapshots__/show-status-for-a-kube-object.test.tsx.snap b/src/behaviours/cluster/kube-object-status-icon/__snapshots__/show-status-for-a-kube-object.test.tsx.snap
new file mode 100644
index 0000000000..ec1b142188
--- /dev/null
+++ b/src/behaviours/cluster/kube-object-status-icon/__snapshots__/show-status-for-a-kube-object.test.tsx.snap
@@ -0,0 +1,2515 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`show status for a kube object given application starts and in test page renders 1`] = `
+
+
+
+`;
+
+exports[`show status for a kube object given application starts and in test page when critical status emerges renders 1`] = `
+
+
+
+`;
+
+exports[`show status for a kube object given application starts and in test page when info status emerges renders 1`] = `
+
+
+
+`;
+
+exports[`show status for a kube object given application starts and in test page when status for irrelevant kube object api version emerges renders 1`] = `
+
+
+
+`;
+
+exports[`show status for a kube object given application starts and in test page when status for irrelevant kube object kind emerges renders 1`] = `
+
+
+
+`;
+
+exports[`show status for a kube object given application starts and in test page when warning status emerges renders 1`] = `
+
+
+
+`;
diff --git a/src/behaviours/cluster/kube-object-status-icon/extension-api/__snapshots__/disable-kube-object-statuses-when-cluster-is-not-relevant.test.tsx.snap b/src/behaviours/cluster/kube-object-status-icon/extension-api/__snapshots__/disable-kube-object-statuses-when-cluster-is-not-relevant.test.tsx.snap
index fdb44e7371..cd98888838 100644
--- a/src/behaviours/cluster/kube-object-status-icon/extension-api/__snapshots__/disable-kube-object-statuses-when-cluster-is-not-relevant.test.tsx.snap
+++ b/src/behaviours/cluster/kube-object-status-icon/extension-api/__snapshots__/disable-kube-object-statuses-when-cluster-is-not-relevant.test.tsx.snap
@@ -267,6 +267,7 @@ exports[`disable kube object statuses when cluster is not relevant given extensi
>
({
+ withTooltip:
+ (Target: any) =>
+ ({ tooltip, ...props }: any) => {
+ if (tooltip) {
+ const testId = props["data-testid"];
+
+ return (
+ <>
+
+
+ {tooltip.children || tooltip}
+
+ >
+ );
+ }
+
+ return ;
+ },
+}));
+
+describe("show status for a kube object", () => {
+ let builder: ApplicationBuilder;
+ let infoStatusIsShown: boolean;
+ let warningStatusIsShown: boolean;
+ let criticalStatusIsShown: boolean;
+
+ beforeEach(() => {
+ useFakeTime("2015-10-21T07:28:00Z");
+
+ builder = getApplicationBuilder();
+
+ const rendererDi = builder.dis.rendererDi;
+
+ infoStatusIsShown = false;
+
+ const infoStatusInjectable = getInjectable({
+ id: "some-info-status",
+ injectionToken: kubeObjectStatusTextInjectionToken,
+
+ instantiate: () => ({
+ apiVersions: ["some-api-version"],
+ kind: "some-kind",
+ enabled: computed(() => true),
+
+ resolve: (resource) => infoStatusIsShown ? ({
+ level: KubeObjectStatusLevel.INFO,
+ text: `Some info status for ${resource.getName()}`,
+ timestamp: "2015-10-19T07:28:00Z",
+ }) : null,
+ }),
+ });
+
+ warningStatusIsShown = false;
+
+ const warningStatusInjectable = getInjectable({
+ id: "some-warning-status",
+ injectionToken: kubeObjectStatusTextInjectionToken,
+
+ instantiate: () => ({
+ apiVersions: ["some-api-version"],
+ kind: "some-kind",
+ enabled: computed(() => true),
+
+ resolve: (resource) => warningStatusIsShown ? ({
+ level: KubeObjectStatusLevel.WARNING,
+ text: `Some warning status for ${resource.getName()}`,
+ timestamp: "2015-10-19T07:28:00Z",
+ }) : null,
+ }),
+ });
+
+ criticalStatusIsShown = false;
+
+ const criticalStatusInjectable = getInjectable({
+ id: "some-critical-status",
+ injectionToken: kubeObjectStatusTextInjectionToken,
+
+ instantiate: () => ({
+ apiVersions: ["some-api-version"],
+ kind: "some-kind",
+ enabled: computed(() => true),
+
+ resolve: (resource) => {
+ return criticalStatusIsShown
+ ? {
+ level: KubeObjectStatusLevel.CRITICAL,
+ text: `Some critical status for ${resource.getName()}`,
+ timestamp: "2015-10-19T07:28:00Z",
+ }
+ : null;
+ },
+ }),
+ });
+
+ rendererDi.register(
+ testRouteInjectable,
+ testRouteComponentInjectable,
+ infoStatusInjectable,
+ warningStatusInjectable,
+ criticalStatusInjectable,
+ someAtomInjectable,
+ );
+
+ builder.setEnvironmentToClusterFrame();
+ });
+
+ describe("given application starts and in test page", () => {
+ let rendererDi: DiContainer;
+ let rendered: RenderResult;
+ let rerenderParent: () => void;
+
+ beforeEach(async () => {
+ rendered = await builder.render();
+
+ rendererDi = builder.dis.rendererDi;
+
+ const someAtom = rendererDi.inject(someAtomInjectable);
+
+ rerenderParent = rerenderParentFor(someAtom);
+
+ const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
+ const testRoute = rendererDi.inject(testRouteInjectable);
+
+ navigateToRoute(testRoute);
+ });
+
+ it("renders", () => {
+ expect(rendered.baseElement).toMatchSnapshot();
+ });
+
+ it("does not show any statuses yet", () => {
+ const status = rendered.queryByTestId(
+ "kube-object-status-icon-for-some-uid",
+ );
+
+ expect(status).not.toBeInTheDocument();
+ });
+
+ describe("when status for irrelevant kube object kind emerges", () => {
+ beforeEach(() => {
+ rendererDi.register(statusForIrrelevantKubeObjectKindInjectable);
+
+ rerenderParent();
+ });
+
+ it("renders", () => {
+ expect(rendered.baseElement).toMatchSnapshot();
+ });
+
+ it("does not show any statuses", () => {
+ const status = rendered.queryByTestId(
+ "kube-object-status-icon-for-some-uid",
+ );
+
+ expect(status).not.toBeInTheDocument();
+ });
+ });
+
+ describe("when status for irrelevant kube object api version emerges", () => {
+ beforeEach(() => {
+ rendererDi.register(statusForIrrelevantKubeObjectApiVersionInjectable);
+
+ rerenderParent();
+ });
+
+ it("renders", () => {
+ expect(rendered.baseElement).toMatchSnapshot();
+ });
+
+ it("does not show any statuses", () => {
+ const status = rendered.queryByTestId(
+ "kube-object-status-icon-for-some-uid",
+ );
+
+ expect(status).not.toBeInTheDocument();
+ });
+ });
+
+ describe("when info status emerges", () => {
+ beforeEach(() => {
+ infoStatusIsShown = true;
+
+ rerenderParent();
+ });
+
+ it("renders", () => {
+ expect(rendered.baseElement).toMatchSnapshot();
+ });
+
+ it("shows status", () => {
+ const status = rendered.getByTestId(
+ "kube-object-status-icon-for-some-uid",
+ );
+
+ expect(status).toBeInTheDocument();
+ });
+
+ it("show info status", () => {
+ const tooltipContent = rendered.getByTestId(
+ "tooltip-content-for-kube-object-status-icon-for-some-uid",
+ );
+
+ expect(tooltipContent).toHaveTextContent(
+ "Some info status for some-name",
+ );
+ });
+ });
+
+ describe("when warning status emerges", () => {
+ beforeEach(() => {
+ warningStatusIsShown = true;
+
+ rerenderParent();
+ });
+
+ it("renders", () => {
+ expect(rendered.baseElement).toMatchSnapshot();
+ });
+
+ it("show warning status", () => {
+ const tooltipContent = rendered.getByTestId(
+ "tooltip-content-for-kube-object-status-icon-for-some-uid",
+ );
+
+ expect(tooltipContent).toHaveTextContent(
+ "Some warning status for some-name",
+ );
+ });
+ });
+
+ describe("when critical status emerges", () => {
+ beforeEach(() => {
+ criticalStatusIsShown = true;
+
+ rerenderParent();
+ });
+
+ it("renders", () => {
+ expect(rendered.baseElement).toMatchSnapshot();
+ });
+
+ it("show critical status", () => {
+ const tooltipContent = rendered.getByTestId(
+ "tooltip-content-for-kube-object-status-icon-for-some-uid",
+ );
+
+ expect(tooltipContent).toHaveTextContent(
+ "Some critical status for some-name",
+ );
+ });
+ });
+ });
+});
+
+const testRouteInjectable = getInjectable({
+ id: "test-route",
+
+ instantiate: () => ({
+ path: "/test-route",
+ clusterFrame: true,
+ isEnabled: computed(() => true),
+ }),
+
+ injectionToken: frontEndRouteInjectionToken,
+});
+
+const rerenderParentFor = (atom: IAtom) => () => {
+ act(() => {
+ atom.reportChanged();
+ });
+};
+
+const TestComponent = observer(({ someAtom }: { someAtom: IAtom }) => {
+ void someAtom.reportObserved();
+
+ return (
+
+ );
+});
+
+const testRouteComponentInjectable = getInjectable({
+ id: "test-route-component",
+
+ instantiate: (di) => {
+ const someAtom = di.inject(someAtomInjectable);
+
+ return {
+ route: di.inject(testRouteInjectable),
+ Component: () => ,
+ };
+ },
+
+ injectionToken: routeSpecificComponentInjectionToken,
+});
+
+const someAtomInjectable = getInjectable({
+ id: "some-atom",
+ instantiate: () => createAtom("some-atom"),
+});
+
+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: "/foo",
+ },
+ });
+
+const statusForIrrelevantKubeObjectKindInjectable = getInjectable({
+ id: "status-for-irrelevant-kube-object-kind",
+ injectionToken: kubeObjectStatusTextInjectionToken,
+
+ instantiate: () => ({
+ apiVersions: ["some-api-version"],
+ kind: "some-other-kind",
+ enabled: computed(() => true),
+
+ resolve: () => ({
+ level: KubeObjectStatusLevel.INFO,
+ text: "irrelevant",
+ timestamp: "2015-10-19T07:28:00Z",
+ }),
+ }),
+});
+
+const statusForIrrelevantKubeObjectApiVersionInjectable = getInjectable({
+ id: "status-for-irrelevant-kube-object-api-version",
+ injectionToken: kubeObjectStatusTextInjectionToken,
+
+ instantiate: () => ({
+ apiVersions: ["some-other-api-version"],
+ kind: "some-kind",
+ enabled: computed(() => true),
+
+ resolve: () => ({
+ level: KubeObjectStatusLevel.INFO,
+ text: "irrelevant",
+ timestamp: "2015-10-19T07:28:00Z",
+ }),
+ }),
+});
diff --git a/src/renderer/components/kube-object-status-icon/__snapshots__/kube-object-status-icon.test.tsx.snap b/src/renderer/components/kube-object-status-icon/__snapshots__/kube-object-status-icon.test.tsx.snap
deleted file mode 100644
index 599a0c6489..0000000000
--- a/src/renderer/components/kube-object-status-icon/__snapshots__/kube-object-status-icon.test.tsx.snap
+++ /dev/null
@@ -1,116 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`kube-object-status-icon given info and warning statuses are present, when rendered, renders with statuses 1`] = `
-
-
-
-`;
-
-exports[`kube-object-status-icon given level "critical" status, when rendered, renders with status 1`] = `
-
-
-
-`;
-
-exports[`kube-object-status-icon given level "info" status, when rendered, renders with status 1`] = `
-
-
-
-`;
-
-exports[`kube-object-status-icon given level "warning" status, when rendered, renders with status 1`] = `
-
-
-
-`;
-
-exports[`kube-object-status-icon given no statuses, when rendered, renders as empty 1`] = ``;
-
-exports[`kube-object-status-icon given registration for wrong api version, when rendered, renders as empty 1`] = `
-
-
-
-`;
-
-exports[`kube-object-status-icon given registration for wrong kind, when rendered, renders as empty 1`] = `
-
-
-
-`;
-
-exports[`kube-object-status-icon given registration without status for exact kube object, when rendered, renders as empty 1`] = `
-
-
-
-`;
-
-exports[`kube-object-status-icon given status for all levels is present, when rendered, renders with statuses 1`] = `
-
-
-
-`;
diff --git a/src/renderer/components/kube-object-status-icon/kube-object-status-icon.test.tsx b/src/renderer/components/kube-object-status-icon/kube-object-status-icon.test.tsx
deleted file mode 100644
index e1c3ffdcce..0000000000
--- a/src/renderer/components/kube-object-status-icon/kube-object-status-icon.test.tsx
+++ /dev/null
@@ -1,251 +0,0 @@
-/**
- * Copyright (c) OpenLens Authors. All rights reserved.
- * Licensed under MIT License. See LICENSE in root directory for more information.
- */
-import { getDiForUnitTesting } from "../../getDiForUnitTesting";
-import type { DiRender } from "../test-utils/renderFor";
-import { renderFor } from "../test-utils/renderFor";
-import type { KubeObjectStatus } from "../../../common/k8s-api/kube-object-status";
-import { KubeObjectStatusLevel } from "../../../common/k8s-api/kube-object-status";
-import { KubeObject } from "../../../common/k8s-api/kube-object";
-import { KubeObjectStatusIcon } from "./kube-object-status-icon";
-import React from "react";
-import { useFakeTime } from "../../../common/test-utils/use-fake-time";
-import { getInjectable } from "@ogre-tools/injectable";
-import type { DiContainer } from "@ogre-tools/injectable";
-import { kubeObjectStatusTextInjectionToken } from "./kube-object-status-text-injection-token";
-import { computed } from "mobx";
-
-describe("kube-object-status-icon", () => {
- let render: DiRender;
- let di: DiContainer;
-
- beforeEach(() => {
- useFakeTime("2015-10-21T07:28:00Z");
-
- di = getDiForUnitTesting({ doGeneralOverrides: true });
-
- render = renderFor(di);
- });
-
- it("given no statuses, when rendered, renders as empty", () => {
- const kubeObject = getKubeObjectStub("irrelevant", "irrelevant");
-
- const { container } = render();
-
- expect(container).toMatchSnapshot();
- });
-
- it('given level "critical" status, when rendered, renders with status', () => {
- const kubeObject = getKubeObjectStub("some-kind", "some-api-version");
-
- const statusTextInjectable = getStatusTextInjectable(
- KubeObjectStatusLevel.CRITICAL,
- "critical",
- "some-kind",
- ["some-api-version"],
- );
-
- di.register(statusTextInjectable);
-
- const { baseElement } = render(
- ,
- );
-
- expect(baseElement).toMatchSnapshot();
- });
-
- it('given level "info" status, when rendered, renders with status', () => {
- const kubeObject = getKubeObjectStub("some-kind", "some-api-version");
-
- const statusTextInjectable = getStatusTextInjectable(
- KubeObjectStatusLevel.INFO,
- "info",
- "some-kind",
- ["some-api-version"],
- );
-
- di.register(statusTextInjectable);
-
- const { baseElement } = render(
- ,
- );
-
- expect(baseElement).toMatchSnapshot();
- });
-
- it('given level "warning" status, when rendered, renders with status', () => {
- const kubeObject = getKubeObjectStub("some-kind", "some-api-version");
-
- const statusTextInjectable = getStatusTextInjectable(
- KubeObjectStatusLevel.WARNING,
- "warning",
- "some-kind",
- ["some-api-version"],
- );
-
- di.register(statusTextInjectable);
-
- const { baseElement } = render(
- ,
- );
-
- expect(baseElement).toMatchSnapshot();
- });
-
- it("given status for all levels is present, when rendered, renders with statuses", () => {
- const kubeObject = getKubeObjectStub("some-kind", "some-api-version");
-
- const criticalStatusTextInjectable = getStatusTextInjectable(
- KubeObjectStatusLevel.CRITICAL,
- "critical",
- "some-kind",
- ["some-api-version"],
- );
-
- const warningStatusTextInjectable = getStatusTextInjectable(
- KubeObjectStatusLevel.WARNING,
- "warning",
- "some-kind",
- ["some-api-version"],
- );
-
- const infoStatusTextInjectable = getStatusTextInjectable(
- KubeObjectStatusLevel.INFO,
- "info",
- "some-kind",
- ["some-api-version"],
- );
-
- di.register(
- criticalStatusTextInjectable,
- warningStatusTextInjectable,
- infoStatusTextInjectable,
- );
-
- const { baseElement } = render(
- ,
- );
-
- expect(baseElement).toMatchSnapshot();
- });
-
- it("given info and warning statuses are present, when rendered, renders with statuses", () => {
- const kubeObject = getKubeObjectStub("some-kind", "some-api-version");
-
- const warningStatusTextInjectable = getStatusTextInjectable(
- KubeObjectStatusLevel.WARNING,
- "warning",
- "some-kind",
- ["some-api-version"],
- );
-
- const infoStatusTextInjectable = getStatusTextInjectable(
- KubeObjectStatusLevel.INFO,
- "info",
- "some-kind",
- ["some-api-version"],
- );
-
- di.register(warningStatusTextInjectable, infoStatusTextInjectable);
-
- const { baseElement } = render(
- ,
- );
-
- expect(baseElement).toMatchSnapshot();
- });
-
-
- it("given registration for wrong api version, when rendered, renders as empty", () => {
- const kubeObject = getKubeObjectStub("some-kind", "some-api-version");
-
- const statusTextInjectable = getStatusTextInjectable(
- KubeObjectStatusLevel.CRITICAL,
- "irrelevant",
- "some-kind",
- ["some-other-api-version"],
- );
-
- di.register(statusTextInjectable);
-
- const { baseElement } = render(
- ,
- );
-
- expect(baseElement).toMatchSnapshot();
- });
-
- it("given registration for wrong kind, when rendered, renders as empty", () => {
- const kubeObject = getKubeObjectStub("some-kind", "some-api-version");
-
- const statusTextInjectable = getStatusTextInjectable(
- KubeObjectStatusLevel.CRITICAL,
- "irrelevant",
- "some-other-kind",
- ["some-api-version"],
- );
-
- di.register(statusTextInjectable);
-
- const { baseElement } = render(
- ,
- );
-
- expect(baseElement).toMatchSnapshot();
- });
-
- it("given registration without status for exact kube object, when rendered, renders as empty", () => {
- const kubeObject = getKubeObjectStub("some-kind", "some-api-version");
-
- const statusTextInjectable = getInjectable({
- id: "some-id",
- instantiate: () => ({
- apiVersions: ["some-api-version"],
- kind: "some-kind",
- resolve: () => { return undefined as unknown as KubeObjectStatus; },
- enabled: computed(() => true),
- }),
-
- injectionToken: kubeObjectStatusTextInjectionToken,
- });
-
- di.register(statusTextInjectable);
-
- const { baseElement } = render(
- ,
- );
-
- expect(baseElement).toMatchSnapshot();
- });
-});
-
-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: "/foo",
- },
-});
-
-const getStatusTextInjectable = (level: KubeObjectStatusLevel, title: string, kind: string, apiVersions: string[]) => getInjectable({
- id: title,
- instantiate: () => ({
- apiVersions,
- kind,
-
- resolve: (kubeObject: KubeObject) => ({
- level,
- text: `Some ${title} status for ${kubeObject.getName()}`,
- timestamp: "2015-10-19T07:28:00Z",
- }),
-
- enabled: computed(() => true),
- }),
-
- injectionToken: kubeObjectStatusTextInjectionToken,
-});
diff --git a/src/renderer/components/kube-object-status-icon/kube-object-status-icon.tsx b/src/renderer/components/kube-object-status-icon/kube-object-status-icon.tsx
index dd5010e9d9..dd9e68d3f8 100644
--- a/src/renderer/components/kube-object-status-icon/kube-object-status-icon.tsx
+++ b/src/renderer/components/kube-object-status-icon/kube-object-status-icon.tsx
@@ -7,7 +7,7 @@ import "./kube-object-status-icon.scss";
import React from "react";
import { Icon } from "../icon";
-import { cssNames, formatDuration, getOrInsert } from "../../utils";
+import { cssNames, formatDuration, getOrInsert, isDefined } from "../../utils";
import { withInjectables } from "@ogre-tools/injectable-react";
import kubeObjectStatusTextsForObjectInjectable from "./kube-object-status-texts-for-object.injectable";
import type { KubeObject } from "../../../common/k8s-api/kube-object";
@@ -15,6 +15,7 @@ import type { KubeObjectStatus } from "../../../common/k8s-api/kube-object-statu
import { KubeObjectStatusLevel } from "../../../common/k8s-api/kube-object-status";
import type { IComputedValue } from "mobx";
import { observer } from "mobx-react";
+import type { KubeObjectStatusText } from "./kube-object-status-text-injection-token";
function statusClassName(level: KubeObjectStatusLevel): string {
switch (level) {
@@ -78,7 +79,7 @@ export interface KubeObjectStatusIconProps {
}
interface Dependencies {
- statuses: IComputedValue;
+ statuses: IComputedValue;
}
@observer
@@ -107,7 +108,11 @@ class NonInjectedKubeObjectStatusIcon extends React.Component statusText.resolve(this.props.object))
+ .filter(isDefined);
if (statuses.length === 0) {
return null;
@@ -119,6 +124,7 @@ class NonInjectedKubeObjectStatusIcon extends React.Component
diff --git a/src/renderer/components/kube-object-status-icon/kube-object-status-text-injection-token.ts b/src/renderer/components/kube-object-status-icon/kube-object-status-text-injection-token.ts
index bac6e127d4..10fed8bbff 100644
--- a/src/renderer/components/kube-object-status-icon/kube-object-status-text-injection-token.ts
+++ b/src/renderer/components/kube-object-status-icon/kube-object-status-text-injection-token.ts
@@ -10,7 +10,7 @@ import type { IComputedValue } from "mobx";
export interface KubeObjectStatusText {
kind: string;
apiVersions: string[];
- resolve: (object: KubeObject) => KubeObjectStatus;
+ resolve: (object: KubeObject) => KubeObjectStatus | null;
enabled: IComputedValue;
}
diff --git a/src/renderer/components/kube-object-status-icon/kube-object-status-texts-for-object.injectable.ts b/src/renderer/components/kube-object-status-icon/kube-object-status-texts-for-object.injectable.ts
index 108c79b273..12ce4c2b9c 100644
--- a/src/renderer/components/kube-object-status-icon/kube-object-status-texts-for-object.injectable.ts
+++ b/src/renderer/components/kube-object-status-icon/kube-object-status-texts-for-object.injectable.ts
@@ -6,7 +6,6 @@ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
import kubeObjectStatusTextsInjectable from "./kube-object-status-texts.injectable";
import type { KubeObject } from "../../../common/k8s-api/kube-object";
import { conforms, eq, includes } from "lodash/fp";
-import type { KubeObjectStatusRegistration } from "./kube-object-status-registration";
import { computed } from "mobx";
const kubeObjectStatusTextsForObjectInjectable = getInjectable({
@@ -18,9 +17,7 @@ const kubeObjectStatusTextsForObjectInjectable = getInjectable({
return computed(() =>
allStatusTexts
.get()
- .filter(toKubeObjectRelated(kubeObject))
- .map(toStatus(kubeObject))
- .filter(Boolean),
+ .filter(toKubeObjectRelated(kubeObject)),
);
},
@@ -35,8 +32,4 @@ const toKubeObjectRelated = (kubeObject: KubeObject) =>
apiVersions: includes(kubeObject.apiVersion),
});
-const toStatus =
- (kubeObject: KubeObject) => (item: KubeObjectStatusRegistration) =>
- item.resolve(kubeObject);
-
export default kubeObjectStatusTextsForObjectInjectable;