## Description fix: Error log on a widget property not clearing out when the widget property is deleted Fixes #12894 ## Type of change - Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? - 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
418 lines
14 KiB
TypeScript
418 lines
14 KiB
TypeScript
import { ObjectsRegistry } from "../Objects/Registry";
|
|
const path = require("path");
|
|
|
|
type filterTypes =
|
|
| "contains"
|
|
| "does not contain"
|
|
| "starts with"
|
|
| "ends with"
|
|
| "is exactly"
|
|
| "empty"
|
|
| "not empty"
|
|
| "is equal to"
|
|
| "not equal to"
|
|
| "greater than"
|
|
| "greater than or equal to"
|
|
| "less than"
|
|
| "less than or equal to";
|
|
type columnTypeValues =
|
|
| "Plain Text"
|
|
| "URL"
|
|
| "Number"
|
|
| "Image"
|
|
| "Video"
|
|
| "Date"
|
|
| "Button"
|
|
| "Menu Button"
|
|
| "Icon Button";
|
|
|
|
export class TableV2 {
|
|
public agHelper = ObjectsRegistry.AggregateHelper;
|
|
public locator = ObjectsRegistry.CommonLocators;
|
|
public deployMode = ObjectsRegistry.DeployMode;
|
|
public propPane = ObjectsRegistry.PropertyPane;
|
|
|
|
private _tableWrap = "//div[@class='tableWrap']";
|
|
private _tableHeader =
|
|
this._tableWrap + "//div[@class='thead']//div[@class='tr'][1]";
|
|
private _columnHeader = (columnName: string) =>
|
|
this._tableWrap +
|
|
"//div[@class='thead']//div[@class='tr'][1]//div[@role='columnheader']//div[text()='" +
|
|
columnName +
|
|
"']/parent::div/parent::div";
|
|
private _nextPage = ".t--widget-tablewidgetv2 .t--table-widget-next-page";
|
|
private _previousPage = ".t--widget-tablewidgetv2 .t--table-widget-prev-page";
|
|
private _pageNumber = ".t--widget-tablewidgetv2 .page-item";
|
|
private _pageNumberServerSideOff =
|
|
".t--widget-tablewidgetv2 .t--table-widget-page-input input";
|
|
_tableRow = (rowNum: number, colNum: number) =>
|
|
`.t--widget-tablewidgetv2 .tbody .td[data-rowindex=${rowNum}][data-colindex=${colNum}]`;
|
|
_tableRowColumnData = (rowNum: number, colNum: number) =>
|
|
this._tableRow(rowNum, colNum) + ` .cell-wrapper`;
|
|
_tableEmptyColumnData = `.t--widget-tablewidgetv2 .tbody .td`; //selected-row
|
|
_tableSelectedRow =
|
|
this._tableWrap +
|
|
"//div[contains(@class, 'tbody')]//div[contains(@class, 'selected-row')]/div";
|
|
_liNextPage = "li[title='Next Page']";
|
|
_liPreviousPage = "li[title='Previous Page']";
|
|
_liCurrentSelectedPage =
|
|
"//div[@type='LIST_WIDGET']//ul[contains(@class, 'rc-pagination')]/li[contains(@class, 'rc-pagination-item-active')]/a";
|
|
private _searchText = "input[type='search']";
|
|
_searchBoxCross =
|
|
"//div[contains(@class, 't--search-input')]/following-sibling::div";
|
|
_addIcon = "button span[icon='add']";
|
|
_trashIcon = "button span[icon='trash']";
|
|
_visibleTextSpan = (spanText: string) => "//span[text()='" + spanText + "']";
|
|
_filterBtn = ".t--table-filter-toggle-btn";
|
|
_filterColumnsDropdown = ".t--table-filter-columns-dropdown";
|
|
_dropdownText = ".t--dropdown-option";
|
|
_filterConditionDropdown = ".t--table-filter-conditions-dropdown";
|
|
_filterInputValue = ".t--table-filter-value-input";
|
|
_addColumn = ".t--add-column-btn";
|
|
_deleteColumn = ".t--delete-column-btn";
|
|
_defaultColNameV2 =
|
|
"[data-rbd-draggable-id='customColumn1'] input[type='text']";
|
|
private _filterApplyBtn = ".t--apply-filter-btn";
|
|
private _filterCloseBtn = ".t--close-filter-btn";
|
|
private _removeFilter = ".t--table-filter-remove-btn";
|
|
private _clearAllFilter = ".t--clear-all-filter-btn";
|
|
private _addFilter = ".t--add-filter-btn";
|
|
_filterOperatorDropdown = ".t--table-filter-operators-dropdown";
|
|
private _downloadBtn = ".t--table-download-btn";
|
|
private _downloadOption = ".t--table-download-data-option";
|
|
private _tableWidgetV2 = ".t--widget-tablewidgetv2";
|
|
private _propertyPaneBackBtn = ".t--property-pane-back-btn";
|
|
|
|
_columnSettings = (columnName: string) =>
|
|
"//input[@placeholder='Column Title'][@value='" +
|
|
columnName +
|
|
"']/ancestor::div/following-sibling::div[contains(@class, 't--edit-column-btn')]";
|
|
_columnSettingsV2 = (columnName: string) =>
|
|
`.t--property-pane-view .tablewidgetv2-primarycolumn-list div[data-rbd-draggable-id=${columnName}] .t--edit-column-btn`;
|
|
_showPageItemsCount = "div.show-page-items";
|
|
_filtersCount = this._filterBtn + " span.action-title";
|
|
|
|
public WaitUntilTableLoad() {
|
|
cy.waitUntil(() => this.ReadTableRowColumnData(0, 0, 2000), {
|
|
errorMsg: "Table is not populated",
|
|
timeout: 10000,
|
|
interval: 2000,
|
|
}).then((cellData) => {
|
|
expect(cellData).not.empty;
|
|
this.agHelper.Sleep(500);
|
|
});
|
|
}
|
|
|
|
public WaitForTableEmpty() {
|
|
cy.waitUntil(() => cy.get(this._tableEmptyColumnData), {
|
|
errorMsg: "Table is populated when not expected",
|
|
timeout: 10000,
|
|
interval: 2000,
|
|
}).then(($children) => {
|
|
cy.wrap($children)
|
|
.children()
|
|
.should("have.length", 0); //or below
|
|
//expect($children).to.have.lengthOf(0)
|
|
this.agHelper.Sleep(500);
|
|
});
|
|
}
|
|
|
|
public AssertTableHeaderOrder(expectedOrder: string) {
|
|
cy.xpath(this._tableHeader)
|
|
.invoke("text")
|
|
.then((x) => {
|
|
expect(x).to.eq(expectedOrder);
|
|
});
|
|
}
|
|
|
|
public ReadTableRowColumnData(
|
|
rowNum: number,
|
|
colNum: number,
|
|
timeout = 1000,
|
|
) {
|
|
//timeout can be sent higher values incase of larger tables
|
|
this.agHelper.Sleep(timeout); //Settling time for table!
|
|
return cy.get(this._tableRowColumnData(rowNum, colNum)).invoke("text");
|
|
}
|
|
|
|
public AssertHiddenColumns(columnNames: string[]) {
|
|
columnNames.forEach(($header) => {
|
|
cy.xpath(this._columnHeader($header))
|
|
.invoke("attr", "class")
|
|
.then((classes) => {
|
|
expect(classes).includes("hidden-header");
|
|
});
|
|
});
|
|
}
|
|
|
|
public NavigateToNextPage() {
|
|
let curPageNo: number;
|
|
cy.get(this._pageNumber)
|
|
.invoke("text")
|
|
.then(($currentPageNo) => (curPageNo = Number($currentPageNo)));
|
|
cy.get(this._nextPage).click();
|
|
cy.get(this._pageNumber)
|
|
.invoke("text")
|
|
.then(($newPageNo) => expect(Number($newPageNo)).to.eq(curPageNo + 1));
|
|
}
|
|
|
|
public NavigateToPreviousPage() {
|
|
let curPageNo: number;
|
|
cy.get(this._pageNumber)
|
|
.invoke("text")
|
|
.then(($currentPageNo) => (curPageNo = Number($currentPageNo)));
|
|
cy.get(this._previousPage).click();
|
|
cy.get(this._pageNumber)
|
|
.invoke("text")
|
|
.then(($newPageNo) => expect(Number($newPageNo)).to.eq(curPageNo - 1));
|
|
}
|
|
|
|
public AssertPageNumber(pageNo: number, serverSide: "Off" | "On" = "On") {
|
|
if (serverSide == "On")
|
|
cy.get(this._pageNumber).should("have.text", Number(pageNo));
|
|
else {
|
|
cy.get(this._pageNumberServerSideOff).should(
|
|
"have.value",
|
|
Number(pageNo),
|
|
);
|
|
cy.get(this._previousPage).should("have.attr", "disabled");
|
|
cy.get(this._nextPage).should("have.attr", "disabled");
|
|
}
|
|
if (pageNo == 1) cy.get(this._previousPage).should("have.attr", "disabled");
|
|
}
|
|
|
|
public AssertSelectedRow(rowNum = 0) {
|
|
cy.xpath(this._tableSelectedRow)
|
|
.invoke("attr", "data-rowindex")
|
|
.then(($rowIndex) => {
|
|
expect(Number($rowIndex)).to.eq(rowNum);
|
|
});
|
|
}
|
|
|
|
public SelectTableRow(rowIndex: number, columnIndex = 0, select = true) {
|
|
//rowIndex - 0 for 1st row
|
|
this.agHelper
|
|
.GetElement(this._tableRow(rowIndex, columnIndex))
|
|
.parent("div")
|
|
.invoke("attr", "class")
|
|
.then(($classes: any) => {
|
|
if (
|
|
(select && !$classes?.includes("selected-row")) ||
|
|
(!select && $classes?.includes("selected-row"))
|
|
)
|
|
this.agHelper.GetNClick(
|
|
this._tableRow(rowIndex, columnIndex),
|
|
0,
|
|
true,
|
|
);
|
|
});
|
|
|
|
this.agHelper.Sleep(); //for select to reflect
|
|
}
|
|
|
|
public AssertSearchText(searchTxt: string) {
|
|
cy.get(this._searchText).should("have.value", searchTxt);
|
|
}
|
|
|
|
public SearchTable(searchTxt: string, index = 0) {
|
|
cy.get(this._searchText)
|
|
.eq(index)
|
|
.type(searchTxt);
|
|
}
|
|
|
|
public RemoveSearchTextNVerify(cellDataAfterSearchRemoved: string) {
|
|
this.agHelper.GetNClick(this._searchBoxCross);
|
|
this.ReadTableRowColumnData(0, 0).then((aftSearchRemoved) => {
|
|
expect(aftSearchRemoved).to.eq(cellDataAfterSearchRemoved);
|
|
});
|
|
}
|
|
|
|
public OpenFilter() {
|
|
this.agHelper.GetNClick(this._filterBtn);
|
|
}
|
|
|
|
public OpenNFilterTable(
|
|
colName: string,
|
|
colCondition: filterTypes,
|
|
inputText = "",
|
|
operator: "AND" | "OR" | "" = "",
|
|
index = 0,
|
|
) {
|
|
if (operator) {
|
|
this.agHelper.GetNClick(this._addFilter);
|
|
this.agHelper.GetNClick(this._filterOperatorDropdown);
|
|
cy.get(this._dropdownText)
|
|
.contains(operator)
|
|
.click();
|
|
} else this.OpenFilter();
|
|
|
|
this.agHelper.GetNClick(this._filterColumnsDropdown, index, true);
|
|
cy.get(this._dropdownText)
|
|
.contains(colName)
|
|
.click();
|
|
this.agHelper.GetNClick(this._filterConditionDropdown, index, true);
|
|
cy.get(this._dropdownText)
|
|
.contains(colCondition)
|
|
.click();
|
|
|
|
if (inputText)
|
|
this.agHelper
|
|
.GetNClick(this._filterInputValue, index, true)
|
|
.type(inputText)
|
|
.wait(500);
|
|
|
|
this.agHelper.GetNClick(this._filterApplyBtn, undefined, true);
|
|
//this.agHelper.ClickButton("APPLY")
|
|
}
|
|
|
|
public RemoveFilterNVerify(
|
|
cellDataAfterFilterRemoved: string,
|
|
toClose = true,
|
|
removeOne = true,
|
|
index = 0,
|
|
) {
|
|
if (removeOne) this.agHelper.GetNClick(this._removeFilter, index);
|
|
else this.agHelper.GetNClick(this._clearAllFilter);
|
|
|
|
if (toClose) this.CloseFilter();
|
|
this.ReadTableRowColumnData(0, 0).then((aftFilterRemoved) => {
|
|
expect(aftFilterRemoved).to.eq(cellDataAfterFilterRemoved);
|
|
});
|
|
}
|
|
|
|
public CloseFilter() {
|
|
this.agHelper.GetNClick(this._filterCloseBtn);
|
|
}
|
|
|
|
public DownloadFromTable(filetype: "Download as CSV" | "Download as Excel") {
|
|
cy.get(this._downloadBtn).click({ force: true });
|
|
cy.get(this._downloadOption)
|
|
.contains(filetype)
|
|
.click({ force: true });
|
|
}
|
|
|
|
public ValidateDownloadNVerify(fileName: string, textToBePresent: string) {
|
|
const downloadsFolder = Cypress.config("downloadsFolder");
|
|
cy.log("downloadsFolder is:" + downloadsFolder);
|
|
cy.readFile(path.join(downloadsFolder, fileName)).should("exist");
|
|
this.VerifyDownloadedFile(fileName, textToBePresent);
|
|
}
|
|
|
|
public VerifyDownloadedFile(fileName: string, textToBePresent: string) {
|
|
const downloadedFilename = Cypress.config("downloadsFolder")
|
|
.concat("/")
|
|
.concat(fileName);
|
|
cy.readFile(downloadedFilename, "binary", {
|
|
timeout: 15000,
|
|
}).should((buffer) => expect(buffer).to.contain(textToBePresent));
|
|
}
|
|
|
|
public ChangeColumnType(columnName: string, newDataType: columnTypeValues) {
|
|
this.agHelper.GetNClick(this._columnSettings(columnName));
|
|
this.agHelper.SelectDropdownList("Column Type", newDataType);
|
|
this.agHelper.ValidateNetworkStatus("@updateLayout");
|
|
}
|
|
|
|
public ChangeColumnTypeV2(columnName: string, newDataType: columnTypeValues) {
|
|
cy.get(this._tableWidgetV2)
|
|
.click()
|
|
.then(() => {
|
|
cy.get(this._columnSettingsV2(columnName)).click();
|
|
this.agHelper.SelectDropdownList("Column Type", newDataType);
|
|
cy.get(this._propertyPaneBackBtn).click();
|
|
});
|
|
}
|
|
|
|
public AssertURLColumnNavigation(
|
|
row: number,
|
|
col: number,
|
|
expectedURL: string,
|
|
) {
|
|
this.deployMode.StubbingWindow();
|
|
this.agHelper
|
|
.GetNClick(this._tableRowColumnData(row, col))
|
|
.then(($cellData) => {
|
|
//Cypress.$($cellData).trigger('click');
|
|
cy.url().should("eql", expectedURL);
|
|
this.agHelper.Sleep();
|
|
cy.go(-1);
|
|
this.WaitUntilTableLoad();
|
|
});
|
|
}
|
|
|
|
//List methods - keeping it for now!
|
|
public NavigateToNextPage_List() {
|
|
let curPageNo: number;
|
|
cy.xpath(this._liCurrentSelectedPage)
|
|
.invoke("text")
|
|
.then(($currentPageNo) => (curPageNo = Number($currentPageNo)));
|
|
cy.get(this._liNextPage).click();
|
|
//cy.scrollTo('top', { easing: 'linear' })
|
|
cy.xpath(this._liCurrentSelectedPage)
|
|
.invoke("text")
|
|
.then(($newPageNo) => expect(Number($newPageNo)).to.eq(curPageNo + 1));
|
|
}
|
|
|
|
public NavigateToPreviousPage_List() {
|
|
let curPageNo: number;
|
|
cy.xpath(this._liCurrentSelectedPage)
|
|
.invoke("text")
|
|
.then(($currentPageNo) => (curPageNo = Number($currentPageNo)));
|
|
cy.get(this._liPreviousPage).click();
|
|
//cy.scrollTo('top', { easing: 'linear' })
|
|
cy.xpath(this._liCurrentSelectedPage)
|
|
.invoke("text")
|
|
.then(($newPageNo) => expect(Number($newPageNo)).to.eq(curPageNo - 1));
|
|
}
|
|
|
|
public AssertPageNumber_List(pageNo: number, checkNoNextPage = false) {
|
|
cy.xpath(this._liCurrentSelectedPage)
|
|
.invoke("text")
|
|
.then(($currentPageNo) => expect(Number($currentPageNo)).to.eq(pageNo));
|
|
|
|
if (pageNo == 1)
|
|
cy.get(this._liPreviousPage).should("have.attr", "aria-disabled", "true");
|
|
|
|
if (checkNoNextPage)
|
|
cy.get(this._liNextPage).should("have.attr", "aria-disabled", "true");
|
|
else cy.get(this._liNextPage).should("have.attr", "aria-disabled", "false");
|
|
}
|
|
|
|
public AddColumn(colId: string) {
|
|
cy.get(this._addColumn).scrollIntoView();
|
|
cy.get(this._addColumn)
|
|
.should("be.visible")
|
|
.click({ force: true });
|
|
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
cy.wait(3000);
|
|
cy.get(this._defaultColNameV2).clear({
|
|
force: true,
|
|
});
|
|
cy.get(this._defaultColNameV2).type(colId, { force: true });
|
|
}
|
|
|
|
public EditColumn(colId: string, shouldReturnToMainPane = true) {
|
|
if (shouldReturnToMainPane) {
|
|
this.propPane.NavigateBackToPropertyPane();
|
|
}
|
|
cy.get("[data-rbd-draggable-id='" + colId + "'] .t--edit-column-btn").click(
|
|
{
|
|
force: true,
|
|
},
|
|
);
|
|
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
cy.wait(1500);
|
|
}
|
|
|
|
public DeleteColumn(colId: string) {
|
|
this.propPane.NavigateBackToPropertyPane();
|
|
cy.get(
|
|
"[data-rbd-draggable-id='" + colId + "'] .t--delete-column-btn",
|
|
).click({
|
|
force: true,
|
|
});
|
|
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
cy.wait(1000);
|
|
}
|
|
}
|