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 && (