Fixes: https://github.com/appsmithorg/appsmith/issues/24202 #### Type of change - Chore (housekeeping or task changes that don't impact user perception) ## Testing > #### How Has This Been Tested? > Please describe the tests that you ran to verify your changes. Also list any relevant details for your test configuration. > Delete anything that is not relevant - [ ] 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: - [ ] [Speedbreak features](https://github.com/appsmithorg/TestSmith/wiki/Test-plan-implementation#speedbreaker-features-to-consider-for-every-change) have been covered - [ ] Test plan covers all impacted features and [areas of interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans/_edit#areas-of-interest) - [ ] Test plan has been peer reviewed by project stakeholders and other QA members - [ ] Manually tested functionality on DP - [ ] We had an implementation alignment call with stakeholders post QA Round 2 - [ ] Cypress test cases have been added and approved by SDET/manual QA - [ ] Added `Test Plan Approved` label after Cypress tests were reviewed - [ ] Added `Test Plan Approved` label after JUnit tests were reviewed
402 lines
10 KiB
TypeScript
402 lines
10 KiB
TypeScript
import { updateWidgetPositions } from "./positionUtils";
|
|
import * as utils from "./flexWidgetUtils";
|
|
import {
|
|
MAIN_CONTAINER_WIDGET_WITH_BUTTON,
|
|
buttonData,
|
|
} from "./data/heightTestData";
|
|
import { EMPTY_TABS_DATA, TABS_DATA } from "./data/tabsData";
|
|
|
|
describe("auto-layout: heightUpdates", () => {
|
|
beforeEach(() => {
|
|
jest
|
|
.spyOn(utils, "getWidgetMinMaxDimensionsInPixel")
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
.mockImplementation((widget: any, width: number) => {
|
|
if (widget?.type === "CONTAINER_WIDGET")
|
|
return {
|
|
minWidth: 280,
|
|
minHeight: 50,
|
|
maxWidth: undefined,
|
|
maxHeight: undefined,
|
|
};
|
|
return {
|
|
minWidth: undefined,
|
|
minHeight: undefined,
|
|
maxWidth: undefined,
|
|
maxHeight: undefined,
|
|
};
|
|
});
|
|
});
|
|
it("Canvas and container should increase in height on adding new widgets in a new row", () => {
|
|
const data: { [k: string]: any } = { ...MAIN_CONTAINER_WIDGET_WITH_BUTTON };
|
|
let updatedWidgets = updateWidgetPositions(data, "3", false, 4896);
|
|
expect(updatedWidgets["2"].bottomRow).toBe(6);
|
|
|
|
// Add a button in a new row
|
|
const newButton = buttonData("5", "3");
|
|
const data2 = {
|
|
...data,
|
|
"5": newButton,
|
|
"3": {
|
|
...data["3"],
|
|
children: ["4", "5"],
|
|
flexLayers: [
|
|
{
|
|
children: [
|
|
{
|
|
id: "4",
|
|
align: "start",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
id: "5",
|
|
align: "start",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
};
|
|
updatedWidgets = updateWidgetPositions(data2, "3", false, 4896);
|
|
/**
|
|
* buttonHeight = 4
|
|
* rowGap = 1.2
|
|
* buffer = 2
|
|
* total = 4 + 4 + 1.2 + 2 = 11.2
|
|
*/
|
|
expect(updatedWidgets["2"].bottomRow).toBeGreaterThan(6);
|
|
expect(Math.round(updatedWidgets["2"].bottomRow)).toBe(11);
|
|
});
|
|
|
|
it("canvas and container should decrease in height on removing widgets", () => {
|
|
const data: { [k: string]: any } = { ...MAIN_CONTAINER_WIDGET_WITH_BUTTON };
|
|
// Add a button in a new row
|
|
const newButton = buttonData("5", "3");
|
|
const data2 = {
|
|
...data,
|
|
"5": newButton,
|
|
"3": {
|
|
...data["3"],
|
|
children: ["4", "5"],
|
|
flexLayers: [
|
|
{
|
|
children: [
|
|
{
|
|
id: "4",
|
|
align: "start",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
id: "5",
|
|
align: "start",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
};
|
|
let updatedWidgets = updateWidgetPositions(data2, "3", false, 4896);
|
|
/**
|
|
* buttonHeight = 4
|
|
* rowGap = 1.2
|
|
* buffer = 2
|
|
* total = 4 + 4 + 1.2 + 2 = 11.2
|
|
*/
|
|
expect(Math.round(updatedWidgets["2"].bottomRow)).toBe(11);
|
|
|
|
// Remove the button
|
|
const data3 = {
|
|
"0": data["0"],
|
|
"2": data["2"],
|
|
"3": {
|
|
...data["3"],
|
|
children: ["4"],
|
|
flexLayers: [
|
|
{
|
|
children: [
|
|
{
|
|
id: "4",
|
|
align: "start",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
"4": data["4"],
|
|
};
|
|
updatedWidgets = updateWidgetPositions(data3, "3", false, 4896);
|
|
expect(updatedWidgets["2"].bottomRow).toBe(6);
|
|
});
|
|
|
|
it("should update canvas height on deleting all children", () => {
|
|
const data: { [k: string]: any } = { ...MAIN_CONTAINER_WIDGET_WITH_BUTTON };
|
|
// Add a button in a new row
|
|
const newButton = buttonData("5", "3");
|
|
const data2 = {
|
|
...data,
|
|
"5": newButton,
|
|
"3": {
|
|
...data["3"],
|
|
children: ["4", "5"],
|
|
flexLayers: [
|
|
{
|
|
children: [
|
|
{
|
|
id: "4",
|
|
align: "start",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
id: "5",
|
|
align: "start",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
};
|
|
let updatedWidgets = updateWidgetPositions(data2, "3", false, 4896);
|
|
expect(Math.round(updatedWidgets["2"].bottomRow)).toBe(11);
|
|
|
|
// Remove all child widgets
|
|
const data3 = {
|
|
"0": data["0"],
|
|
"2": data["2"],
|
|
"3": {
|
|
...data["3"],
|
|
children: [],
|
|
flexLayers: [],
|
|
},
|
|
"4": data["4"],
|
|
};
|
|
updatedWidgets = updateWidgetPositions(data3, "3", false, 4896);
|
|
/**
|
|
* Container (minHeight = 5)
|
|
* Canvas
|
|
*
|
|
* total height = 5
|
|
*/
|
|
expect(updatedWidgets["2"].bottomRow).toBe(5);
|
|
});
|
|
});
|
|
|
|
describe("auto-layout dynamic height: tabs widget", () => {
|
|
beforeEach(() => {
|
|
jest
|
|
.spyOn(utils, "getWidgetMinMaxDimensionsInPixel")
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
.mockImplementation((widget: any, width: number) => {
|
|
if (widget?.type === "TABS_WIDGET")
|
|
return {
|
|
minWidth: 280,
|
|
minHeight: 300,
|
|
maxWidth: undefined,
|
|
maxHeight: undefined,
|
|
};
|
|
return {
|
|
minWidth: undefined,
|
|
minHeight: undefined,
|
|
maxWidth: undefined,
|
|
maxHeight: undefined,
|
|
};
|
|
});
|
|
});
|
|
|
|
it("should assign a height of 30 rows (minHeight) to an empty tabs widget", () => {
|
|
const data: { [k: string]: any } = EMPTY_TABS_DATA;
|
|
const updatedWidgets = updateWidgetPositions(
|
|
data,
|
|
"2",
|
|
false,
|
|
4896,
|
|
false,
|
|
{ "1": { selectedTabWidgetId: "2" } },
|
|
);
|
|
/**
|
|
* minHeight of TabsWidget = 30;
|
|
* Buffer for Tabs header = 4;
|
|
* Height of canvas = 30 - 4 = 26 * 10 = 260;
|
|
*/
|
|
expect(updatedWidgets["1"].bottomRow).toBe(30);
|
|
expect(updatedWidgets["2"].bottomRow).toBe(260);
|
|
});
|
|
|
|
it("should update height of Tabs widget based on selected tab height", () => {
|
|
const data: { [k: string]: any } = TABS_DATA;
|
|
let selectedTabWidgetId = "2";
|
|
const updatedWidgets = updateWidgetPositions(
|
|
data,
|
|
selectedTabWidgetId,
|
|
false,
|
|
4896,
|
|
false,
|
|
{ "1": { selectedTabWidgetId: selectedTabWidgetId } },
|
|
);
|
|
/**
|
|
* TABS
|
|
* CANVAS
|
|
* AUDIO RECORDER (height = 7)
|
|
* TABLE (height = 30)
|
|
*
|
|
* canvas height = 7 + 30 + 1.2 (row gap) + 2 (buffer) = 40.2 * 10 = 402
|
|
* tabs height = 40.2 + 4 (buffer for tabs header) = 44.2
|
|
*/
|
|
expect(updatedWidgets["1"].bottomRow).toBe(44.2);
|
|
expect(updatedWidgets["2"].bottomRow).toBe(402);
|
|
|
|
// Switch to second tab which is empty
|
|
selectedTabWidgetId = "3";
|
|
const updatedWidgets2 = updateWidgetPositions(
|
|
data,
|
|
selectedTabWidgetId,
|
|
false,
|
|
4896,
|
|
false,
|
|
{ "1": { selectedTabWidgetId: selectedTabWidgetId } },
|
|
);
|
|
expect(updatedWidgets2["1"].bottomRow).toBe(30);
|
|
expect(updatedWidgets2["3"].bottomRow).toBe(260);
|
|
});
|
|
|
|
it("should account for the height of the tabs header", () => {
|
|
const data: { [k: string]: any } = TABS_DATA;
|
|
const selectedTabWidgetId = "2";
|
|
const updatedWidgets = updateWidgetPositions(
|
|
data,
|
|
selectedTabWidgetId,
|
|
false,
|
|
4896,
|
|
false,
|
|
{ "1": { selectedTabWidgetId: selectedTabWidgetId } },
|
|
);
|
|
/**
|
|
* TABS
|
|
* CANVAS
|
|
* AUDIO RECORDER (height = 7)
|
|
* TABLE (height = 30)
|
|
*
|
|
* canvas height = 7 + 30 + 1.2 (row gap) + 2 (buffer) = 40.2 * 10 = 402
|
|
* tabs height = 40.2 + 4 (buffer for tabs header) = 44.2
|
|
*/
|
|
expect(updatedWidgets["1"].bottomRow).toBe(44.2);
|
|
expect(updatedWidgets["2"].bottomRow).toBe(402);
|
|
|
|
// set shouldShowTabs to false
|
|
const data2: { [k: string]: any } = {
|
|
...TABS_DATA,
|
|
"1": {
|
|
...TABS_DATA["1"],
|
|
shouldShowTabs: false,
|
|
},
|
|
"2": {
|
|
...TABS_DATA["2"],
|
|
bottomRow: 300, // height of tabs widget is being set by a prior saga, so changing bottomRow here to trigger parent height update.
|
|
},
|
|
};
|
|
const updatedWidgets2 = updateWidgetPositions(
|
|
data2,
|
|
selectedTabWidgetId,
|
|
false,
|
|
4896,
|
|
false,
|
|
{ "1": { selectedTabWidgetId: selectedTabWidgetId } },
|
|
);
|
|
// height of canvas remains the same.
|
|
expect(updatedWidgets2["2"].bottomRow).toBe(402);
|
|
expect(updatedWidgets2["1"].bottomRow).toBe(40.2);
|
|
});
|
|
|
|
it("should not add buffer for header if showShouldTabs is false", () => {
|
|
const data: { [k: string]: any } = {
|
|
...TABS_DATA,
|
|
"1": {
|
|
...TABS_DATA["1"],
|
|
shouldShowTabs: false,
|
|
},
|
|
"2": {
|
|
...TABS_DATA["2"],
|
|
bottomRow: 300,
|
|
},
|
|
};
|
|
const updatedWidgets = updateWidgetPositions(
|
|
data,
|
|
"2",
|
|
false,
|
|
4896,
|
|
false,
|
|
{ "1": { selectedTabWidgetId: "2" } },
|
|
);
|
|
expect(updatedWidgets["2"].bottomRow).toBe(402);
|
|
expect(updatedWidgets["1"].bottomRow).toBe(40.2);
|
|
});
|
|
|
|
it("should use the first child canvas for height calculation if selectedTabWidgetId is undefined", () => {
|
|
const data: { [k: string]: any } = {
|
|
...TABS_DATA,
|
|
"1": {
|
|
...TABS_DATA["1"],
|
|
shouldShowTabs: false,
|
|
},
|
|
};
|
|
const updatedWidgets = updateWidgetPositions(
|
|
data,
|
|
"1",
|
|
false,
|
|
4896,
|
|
false,
|
|
{ "1": { selectedTabWidgetId: undefined } },
|
|
);
|
|
expect(updatedWidgets["2"].bottomRow).toBe(402);
|
|
expect(updatedWidgets["1"].bottomRow).toBe(40.2);
|
|
});
|
|
|
|
it("should stretch on mobile viewport to accommodate widget wrapping", () => {
|
|
// Place the two child fill widgets in the same row so that they wrap on mobile viewport.
|
|
const data: { [k: string]: any } = {
|
|
...TABS_DATA,
|
|
"2": {
|
|
...TABS_DATA["2"],
|
|
flexLayers: [
|
|
{
|
|
children: [
|
|
{
|
|
id: "4",
|
|
align: "start",
|
|
},
|
|
{
|
|
id: "5",
|
|
align: "start",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
};
|
|
const updatedWidgets = updateWidgetPositions(
|
|
data,
|
|
"2",
|
|
false,
|
|
4896,
|
|
false,
|
|
{
|
|
"1": { selectedTabWidgetId: "2" },
|
|
},
|
|
);
|
|
const bottomRow = updatedWidgets["1"].bottomRow;
|
|
const updatedWidgets2 = updateWidgetPositions(data, "2", true, 478, false, {
|
|
"1": { selectedTabWidgetId: "2" },
|
|
});
|
|
const mobileBottomRow = updatedWidgets2["1"].mobileBottomRow;
|
|
expect(mobileBottomRow).toBeGreaterThan(bottomRow);
|
|
});
|
|
});
|