diff --git a/src/renderer/components/+namespaces/__snapshots__/namespace-select-filter.test.tsx.snap b/src/renderer/components/+namespaces/__snapshots__/namespace-select-filter.test.tsx.snap new file mode 100644 index 0000000000..17b797c044 --- /dev/null +++ b/src/renderer/components/+namespaces/__snapshots__/namespace-select-filter.test.tsx.snap @@ -0,0 +1,868 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` renders 1`] = ` + +
+
+
+ + +
+
+
+ All namespaces +
+
+ +
+
+
+ + +
+
+
+
+
+ +`; + +exports[` when clicked renders 1`] = ` + +
+
+
+ + +
+
+
+ All namespaces +
+
+ +
+
+
+ + +
+
+
+
+
+
+
+
+
+ All Namespaces +
+
+
+ + + layers + + + + default + + + + check + + +
+
+
+
+ + + layers + + + + kube-system + + + + check + + +
+
+
+
+ + + layers + + + + kube-system-2 + + + + check + + +
+
+
+
+
+ +`; + +exports[` when clicked when 'kube-system' is clicked renders 1`] = ` + +
+
+
+ + +
+
+
+ Namespace: kube-system +
+
+ +
+
+
+ + +
+
+
+
+
+ +`; + +exports[` when clicked when 'kube-system' is clicked when clicked again renders 1`] = ` + +
+
+
+ + +
+
+
+ Namespace: kube-system +
+
+ +
+
+
+ + +
+
+
+
+
+
+
+
+
+ All Namespaces +
+
+
+ + + layers + + + + kube-system + + + + check + + +
+
+
+
+ + + layers + + + + default + +
+
+
+
+ + + layers + + + + kube-system-2 + +
+
+
+
+
+ +`; + +exports[` when clicked when 'kube-system' is clicked when clicked again when 'default' is clicked renders 1`] = ` + +
+
+
+ + +
+
+
+ Namespace: default +
+
+ +
+
+
+ + +
+
+
+
+
+ +`; + +exports[` when clicked when 'kube-system' is clicked when clicked again when 'default' is clicked when clicked again, then holding down multi select key, and then clicking 'kube-system-2' when 'kube-system-2' is clicked renders 1`] = ` + +
+
+
+ + +
+
+
+ Namespaces: default, kube-system-2 +
+
+ +
+
+
+ + +
+
+
+
+
+
+
+
+
+ All Namespaces +
+
+
+ + + layers + + + + default + + + + check + + +
+
+
+
+ + + layers + + + + kube-system + +
+
+
+
+ + + layers + + + + kube-system-2 + + + + check + + +
+
+
+
+
+ +`; diff --git a/src/renderer/components/+namespaces/namespace-select-filter-model/namespace-select-filter-model.tsx b/src/renderer/components/+namespaces/namespace-select-filter-model/namespace-select-filter-model.tsx index 1c34690819..718790cb88 100644 --- a/src/renderer/components/+namespaces/namespace-select-filter-model/namespace-select-filter-model.tsx +++ b/src/renderer/components/+namespaces/namespace-select-filter-model/namespace-select-filter-model.tsx @@ -70,11 +70,13 @@ export class NamespaceSelectFilterModel { { value: selectAllNamespaces, label: "All Namespaces", + id: "all-namespaces", isSelected: false, }, ...baseOptions.map(namespace => ({ value: namespace, label: namespace, + id: namespace, isSelected: selectedNames.has(namespace), })), ]; @@ -94,6 +96,7 @@ export class NamespaceSelectFilterModel { small material="check" className="box right" + data-testid={`namespace-select-filter-option-${value}-selected`} /> )} diff --git a/src/renderer/components/+namespaces/namespace-select-filter.test.tsx b/src/renderer/components/+namespaces/namespace-select-filter.test.tsx new file mode 100644 index 0000000000..abc40f62e7 --- /dev/null +++ b/src/renderer/components/+namespaces/namespace-select-filter.test.tsx @@ -0,0 +1,182 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ + +import type { DiContainer } from "@ogre-tools/injectable"; +import type { RenderResult } from "@testing-library/react"; +import { fireEvent } from "@testing-library/react"; +import React from "react"; +import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable"; +import { Namespace } from "../../../common/k8s-api/endpoints"; +import { getDiForUnitTesting } from "../../getDiForUnitTesting"; +import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable"; +import { renderFor } from "../test-utils/renderFor"; +import { NamespaceSelectFilter } from "./namespace-select-filter"; +import type { NamespaceStore } from "./store"; +import namespaceStoreInjectable from "./store.injectable"; + +function createNamespace(name: string): Namespace { + return new Namespace({ + apiVersion: "v1", + kind: "Namespace", + metadata: { + name, + resourceVersion: "1", + selfLink: `/api/v1/namespaces/${name}`, + uid: `${name}-1`, + }, + }); +} + +describe("", () => { + let di: DiContainer; + let namespaceStore: NamespaceStore; + let result: RenderResult; + + beforeEach(() => { + di = getDiForUnitTesting({ doGeneralOverrides: true }); + di.override(directoryForUserDataInjectable, () => "/some-directory"); + di.override(storesAndApisCanBeCreatedInjectable, () => true); + namespaceStore = di.inject(namespaceStoreInjectable); + + const render = renderFor(di); + + namespaceStore.items.replace([ + createNamespace("default"), + createNamespace("kube-system"), + createNamespace("kube-system-2"), + ]); + + result = render(( + + )); + }); + + it("renders", () => { + expect(result.baseElement).toMatchSnapshot(); + }); + + describe("when clicked", () => { + beforeEach(() => { + result.getByTestId("namespace-select-filter").click(); + }); + + it("renders", () => { + expect(result.baseElement).toMatchSnapshot(); + }); + + it("opens menu", () => { + expect(result.baseElement.querySelector("#react-select-namespace-select-filter-listbox")).not.toBeNull(); + }); + + describe("when 'kube-system' is clicked", () => { + beforeEach(() => { + result.getByText("kube-system").click(); + }); + + it("renders", () => { + expect(result.baseElement).toMatchSnapshot(); + }); + + it("has only 'kube-system' is selected in the store", () => { + expect(namespaceStore.contextNamespaces).toEqual(["kube-system"]); + }); + + it("closes menu", () => { + expect(result.baseElement.querySelector("#react-select-namespace-select-filter-listbox")).toBeNull(); + }); + + describe("when clicked again", () => { + beforeEach(() => { + result.getByTestId("namespace-select-filter").click(); + }); + + it("renders", () => { + expect(result.baseElement).toMatchSnapshot(); + }); + + it("shows 'kube-system' as selected", () => { + expect(result.queryByTestId("namespace-select-filter-option-kube-system-selected")).not.toBeNull(); + }); + + it("does not show 'default' as selected", () => { + expect(result.queryByTestId("namespace-select-filter-option-default-selected")).toBeNull(); + }); + + describe("when 'default' is clicked", () => { + beforeEach(() => { + result.getByText("default").click(); + }); + + it("renders", () => { + expect(result.baseElement).toMatchSnapshot(); + }); + + it("has only 'default' is selected in the store", () => { + expect(namespaceStore.contextNamespaces).toEqual(["default"]); + }); + + it("closes menu", () => { + expect(result.baseElement.querySelector("#react-select-namespace-select-filter-listbox")).toBeNull(); + }); + + describe("when clicked again, then holding down multi select key, and then clicking 'kube-system-2'", () => { + beforeEach(() => { + const filter = result.getByTestId("namespace-select-filter"); + + filter.click(); + fireEvent.keyDown(filter, { key: "Meta" }); + }); + + describe("when 'kube-system-2' is clicked", () => { + beforeEach(() => { + result.getByText("kube-system-2").click(); + }); + + it("renders", () => { + expect(result.baseElement).toMatchSnapshot(); + }); + + it("has both 'default' and 'kube-system-2' as selected in the store", () => { + expect(new Set(namespaceStore.contextNamespaces)).toEqual(new Set(["default", "kube-system-2"])); + }); + + it("keeps menu open", () => { + expect(result.baseElement.querySelector("#react-select-namespace-select-filter-listbox")).not.toBeNull(); + }); + + it("does not show 'kube-system' as selected", () => { + expect(result.queryByTestId("namespace-select-filter-option-kube-system-selected")).toBeNull(); + }); + + describe("when releasing multi select key", () => { + beforeEach(() => { + const filter = result.getByTestId("namespace-select-filter"); + + fireEvent.keyUp(filter, { key: "Meta" }); + }); + + it("closes menu", () => { + expect(result.baseElement.querySelector("#react-select-namespace-select-filter-listbox")).toBeNull(); + }); + }); + }); + + describe("when releasing multi select key", () => { + beforeEach(() => { + const filter = result.getByTestId("namespace-select-filter"); + + fireEvent.keyUp(filter, { key: "Meta" }); + }); + + it("keeps menu open", () => { + expect(result.baseElement.querySelector("#react-select-namespace-select-filter-listbox")).not.toBeNull(); + }); + }); + }); + }); + }); + }); + }); +}); diff --git a/src/renderer/components/+namespaces/namespace-select-filter.tsx b/src/renderer/components/+namespaces/namespace-select-filter.tsx index b68e211464..969cf9f917 100644 --- a/src/renderer/components/+namespaces/namespace-select-filter.tsx +++ b/src/renderer/components/+namespaces/namespace-select-filter.tsx @@ -30,6 +30,7 @@ const NonInjectedNamespaceSelectFilter = observer(({ model, id }: Dependencies & onKeyDown={model.onKeyDown} onClick={model.onClick} className="NamespaceSelectFilterParent" + data-testid="namespace-select-filter" > id={id} diff --git a/src/renderer/components/select/select.tsx b/src/renderer/components/select/select.tsx index d38ff57f3a..61b6de1284 100644 --- a/src/renderer/components/select/select.tsx +++ b/src/renderer/components/select/select.tsx @@ -25,6 +25,7 @@ export interface SelectOption { label: React.ReactNode; isDisabled?: boolean; isSelected?: boolean; + id?: string; } /**