import React from "react"; import { Route, Routes } from "react-router-dom"; import { RefineCloneButtonProps, RefineButtonTestIds, } from "@refinedev/ui-types"; import { act, fireEvent, render, TestWrapper, waitFor } from "@test"; export const buttonCloneTests = function ( CloneButton: React.ComponentType>, ): void { describe("[@refinedev/ui-tests] Common Tests / Clone Button", () => { beforeAll(() => { jest.spyOn(console, "warn").mockImplementation(jest.fn()); }); it("should render button successfuly", async () => { const { container, getByText } = render(, { wrapper: TestWrapper({}), }); expect(container).toBeTruthy(); expect(getByText("Clone").closest("button")).not.toBeDisabled(); }); it("should have the correct test-id", async () => { const { queryByTestId } = render(, { wrapper: TestWrapper({}), }); expect(queryByTestId(RefineButtonTestIds.CloneButton)).toBeTruthy(); }); it("should render text by children", async () => { const { container, getByText } = render( refine, { wrapper: TestWrapper({}), }, ); expect(container).toBeTruthy(); getByText("refine"); }); it("should render without text show only icon", async () => { const { container, queryByText } = render( , { wrapper: TestWrapper({}), }, ); expect(container).toBeTruthy(); expect(queryByText("Clone")).not.toBeInTheDocument(); }); describe("access control", () => { describe("with global access control only", () => { describe("with default behaviour", () => { describe("when user not have access", () => { it("should render disabled button with reason text", async () => { const { container, getByText } = render( Clone , { wrapper: TestWrapper({ accessControlProvider: { can: async ({ params, action }) => { if ( action === "create" && params?.id === "1" ) { return { can: false, reason: "Access Denied", }; } return { can: true, }; }, }, }), }, ); expect(container).toBeTruthy(); await waitFor(() => expect( getByText("Clone").closest("button"), ).toBeDisabled(), ); waitFor(() => expect( getByText("Clone") .closest("button") ?.getAttribute("title"), ).toBe("Access Denied"), ); }); }); describe("when user have access", () => { it("should render enabled button", async () => { const { container, getByText } = render( Clone , { wrapper: TestWrapper({ accessControlProvider: { can: async ({ params, action }) => { if ( action === "create" && params?.id === "1" ) { return { can: false, }; } return { can: true, }; }, }, }), }, ); expect(container).toBeTruthy(); await waitFor(() => expect( getByText("Clone").closest("button"), ).not.toBeDisabled(), ); }); }); }); describe("when hideIfUnauthorized is true", () => { it("should not render button", async () => { const { container, queryByText } = render( Clone, { wrapper: TestWrapper({ accessControlProvider: { can: async () => ({ can: false }), options: { buttons: { hideIfUnauthorized: true, }, }, }, }), }, ); expect(container).toBeTruthy(); expect(queryByText("Clone")).not.toBeInTheDocument(); }); }); describe("when access control is disabled explicitly", () => { it("should render enabled button", async () => { const { container, getByText } = render( Clone, { wrapper: TestWrapper({ accessControlProvider: { can: async () => ({ can: false }), options: { buttons: { enableAccessControl: false, hideIfUnauthorized: true, }, }, }, }), }, ); expect(container).toBeTruthy(); expect( getByText("Clone").closest("button"), ).not.toBeDisabled(); }); }); }); describe("with global config and accessControl prop", () => { describe("when access control enabled globally", () => { describe("when access control is disabled with prop", () => { it("should render enabled button", async () => { const { container, getByText } = render( Clone , { wrapper: TestWrapper({ accessControlProvider: { can: async () => { return { can: false, }; }, options: { buttons: { enableAccessControl: true, hideIfUnauthorized: true, }, }, }, }), }, ); expect(container).toBeTruthy(); await waitFor(() => expect( getByText("Clone").closest("button"), ).not.toBeDisabled(), ); }); }); describe("when hideIfUnauthorized false globally", () => { describe("when hideIfUnauthorized enabled with prop", () => { it("should not render button", async () => { const { container, queryByText } = render( Clone , { wrapper: TestWrapper({ accessControlProvider: { can: async () => ({ can: false, }), options: { buttons: { hideIfUnauthorized: false, }, }, }, }), }, ); expect(container).toBeTruthy(); expect( queryByText("Clone"), ).not.toBeInTheDocument(); }); }); }); }); describe("when access control disabled globally", () => { describe("when access control enabled with prop", () => { it("should render disabled button with reason text", async () => { const { container, getByText } = render( Clone , { wrapper: TestWrapper({ accessControlProvider: { can: async () => { return { can: false, reason: "Access Denied", }; }, }, }), }, ); expect(container).toBeTruthy(); await waitFor(() => expect( getByText("Clone").closest("button"), ).toBeDisabled(), ); waitFor(() => expect( getByText("Clone") .closest("button") ?.getAttribute("title"), ).toBe("Access Denied"), ); }); }); }); describe("when hideIfUnauthorized enabled globally", () => { describe("when hideIfUnauthorized disabled with prop", () => { it("should render button", async () => { const { container, queryByText } = render( Clone , { wrapper: TestWrapper({ accessControlProvider: { can: async () => ({ can: false, }), options: { buttons: { hideIfUnauthorized: true, }, }, }, }), }, ); expect(container).toBeTruthy(); expect(queryByText("Clone")).toBeInTheDocument(); }); }); }); }); }); it("should render called function successfully if click the button", async () => { const clone = jest.fn(); const { getByText } = render( clone()} recordItemId="1" />, { wrapper: TestWrapper({ resources: [{ name: "posts" }], }), }, ); await act(async () => { fireEvent.click(getByText("Clone")); }); expect(clone).toHaveBeenCalledTimes(1); }); it("should create page redirect clone route called function successfully if click the button", async () => { const { getByText } = render( } /> , { wrapper: TestWrapper({ routerInitialEntries: ["/posts"], }), }, ); await act(async () => { fireEvent.click(getByText("Clone")); }); expect(window.location.pathname).toBe("/posts/clone/1"); }); it("should edit page redirect clone route called function successfully if click the button", async () => { const { getByText } = render( } /> , { wrapper: TestWrapper({ routerInitialEntries: ["/posts/edit/1"], }), }, ); await act(async () => { fireEvent.click(getByText("Clone")); }); expect(window.location.pathname).toBe("/posts/clone/1"); }); it("should custom resource and recordItemId redirect clone route called function successfully if click the button", async () => { const { getByText } = render( } /> , { wrapper: TestWrapper({ resources: [{ name: "posts" }, { name: "categories" }], routerInitialEntries: ["/posts"], }), }, ); await act(async () => { fireEvent.click(getByText("Clone")); }); expect(window.location.pathname).toBe("/categories/clone/1"); }); it("should redirect with custom route called function successfully if click the button", async () => { const { getByText } = render( } /> , { wrapper: TestWrapper({ resources: [ { name: "posts", meta: { route: "custom-route-posts" }, }, { name: "posts" }, ], routerInitialEntries: ["/posts"], }), }, ); await act(async () => { fireEvent.click(getByText("Clone")); }); expect(window.location.pathname).toBe( "/custom-route-posts/clone/1", ); }); }); };