diff --git a/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/EntityCheckboxSelector.test.tsx b/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/EntityCheckboxSelector.test.tsx new file mode 100644 index 0000000000..62245b85da --- /dev/null +++ b/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/EntityCheckboxSelector.test.tsx @@ -0,0 +1,41 @@ +import React from "react"; +import { render, screen, fireEvent } from "@testing-library/react"; +import "@testing-library/jest-dom"; +import EntityCheckboxSelector from "./EntityCheckboxSelector"; + +describe("", () => { + const baseProps = { + entities: [ + { id: "1", name: "Entity1" }, + { id: "2", name: "Entity2" }, + ], + onEntityChecked: jest.fn(), + selectedIds: ["1"], + }; + + it("renders the component with correct props", () => { + render(); + expect(screen.getByText("Entity1")).toBeInTheDocument(); + expect(screen.getByText("Entity2")).toBeInTheDocument(); + }); + + it("checks the selected checkbox", () => { + render(); + const entityCheckbox = screen.getByLabelText("Entity1"); + expect(entityCheckbox).toBeChecked(); + }); + + it("handles checkbox click", () => { + render(); + const entityCheckbox = screen.getByLabelText("Entity2"); + fireEvent.click(entityCheckbox); + expect(baseProps.onEntityChecked).toHaveBeenCalledWith("2", true); + }); + + it("handles checkbox uncheck", () => { + render(); + const entityCheckbox = screen.getByLabelText("Entity1"); + fireEvent.click(entityCheckbox); + expect(baseProps.onEntityChecked).toHaveBeenCalledWith("1", false); + }); +}); diff --git a/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/JSObjectsNQueriesExport.test.tsx b/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/JSObjectsNQueriesExport.test.tsx new file mode 100644 index 0000000000..1a29163ce1 --- /dev/null +++ b/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/JSObjectsNQueriesExport.test.tsx @@ -0,0 +1,52 @@ +import React from "react"; +import { render, screen, fireEvent } from "@testing-library/react"; +import "@testing-library/jest-dom"; +import JSObjectsNQueriesExport from "./JSObjectsNQueriesExport"; +import { lightTheme } from "selectors/themeSelectors"; +import { mockAppDSProps, mockDataBaseProps } from "./unitTestUtils"; +import { ThemeProvider } from "styled-components"; + +jest.mock("react-redux", () => { + const originalModule = jest.requireActual("react-redux"); + return { + ...originalModule, + useDispatch: () => jest.fn(), + useSelector: () => jest.fn(), + }; +}); + +const baseProps = { + appDS: mockAppDSProps, + data: mockDataBaseProps, + selectedQueries: [], + updateSelectedQueries: jest.fn(), +}; + +const BaseComponentRender = () => ( + + + +); + +describe("", () => { + it("renders the component with correct props", () => { + render(); + const moviesDatabase = screen.getByText("Movies"); + expect(moviesDatabase).toBeInTheDocument(); + const usersDatabase = screen.getByText("users"); + expect(usersDatabase).toBeInTheDocument(); + const moviesQuery = screen.getByText("Query1"); + expect(moviesQuery).toBeInTheDocument(); + const usersQuery = screen.getByText("getUsers"); + expect(usersQuery).toBeInTheDocument(); + }); + + it("toggles the query list when datasource is clicked", () => { + render(); + const moviesDatasource = screen.getByText("Movies"); + fireEvent.click(moviesDatasource); + expect(screen.getByText("Query1")).not.toBeVisible(); + fireEvent.click(moviesDatasource); + expect(screen.getByText("Query1")).toBeVisible(); + }); +}); diff --git a/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/PartialExportModal.test.tsx b/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/PartialExportModal.test.tsx new file mode 100644 index 0000000000..9f2efa6599 --- /dev/null +++ b/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/PartialExportModal.test.tsx @@ -0,0 +1,183 @@ +import React from "react"; +import { render, screen, fireEvent, waitFor } from "@testing-library/react"; +import "@testing-library/jest-dom"; +import PartialExportModal from "./index"; +import { lightTheme } from "selectors/themeSelectors"; +import { ThemeProvider } from "styled-components"; +import configureStore from "redux-mock-store"; +import { Provider } from "react-redux"; +import { defaultAppState } from "./unitTestUtils"; +import { + PARTIAL_IMPORT_EXPORT, + createMessage, +} from "@appsmith/constants/messages"; +import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants"; + +interface TestEntityResetProps { + entityTitle: string; + entityItemTitle: string; +} + +const mockStore = configureStore([]); + +jest.mock("pages/Editor/Explorer/Widgets/WidgetIcon", () => ({ + __esModule: true, + default: () =>
, +})); + +describe("", () => { + let store: any; + + beforeEach(() => { + store = mockStore(defaultAppState); + }); + + const BaseComponentRender = () => ( + + + jest.fn()} isModalOpen /> + + + ); + + const testEntityReset = (props: TestEntityResetProps) => { + const entityResetTestId = `t--partial-export-modal-reset-${props.entityTitle}`; + const entity = screen.getByText(props.entityTitle); + const entityItem = screen.getByLabelText(props.entityItemTitle); + const exportButton = screen.getByTestId("t-partial-export-entities-btn"); + + expect(screen.queryByTestId(entityResetTestId)).not.toBeInTheDocument(); + fireEvent.click(entity); + fireEvent.click(entityItem); + expect(screen.getByTestId(entityResetTestId)).toBeInTheDocument(); + expect(exportButton).not.toBeDisabled(); + fireEvent.click(screen.getByTestId(entityResetTestId)); + expect(screen.getByLabelText(props.entityItemTitle)).not.toBeChecked(); + expect(screen.queryByTestId(entityResetTestId)).not.toBeInTheDocument(); + expect(exportButton).toBeDisabled(); + }; + + it("renders the component with correct props", () => { + render(); + const pageList = defaultAppState.entities.pageList; + const currentPageName = pageList.pages.find( + (page: any) => page.pageId === pageList.currentPageId, + )?.pageName; + expect(screen.getByText(`Export - ${currentPageName}`)).toBeInTheDocument(); + expect( + screen.getByText( + createMessage(PARTIAL_IMPORT_EXPORT.export.modalSubHeading), + ), + ).toBeInTheDocument(); + expect( + screen.getByText( + createMessage(PARTIAL_IMPORT_EXPORT.export.sections.jsObjects), + ), + ).toBeInTheDocument(); + expect( + screen.getByText( + createMessage(PARTIAL_IMPORT_EXPORT.export.sections.databases), + ), + ).toBeInTheDocument(); + expect( + screen.getByText( + createMessage(PARTIAL_IMPORT_EXPORT.export.sections.queries), + ), + ).toBeInTheDocument(); + expect( + screen.getByText( + createMessage(PARTIAL_IMPORT_EXPORT.export.sections.customLibs), + ), + ).toBeInTheDocument(); + expect( + screen.getByText( + createMessage(PARTIAL_IMPORT_EXPORT.export.sections.widgets), + ), + ).toBeInTheDocument(); + expect; + expect( + screen.getByText(createMessage(PARTIAL_IMPORT_EXPORT.export.cta)), + ).toBeInTheDocument(); + expect(screen.getByTestId("t-partial-export-entities-btn")).toBeDisabled(); + }); + + it("resets JS objects after an item has been clicked", () => { + render(); + testEntityReset({ + entityTitle: createMessage( + PARTIAL_IMPORT_EXPORT.export.sections.jsObjects, + ), + entityItemTitle: "JSObject1", + }); + }); + + it("resets Databases after an item has been clicked", () => { + render(); + testEntityReset({ + entityTitle: createMessage( + PARTIAL_IMPORT_EXPORT.export.sections.databases, + ), + entityItemTitle: "Movies", + }); + }); + + it("resets Queries after an item has been clicked", () => { + render(); + testEntityReset({ + entityTitle: createMessage(PARTIAL_IMPORT_EXPORT.export.sections.queries), + entityItemTitle: "Query1", + }); + }); + + it("resets Custom libraries after an item has been clicked", () => { + render(); + testEntityReset({ + entityTitle: createMessage( + PARTIAL_IMPORT_EXPORT.export.sections.customLibs, + ), + entityItemTitle: "jspdf", + }); + }); + + it("resets Widgets after an item has been clicked", () => { + render(); + testEntityReset({ + entityTitle: createMessage(PARTIAL_IMPORT_EXPORT.export.sections.widgets), + entityItemTitle: "txt_userFullName", + }); + }); + + it("triggers onExportClick with correct action and payload", async () => { + render(); + const exportButton = screen.getByTestId("t-partial-export-entities-btn"); + const jsObjectsEntity = screen.getByText( + createMessage(PARTIAL_IMPORT_EXPORT.export.sections.jsObjects), + ); + const jsObjectsEntityItem = screen.getByLabelText( + defaultAppState.entities.jsActions[0].config.name, + ); + const jsObjectsEntityItemId = + defaultAppState.entities.jsActions[0].config.id; + + fireEvent.click(jsObjectsEntity); + fireEvent.click(jsObjectsEntityItem); + fireEvent.click(exportButton); + + await waitFor(() => { + expect(store.getActions()).toEqual( + expect.arrayContaining([ + { + type: ReduxActionTypes.PARTIAL_EXPORT_INIT, + payload: { + jsObjects: [jsObjectsEntityItemId], + datasources: [], + customJSLibs: [], + widgets: [], + queries: [], + }, + }, + ]), + ); + }); + }); +}); diff --git a/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/WidgetsExport.test.tsx b/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/WidgetsExport.test.tsx new file mode 100644 index 0000000000..25b0035b09 --- /dev/null +++ b/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/WidgetsExport.test.tsx @@ -0,0 +1,81 @@ +import React from "react"; +import { render, screen, fireEvent } from "@testing-library/react"; +import "@testing-library/jest-dom"; +import WidgetsExport from "./WidgetsExport"; +import { ThemeProvider } from "styled-components"; +import { lightTheme } from "selectors/themeSelectors"; +import { + getAllWidgetIds, + mockTblUserInfoWidgetId, + mockWidgetsProps, +} from "./unitTestUtils"; + +jest.mock("pages/Editor/Explorer/Widgets/WidgetIcon", () => ({ + __esModule: true, + default: () =>
, +})); + +describe("", () => { + const baseProps = { + selectAllchecked: false, + selectedWidgetIds: [], + updateSelectAllChecked: jest.fn(), + updateSelectedWidgets: jest.fn(), + }; + + const BaseComponentRender = () => ( + + + + ); + + it("renders the component with correct props", () => { + render(); + expect(screen.getByText("Select All")).toBeInTheDocument(); + expect(screen.getByText("tbl_userInfo")).toBeInTheDocument(); + expect(screen.getByText("txt_pageTitle")).toBeInTheDocument(); + }); + + it('handles "Select All" checkbox click', () => { + render(); + const widgetIds = getAllWidgetIds(mockWidgetsProps); + const selectAllCheckbox = screen.getByTestId( + "t--partial-export-modal-widget-select-all", + ); + fireEvent.click(selectAllCheckbox!); + expect(baseProps.updateSelectAllChecked).toHaveBeenCalledWith(true); + expect(baseProps.updateSelectedWidgets).toHaveBeenCalledWith( + widgetIds.slice(1), + ); + }); + + it('handles "Select All" and widget click', () => { + render(); + const widgetIds = getAllWidgetIds(mockWidgetsProps); + const selectAllCheckbox = screen.getByTestId( + "t--partial-export-modal-widget-select-all", + ); + const widgetCheckbox = screen.getByTestId( + `t--partial-export-modal-widget-select-${mockTblUserInfoWidgetId}`, + ); + fireEvent.click(selectAllCheckbox!); + expect(baseProps.updateSelectAllChecked).toHaveBeenCalledWith(true); + expect(baseProps.updateSelectedWidgets).toHaveBeenCalledWith( + widgetIds.slice(1), + ); + fireEvent.click(widgetCheckbox); + expect(selectAllCheckbox).not.toBeChecked(); + expect(widgetCheckbox).not.toBeChecked(); + }); + + it("handles widget checkbox click", () => { + render(); + const widgetCheckbox = screen.getByTestId( + `t--partial-export-modal-widget-select-${mockTblUserInfoWidgetId}`, + ); + fireEvent.click(widgetCheckbox); + expect(baseProps.updateSelectedWidgets).toHaveBeenCalledWith([ + mockTblUserInfoWidgetId, + ]); + }); +}); diff --git a/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/WidgetsExport.tsx b/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/WidgetsExport.tsx index 8102ee280a..73c2127273 100644 --- a/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/WidgetsExport.tsx +++ b/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/WidgetsExport.tsx @@ -80,9 +80,13 @@ function WidgetSelector({ ) { const isSelected = selectedWidgetIds.includes(widget.widgetId); return ( -
0 ? level + 8 : level }}> +
0 ? level + 8 : level }} + > toggleNode(widget, checked)} @@ -113,6 +117,7 @@ function WidgetSelector({ diff --git a/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/index.tsx b/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/index.tsx index 37dc788647..e71dbed2fa 100644 --- a/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/index.tsx +++ b/app/client/src/components/editorComponents/PartialImportExport/PartialExportModal/index.tsx @@ -273,7 +273,7 @@ const PartiaExportModel = ({ handleModalClose, isModalOpen }: Props) => { {entities.map( ({ content, icon, onResetClick, shouldShowReset, title }) => ( - <> +
@@ -291,6 +291,7 @@ const PartiaExportModel = ({ handleModalClose, isModalOpen }: Props) => { {shouldShowReset && (