mirror of
https://github.com/formbricks/formbricks.git
synced 2026-04-20 11:22:55 -05:00
Added finally block and tests
This commit is contained in:
@@ -1,9 +1,16 @@
|
||||
// Import the actions to access mocked functions
|
||||
import { deleteSurveyAction } from "@/modules/survey/list/actions";
|
||||
import { TSurvey } from "@/modules/survey/list/types/surveys";
|
||||
import { cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react";
|
||||
import { userEvent } from "@testing-library/user-event";
|
||||
import { afterEach, describe, expect, test, vi } from "vitest";
|
||||
import toast from "react-hot-toast";
|
||||
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import { SurveyDropDownMenu } from "./survey-dropdown-menu";
|
||||
|
||||
// Cast to mocked functions
|
||||
const mockDeleteSurveyAction = vi.mocked(deleteSurveyAction);
|
||||
const mockToast = vi.mocked(toast);
|
||||
|
||||
// Mock translation
|
||||
vi.mock("@tolgee/react", () => ({
|
||||
useTranslate: () => ({ t: (key: string) => key }),
|
||||
@@ -43,6 +50,24 @@ vi.mock("@/modules/survey/list/actions", () => ({
|
||||
getSurveyAction: vi.fn(() =>
|
||||
Promise.resolve({ data: { id: "duplicatedSurveyId", name: "Duplicated Survey" } })
|
||||
),
|
||||
deleteSurveyAction: vi.fn(),
|
||||
}));
|
||||
|
||||
// Mock next/navigation
|
||||
const mockRouterRefresh = vi.fn();
|
||||
vi.mock("next/navigation", () => ({
|
||||
useRouter: () => ({
|
||||
refresh: mockRouterRefresh,
|
||||
push: vi.fn(),
|
||||
}),
|
||||
}));
|
||||
|
||||
// Mock react-hot-toast
|
||||
vi.mock("react-hot-toast", () => ({
|
||||
default: {
|
||||
success: vi.fn(),
|
||||
error: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
describe("SurveyDropDownMenu", () => {
|
||||
@@ -240,4 +265,245 @@ describe("SurveyDropDownMenu", () => {
|
||||
expect(mockDuplicateSurvey).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("handleDeleteSurvey", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test("successfully deletes survey - calls all expected functions and shows success toast", async () => {
|
||||
const mockDeleteSurvey = vi.fn();
|
||||
mockDeleteSurveyAction.mockResolvedValueOnce({ data: true });
|
||||
|
||||
render(
|
||||
<SurveyDropDownMenu
|
||||
environmentId="env123"
|
||||
survey={fakeSurvey}
|
||||
publicDomain="http://survey.test"
|
||||
refreshSingleUseId={vi.fn()}
|
||||
duplicateSurvey={vi.fn()}
|
||||
deleteSurvey={mockDeleteSurvey}
|
||||
/>
|
||||
);
|
||||
|
||||
// Open dropdown and click delete
|
||||
const menuWrapper = screen.getByTestId("survey-dropdown-menu");
|
||||
const triggerElement = menuWrapper.querySelector("[class*='p-2']") as HTMLElement;
|
||||
await userEvent.click(triggerElement);
|
||||
|
||||
const deleteButton = screen.getByText("common.delete");
|
||||
await userEvent.click(deleteButton);
|
||||
|
||||
// Confirm deletion in dialog
|
||||
const confirmDeleteButton = screen.getByText("common.delete");
|
||||
await userEvent.click(confirmDeleteButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockDeleteSurveyAction).toHaveBeenCalledWith({ surveyId: "testSurvey" });
|
||||
expect(mockDeleteSurvey).toHaveBeenCalledWith("testSurvey");
|
||||
expect(mockToast.success).toHaveBeenCalledWith("environments.surveys.survey_deleted_successfully");
|
||||
expect(mockRouterRefresh).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
test("handles deletion error - shows error toast and resets loading state", async () => {
|
||||
const mockDeleteSurvey = vi.fn();
|
||||
const deletionError = new Error("Deletion failed");
|
||||
mockDeleteSurveyAction.mockRejectedValueOnce(deletionError);
|
||||
|
||||
render(
|
||||
<SurveyDropDownMenu
|
||||
environmentId="env123"
|
||||
survey={fakeSurvey}
|
||||
publicDomain="http://survey.test"
|
||||
refreshSingleUseId={vi.fn()}
|
||||
duplicateSurvey={vi.fn()}
|
||||
deleteSurvey={mockDeleteSurvey}
|
||||
/>
|
||||
);
|
||||
|
||||
// Open dropdown and click delete
|
||||
const menuWrapper = screen.getByTestId("survey-dropdown-menu");
|
||||
const triggerElement = menuWrapper.querySelector("[class*='p-2']") as HTMLElement;
|
||||
await userEvent.click(triggerElement);
|
||||
|
||||
const deleteButton = screen.getByText("common.delete");
|
||||
await userEvent.click(deleteButton);
|
||||
|
||||
// Confirm deletion in dialog
|
||||
const confirmDeleteButton = screen.getByText("common.delete");
|
||||
await userEvent.click(confirmDeleteButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockDeleteSurveyAction).toHaveBeenCalledWith({ surveyId: "testSurvey" });
|
||||
expect(mockDeleteSurvey).not.toHaveBeenCalled();
|
||||
expect(mockToast.error).toHaveBeenCalledWith("environments.surveys.error_deleting_survey");
|
||||
expect(mockRouterRefresh).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
test("manages loading state correctly during successful deletion", async () => {
|
||||
const mockDeleteSurvey = vi.fn();
|
||||
mockDeleteSurveyAction.mockImplementation(
|
||||
() => new Promise((resolve) => setTimeout(() => resolve({ data: true }), 100))
|
||||
);
|
||||
|
||||
render(
|
||||
<SurveyDropDownMenu
|
||||
environmentId="env123"
|
||||
survey={fakeSurvey}
|
||||
publicDomain="http://survey.test"
|
||||
refreshSingleUseId={vi.fn()}
|
||||
duplicateSurvey={vi.fn()}
|
||||
deleteSurvey={mockDeleteSurvey}
|
||||
/>
|
||||
);
|
||||
|
||||
// Open dropdown and click delete
|
||||
const menuWrapper = screen.getByTestId("survey-dropdown-menu");
|
||||
const triggerElement = menuWrapper.querySelector("[class*='p-2']") as HTMLElement;
|
||||
await userEvent.click(triggerElement);
|
||||
|
||||
const deleteButton = screen.getByText("common.delete");
|
||||
await userEvent.click(deleteButton);
|
||||
|
||||
// Confirm deletion in dialog using a more reliable selector
|
||||
const confirmDeleteButton = screen.getByText("common.delete");
|
||||
await userEvent.click(confirmDeleteButton);
|
||||
|
||||
// Wait for the deletion process to complete
|
||||
await waitFor(() => {
|
||||
expect(mockDeleteSurveyAction).toHaveBeenCalled();
|
||||
expect(mockDeleteSurvey).toHaveBeenCalled();
|
||||
expect(mockToast.success).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
test("manages loading state correctly during failed deletion", async () => {
|
||||
const mockDeleteSurvey = vi.fn();
|
||||
mockDeleteSurveyAction.mockImplementation(
|
||||
() => new Promise((_, reject) => setTimeout(() => reject(new Error("Network error")), 100))
|
||||
);
|
||||
|
||||
render(
|
||||
<SurveyDropDownMenu
|
||||
environmentId="env123"
|
||||
survey={fakeSurvey}
|
||||
publicDomain="http://survey.test"
|
||||
refreshSingleUseId={vi.fn()}
|
||||
duplicateSurvey={vi.fn()}
|
||||
deleteSurvey={mockDeleteSurvey}
|
||||
/>
|
||||
);
|
||||
|
||||
// Open dropdown and click delete
|
||||
const menuWrapper = screen.getByTestId("survey-dropdown-menu");
|
||||
const triggerElement = menuWrapper.querySelector("[class*='p-2']") as HTMLElement;
|
||||
await userEvent.click(triggerElement);
|
||||
|
||||
const deleteButton = screen.getByText("common.delete");
|
||||
await userEvent.click(deleteButton);
|
||||
|
||||
// Confirm deletion in dialog using a more reliable selector
|
||||
const confirmDeleteButton = screen.getByText("common.delete");
|
||||
await userEvent.click(confirmDeleteButton);
|
||||
|
||||
// Wait for the error to occur
|
||||
await waitFor(() => {
|
||||
expect(mockDeleteSurveyAction).toHaveBeenCalled();
|
||||
expect(mockToast.error).toHaveBeenCalledWith("environments.surveys.error_deleting_survey");
|
||||
});
|
||||
|
||||
// Verify that deleteSurvey callback was not called due to error
|
||||
expect(mockDeleteSurvey).not.toHaveBeenCalled();
|
||||
expect(mockRouterRefresh).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("does not call router.refresh or success toast when deleteSurveyAction throws", async () => {
|
||||
const mockDeleteSurvey = vi.fn();
|
||||
mockDeleteSurveyAction.mockRejectedValueOnce(new Error("API Error"));
|
||||
|
||||
render(
|
||||
<SurveyDropDownMenu
|
||||
environmentId="env123"
|
||||
survey={fakeSurvey}
|
||||
publicDomain="http://survey.test"
|
||||
refreshSingleUseId={vi.fn()}
|
||||
duplicateSurvey={vi.fn()}
|
||||
deleteSurvey={mockDeleteSurvey}
|
||||
/>
|
||||
);
|
||||
|
||||
// Open dropdown and click delete
|
||||
const menuWrapper = screen.getByTestId("survey-dropdown-menu");
|
||||
const triggerElement = menuWrapper.querySelector("[class*='p-2']") as HTMLElement;
|
||||
await userEvent.click(triggerElement);
|
||||
|
||||
const deleteButton = screen.getByText("common.delete");
|
||||
await userEvent.click(deleteButton);
|
||||
|
||||
// Confirm deletion in dialog
|
||||
const confirmDeleteButton = screen.getByText("common.delete");
|
||||
await userEvent.click(confirmDeleteButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockDeleteSurveyAction).toHaveBeenCalled();
|
||||
expect(mockToast.error).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
// Verify success-path functions are not called
|
||||
expect(mockDeleteSurvey).not.toHaveBeenCalled();
|
||||
expect(mockToast.success).not.toHaveBeenCalled();
|
||||
expect(mockRouterRefresh).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("calls functions in correct order during successful deletion", async () => {
|
||||
const mockDeleteSurvey = vi.fn();
|
||||
const callOrder: string[] = [];
|
||||
|
||||
mockDeleteSurveyAction.mockImplementation(async () => {
|
||||
callOrder.push("deleteSurveyAction");
|
||||
return { data: true };
|
||||
});
|
||||
|
||||
mockDeleteSurvey.mockImplementation(() => {
|
||||
callOrder.push("deleteSurvey");
|
||||
});
|
||||
|
||||
(mockToast.success as any).mockImplementation(() => {
|
||||
callOrder.push("toast.success");
|
||||
});
|
||||
|
||||
mockRouterRefresh.mockImplementation(() => {
|
||||
callOrder.push("router.refresh");
|
||||
});
|
||||
|
||||
render(
|
||||
<SurveyDropDownMenu
|
||||
environmentId="env123"
|
||||
survey={fakeSurvey}
|
||||
publicDomain="http://survey.test"
|
||||
refreshSingleUseId={vi.fn()}
|
||||
duplicateSurvey={vi.fn()}
|
||||
deleteSurvey={mockDeleteSurvey}
|
||||
/>
|
||||
);
|
||||
|
||||
// Open dropdown and click delete
|
||||
const menuWrapper = screen.getByTestId("survey-dropdown-menu");
|
||||
const triggerElement = menuWrapper.querySelector("[class*='p-2']") as HTMLElement;
|
||||
await userEvent.click(triggerElement);
|
||||
|
||||
const deleteButton = screen.getByText("common.delete");
|
||||
await userEvent.click(deleteButton);
|
||||
|
||||
// Confirm deletion in dialog
|
||||
const confirmDeleteButton = screen.getByText("common.delete");
|
||||
await userEvent.click(confirmDeleteButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(callOrder).toEqual(["deleteSurveyAction", "deleteSurvey", "toast.success", "router.refresh"]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -74,8 +74,9 @@ export const SurveyDropDownMenu = ({
|
||||
toast.success(t("environments.surveys.survey_deleted_successfully"));
|
||||
router.refresh();
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
toast.error(t("environments.surveys.error_deleting_survey"));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user