PromucFlow_constructor/app/client/test/testCommon.ts
Apeksha Bhosale 2b25e1e9b0
fix: Improving performance of JS evaluations by splitting the data tree (#21547)
## Description
This is the second phase of the split data tree. In the previous version, we collected all config paths in each entity and put them in the `__config__` property. All those config properties do get inserted into final data tree which we don't need at all. 
As part of this change, we will be creating another tree i.e **'configTree'**  which will contain all config of each entity. 

unEvalTree is split into 2 trees => 
1. unEvalTree 
2.  configTree

Example: 
previous unEvalTree Api1 content 
<img width="1766" alt="image" src="https://user-images.githubusercontent.com/7846888/215990868-0b095421-e7b8-44bc-89aa-065b35e237d6.png">


After this change
unEvalTree Api1 content
<img width="1758" alt="image" src="https://user-images.githubusercontent.com/7846888/215991045-506fb10a-645a-4aad-8e77-0f3786a86977.png">
Note- above example doesn't have '__config__' property

configTree Api1 content 
<img width="1760" alt="image" src="https://user-images.githubusercontent.com/7846888/215991169-a2e03443-5d6a-4ff1-97c5-a12593e46395.png">


## Type of change
- Chore (housekeeping or task changes that don't impact user perception)
- #11351


## How Has This Been Tested?
- Manual
- Jest
- Cypress

### Test Plan
> Add Testsmith test cases links that relate to this PR

### Issues raised during DP testing
> Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR)


## Checklist:
### Dev activity
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] PR is being merged under a feature flag


### QA activity:
- [ ] Test plan has been approved by relevant developers
- [ ] Test plan has been peer reviewed by QA
- [ ] Cypress test cases have been added and approved by either SDET or manual QA
- [ ] Organized project review call with relevant stakeholders after Round 1/2 of QA
- [ ] Added Test Plan Approved label after reveiwing all Cypress test

Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
2023-03-20 16:34:02 +05:30

254 lines
6.4 KiB
TypeScript

import {
Page,
ReduxActionTypes,
} from "@appsmith/constants/ReduxActionConstants";
import { initEditor } from "actions/initActions";
import { setAppMode, updateCurrentPage } from "actions/pageActions";
import { APP_MODE } from "entities/App";
import { useDispatch } from "react-redux";
import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer";
import { createSelector } from "reselect";
import { getCanvasWidgetsPayload } from "sagas/PageSagas";
import { getCanvasWidgets } from "selectors/entitiesSelector";
import { editorInitializer } from "utils/editor/EditorUtils";
import { extractCurrentDSL } from "utils/WidgetPropsUtils";
import type { AppState } from "@appsmith/reducers";
import type { WidgetEntity } from "entities/DataTree/dataTreeFactory";
import urlBuilder from "entities/URLRedirect/URLAssembly";
import CanvasWidgetsNormalizer from "normalizers/CanvasWidgetsNormalizer";
import type { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsStructureReducer";
import type { DSLWidget } from "widgets/constants";
export const useMockDsl = (dsl: any, mode?: APP_MODE) => {
const dispatch = useDispatch();
dispatch(setAppMode(mode || APP_MODE.EDIT));
const mockResp: any = {
data: {
id: "page_id",
pageId: "page_id",
name: "Page1",
applicationId: "app_id",
isDefault: true,
isHidden: false,
slug: "page-1",
layouts: [
{
id: "layout_id",
dsl,
layoutOnLoadActions: [],
layoutActions: [],
},
],
userPermissions: [
"read:pages",
"manage:pages",
"create:pageActions",
"delete:pages",
],
},
};
const canvasWidgetsPayload = getCanvasWidgetsPayload(mockResp);
dispatch({
type: ReduxActionTypes.FETCH_PAGE_DSLS_SUCCESS,
payload: [
{
pageId: mockResp.data.id,
dsl: extractCurrentDSL(mockResp),
},
],
});
const pages: Page[] = [
{
pageName: mockResp.data.name,
pageId: mockResp.data.id,
isDefault: mockResp.data.isDefault,
isHidden: !!mockResp.data.isHidden,
slug: mockResp.data.slug,
userPermissions: [
"read:pages",
"manage:pages",
"create:pageActions",
"delete:pages",
],
},
];
dispatch({
type: ReduxActionTypes.FETCH_PAGE_LIST_SUCCESS,
payload: {
pages,
applicationId: mockResp.data.applicationId,
},
});
dispatch({
type: "UPDATE_LAYOUT",
payload: { widgets: canvasWidgetsPayload.widgets },
});
dispatch(updateCurrentPage(mockResp.data.id));
};
export function MockPageDSL({ children, dsl }: any) {
editorInitializer();
useMockDsl(dsl);
return children;
}
export const mockGetCanvasWidgetDsl = createSelector(
getCanvasWidgets,
(canvasWidgets: CanvasWidgetsReduxState): DSLWidget => {
return CanvasWidgetsNormalizer.denormalize("0", {
canvasWidgets,
});
},
);
const getChildWidgets = (
canvasWidgets: CanvasWidgetsReduxState,
widgetId: string,
) => {
const parentWidget = canvasWidgets[widgetId];
if (parentWidget.children) {
return parentWidget.children.map((childWidgetId) => {
const childWidget = { ...canvasWidgets[childWidgetId] } as WidgetEntity;
if (childWidget?.children?.length > 0) {
childWidget.children = getChildWidgets(canvasWidgets, childWidgetId);
}
return childWidget;
});
}
return [];
};
export const mockGetChildWidgets = (state: AppState, widgetId: string) => {
return getChildWidgets(state.entities.canvasWidgets, widgetId);
};
export const mockGetPagePermissions = () => {
return ["read:pages", "manage:pages", "create:pageActions", "delete:pages"];
};
export const mockCreateCanvasWidget = (
canvasWidget: FlattenedWidgetProps,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
evaluatedWidget: WidgetEntity,
): any => {
return { ...canvasWidget };
};
export const mockGetWidgetEvalValues = (
state: AppState,
widgetName: string,
) => {
return Object.values(state.entities.canvasWidgets).find(
(widget) => widget.widgetName === widgetName,
) as WidgetEntity;
};
export const syntheticTestMouseEvent = (
event: MouseEvent,
optionsToAdd = {},
) => {
const options = Object.entries(optionsToAdd);
options.forEach(([key, value]) => {
Object.defineProperty(event, key, { get: () => value });
});
return event;
};
export function MockApplication({ children }: any) {
editorInitializer();
const dispatch = useDispatch();
dispatch(initEditor({ pageId: "page_id", mode: APP_MODE.EDIT }));
const mockResp: any = {
workspaceId: "workspace_id",
pages: [
{
id: "page_id",
pageId: "page_id",
name: "Page1",
isDefault: true,
slug: "page-1",
userPermissions: [
"read:pages",
"manage:pages",
"create:pageActions",
"delete:pages",
],
},
],
id: "app_id",
isDefault: true,
name: "appName",
slug: "app-name",
applicationVersion: 2,
};
urlBuilder.updateURLParams(
{
applicationId: mockResp.id,
applicationSlug: mockResp.slug,
applicationVersion: mockResp.applicationVersion,
},
[
{
pageId: mockResp.pages[0].id,
pageSlug: mockResp.pages[0].slug,
},
],
);
dispatch({
type: ReduxActionTypes.FETCH_APPLICATION_SUCCESS,
payload: mockResp,
});
dispatch({
type: ReduxActionTypes.FETCH_PAGE_LIST_SUCCESS,
payload: {
pages: mockResp.pages,
},
});
dispatch({
type: ReduxActionTypes.SWITCH_CURRENT_PAGE_ID,
payload: {
id: "page_id",
slug: "page-1",
permissions: [
"read:pages",
"manage:pages",
"create:pageActions",
"delete:pages",
],
},
});
return children;
}
//got it from @blueprintjs/test-commons to dispatch hotkeys events
export function dispatchTestKeyboardEventWithCode(
target: EventTarget,
eventType: string,
key: string,
keyCode: number,
shift = false,
meta = false,
) {
const event = document.createEvent("KeyboardEvent");
(event as any).initKeyboardEvent(
eventType,
true,
true,
window,
key,
0,
meta,
false,
shift,
);
Object.defineProperty(event, "key", { get: () => key });
Object.defineProperty(event, "which", { get: () => keyCode });
target.dispatchEvent(event);
}