From 0de2e79871c3e865f5a662d0dfc5e954800394f1 Mon Sep 17 00:00:00 2001 From: bbehnke Date: Thu, 26 Oct 2023 16:12:49 -0700 Subject: [PATCH] fix: more sidebar tests Signed-off-by: bbehnke --- .../partials/ISBUpdate/index.test.tsx | 226 ++++++++++++++++++ .../partials/PipelineCreate/index.test.tsx | 223 +++++++++++++++++ .../partials/PipelineCreate/index.tsx | 2 +- 3 files changed, 450 insertions(+), 1 deletion(-) create mode 100644 ui/src/components/common/SlidingSidebar/partials/ISBUpdate/index.test.tsx create mode 100644 ui/src/components/common/SlidingSidebar/partials/PipelineCreate/index.test.tsx diff --git a/ui/src/components/common/SlidingSidebar/partials/ISBUpdate/index.test.tsx b/ui/src/components/common/SlidingSidebar/partials/ISBUpdate/index.test.tsx new file mode 100644 index 0000000000..766fea7f16 --- /dev/null +++ b/ui/src/components/common/SlidingSidebar/partials/ISBUpdate/index.test.tsx @@ -0,0 +1,226 @@ +import React from "react"; +import { + fireEvent, + render, + screen, + waitFor, + act, +} from "@testing-library/react"; +import { ISBUpdate } from "./index"; +import fetch from "jest-fetch-mock"; + +import "@testing-library/jest-dom"; + +// Mock SpecEditor +jest.mock("../../../SpecEditor", () => { + const originalModule = jest.requireActual("../../../SpecEditor"); + const react = jest.requireActual("react"); + // Mock any module exports here + return { + __esModule: true, + ...originalModule, + // Named export mocks + SpecEditor: (props: any) => { + const [mutated, setMutated] = react.useState(false); + const handleMutateClick = react.useCallback(() => { + props.onMutatedChange(mutated); + setMutated(!mutated); + }, [mutated, props.onMutatedChange]); + return ( +
+
{JSON.stringify(props.validationMessage)}
+
{JSON.stringify(props.statusIndicator)}
+
{props.initialYaml}
+
+ ); + }, + }; +}); + +describe("ISBUpdate", () => { + beforeEach(() => { + jest.clearAllMocks(); + fetch.resetMocks(); + }); + + it("renders title and spec editor", async () => { + const mockSetModalOnClose = jest.fn(); + render( + + ); + await waitFor(() => { + expect(screen.getByText(`Edit ISB Service: test-isb`)).toBeInTheDocument(); + expect(screen.getByTestId("spec-editor-reset")).toBeInTheDocument(); + }); + // Click reset + act(() => { + const resetBtn = screen.getByTestId("spec-editor-reset"); + fireEvent.click(resetBtn); + }); + // Fire mutation change twice to run both branches + act(() => { + const mutationBtn = screen.getByTestId("spec-editor-mutated"); + fireEvent.click(mutationBtn); + }); + expect(mockSetModalOnClose).toHaveBeenCalledWith(undefined); + mockSetModalOnClose.mockClear(); + act(() => { + const mutationBtn = screen.getByTestId("spec-editor-mutated"); + fireEvent.click(mutationBtn); + }); + expect(mockSetModalOnClose).toHaveBeenCalledWith({ + iconType: "warn", + message: "Are you sure you want to discard your changes?", + }); + }); + + it("validation success", async () => { + fetch.mockResponseOnce(JSON.stringify({ data: {} })); + const mockSetModalOnClose = jest.fn(); + render( + + ); + await waitFor(() => { + expect(screen.getByText(`Edit ISB Service: test-isb`)).toBeInTheDocument(); + expect(screen.getByTestId("spec-editor-reset")).toBeInTheDocument(); + }); + // Click reset + act(() => { + const validateBtn = screen.getByTestId("spec-editor-validate"); + fireEvent.click(validateBtn); + }); + await waitFor(() => { + expect( + screen.getByText( + `{"type":"success","message":"Successfully validated"}` + ) + ).toBeInTheDocument(); + }); + }); + + it("validation failure", async () => { + fetch.mockResponseOnce(JSON.stringify({ errMsg: "failed" })); + const mockSetModalOnClose = jest.fn(); + render( + + ); + await waitFor(() => { + expect(screen.getByText(`Edit ISB Service: test-isb`)).toBeInTheDocument(); + expect(screen.getByTestId("spec-editor-reset")).toBeInTheDocument(); + }); + // Click reset + act(() => { + const validateBtn = screen.getByTestId("spec-editor-validate"); + fireEvent.click(validateBtn); + }); + await waitFor(() => { + expect( + screen.getByText(`{"type":"error","message":"Error: failed"}`) + ).toBeInTheDocument(); + }); + }); + + it("submit success", async () => { + fetch.mockResponseOnce(JSON.stringify({ data: {} })); + const mockUpdateComplete = jest.fn(); + render( + + ); + await waitFor(() => { + expect(screen.getByText(`Edit ISB Service: test-isb`)).toBeInTheDocument(); + expect(screen.getByTestId("spec-editor-reset")).toBeInTheDocument(); + }); + // Click reset + act(() => { + const submitBtn = screen.getByTestId("spec-editor-submit"); + fireEvent.click(submitBtn); + }); + await waitFor(() => { + expect( + screen.getByText( + `{"submit":{"status":1,"message":"ISB Service updated successfully","allowRetry":false}}` + ) + ).toBeInTheDocument(); + }); + // Wait for onUpdateComplete call + await new Promise((r) => setTimeout(r, 1000)); + expect(mockUpdateComplete).toHaveBeenCalledTimes(1); + }); + + it("submit failure", async () => { + fetch.mockResponseOnce(JSON.stringify({ errMsg: "failed" })); + const mockUpdateComplete = jest.fn(); + render( + + ); + await waitFor(() => { + expect(screen.getByText(`Edit ISB Service: test-isb`)).toBeInTheDocument(); + expect(screen.getByTestId("spec-editor-reset")).toBeInTheDocument(); + }); + // Click reset + act(() => { + const submitBtn = screen.getByTestId("spec-editor-submit"); + fireEvent.click(submitBtn); + }); + await waitFor(() => { + expect( + screen.getByText(`{"type":"error","message":"Error: failed"}`) + ).toBeInTheDocument(); + }); + }); +}); diff --git a/ui/src/components/common/SlidingSidebar/partials/PipelineCreate/index.test.tsx b/ui/src/components/common/SlidingSidebar/partials/PipelineCreate/index.test.tsx new file mode 100644 index 0000000000..db90d753b1 --- /dev/null +++ b/ui/src/components/common/SlidingSidebar/partials/PipelineCreate/index.test.tsx @@ -0,0 +1,223 @@ +import React from "react"; +import { + fireEvent, + render, + screen, + waitFor, + act, +} from "@testing-library/react"; +import { PipelineCreate } from "./index"; +import fetch from "jest-fetch-mock"; +import { BrowserRouter } from "react-router-dom"; + +import "@testing-library/jest-dom"; + +// Mock SpecEditor +jest.mock("../../../SpecEditor", () => { + const originalModule = jest.requireActual("../../../SpecEditor"); + const react = jest.requireActual("react"); + // Mock any module exports here + return { + __esModule: true, + ...originalModule, + // Named export mocks + SpecEditor: (props: any) => { + const [mutated, setMutated] = react.useState(false); + const handleMutateClick = react.useCallback(() => { + props.onMutatedChange(mutated); + setMutated(!mutated); + }, [mutated, props.onMutatedChange]); + return ( +
+
{JSON.stringify(props.validationMessage)}
+
{JSON.stringify(props.statusIndicator)}
+
{props.initialYaml}
+
+ ); + }, + }; +}); + +describe("PipelineCreate", () => { + beforeEach(() => { + jest.clearAllMocks(); + fetch.resetMocks(); + }); + + it("renders title and spec editor", async () => { + const mockSetModalOnClose = jest.fn(); + render( + , + { wrapper: BrowserRouter } + ); + await waitFor(() => { + expect(screen.getByText("Create Pipeline")).toBeInTheDocument(); + expect(screen.getByTestId("spec-editor-reset")).toBeInTheDocument(); + }); + // Click reset + act(() => { + const resetBtn = screen.getByTestId("spec-editor-reset"); + fireEvent.click(resetBtn); + }); + // Fire mutation change twice to run both branches + act(() => { + const mutationBtn = screen.getByTestId("spec-editor-mutated"); + fireEvent.click(mutationBtn); + }); + expect(mockSetModalOnClose).toHaveBeenCalledWith(undefined); + mockSetModalOnClose.mockClear(); + act(() => { + const mutationBtn = screen.getByTestId("spec-editor-mutated"); + fireEvent.click(mutationBtn); + }); + expect(mockSetModalOnClose).toHaveBeenCalledWith({ + iconType: "warn", + message: "Are you sure you want to discard your changes?", + }); + }); + + it("validation success", async () => { + fetch.mockResponseOnce(JSON.stringify({ data: {} })); + const mockSetModalOnClose = jest.fn(); + render( + , + { wrapper: BrowserRouter } + ); + await waitFor(() => { + expect(screen.getByText("Create Pipeline")).toBeInTheDocument(); + expect(screen.getByTestId("spec-editor-reset")).toBeInTheDocument(); + }); + // Click reset + act(() => { + const validateBtn = screen.getByTestId("spec-editor-validate"); + fireEvent.click(validateBtn); + }); + await waitFor(() => { + expect( + screen.getByText( + `{"type":"success","message":"Successfully validated"}` + ) + ).toBeInTheDocument(); + }); + }); + + it("validation failure", async () => { + fetch.mockResponseOnce(JSON.stringify({ errMsg: "failed" })); + const mockSetModalOnClose = jest.fn(); + render( + , + { wrapper: BrowserRouter } + ); + await waitFor(() => { + expect(screen.getByText("Create Pipeline")).toBeInTheDocument(); + expect(screen.getByTestId("spec-editor-reset")).toBeInTheDocument(); + }); + // Click reset + act(() => { + const validateBtn = screen.getByTestId("spec-editor-validate"); + fireEvent.click(validateBtn); + }); + await waitFor(() => { + expect( + screen.getByText(`{"type":"error","message":"Error: failed"}`) + ).toBeInTheDocument(); + }); + }); + + it("submit success", async () => { + fetch.once(JSON.stringify({ data: {} })).once(JSON.stringify({ data: {} })); + const mockUpdateComplete = jest.fn(); + render( + , + { wrapper: BrowserRouter } + ); + await waitFor(() => { + expect(screen.getByText("Create Pipeline")).toBeInTheDocument(); + expect(screen.getByTestId("spec-editor-reset")).toBeInTheDocument(); + }); + // Click + act(() => { + const submitBtn = screen.getByTestId("spec-editor-submit"); + fireEvent.click(submitBtn); + }); + await new Promise((r) => setTimeout(r, 1000)); + await waitFor(() => { + expect( + screen.getByText( + `{"submit":{"status":1,"message":"Pipeline submitted successfully","allowRetry":false},"processing":{"status":1,"message":"Pipeline created successfully"}}` + ) + ).toBeInTheDocument(); + }); + // Wait for onUpdateComplete call + await new Promise((r) => setTimeout(r, 1000)); + expect(mockUpdateComplete).toHaveBeenCalledTimes(1); + }); + + it("submit failure", async () => { + fetch.mockResponseOnce(JSON.stringify({ errMsg: "failed" })); + const mockUpdateComplete = jest.fn(); + render( + , + { wrapper: BrowserRouter } + ); + await waitFor(() => { + expect(screen.getByText("Create Pipeline")).toBeInTheDocument(); + expect(screen.getByTestId("spec-editor-reset")).toBeInTheDocument(); + }); + // Click reset + act(() => { + const submitBtn = screen.getByTestId("spec-editor-submit"); + fireEvent.click(submitBtn); + }); + await waitFor(() => { + expect( + screen.getByText(`{"type":"error","message":"Error: failed"}`) + ).toBeInTheDocument(); + }); + }); +}); diff --git a/ui/src/components/common/SlidingSidebar/partials/PipelineCreate/index.tsx b/ui/src/components/common/SlidingSidebar/partials/PipelineCreate/index.tsx index 6ea4e281d9..da1f99781e 100644 --- a/ui/src/components/common/SlidingSidebar/partials/PipelineCreate/index.tsx +++ b/ui/src/components/common/SlidingSidebar/partials/PipelineCreate/index.tsx @@ -76,7 +76,7 @@ export function PipelineCreate({ if (!createdPipelineId) { return; } - let timer: number; + let timer: NodeJS.Timeout; if (pipelineAvailable) { setStatus((prev) => { const existing = prev ? { ...prev } : {};