fix: removed -1 and 2d array population error in the selectedRowIndices (#9606)

* fix: removed -1 and 2d array population error in the selectedRowIndices

* test: init integration test for bug fix

* test: completed the integration tests for bug fixes

* test: added unit test for edge case in propertyUtils

* refactor: removed unused import

* feat: added selectedRowIndices as an option in the autocomplete

* fix: fixed table widget test cases
This commit is contained in:
Keyur Paralkar 2021-12-15 17:44:50 +05:30 committed by GitHub
parent 0c74e7273e
commit 3a1c2b0799
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 493 additions and 13 deletions

View File

@ -0,0 +1,208 @@
{
"dsl": {
"widgetName": "MainContainer",
"backgroundColor": "none",
"rightColumn": 744,
"snapColumns": 64,
"detachFromLayout": true,
"widgetId": "0",
"topRow": 0,
"bottomRow": 1120,
"containerStyle": "none",
"snapRows": 125,
"parentRowSpace": 1,
"type": "CANVAS_WIDGET",
"canExtend": true,
"version": 46,
"minHeight": 1100,
"parentColumnSpace": 1,
"dynamicBindingPathList": [],
"leftColumn": 0,
"children": [
{
"widgetName": "Text1",
"dynamicPropertyPathList": [],
"displayName": "Text",
"iconSVG": "/static/media/icon.97c59b52.svg",
"topRow": 23,
"bottomRow": 41,
"parentRowSpace": 10,
"type": "TEXT_WIDGET",
"hideCard": false,
"parentColumnSpace": 26.59375,
"dynamicTriggerPathList": [],
"leftColumn": 6,
"dynamicBindingPathList": [
{
"key": "text"
}
],
"text": "{{Table1.selectedRowIndices}}",
"key": "zzkmsgz6bl",
"rightColumn": 30,
"backgroundColor": "",
"textAlign": "LEFT",
"widgetId": "vmo0ewamhx",
"isVisible": true,
"fontStyle": "BOLD",
"textColor": "#231F20",
"version": 1,
"parentId": "0",
"renderMode": "CANVAS",
"isLoading": false,
"fontSize": "PARAGRAPH"
},
{
"multiRowSelection": false,
"widgetName": "Table1",
"defaultPageSize": 0,
"columnOrder": [
"step",
"task",
"status",
"action"
],
"isVisibleDownload": true,
"dynamicPropertyPathList": [],
"displayName": "Table",
"iconSVG": "/static/media/icon.db8a9cbd.svg",
"topRow": 41,
"bottomRow": 69,
"isSortable": true,
"parentRowSpace": 10,
"type": "TABLE_WIDGET",
"defaultSelectedRow": "0",
"hideCard": false,
"parentColumnSpace": 25.6875,
"dynamicTriggerPathList": [],
"dynamicBindingPathList": [
{
"key": "primaryColumns.step.computedValue"
},
{
"key": "primaryColumns.task.computedValue"
},
{
"key": "primaryColumns.status.computedValue"
},
{
"key": "primaryColumns.action.computedValue"
}
],
"leftColumn": 19,
"primaryColumns": {
"step": {
"index": 0,
"width": 150,
"id": "step",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textSize": "PARAGRAPH",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isCellVisible": true,
"isDerived": false,
"label": "step",
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.step))}}"
},
"task": {
"index": 1,
"width": 150,
"id": "task",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textSize": "PARAGRAPH",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isCellVisible": true,
"isDerived": false,
"label": "task",
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.task))}}"
},
"status": {
"index": 2,
"width": 150,
"id": "status",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textSize": "PARAGRAPH",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isCellVisible": true,
"isDerived": false,
"label": "status",
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.status))}}"
},
"action": {
"index": 3,
"width": 150,
"id": "action",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "button",
"textSize": "PARAGRAPH",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isCellVisible": true,
"isDisabled": false,
"isDerived": false,
"label": "action",
"onClick": "{{currentRow.step === '#1' ? showAlert('Done', 'success') : currentRow.step === '#2' ? navigateTo('https://docs.appsmith.com/core-concepts/connecting-to-data-sources/querying-a-database',undefined,'NEW_WINDOW') : navigateTo('https://docs.appsmith.com/core-concepts/displaying-data-read/display-data-tables',undefined,'NEW_WINDOW')}}",
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.action))}}"
}
},
"delimiter": ",",
"key": "fzi9jh5j7j",
"derivedColumns": {},
"rightColumn": 44,
"textSize": "PARAGRAPH",
"widgetId": "2tk8bgzwaz",
"isVisibleFilters": true,
"tableData": [
{
"step": "#1",
"task": "Drop a table",
"status": "✅",
"action": ""
},
{
"step": "#2",
"task": "Create a query fetch_users with the Mock DB",
"status": "--",
"action": ""
},
{
"step": "#3",
"task": "Bind the query using => fetch_users.data",
"status": "--",
"action": ""
}
],
"isVisible": true,
"label": "Data",
"searchKey": "",
"version": 3,
"totalRecordsCount": 0,
"parentId": "0",
"renderMode": "CANVAS",
"isLoading": false,
"horizontalAlignment": "LEFT",
"isVisibleSearch": true,
"isVisiblePagination": true,
"verticalAlignment": "CENTER",
"columnSizeMap": {
"task": 245,
"step": 62,
"status": 75
}
}
]
}
}

View File

@ -37,7 +37,7 @@ describe("Test Suite to validate copy/paste table Widget", function() {
.last()
.click();
cy.get(apiwidget.propertyList).then(function($lis) {
expect($lis).to.have.length(11);
expect($lis).to.have.length(12);
expect($lis.eq(0)).to.contain("{{Table1Copy.selectedRow}}");
expect($lis.eq(1)).to.contain("{{Table1Copy.selectedRows}}");
});

View File

@ -0,0 +1,52 @@
const dsl = require("../../../../fixtures/tableWithTextWidgetDsl.json");
const widgetsPage = require("../../../../locators/Widgets.json");
describe("Table widget edge case scenario testing", function() {
before(() => {
cy.addDsl(dsl);
});
it("Check if the selectedRowIndices does not contain 2d array", function() {
cy.openPropertyPane("tablewidget");
//Enable Multi row select
cy.get(widgetsPage.toggleEnableMultirowselection)
.first()
.click({ force: true });
//Change the value of default selected row
cy.updateCodeInput(".t--property-control-defaultselectedrow", "1");
//Disable Multi row select
cy.get(widgetsPage.toggleEnableMultirowselection)
.first()
.click({ force: true });
cy.get(`${widgetsPage.textWidget} .bp3-ui-text`).should("have.text", "[]");
//Enable Multi row select
cy.get(widgetsPage.toggleEnableMultirowselection)
.first()
.click({ force: true });
cy.get(`${widgetsPage.textWidget} .bp3-ui-text`).should(
"have.text",
"[ 1]",
);
//Disable Multi row select
cy.get(widgetsPage.toggleEnableMultirowselection)
.first()
.click({ force: true });
//Enable Multi row select
cy.get(widgetsPage.toggleEnableMultirowselection)
.first()
.click({ force: true });
cy.get(`${widgetsPage.textWidget} .bp3-ui-text`).should(
"have.text",
"[ 1]",
);
});
});

View File

@ -0,0 +1,44 @@
const dsl = require("../../../../fixtures/tableWithTextWidgetDsl.json");
const widgetsPage = require("../../../../locators/Widgets.json");
const commonlocators = require("../../../../locators/commonlocators.json");
describe("Table widget edge case scenario testing", function() {
before(() => {
cy.addDsl(dsl);
});
it("Check if the selectedRowIndices does not contain -1", function() {
cy.openPropertyPane("tablewidget");
//Update the property default selected row to blank
cy.updateCodeInput(".t--property-control-defaultselectedrow", "");
//Check if the evaluated value is undefined
cy.get(commonlocators.evaluatedCurrentValue)
.first()
.should("be.visible")
.should("have.text", "undefined");
//Check the value present in the textfield which is selectedRowIndices is blank
cy.get(`${widgetsPage.textWidget} .bp3-ui-text`).should("have.text", "");
//Enable the "Enable Multi Row selection"
cy.get(widgetsPage.toggleEnableMultirowselection)
.first()
.click({ force: true });
//Check the value present in the textfield which is selectedRowIndices is []
cy.get(`${widgetsPage.textWidget} .bp3-ui-text`).should("have.text", "[]");
//Select the 1st, 2nd and 3rd row
cy.isSelectRow("0");
cy.isSelectRow("1");
cy.isSelectRow("2");
//Check the value present in the textfield which is selectedRowIndices is [0,1,2]
cy.get(`${widgetsPage.textWidget} .bp3-ui-text`).should(
"have.text",
"[ 0, 1, 2]",
);
});
});
//

View File

@ -35,18 +35,19 @@ describe("Entity explorer tests related to widgets and validation", function() {
.last()
.click({ force: true });
cy.get(apiwidget.propertyList).then(function($lis) {
expect($lis).to.have.length(11);
expect($lis).to.have.length(12);
expect($lis.eq(0)).to.contain("{{Table1.selectedRow}}");
expect($lis.eq(1)).to.contain("{{Table1.selectedRows}}");
expect($lis.eq(2)).to.contain("{{Table1.triggeredRow}}");
expect($lis.eq(3)).to.contain("{{Table1.selectedRowIndex}}");
expect($lis.eq(4)).to.contain("{{Table1.tableData}}");
expect($lis.eq(5)).to.contain("{{Table1.pageNo}}");
expect($lis.eq(6)).to.contain("{{Table1.pageSize}}");
expect($lis.eq(7)).to.contain("{{Table1.isVisible}}");
expect($lis.eq(8)).to.contain("{{Table1.searchText}}");
expect($lis.eq(9)).to.contain("{{Table1.totalRecordsCount}}");
expect($lis.eq(10)).to.contain("{{Table1.sortOrder}}");
expect($lis.eq(2)).to.contain("{{Table1.selectedRowIndices}}");
expect($lis.eq(3)).to.contain("{{Table1.triggeredRow}}");
expect($lis.eq(4)).to.contain("{{Table1.selectedRowIndex}}");
expect($lis.eq(5)).to.contain("{{Table1.tableData}}");
expect($lis.eq(6)).to.contain("{{Table1.pageNo}}");
expect($lis.eq(7)).to.contain("{{Table1.pageSize}}");
expect($lis.eq(8)).to.contain("{{Table1.isVisible}}");
expect($lis.eq(9)).to.contain("{{Table1.searchText}}");
expect($lis.eq(10)).to.contain("{{Table1.totalRecordsCount}}");
expect($lis.eq(11)).to.contain("{{Table1.sortOrder}}");
});
});

View File

@ -106,6 +106,7 @@ export const entityDefinitions: Record<string, unknown> = {
"!url": "https://docs.appsmith.com/widget-reference/table",
selectedRow: generateTypeDef(widget.selectedRow),
selectedRows: generateTypeDef(widget.selectedRows),
selectedRowIndices: generateTypeDef(widget.selectedRowIndices),
triggeredRow: generateTypeDef(widget.triggeredRow),
selectedRowIndex: "number",
tableData: generateTypeDef(widget.tableData),

View File

@ -48,7 +48,7 @@ const RULES: Record<AutocompleteDataType, Array<string>> = {
"CONTAINER_WIDGET.backgroundColor",
],
OBJECT: ["ACTION.data"],
ARRAY: ["ACTION.data"],
ARRAY: ["ACTION.data", "TABLE_WIDGET.selectedRowIndices"],
BOOLEAN: [
"CHECKBOX_WIDGET.isChecked",
"SWITCH_WIDGET.isSwitchedOn",

View File

@ -637,7 +637,11 @@ class TableWidget extends BaseWidget<TableWidgetProps, WidgetState> {
// Use the selectedRowIndex if available as default selected index
let selectedRowIndices: number[] = [];
// Check if selectedRowIndex is valid
if (this.props.selectedRowIndex && this.props.selectedRowIndex > -1) {
if (
this.props.selectedRowIndex !== undefined &&
this.props.selectedRowIndex > -1 &&
!Array.isArray(this.props.selectedRowIndex)
) {
selectedRowIndices = [this.props.selectedRowIndex];
}
// Else use the defaultSelectedRow if available
@ -649,6 +653,7 @@ class TableWidget extends BaseWidget<TableWidgetProps, WidgetState> {
? [this.props.defaultSelectedRow]
: this.props.defaultSelectedRow;
}
this.props.updateWidgetMetaProperty(
"selectedRowIndices",
selectedRowIndices,

View File

@ -0,0 +1,162 @@
import { defaultSelectedRowValidation } from "./propertyUtils";
import _ from "lodash";
const tableWProps = {
multiRowSelection: false,
widgetName: "Table1",
defaultPageSize: 0,
columnOrder: ["step", "task", "status", "action"],
isVisibleDownload: true,
dynamicPropertyPathList: [],
displayName: "Table",
iconSVG: "/static/media/icon.db8a9cbd.svg",
topRow: 54,
bottomRow: 82,
isSortable: true,
parentRowSpace: 10,
type: "TABLE_WIDGET",
defaultSelectedRow: "0",
hideCard: false,
parentColumnSpace: 25.6875,
dynamicTriggerPathList: [],
dynamicBindingPathList: [
{
key: "primaryColumns.step.computedValue",
},
{
key: "primaryColumns.task.computedValue",
},
{
key: "primaryColumns.status.computedValue",
},
{
key: "primaryColumns.action.computedValue",
},
],
leftColumn: 25,
primaryColumns: {
step: {
index: 0,
width: 150,
id: "step",
horizontalAlignment: "LEFT",
verticalAlignment: "CENTER",
columnType: "text",
textSize: "PARAGRAPH",
enableFilter: true,
enableSort: true,
isVisible: true,
isCellVisible: true,
isDerived: false,
label: "step",
computedValue:
"{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.step))}}",
},
task: {
index: 1,
width: 150,
id: "task",
horizontalAlignment: "LEFT",
verticalAlignment: "CENTER",
columnType: "text",
textSize: "PARAGRAPH",
enableFilter: true,
enableSort: true,
isVisible: true,
isCellVisible: true,
isDerived: false,
label: "task",
computedValue:
"{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.task))}}",
},
status: {
index: 2,
width: 150,
id: "status",
horizontalAlignment: "LEFT",
verticalAlignment: "CENTER",
columnType: "text",
textSize: "PARAGRAPH",
enableFilter: true,
enableSort: true,
isVisible: true,
isCellVisible: true,
isDerived: false,
label: "status",
computedValue:
"{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.status))}}",
},
action: {
index: 3,
width: 150,
id: "action",
horizontalAlignment: "LEFT",
verticalAlignment: "CENTER",
columnType: "button",
textSize: "PARAGRAPH",
enableFilter: true,
enableSort: true,
isVisible: true,
isCellVisible: true,
isDisabled: false,
isDerived: false,
label: "action",
onClick:
"{{currentRow.step === '#1' ? showAlert('Done', 'success') : currentRow.step === '#2' ? navigateTo('https://docs.appsmith.com/core-concepts/connecting-to-data-sources/querying-a-database',undefined,'NEW_WINDOW') : navigateTo('https://docs.appsmith.com/core-concepts/displaying-data-read/display-data-tables',undefined,'NEW_WINDOW')}}",
computedValue:
"{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.action))}}",
},
},
delimiter: ",",
key: "fzi9jh5j7j",
derivedColumns: {},
rightColumn: 50,
textSize: "PARAGRAPH",
widgetId: "2tk8bgzwaz",
isVisibleFilters: true,
tableData: [
{
step: "#1",
task: "Drop a table",
status: "✅",
action: "",
},
{
step: "#2",
task: "Create a query fetch_users with the Mock DB",
status: "--",
action: "",
},
{
step: "#3",
task: "Bind the query using => fetch_users.data",
status: "--",
action: "",
},
],
isVisible: true,
label: "Data",
searchKey: "",
version: 3,
totalRecordsCount: 0,
parentId: "0",
renderMode: "CANVAS",
isLoading: false,
horizontalAlignment: "LEFT",
isVisibleSearch: true,
isVisiblePagination: true,
verticalAlignment: "CENTER",
columnSizeMap: {
task: 245,
step: 62,
status: 75,
},
};
describe("unit test case for property utils", () => {
it("case: check if the defaultSelectedRowValiation returns parsed value as undefined", () => {
const value = defaultSelectedRowValidation("", tableWProps as any, _);
expect(value.isValid).toBeTruthy();
expect(value.parsed).toEqual(undefined);
});
});

View File

@ -72,6 +72,13 @@ export function defaultSelectedRowValidation(
} else {
try {
const _value: string = value as string;
if (_value === "") {
return {
isValid: true,
parsed: undefined,
};
}
if (Number.isInteger(parseInt(_value, 10)) && parseInt(_value, 10) > -1)
return { isValid: true, parsed: parseInt(_value, 10) };