diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/JS/hooks.ts b/app/client/src/ce/pages/Editor/IDE/EditorPane/JS/hooks.tsx similarity index 76% rename from app/client/src/ce/pages/Editor/IDE/EditorPane/JS/hooks.ts rename to app/client/src/ce/pages/Editor/IDE/EditorPane/JS/hooks.tsx index 58614a67abe9..11fff284d534 100644 --- a/app/client/src/ce/pages/Editor/IDE/EditorPane/JS/hooks.ts +++ b/app/client/src/ce/pages/Editor/IDE/EditorPane/JS/hooks.tsx @@ -1,4 +1,5 @@ -import { useCallback } from "react"; +import { lazy, Suspense, useCallback } from "react"; +import React from "react"; import { useDispatch, useSelector } from "react-redux"; import { createNewJSCollection } from "actions/jsPaneActions"; import { getCurrentPageId } from "selectors/editorSelectors"; @@ -7,17 +8,16 @@ import { createMessage, EDITOR_PANE_TEXTS } from "ee/constants/messages"; import { JsFileIconV2 } from "pages/Editor/Explorer/ExplorerIcons"; import { SEARCH_ITEM_TYPES } from "components/editorComponents/GlobalSearch/utils"; import type { UseRoutes } from "ee/entities/IDE/constants"; -import JSEditor from "pages/Editor/JSEditor"; -import AddJS from "pages/Editor/IDE/EditorPane/JS/Add"; import { ADD_PATH } from "ee/constants/routes/appRoutes"; import history from "utils/history"; import { FocusEntity, identifyEntityFromPath } from "navigation/FocusEntity"; import { useModuleOptions } from "ee/utils/moduleInstanceHelpers"; import { getJSUrl } from "ee/pages/Editor/IDE/EditorPane/JS/utils"; -import { JSBlankState } from "pages/Editor/JSEditor/JSBlankState"; import { getIDEViewMode } from "selectors/ideSelectors"; import { EditorViewMode } from "ee/entities/IDE/constants"; import { setListViewActiveState } from "actions/ideActions"; +import { retryPromise } from "utils/AppsmithUtils"; +import Skeleton from "widgets/Skeleton"; export const useJSAdd = () => { const pageId = useSelector(getCurrentPageId); @@ -93,23 +93,59 @@ export const useGroupedAddJsOperations = (): GroupedAddOperations => { ]; }; +const AddJS = lazy(async () => + retryPromise( + async () => + import( + /* webpackChunkName: "AddJS" */ "pages/Editor/IDE/EditorPane/JS/Add" + ), + ), +); +const JSEditor = lazy(async () => + retryPromise( + async () => + import(/* webpackChunkName: "JSEditor" */ "pages/Editor/JSEditor"), + ), +); + +const JSEmpty = lazy(async () => + retryPromise( + async () => + import( + /* webpackChunkName: "JSEmpty" */ "pages/Editor/JSEditor/JSBlankState" + ), + ), +); + export const useJSEditorRoutes = (path: string): UseRoutes => { return [ { exact: true, key: "AddJS", - component: AddJS, + component: (args) => ( + }> + + + ), path: [`${path}${ADD_PATH}`, `${path}/:baseCollectionId${ADD_PATH}`], }, { exact: true, key: "JSEditor", - component: JSEditor, + component: (args) => ( + }> + + + ), path: [path + "/:baseCollectionId"], }, { key: "JSEmpty", - component: JSBlankState, + component: (args) => ( + }> + + + ), exact: true, path: [path], }, diff --git a/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/hooks.tsx b/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/hooks.tsx index 73ffb6ab8a74..c2f673f48330 100644 --- a/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/hooks.tsx +++ b/app/client/src/ce/pages/Editor/IDE/EditorPane/Query/hooks.tsx @@ -1,4 +1,5 @@ -import { useCallback, useMemo } from "react"; +import { lazy, Suspense, useCallback, useMemo } from "react"; +import React from "react"; import history from "utils/history"; import { useLocation } from "react-router"; import { FocusEntity, identifyEntityFromPath } from "navigation/FocusEntity"; @@ -23,19 +24,17 @@ import { BUILDER_PATH_DEPRECATED, } from "ee/constants/routes/appRoutes"; import { SAAS_EDITOR_API_ID_PATH } from "pages/Editor/SaaSEditor/constants"; -import ApiEditor from "pages/Editor/APIEditor"; import type { UseRoutes } from "ee/entities/IDE/constants"; -import QueryEditor from "pages/Editor/QueryEditor"; -import AddQuery from "pages/Editor/IDE/EditorPane/Query/Add"; import type { AppState } from "ee/reducers"; import keyBy from "lodash/keyBy"; import { getPluginEntityIcon } from "pages/Editor/Explorer/ExplorerIcons"; import type { ListItemProps } from "@appsmith/ads"; import { createAddClassName } from "pages/Editor/IDE/EditorPane/utils"; -import { QueriesBlankState } from "pages/Editor/QueryEditor/QueriesBlankState"; import { getIDEViewMode } from "selectors/ideSelectors"; import { EditorViewMode } from "ee/entities/IDE/constants"; import { setListViewActiveState } from "actions/ideActions"; +import { retryPromise } from "utils/AppsmithUtils"; +import Skeleton from "widgets/Skeleton"; export const useQueryAdd = () => { const location = useLocation(); @@ -114,11 +113,48 @@ export const useGroupedAddQueryOperations = (): GroupedAddOperations => { return groups; }; +const ApiEditor = lazy(async () => + retryPromise( + async () => + import(/* webpackChunkName: "APIEditor" */ "pages/Editor/APIEditor"), + ), +); + +const AddQuery = lazy(async () => + retryPromise( + async () => + import( + /* webpackChunkName: "AddQuery" */ "pages/Editor/IDE/EditorPane/Query/Add" + ), + ), +); +const QueryEditor = lazy(async () => + retryPromise( + async () => + import(/* webpackChunkName: "QueryEditor" */ "pages/Editor/QueryEditor"), + ), +); + +const QueryEmpty = lazy(async () => + retryPromise( + async () => + import( + /* webpackChunkName: "QueryEmpty" */ "pages/Editor/QueryEditor/QueriesBlankState" + ), + ), +); + export const useQueryEditorRoutes = (path: string): UseRoutes => { return [ { key: "ApiEditor", - component: ApiEditor, + component: (args) => { + return ( + }> + + + ); + }, exact: true, path: [ BUILDER_PATH + API_EDITOR_ID_PATH, @@ -129,12 +165,22 @@ export const useQueryEditorRoutes = (path: string): UseRoutes => { { key: "AddQuery", exact: true, - component: AddQuery, + component: (args) => ( + }> + + + ), path: [`${path}${ADD_PATH}`, `${path}/:baseQueryId${ADD_PATH}`], }, { key: "SAASEditor", - component: QueryEditor, + component: (args) => { + return ( + }> + + + ); + }, exact: true, path: [ BUILDER_PATH + SAAS_EDITOR_API_ID_PATH, @@ -144,13 +190,23 @@ export const useQueryEditorRoutes = (path: string): UseRoutes => { }, { key: "QueryEditor", - component: QueryEditor, + component: (args) => { + return ( + }> + + + ); + }, exact: true, path: [path + "/:baseQueryId"], }, { key: "QueryEmpty", - component: QueriesBlankState, + component: (args) => ( + }> + + + ), exact: true, path: [path], }, diff --git a/app/client/src/pages/Editor/IDE/EditorPane/JS/JSRender.test.tsx b/app/client/src/pages/Editor/IDE/EditorPane/JS/JSRender.test.tsx index b0decd243581..fa0c0f25f28c 100644 --- a/app/client/src/pages/Editor/IDE/EditorPane/JS/JSRender.test.tsx +++ b/app/client/src/pages/Editor/IDE/EditorPane/JS/JSRender.test.tsx @@ -1,5 +1,5 @@ import localStorage from "utils/localStorage"; -import { render } from "test/testUtils"; +import { render, waitFor } from "test/testUtils"; import { Route } from "react-router-dom"; import { BUILDER_PATH } from "ee/constants/routes/appRoutes"; import IDE from "pages/Editor/IDE/index"; @@ -19,8 +19,8 @@ const basePageId = "0123456789abcdef00000000"; describe("IDE Render: JS", () => { localStorage.setItem("SPLITPANE_ANNOUNCEMENT", "false"); describe("JS Blank State", () => { - it("Renders Fullscreen Blank State", () => { - const { getByRole, getByText } = render( + it("Renders Fullscreen Blank State", async () => { + const { findByText, getByRole, getByText } = render( , @@ -31,7 +31,7 @@ describe("IDE Render: JS", () => { ); // Main pane text - getByText(createMessage(EDITOR_PANE_TEXTS.js_blank_state)); + await findByText(createMessage(EDITOR_PANE_TEXTS.js_blank_state)); // Left pane text getByText(createMessage(EDITOR_PANE_TEXTS.js_blank_state_description)); @@ -68,8 +68,8 @@ describe("IDE Render: JS", () => { }); }); - it("Renders Fullscreen Add in Blank State", () => { - const { getByTestId, getByText } = render( + it("Renders Fullscreen Add in Blank State", async () => { + const { findByText, getByTestId, getByText } = render( , @@ -80,7 +80,7 @@ describe("IDE Render: JS", () => { ); // Main pane text - getByText(createMessage(EDITOR_PANE_TEXTS.js_create_tab_title)); + await findByText(createMessage(EDITOR_PANE_TEXTS.js_create_tab_title)); // Left pane description getByText(createMessage(EDITOR_PANE_TEXTS.js_blank_state_description)); @@ -117,7 +117,7 @@ describe("IDE Render: JS", () => { }); describe("JS Edit Render", () => { - it("Renders JS routes in Full screen", () => { + it("Renders JS routes in Full screen", async () => { const page = PageFactory.build(); const js1 = JSObjectFactory.build({ pageId: page.pageId, @@ -143,6 +143,15 @@ describe("IDE Render: JS", () => { }, ); + await waitFor( + async () => { + const elements = getAllByText("JSObject1"); // Use the common test ID or selector + + expect(elements).toHaveLength(3); // Wait until there are exactly 3 elements + }, + { timeout: 3000, interval: 500 }, + ); + // There will be 3 JSObject1 text (Left pane list, editor tab and Editor form) expect(getAllByText("JSObject1").length).toEqual(3); // Left pane active state diff --git a/app/client/src/pages/Editor/IDE/EditorPane/Query/QueryRender.test.tsx b/app/client/src/pages/Editor/IDE/EditorPane/Query/QueryRender.test.tsx index 3bc3dca089ba..65314ae7a727 100644 --- a/app/client/src/pages/Editor/IDE/EditorPane/Query/QueryRender.test.tsx +++ b/app/client/src/pages/Editor/IDE/EditorPane/Query/QueryRender.test.tsx @@ -12,7 +12,7 @@ import { sagasToRunForTests } from "test/sagas"; import userEvent from "@testing-library/user-event"; import { getIDETestState } from "test/factories/AppIDEFactoryUtils"; import { PageFactory } from "test/factories/PageFactory"; -import { screen } from "@testing-library/react"; +import { screen, waitFor } from "@testing-library/react"; import { GoogleSheetFactory } from "test/factories/Actions/GoogleSheetFactory"; const FeatureFlags = { @@ -24,8 +24,8 @@ const basePageId = "0123456789abcdef00000000"; describe("IDE URL rendering of Queries", () => { localStorage.setItem("SPLITPANE_ANNOUNCEMENT", "false"); describe("Query Blank State", () => { - it("Renders Fullscreen Blank State", () => { - const { getByRole, getByText } = render( + it("Renders Fullscreen Blank State", async () => { + const { findByText, getByRole, getByText } = render( , @@ -36,7 +36,7 @@ describe("IDE URL rendering of Queries", () => { ); // Main pane text - getByText(createMessage(EDITOR_PANE_TEXTS.query_blank_state)); + await findByText(createMessage(EDITOR_PANE_TEXTS.query_blank_state)); // Left pane text getByText(createMessage(EDITOR_PANE_TEXTS.query_blank_state_description)); @@ -69,8 +69,8 @@ describe("IDE URL rendering of Queries", () => { getByText(/new query \/ api/i); }); - it("Renders Fullscreen Add in Blank State", () => { - const { getByTestId, getByText } = render( + it("Renders Fullscreen Add in Blank State", async () => { + const { findByText, getByTestId, getByText } = render( , @@ -81,7 +81,9 @@ describe("IDE URL rendering of Queries", () => { ); // Create options are rendered - getByText(createMessage(EDITOR_PANE_TEXTS.queries_create_from_existing)); + await findByText( + createMessage(EDITOR_PANE_TEXTS.queries_create_from_existing), + ); getByText("New datasource"); getByText("REST API"); // Check new tab presence @@ -130,7 +132,7 @@ describe("IDE URL rendering of Queries", () => { }); describe("API Routes", () => { - it("Renders Api routes in Full screen", () => { + it("Renders Api routes in Full screen", async () => { const page = PageFactory.build(); const anApi = APIFactory.build({ pageId: page.pageId }); const state = getIDETestState({ @@ -153,6 +155,15 @@ describe("IDE URL rendering of Queries", () => { }, ); + await waitFor( + async () => { + const elements = getAllByText("Api1"); // Use the common test ID or selector + + expect(elements).toHaveLength(3); // Wait until there are exactly 3 elements + }, + { timeout: 3000, interval: 500 }, + ); + // There will be 3 Api1 text (Left pane list, editor tab and Editor form) expect(getAllByText("Api1").length).toEqual(3); // Left pane active state @@ -343,6 +354,14 @@ describe("IDE URL rendering of Queries", () => { }, ); + await waitFor( + async () => { + const elements = getAllByText("Query1"); // Use the common test ID or selector + + expect(elements).toHaveLength(3); // Wait until there are exactly 3 elements + }, + { timeout: 3000, interval: 500 }, + ); // There will be 3 Query1 text (Left pane list, editor tab and Editor form) expect(getAllByText("Query1").length).toBe(3); // Left pane active state diff --git a/app/client/src/pages/Editor/JSEditor/JSBlankState.tsx b/app/client/src/pages/Editor/JSEditor/JSBlankState.tsx index acf141ca0bec..303f41b1893b 100644 --- a/app/client/src/pages/Editor/JSEditor/JSBlankState.tsx +++ b/app/client/src/pages/Editor/JSEditor/JSBlankState.tsx @@ -26,4 +26,4 @@ const JSBlankState = () => { ); }; -export { JSBlankState }; +export default JSBlankState; diff --git a/app/client/src/pages/Editor/JSEditor/index.tsx b/app/client/src/pages/Editor/JSEditor/index.tsx index e625d5057013..6fcd8956119b 100644 --- a/app/client/src/pages/Editor/JSEditor/index.tsx +++ b/app/client/src/pages/Editor/JSEditor/index.tsx @@ -15,7 +15,6 @@ import AppJSEditorContextMenu from "./AppJSEditorContextMenu"; import { updateFunctionProperty } from "actions/jsPaneActions"; import type { OnUpdateSettingsProps } from "./JSEditorToolbar"; import { saveJSObjectName } from "actions/jsActionActions"; - const LoadingContainer = styled(CenteredWrapper)` height: 50%; `; diff --git a/app/client/src/pages/Editor/QueryEditor/QueriesBlankState.tsx b/app/client/src/pages/Editor/QueryEditor/QueriesBlankState.tsx index 2b6aae11ce00..0f23cd2c0751 100644 --- a/app/client/src/pages/Editor/QueryEditor/QueriesBlankState.tsx +++ b/app/client/src/pages/Editor/QueryEditor/QueriesBlankState.tsx @@ -26,4 +26,4 @@ const QueriesBlankState = () => { ); }; -export { QueriesBlankState }; +export default QueriesBlankState;