mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
chore: Add behavioural tests for deleting sub namespaces
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
89cf491bc0
commit
bb5876b39c
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,127 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { AsyncFnMock } from "@async-fn/jest";
|
||||||
|
import asyncFn from "@async-fn/jest";
|
||||||
|
import type { RenderResult } from "@testing-library/react";
|
||||||
|
import navigateToNamespacesInjectable from "../../common/front-end-routing/routes/cluster/namespaces/navigate-to-namespaces.injectable";
|
||||||
|
import type { RequestDeleteNormalNamespace } from "../../renderer/components/+namespaces/request-delete-normal-namespace.injectable";
|
||||||
|
import requestDeleteNormalNamespaceInjectable from "../../renderer/components/+namespaces/request-delete-normal-namespace.injectable";
|
||||||
|
import type { RequestDeleteSubNamespaceAnchor } from "../../renderer/components/+namespaces/request-delete-sub-namespace.injectable";
|
||||||
|
import requestDeleteSubNamespaceAnchorInjectable from "../../renderer/components/+namespaces/request-delete-sub-namespace.injectable";
|
||||||
|
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||||
|
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||||
|
|
||||||
|
describe("namespaces route when viewed with some subNamespaces", () => {
|
||||||
|
let builder: ApplicationBuilder;
|
||||||
|
let result: RenderResult;
|
||||||
|
let requestDeleteNormalNamespaceMock: AsyncFnMock<RequestDeleteNormalNamespace>;
|
||||||
|
let requestDeleteSubNamespaceAnchorMock: AsyncFnMock<RequestDeleteSubNamespaceAnchor>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
builder = getApplicationBuilder();
|
||||||
|
|
||||||
|
builder.setEnvironmentToClusterFrame();
|
||||||
|
|
||||||
|
builder.namespaces.add("default");
|
||||||
|
builder.namespaces.add("foobar");
|
||||||
|
builder.namespaces.addSubNamespace("my-sub-namespace", "default");
|
||||||
|
|
||||||
|
requestDeleteNormalNamespaceMock = asyncFn();
|
||||||
|
requestDeleteSubNamespaceAnchorMock = asyncFn();
|
||||||
|
|
||||||
|
builder.beforeWindowStart(({ windowDi }) => {
|
||||||
|
builder.allowKubeResource({ group: "", apiName: "namespaces" });
|
||||||
|
windowDi.override(requestDeleteNormalNamespaceInjectable, () => requestDeleteNormalNamespaceMock);
|
||||||
|
windowDi.override(requestDeleteSubNamespaceAnchorInjectable, () => requestDeleteSubNamespaceAnchorMock);
|
||||||
|
});
|
||||||
|
|
||||||
|
result = await builder.render();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when navigating to namespaces view", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
builder.navigateWith(navigateToNamespacesInjectable);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders", () => {
|
||||||
|
expect(result.baseElement).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows the default namespace", () => {
|
||||||
|
expect(result.queryByText("default")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows the foobar namespace", () => {
|
||||||
|
expect(result.queryByText("foobar")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows the my-sub-namespace namespace", () => {
|
||||||
|
expect(result.queryByText("my-sub-namespace")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when clicking on the default namespace context menu button", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
result.getByTestId("icon-for-menu-actions-for-kube-object-menu-for-namespace-default").click();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders", () => {
|
||||||
|
expect(result.baseElement).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows the context menu", () => {
|
||||||
|
expect(result.getByTestId("menu-actions-for-kube-object-menu-for-namespace-default")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when clicking the delete action in the context menu", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
result.getByTestId("menu-action-delete-for-/api/v1/namespaces/default").click();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not call requestDeleteSubNamespaceAnchor", () => {
|
||||||
|
expect(requestDeleteSubNamespaceAnchorMock).not.toBeCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call requestDeleteNormalNamespace", () => {
|
||||||
|
expect(requestDeleteNormalNamespaceMock).toBeCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when clicking on the my-sub-namespace namespace context menu button", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
result.getByTestId("icon-for-menu-actions-for-kube-object-menu-for-namespace-my-sub-namespace").click();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders", () => {
|
||||||
|
expect(result.baseElement).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows the context menu", () => {
|
||||||
|
expect(result.getByTestId("menu-actions-for-kube-object-menu-for-namespace-my-sub-namespace")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when clicking the delete action in the context menu", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
result.getByTestId("menu-action-delete-for-/api/v1/namespaces/my-sub-namespace").click();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call requestDeleteSubNamespaceAnchor", () => {
|
||||||
|
expect(requestDeleteSubNamespaceAnchorMock).toBeCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when requestDeleteSubNamespaceAnchor resolves", () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await requestDeleteSubNamespaceAnchorMock.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should call requestDeleteNormalNamespace", () => {
|
||||||
|
expect(requestDeleteNormalNamespaceMock).toBeCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -162,7 +162,7 @@ class NonInjectedKubeObjectMenu<Kube extends KubeObject> extends React.Component
|
|||||||
<MenuItem
|
<MenuItem
|
||||||
key={`context-menu-item-${index}`}
|
key={`context-menu-item-${index}`}
|
||||||
onClick={() => item.onClick(object)}
|
onClick={() => item.onClick(object)}
|
||||||
data-testid={`menu-action-${item.title.toLowerCase().replace(/\s+/, "-")}`}
|
data-testid={`menu-action-${item.title.toLowerCase().replace(/\s+/, "-")}-for-${object.selfLink}`}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
{...item.icon}
|
{...item.icon}
|
||||||
@ -191,6 +191,7 @@ class NonInjectedKubeObjectMenu<Kube extends KubeObject> extends React.Component
|
|||||||
return (
|
return (
|
||||||
<MenuActions
|
<MenuActions
|
||||||
id={`menu-actions-for-kube-object-menu-for-${object?.getId()}`}
|
id={`menu-actions-for-kube-object-menu-for-${object?.getId()}`}
|
||||||
|
data-testid={`menu-actions-for-kube-object-menu-for-${object?.getId()}`}
|
||||||
className={cssNames("KubeObjectMenu", className)}
|
className={cssNames("KubeObjectMenu", className)}
|
||||||
onOpen={object ? () => this.emitOnContextMenuOpen(object) : undefined}
|
onOpen={object ? () => this.emitOnContextMenuOpen(object) : undefined}
|
||||||
{...menuProps}
|
{...menuProps}
|
||||||
|
|||||||
@ -77,8 +77,7 @@ type WindowDiCallback = (container: { windowDi: DiContainer }) => void | Promise
|
|||||||
|
|
||||||
type LensWindowWithHelpers = LensWindow & { rendered: RenderResult; di: DiContainer };
|
type LensWindowWithHelpers = LensWindow & { rendered: RenderResult; di: DiContainer };
|
||||||
|
|
||||||
const createNamespacesFor = (namespaces: Set<string>): Namespace[] => (
|
const createNamespace = (namespace: string) => new Namespace({
|
||||||
Array.from(namespaces, (namespace) => new Namespace({
|
|
||||||
apiVersion: "v1",
|
apiVersion: "v1",
|
||||||
kind: "Namespace",
|
kind: "Namespace",
|
||||||
metadata: {
|
metadata: {
|
||||||
@ -87,8 +86,24 @@ const createNamespacesFor = (namespaces: Set<string>): Namespace[] => (
|
|||||||
selfLink: `/api/v1/namespaces/${namespace}`,
|
selfLink: `/api/v1/namespaces/${namespace}`,
|
||||||
uid: `namespace-${namespace}`,
|
uid: `namespace-${namespace}`,
|
||||||
},
|
},
|
||||||
}))
|
});
|
||||||
);
|
|
||||||
|
const createSubNamespace = (namespace: string, parent: Namespace) => new Namespace({
|
||||||
|
apiVersion: "v1",
|
||||||
|
kind: "Namespace",
|
||||||
|
metadata: {
|
||||||
|
name: namespace,
|
||||||
|
resourceVersion: "1",
|
||||||
|
selfLink: `/api/v1/namespaces/${namespace}`,
|
||||||
|
uid: `namespace-${namespace}`,
|
||||||
|
annotations: {
|
||||||
|
"hnc.x-k8s.io/subnamespace-of": parent.getName(),
|
||||||
|
},
|
||||||
|
labels: {
|
||||||
|
[`${parent.getName()}.tree.hnc.x-k8s.io/depth`]: "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export interface ApplicationBuilder {
|
export interface ApplicationBuilder {
|
||||||
mainDi: DiContainer;
|
mainDi: DiContainer;
|
||||||
@ -144,6 +159,7 @@ export interface ApplicationBuilder {
|
|||||||
};
|
};
|
||||||
namespaces: {
|
namespaces: {
|
||||||
add: (namespace: string) => void;
|
add: (namespace: string) => void;
|
||||||
|
addSubNamespace: (namespace: string, parent: string) => void;
|
||||||
select: (namespace: string) => void;
|
select: (namespace: string) => void;
|
||||||
};
|
};
|
||||||
helmCharts: {
|
helmCharts: {
|
||||||
@ -303,7 +319,6 @@ export const getApplicationBuilder = () => {
|
|||||||
|
|
||||||
let applicationHasStarted = false;
|
let applicationHasStarted = false;
|
||||||
|
|
||||||
const namespaces = observable.set<string>();
|
|
||||||
const namespaceItems = observable.array<Namespace>();
|
const namespaceItems = observable.array<Namespace>();
|
||||||
const selectedNamespaces = observable.set<string>();
|
const selectedNamespaces = observable.set<string>();
|
||||||
const startApplication = mainDi.inject(startApplicationInjectionToken);
|
const startApplication = mainDi.inject(startApplicationInjectionToken);
|
||||||
@ -385,8 +400,14 @@ export const getApplicationBuilder = () => {
|
|||||||
},
|
},
|
||||||
namespaces: {
|
namespaces: {
|
||||||
add: action((namespace) => {
|
add: action((namespace) => {
|
||||||
namespaces.add(namespace);
|
namespaceItems.push(createNamespace(namespace));
|
||||||
namespaceItems.replace(createNamespacesFor(namespaces));
|
}),
|
||||||
|
addSubNamespace: action((namespace, parent) => {
|
||||||
|
const parentNamespace = namespaceItems.find((n) => n.getName() === parent);
|
||||||
|
|
||||||
|
assert(parentNamespace, `Cannot find namespace with name="${parent}"`);
|
||||||
|
|
||||||
|
namespaceItems.push(createSubNamespace(namespace, parentNamespace));
|
||||||
}),
|
}),
|
||||||
select: action((namespace) => {
|
select: action((namespace) => {
|
||||||
const selectedNamespacesStorage = builder.applicationWindow.only.di.inject(selectedNamespacesStorageInjectable);
|
const selectedNamespacesStorage = builder.applicationWindow.only.di.inject(selectedNamespacesStorageInjectable);
|
||||||
@ -545,7 +566,7 @@ export const getApplicationBuilder = () => {
|
|||||||
return Array.from(selectedNamespaces);
|
return Array.from(selectedNamespaces);
|
||||||
},
|
},
|
||||||
get allowedNamespaces() {
|
get allowedNamespaces() {
|
||||||
return Array.from(namespaces);
|
return Array.from(namespaceItems, n => n.getName());
|
||||||
},
|
},
|
||||||
contextItems: namespaceItems,
|
contextItems: namespaceItems,
|
||||||
api: windowDi.inject(namespaceApiInjectable),
|
api: windowDi.inject(namespaceApiInjectable),
|
||||||
@ -556,6 +577,7 @@ export const getApplicationBuilder = () => {
|
|||||||
pickOnlySelected: () => [],
|
pickOnlySelected: () => [],
|
||||||
isSelectedAll: () => false,
|
isSelectedAll: () => false,
|
||||||
getTotalCount: () => namespaceItems.length,
|
getTotalCount: () => namespaceItems.length,
|
||||||
|
isSelected: () => false,
|
||||||
} as Partial<NamespaceStore> as NamespaceStore));
|
} as Partial<NamespaceStore> as NamespaceStore));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user