Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,11 @@ describe(
.contains("This is a test message")
.should("be.visible");
});
cy.getTableV2DataSelector("0", "5").then(($elemClass) => {
const discardBtnSelector =
$elemClass + " button[data-test-variant='TERTIARY']";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kindly add this locator in locator files related to it.

cy.get(discardBtnSelector).click({ force: true }); // discard changes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use click function from Aghelper.

});
});

it("4. Verify filter condition", () => {
Expand All @@ -162,6 +167,10 @@ describe(
cy.get(selector + checkboxSelector).should("be.checked");
});

cy.getTableV2DataSelector("1", "4").then((selector) => {
cy.get(selector + checkboxSelector).should("be.checked");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we please use assertHelper here ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how could we use AssertHelper module here. I can't find suitable public method to achieve this exact purpose. Could you please elaborate more? @sagar-qa007
Beside this, should I modify on all already existing assertions in this file for consistency as I only change the order of assertions but haven't integrated any new ones?

@rahulbarwal rahulbarwal Oct 22, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rahulbarwal ,
Many thanks, it really helped me.

Could you please check the requested changes @sagar-qa007 ?

});

// Filter and verify unchecked rows
cy.get(widgetsJson.tableFilterRow)
.find(publishPage.conditionDropdown)
Expand All @@ -172,9 +181,6 @@ describe(
cy.getTableV2DataSelector("0", "4").then((selector) => {
cy.get(selector + checkboxSelector).should("not.be.checked");
});
cy.getTableV2DataSelector("1", "4").then((selector) => {
cy.get(selector + checkboxSelector).should("not.be.checked");
});
});

it("5. Verify if onCheckChange is hidden on custom columns", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,12 @@ describe(
cy.wait(100);
agHelper.ValidateToastMessage("This is a test message");
});

cy.getTableV2DataSelector("0", "5").then(($elemClass) => {
const discardBtnSelector =
$elemClass + " button[data-test-variant='TERTIARY']";
cy.get(discardBtnSelector).click({ force: true }); // discard changes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to incorporate above PR comments here.

});
});

it("4. Verify filter condition", () => {
Expand All @@ -154,6 +160,10 @@ describe(
cy.get(selector + switchSelector).should("be.checked");
});

cy.getTableV2DataSelector("1", "4").then((selector) => {
cy.get(selector + switchSelector).should("be.checked");
});

// Filter and verify unchecked rows
cy.get(widgetsJson.tableFilterRow)
.find(publishPage.conditionDropdown)
Expand All @@ -164,9 +174,6 @@ describe(
cy.getTableV2DataSelector("0", "4").then((selector) => {
cy.get(selector + switchSelector).should("not.be.checked");
});
cy.getTableV2DataSelector("1", "4").then((selector) => {
cy.get(selector + switchSelector).should("not.be.checked");
});
});

it("5. Verify if onChange is hidden on custom columns", () => {
Expand Down
21 changes: 16 additions & 5 deletions app/client/src/widgets/TableWidgetV2/widget/derived.js
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,9 @@ export default {

const finalTableData = sortedTableData.filter((row) => {
let isSearchKeyFound = true;
const originalRow = (props.tableData ?? sortedTableData)[
row.__originalIndex__
];
const columnWithDisplayText = Object.values(props.primaryColumns).filter(
(column) => column.columnType === "url" && column.displayText,
);
Expand Down Expand Up @@ -780,7 +783,10 @@ export default {
};

if (searchKey) {
isSearchKeyFound = Object.values(_.omit(displayedRow, hiddenColumns))
isSearchKeyFound = [
...Object.values(_.omit(displayedRow, hiddenColumns)),
...Object.values(_.omit(originalRow, hiddenColumns)),
]
Comment on lines +803 to +806

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider optimizing the search operation.

While including both displayed and original values in the search is thorough, let's think about performance. When dealing with large datasets, concatenating all values and performing string operations could be expensive.

Consider this optimization:

-isSearchKeyFound = [
-  ...Object.values(_.omit(displayedRow, hiddenColumns)),
-  ...Object.values(_.omit(originalRow, hiddenColumns)),
-].join(", ").toLowerCase().includes(searchKey);
+const searchInRow = (row) => Object.values(_.omit(row, hiddenColumns))
+  .some(value => value.toString().toLowerCase().includes(searchKey));
+isSearchKeyFound = searchInRow(displayedRow) || searchInRow(originalRow);

This approach stops searching as soon as a match is found, potentially improving performance with large datasets.

Committable suggestion was skipped due to low confidence.

.join(", ")
.toLowerCase()
.includes(searchKey);
Expand Down Expand Up @@ -811,10 +817,15 @@ export default {
ConditionFunctions[props.filters[i].condition];

if (conditionFunction) {
filterResult = conditionFunction(
displayedRow[props.filters[i].column],
props.filters[i].value,
);
filterResult =
conditionFunction(
originalRow[props.filters[i].column],
props.filters[i].value,
) ||
conditionFunction(
displayedRow[props.filters[i].column],
props.filters[i].value,
);
Comment on lines +837 to +845

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Let's make the filter condition check more readable!

Class, while the logic is correct, we can make it more maintainable by extracting the condition check into a helper function.

Consider this refactor to improve readability:

-filterResult =
-  conditionFunction(
-    originalRow[props.filters[i].column],
-    props.filters[i].value,
-  ) ||
-  conditionFunction(
-    displayedRow[props.filters[i].column],
-    props.filters[i].value,
-  );
+const checkCondition = (row, column, value) => 
+  conditionFunction(row[column], value);
+
+filterResult = 
+  checkCondition(originalRow, props.filters[i].column, props.filters[i].value) ||
+  checkCondition(displayedRow, props.filters[i].column, props.filters[i].value);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
filterResult =
conditionFunction(
originalRow[props.filters[i].column],
props.filters[i].value,
) ||
conditionFunction(
displayedRow[props.filters[i].column],
props.filters[i].value,
);
const checkCondition = (row, column, value) =>
conditionFunction(row[column], value);
filterResult =
checkCondition(originalRow, props.filters[i].column, props.filters[i].value) ||
checkCondition(displayedRow, props.filters[i].column, props.filters[i].value);

}
} catch (e) {
filterResult = false;
Expand Down
226 changes: 226 additions & 0 deletions app/client/src/widgets/TableWidgetV2/widget/derived.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,122 @@ describe("Validates getFilteredTableData Properties", () => {
expect(result).toStrictEqual(expected);
});

it("should filter correctly after editing a value with an applied filter", () => {
const { getFilteredTableData } = derivedProperty;
const input = {
tableData: [
{ id: 1234, name: "Jim Doe" },
{ id: 123, name: "Hamza Khafaga" },
{ id: 234, name: "Khadija Khafaga" },
],
processedTableData: [
{ id: 1234, name: "Jim Doe", __originalIndex__: 0 },
{ id: 123, name: "Hamza Anas", __originalIndex__: 1 },
{ id: 234, name: "Khadija Khafaga", __originalIndex__: 2 },
],
filters: [
{
condition: "contains",
column: "name",
value: "Khafaga",
},
],
sortOrder: { column: "id", order: "desc" },
columnOrder: ["name", "id"],
primaryColumns: {
id: {
index: 1,
width: 150,
id: "id",
alias: "id",
originalId: "id",
horizontalAlignment: "LEFT",
verticalAlignment: "CENTER",
columnType: "number",
textColor: "#231F20",
textSize: "PARAGRAPH",
fontStyle: "REGULAR",
enableFilter: true,
enableSort: true,
isVisible: true,
isDerived: false,
label: "id",
isAscOrder: false,
},
name: {
index: 0,
width: 150,
id: "name",
alias: "name",
originalId: "name",
horizontalAlignment: "LEFT",
verticalAlignment: "CENTER",
columnType: "text",
textColor: "#231F20",
textSize: "PARAGRAPH",
fontStyle: "REGULAR",
enableFilter: true,
enableSort: true,
isVisible: true,
isDerived: false,
label: "awesome",
isAscOrder: undefined,
},
},
tableColumns: [
{
index: 0,
width: 150,
id: "name",
horizontalAlignment: "LEFT",
verticalAlignment: "CENTER",
columnType: "text",
textColor: "#231F20",
textSize: "PARAGRAPH",
fontStyle: "REGULAR",
enableFilter: true,
enableSort: true,
isVisible: true,
isDerived: false,
label: "awesome",
isAscOrder: undefined,
},
{
index: 1,
width: 150,
id: "id",
horizontalAlignment: "LEFT",
verticalAlignment: "CENTER",
columnType: "number",
textColor: "#231F20",
textSize: "PARAGRAPH",
fontStyle: "REGULAR",
enableFilter: true,
enableSort: true,
isVisible: true,
isDerived: false,
label: "id",
isAscOrder: false,
},
],
};

input.orderedTableColumns = Object.values(input.primaryColumns).sort(
(a, b) => {
return input.columnOrder[a.id] < input.columnOrder[b.id];
},
);

const expected = [
{ id: 234, name: "Khadija Khafaga", __originalIndex__: 2 },
{ id: 123, name: "Hamza Anas", __originalIndex__: 1 },
];

let result = getFilteredTableData(input, moment, _);

expect(result).toStrictEqual(expected);
});

it("validates generated sanitized table data with valid property keys", () => {
const { getProcessedTableData } = derivedProperty;

Expand Down Expand Up @@ -1333,6 +1449,116 @@ describe("Validates getFilteredTableData Properties", () => {

expect(result).toStrictEqual(expected);
});

it("filters correctly after editing a value with an applied search key", () => {
const { getFilteredTableData } = derivedProperty;
const input = {
tableData: [
{ id: 1234, name: "Jim Doe" },
{ id: 123, name: "Hamza Khafaga" },
{ id: 234, name: "Khadija Khafaga" },
],
processedTableData: [
{ id: 1234, name: "Jim Doe", __originalIndex__: 0 },
{ id: 123, name: "Hamza Anas", __originalIndex__: 1 },
{ id: 234, name: "Khadija Khafaga", __originalIndex__: 2 },
],
searchText: "Khafaga",
sortOrder: { column: "id", order: "desc" },
columnOrder: ["name", "id"],
primaryColumns: {
id: {
index: 1,
width: 150,
id: "id",
alias: "id",
originalId: "id",
horizontalAlignment: "LEFT",
verticalAlignment: "CENTER",
columnType: "number",
textColor: "#231F20",
textSize: "PARAGRAPH",
fontStyle: "REGULAR",
enableFilter: true,
enableSort: true,
isVisible: true,
isDerived: false,
label: "id",
isAscOrder: false,
},
name: {
index: 0,
width: 150,
id: "name",
alias: "name",
originalId: "name",
horizontalAlignment: "LEFT",
verticalAlignment: "CENTER",
columnType: "text",
textColor: "#231F20",
textSize: "PARAGRAPH",
fontStyle: "REGULAR",
enableFilter: true,
enableSort: true,
isVisible: true,
isDerived: false,
label: "awesome",
isAscOrder: undefined,
},
},
tableColumns: [
{
index: 0,
width: 150,
id: "name",
horizontalAlignment: "LEFT",
verticalAlignment: "CENTER",
columnType: "text",
textColor: "#231F20",
textSize: "PARAGRAPH",
fontStyle: "REGULAR",
enableFilter: true,
enableSort: true,
isVisible: true,
isDerived: false,
label: "awesome",
isAscOrder: undefined,
},
{
index: 1,
width: 150,
id: "id",
horizontalAlignment: "LEFT",
verticalAlignment: "CENTER",
columnType: "number",
textColor: "#231F20",
textSize: "PARAGRAPH",
fontStyle: "REGULAR",
enableFilter: true,
enableSort: true,
isVisible: true,
isDerived: false,
label: "id",
isAscOrder: false,
},
],
};

input.orderedTableColumns = Object.values(input.primaryColumns).sort(
(a, b) => {
return input.columnOrder[a.id] < input.columnOrder[b.id];
},
);

const expected = [
{ id: 234, name: "Khadija Khafaga", __originalIndex__: 2 },
{ id: 123, name: "Hamza Anas", __originalIndex__: 1 },
];

let result = getFilteredTableData(input, moment, _);

expect(result).toStrictEqual(expected);
});
Comment on lines +1540 to +1648

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Students, let's discuss code duplication!

This test case is very similar to the previous one, just using searchText instead of filters. We should consolidate these tests to reduce duplication and make our test suite more maintainable.

Consider using a parameterized test or combining the cases:

describe("filtering after editing a value", () => {
  const baseInput = {
    tableData: [
      { id: 1234, name: "Jim Doe" },
      { id: 123, name: "Hamza Khafaga" },
      { id: 234, name: "Khadija Khafaga" },
    ],
    processedTableData: [
      { id: 1234, name: "Jim Doe", __originalIndex__: 0 },
      { id: 123, name: "Hamza Anas", __originalIndex__: 1 },
      { id: 234, name: "Khadija Khafaga", __originalIndex__: 2 },
    ],
    // ... common properties ...
  };

  const expected = [
    { id: 234, name: "Khadija Khafaga", __originalIndex__: 2 },
    { id: 123, name: "Hamza Anas", __originalIndex__: 1 },
  ];

  it("should work with filters", () => {
    const input = {
      ...baseInput,
      filters: [{
        condition: "contains",
        column: "name",
        value: "Khafaga",
      }],
    };
    expect(getFilteredTableData(input, moment, _)).toStrictEqual(expected);
  });

  it("should work with search", () => {
    const input = {
      ...baseInput,
      searchText: "Khafaga",
    };
    expect(getFilteredTableData(input, moment, _)).toStrictEqual(expected);
  });
});

});

describe("Validate getSelectedRow function", () => {
Expand Down