1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Clean up tests from boilderplate

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>
This commit is contained in:
Alex Andreev 2023-02-06 10:34:31 +03:00
parent 70ca90f3ae
commit b0ab29095e
4 changed files with 145 additions and 192 deletions

View File

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<NamespaceTreeView /> once the subscribe resolves collapses item by clicking minus button 1`] = `
exports[`<NamespaceTreeView /> collapses item by clicking minus button 1`] = `
<body>
<div>
<div
@ -218,7 +218,7 @@ exports[`<NamespaceTreeView /> once the subscribe resolves collapses item by cli
</body>
`;
exports[`<NamespaceTreeView /> once the subscribe resolves expands item by clicking plus button 1`] = `
exports[`<NamespaceTreeView /> expands item by clicking plus button 1`] = `
<body>
<div>
<div
@ -436,7 +436,7 @@ exports[`<NamespaceTreeView /> once the subscribe resolves expands item by click
</body>
`;
exports[`<NamespaceTreeView /> once the subscribe resolves renders 2 levels deep 1`] = `
exports[`<NamespaceTreeView /> renders 2 levels deep 1`] = `
<body>
<div>
<div
@ -654,7 +654,7 @@ exports[`<NamespaceTreeView /> once the subscribe resolves renders 2 levels deep
</body>
`;
exports[`<NamespaceTreeView /> once the subscribe resolves renders namespace with 2 children namespaces 1`] = `
exports[`<NamespaceTreeView /> renders namespace with 2 children namespaces 1`] = `
<body>
<div>
<div
@ -824,7 +824,7 @@ exports[`<NamespaceTreeView /> once the subscribe resolves renders namespace wit
</body>
`;
exports[`<NamespaceTreeView /> once the subscribe resolves renders namespace with children namespaces and a subnamespace 1`] = `
exports[`<NamespaceTreeView /> renders namespace with children namespaces and a subnamespace 1`] = `
<body>
<div>
<div
@ -884,6 +884,56 @@ exports[`<NamespaceTreeView /> once the subscribe resolves renders namespace wit
<div
class="MuiCollapse-wrapperInner"
>
<li
class="MuiTreeItem-root Mui-expanded"
data-testid="namespace-team-c-1"
role="treeitem"
tabindex="-1"
>
<div
class="MuiTreeItem-content"
>
<div
class="MuiTreeItem-iconContainer"
>
<div
style="opacity: 0.3;"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root"
data-testid="minus-square"
focusable="false"
style="width: 14px; height: 14px;"
viewBox="0 0 24 24"
>
<path
d="M22.047 22.074v0 0-20.147 0h-20.12v0 20.147 0h20.12zM22.047 24h-20.12q-.803 0-1.365-.562t-.562-1.365v-20.147q0-.776.562-1.351t1.365-.575h20.147q.776 0 1.351.575t.575 1.351v20.147q0 .803-.575 1.365t-1.378.562v0zM17.873 11.023h-11.826q-.375 0-.669.281t-.294.682v0q0 .401.294 .682t.669.281h11.826q.375 0 .669-.281t.294-.682v0q0-.401-.294-.682t-.669-.281z"
/>
</svg>
</div>
</div>
<div
class="MuiTypography-root MuiTreeItem-label label MuiTypography-body1"
>
team-c
</div>
</div>
<ul
class="MuiCollapse-root MuiTreeItem-group group MuiCollapse-entered"
role="group"
style="min-height: 0px;"
>
<div
class="MuiCollapse-wrapper"
>
<div
class="MuiCollapse-wrapperInner"
/>
</div>
</ul>
</li>
<li
class="MuiTreeItem-root Mui-expanded"
data-testid="namespace-service-1-1"
@ -941,56 +991,6 @@ exports[`<NamespaceTreeView /> once the subscribe resolves renders namespace wit
</div>
</ul>
</li>
<li
class="MuiTreeItem-root Mui-expanded"
data-testid="namespace-team-c-1"
role="treeitem"
tabindex="-1"
>
<div
class="MuiTreeItem-content"
>
<div
class="MuiTreeItem-iconContainer"
>
<div
style="opacity: 0.3;"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root"
data-testid="minus-square"
focusable="false"
style="width: 14px; height: 14px;"
viewBox="0 0 24 24"
>
<path
d="M22.047 22.074v0 0-20.147 0h-20.12v0 20.147 0h20.12zM22.047 24h-20.12q-.803 0-1.365-.562t-.562-1.365v-20.147q0-.776.562-1.351t1.365-.575h20.147q.776 0 1.351.575t.575 1.351v20.147q0 .803-.575 1.365t-1.378.562v0zM17.873 11.023h-11.826q-.375 0-.669.281t-.294.682v0q0 .401.294 .682t.669.281h11.826q.375 0 .669-.281t.294-.682v0q0-.401-.294-.682t-.669-.281z"
/>
</svg>
</div>
</div>
<div
class="MuiTypography-root MuiTreeItem-label label MuiTypography-body1"
>
team-c
</div>
</div>
<ul
class="MuiCollapse-root MuiTreeItem-group group MuiCollapse-entered"
role="group"
style="min-height: 0px;"
>
<div
class="MuiCollapse-wrapper"
>
<div
class="MuiCollapse-wrapperInner"
/>
</div>
</ul>
</li>
</div>
</div>
</ul>
@ -1001,13 +1001,13 @@ exports[`<NamespaceTreeView /> once the subscribe resolves renders namespace wit
</body>
`;
exports[`<NamespaceTreeView /> once the subscribe resolves renders null with regular namespace 1`] = `
exports[`<NamespaceTreeView /> renders null with regular namespace 1`] = `
<body>
<div />
</body>
`;
exports[`<NamespaceTreeView /> once the subscribe resolves renders one namespace without children 1`] = `
exports[`<NamespaceTreeView /> renders one namespace without children 1`] = `
<body>
<div>
<div

View File

@ -0,0 +1,14 @@
import { getInjectable } from "@ogre-tools/injectable";
import namespaceStoreInjectable from "./store.injectable";
const hierarchicalNamespacesInjectable = getInjectable({
id: "hierarchical-namespaces",
instantiate: (di) => {
const namespaceStore = di.inject(namespaceStoreInjectable);
return namespaceStore.getByLabel(["hnc.x-k8s.io/included-namespace=true"]);
},
})
export default hierarchicalNamespacesInjectable;

View File

@ -2,28 +2,15 @@
* 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 { DiContainer } from "@ogre-tools/injectable";
import { fireEvent } from "@testing-library/react";
import React from "react";
import directoryForKubeConfigsInjectable from "../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable";
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
import type { Fetch } from "../../../common/fetch/fetch.injectable";
import fetchInjectable from "../../../common/fetch/fetch.injectable";
import { Namespace } from "../../../common/k8s-api/endpoints";
import { createMockResponseFromString } from "../../../test-utils/mock-responses";
import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.injectable";
import createClusterInjectable from "../../cluster/create-cluster.injectable";
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
import subscribeStoresInjectable from "../../kube-watch-api/subscribe-stores.injectable";
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
import { type Disposer, disposer } from "../../utils";
import type { DiRender } from "../test-utils/renderFor";
import { renderFor } from "../test-utils/renderFor";
import hierarchicalNamespacesInjectable from "./hierarchical-namespaces.injectable";
import { NamespaceTreeView } from "./namespace-tree-view";
import type { NamespaceStore } from "./store";
import namespaceStoreInjectable from "./store.injectable";
jest.mock("react-router-dom", () => ({
Link: ({ children }: { children: React.ReactNode }) => children,
@ -116,149 +103,103 @@ const levelDeepSubChildA = createNamespace("level-deep-subchild-a", {
describe("<NamespaceTreeView />", () => {
let di: DiContainer;
let render: DiRender;
let namespaceStore: NamespaceStore;
let fetchMock: AsyncFnMock<Fetch>;
let cleanup: Disposer;
beforeEach(async () => {
di = getDiForUnitTesting({ doGeneralOverrides: true });
di.unoverride(subscribeStoresInjectable);
di.override(directoryForUserDataInjectable, () => "/some-user-store-path");
di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
di.override(storesAndApisCanBeCreatedInjectable, () => true);
di.override(hierarchicalNamespacesInjectable, () => [
acmeGroup,
orgA,
teamA,
teamB,
teamC,
service1,
levelsDeep,
levelDeepChildA,
levelDeepChildB,
levelDeepSubChildA,
])
fetchMock = asyncFn();
di.override(fetchInjectable, () => fetchMock);
const createCluster = di.inject(createClusterInjectable);
di.override(hostedClusterInjectable, () => createCluster({
contextName: "some-context-name",
id: "some-cluster-id",
kubeConfigPath: "/some-path-to-a-kubeconfig",
}, {
clusterServerUrl: "https://localhost:8080",
}));
namespaceStore = di.inject(namespaceStoreInjectable);
const subscribeStores = di.inject(subscribeStoresInjectable);
cleanup = disposer(subscribeStores([namespaceStore]));
render = renderFor(di);
});
afterEach(() => {
cleanup();
it("renders null with regular namespace", () => {
const result = render(<NamespaceTreeView root={createNamespace("tree-1")} />);
expect(result.baseElement).toMatchSnapshot();
});
describe("once the subscribe resolves", () => {
beforeEach(async () => {
await fetchMock.resolveSpecific([
"https://127.0.0.1:12345/api-kube/api/v1/namespaces",
], createMockResponseFromString("https://127.0.0.1:12345/api-kube/api/v1/namespaces", JSON.stringify({
apiVersion: "v1",
kind: "NamespaceList",
metadata: {},
items: [
createNamespace("test-1"),
createNamespace("test-2"),
createNamespace("test-3"),
createNamespace("test-4"),
createNamespace("test-5"),
acmeGroup,
orgA,
teamA,
teamB,
teamC,
service1,
levelsDeep,
levelDeepChildA,
levelDeepChildB,
levelDeepSubChildA,
],
})));
});
it("renders one namespace without children", () => {
const result = render(<NamespaceTreeView root={singleRoot} />);
it("renders null with regular namespace", () => {
const result = render(<NamespaceTreeView root={createNamespace("tree-1")} />);
expect(result.baseElement).toMatchSnapshot();
});
expect(result.baseElement).toMatchSnapshot();
});
it("renders one namespace without children", () => {
const result = render(<NamespaceTreeView root={singleRoot} />);
expect(result.baseElement).toMatchSnapshot();
});
it("renders namespace with 2 children namespaces", () => {
const result = render(<NamespaceTreeView root={acmeGroup} />);
it("renders namespace with 2 children namespaces", () => {
const result = render(<NamespaceTreeView root={acmeGroup} />);
expect(result.baseElement).toMatchSnapshot();
});
expect(result.baseElement).toMatchSnapshot();
});
it("renders namespace with children namespaces and a subnamespace", () => {
const result = render(<NamespaceTreeView root={orgA} />);
it("renders namespace with children namespaces and a subnamespace", () => {
const result = render(<NamespaceTreeView root={orgA} />);
expect(result.baseElement).toMatchSnapshot();
});
expect(result.baseElement).toMatchSnapshot();
});
it("renders an indicator badge for the subnamespace", () => {
const result = render(<NamespaceTreeView root={orgA} />);
it("renders an indicator badge for the subnamespace", () => {
const result = render(<NamespaceTreeView root={orgA} />);
expect(result.getByTestId("subnamespace-badge-for-service-1-1")).toBeInTheDocument();
});
expect(result.getByTestId("subnamespace-badge-for-service-1-1")).toBeInTheDocument();
});
it("does not render an indicator badge for the true namespace", () => {
const result = render(<NamespaceTreeView root={orgA} />);
const trueNamespace = result.getByTestId("namespace-team-c-1");
it("does not render an indicator badge for the true namespace", () => {
const result = render(<NamespaceTreeView root={orgA} />);
const trueNamespace = result.getByTestId("namespace-team-c-1");
expect(trueNamespace.querySelector("[data-testid='subnamespace-badge-for-team-c-1']")).toBeNull();
});
expect(trueNamespace.querySelector("[data-testid='subnamespace-badge-for-team-c-1']")).toBeNull();
});
it("renders 2 levels deep", () => {
const result = render(<NamespaceTreeView root={levelsDeep} />);
it("renders 2 levels deep", () => {
const result = render(<NamespaceTreeView root={levelsDeep} />);
expect(result.baseElement).toMatchSnapshot();
});
expect(result.baseElement).toMatchSnapshot();
});
it("expands children items by default", () => {
const result = render(<NamespaceTreeView root={levelsDeep} />);
const deepest = result.getByTestId("namespace-level-deep-child-b-1");
it("expands children items by default", () => {
const result = render(<NamespaceTreeView root={levelsDeep} />);
const deepest = result.getByTestId("namespace-level-deep-child-b-1");
expect(deepest).toHaveAttribute("aria-expanded", "true");
});
expect(deepest).toHaveAttribute("aria-expanded", "true");
});
it("collapses item by clicking minus button", () => {
const result = render(<NamespaceTreeView root={levelsDeep} />);
const levelB = result.getByTestId("namespace-level-deep-child-b-1");
const minusButton = levelB.querySelector("[data-testid='minus-square']");
it("collapses item by clicking minus button", () => {
const result = render(<NamespaceTreeView root={levelsDeep} />);
const levelB = result.getByTestId("namespace-level-deep-child-b-1");
const minusButton = levelB.querySelector("[data-testid='minus-square']");
if (minusButton) {
fireEvent.click(minusButton);
}
if (minusButton) {
fireEvent.click(minusButton);
}
expect(result.baseElement).toMatchSnapshot();
});
expect(result.baseElement).toMatchSnapshot();
});
it("expands item by clicking plus button", () => {
const result = render(<NamespaceTreeView root={levelsDeep} />);
const levelB = result.getByTestId("namespace-level-deep-child-b-1");
const minusButton = levelB.querySelector("[data-testid='minus-square']");
it("expands item by clicking plus button", () => {
const result = render(<NamespaceTreeView root={levelsDeep} />);
const levelB = result.getByTestId("namespace-level-deep-child-b-1");
const minusButton = levelB.querySelector("[data-testid='minus-square']");
if (minusButton) {
fireEvent.click(minusButton);
}
if (minusButton) {
fireEvent.click(minusButton);
}
const plusButton = levelB.querySelector("[data-testid='plus-square']");
const plusButton = levelB.querySelector("[data-testid='plus-square']");
if (plusButton) {
fireEvent.click(plusButton);
}
if (plusButton) {
fireEvent.click(plusButton);
}
expect(result.baseElement).toMatchSnapshot();
});
expect(result.baseElement).toMatchSnapshot();
});
});

View File

@ -14,16 +14,15 @@ import type { Namespace } from "../../../common/k8s-api/endpoints";
import { DrawerTitle } from "../drawer";
import type { GetDetailsUrl } from "../kube-detail-params/get-details-url.injectable";
import getDetailsUrlInjectable from "../kube-detail-params/get-details-url.injectable";
import type { NamespaceStore } from "./store";
import namespaceStoreInjectable from "./store.injectable";
import { SubnamespaceBadge } from "./subnamespace-badge";
import hierarchicalNamespacesInjectable from "./hierarchical-namespaces.injectable";
interface NamespaceTreeViewProps {
root: Namespace;
}
interface Dependencies {
namespaceStore: NamespaceStore;
namespaces: Namespace[];
getDetailsUrl: GetDetailsUrl;
}
@ -33,14 +32,13 @@ function isNamespaceControlledByHNC(namespace: Namespace) {
return namespace.getLabels().find(label => label === hierarchicalNamesaceControllerLabel);
}
function NonInjectableNamespaceTreeView({ root, namespaceStore, getDetailsUrl }: Dependencies & NamespaceTreeViewProps) {
const hierarchicalNamespaces = namespaceStore.getByLabel(["hnc.x-k8s.io/included-namespace=true"]);
const [expandedItems, setExpandedItems] = React.useState<string[]>(hierarchicalNamespaces.map(ns => `namespace-${ns.getId()}`));
function NonInjectableNamespaceTreeView({ root, namespaces, getDetailsUrl }: Dependencies & NamespaceTreeViewProps) {
const [expandedItems, setExpandedItems] = React.useState<string[]>(namespaces.map(ns => `namespace-${ns.getId()}`));
const classes = { group: styles.group, label: styles.label };
const nodeId = `namespace-${root.getId()}`;
function renderChildren(parent: Namespace) {
const children = hierarchicalNamespaces.filter(ns =>
const children = namespaces.filter(ns =>
ns.getLabels().find(label => label === `${parent.getName()}.tree.hnc.x-k8s.io/depth=1`),
);
@ -133,7 +131,7 @@ function PlusSquareIcon() {
export const NamespaceTreeView = withInjectables<Dependencies, NamespaceTreeViewProps>(NonInjectableNamespaceTreeView, {
getProps: (di, props) => ({
namespaceStore: di.inject(namespaceStoreInjectable),
namespaces: di.inject(hierarchicalNamespacesInjectable),
getDetailsUrl: di.inject(getDetailsUrlInjectable),
...props,
}),