* fix style bugs * fix select styles * test: fix font size issue for cypress tests * incorporate ashit feedback * test: addresed review comments for cypress tests * add analytics events * height issue in view mode * incorporate code review feedbacks * incorporate code review feedbacks * refactor: addressed review comments; removed border radius and box shadow for text widget; Updated migrations * feat: Makes shadow and radius controls keyboard accessible (#11547) * makes shadow and radius controls keyboard accessible * removes unused imports * moves options out of render method * fix: changed the misnomer background property name to the relevant property name * fix: border radius issue for the map widget * address qa bugs * address qa bugs * fix ux of theming pane when widget is selected * fix: * added backgroundColor to the video widget * restricted pop-over border radius to 0.375rem * added box shadow for the input group for select widget * fix: added delete icon in the delete theme modal * address qa bugs * change checkbox column size in config * add js convertible to button color * remove unused imports * test: fixed jest tests * fix primary color typo * fix: migrations for the theming * fix: * Removed background color from MultiTreeSelect and TreeSelect component. * grouped button's menu button pop over border radius restricting to 0.375rem. * test: updated Dsl migration UT * address qa bugs * address qa bugs * fix: address qa comments * address qa bugs * fix: * migration issue; * unit test cases; * fix rating widget scroll issue * fix youtube video border radius bug * fix select widget * fix select widgets styles * address qa bugs * merge conflicts * makes the reset button keyboard accessible (#12134) * -resolved merge conflicts * address qa bugs * fix: labelTextSize migration fixes * refactor: * made changes to the fontSizeUtils function * fixed the issue related to unit tests * fix button group widget * remove unused imports * fix: fixed the text size migration for the table widget * refactor: addressed review comments for the table widget theming migration * fix button group widget * add init calls for view mode * json form init theme changes * fix: added migration for boxShadow, borderRadius and textSizes for table widget * fix broken fields * test: fixed unit tests * wip * inconsistancy fixes and schemaItem update in updateHook/fieldConfiguration * feat: init json form migration theming * json form primaryColor -> accentColor * update table widget * update table widget * object field label styling * fix: migration related to the JSON form * fix: fixed labelTextSize migration for JSON form nested widgets * property control nested stylesheet lookup * JSONForm label styles form array items * show label for checkbox field array item * fix button group widget * wip * refactor: addressed table widget review comments * refactor: addressed ashit review comments; * added childStylesheet for widgets * feat: Keyboard navigable Color Picker control (#11797) * Makes ColorPicker keyboard accessible * seperate out keyboard and mouse interactions * fix issue with not focusing back to input * Adds test for Color picker * chore: added comment for the boxShadow property * fix: * added unit test cases for the widget and property utils * resolved warning messages * wip * theme config update * fix merge conflicts * refactor: moved theming migration inside the migrations folder * fix qa bugs * fix jest test * fix: unit test cases * fix table column creation logic * refactor: addressed review comments for migrations * fix: Overriding margin and padding for custom render in the dropdown component (#12875) * * fix for custom render padding and margin in ADS dropdown * * fix for removing padding from normal render options * refactor: moved the boxShadow condition to the variable * fix qa bugs * fix: migration QA callouts for audio recorder widget * refactor: added updated comments for boxShadow migration for table widget * fix theme binfings for JSONForm fields under Object * fix table widget theming bug * fix: addressed code review comments * fix: unit test cases * fix: qa migration callouts * fix table widget theming bug * fix JSONForm currency input dropdown not submit form * Added new tests - AppThemingSpec * fix qa bugs * fix unit test * fix JSONForm cellBorderWidth to have default value post migration * fix unit test * fix qa bugs * remove unused imports * fix qa bugs * fix JSONForm input height issue * fix qa bugs * Updating Theming spec * * dropdown color fixes (#13249) * fix caching issue ; * Fixed Theming tests * fix tests * fix tab widget tests * fix: json form children level migration issue * fix table widget tests * Updated test * updated tests * updated test * updated tests * updated tests * updated pageload * fix cypress tests * remove cypress created files * fix color picker issues * Failure fixes * Fixed some more tests * fix: cypress test failures * fix tests * remove consoles * fix table tests * fix qa bugs * updating snapshots for AppPageLayout_spec as per new UI * fix rating widget bug * fix qa bugs * fix: * cypress failing tests * Migration QA callouts * Removed unused imports * update constract check algo * fix color contrast issue * fix: cypress failure test cases * update font sizes labels * fix regression bugs * fix: * JSON form labelTextSize issue fix * Updated comment for the fontSizeUtility function * migrations issues related to table widget borderRadius and boxShadow * fix: default labelTextSize issue for the Input and Select families * fix regression bugs * fix regression bugs * PassingParams spec - added wait time * fix: font family default value issue on JS toggle * fix js toggle issue in text widget * fix tests * fix tests * fix tests * fix cypress tests * fix regression bugs * fix regression bugs * fix: * refactored table widget migration function as per review comments, * added default value to the widget * fix: failing unit test cases * fix theming spec * fix cypress tests * test: fixed failed cypress test * incorporate ashit feedback * fix cypress tests * fix: addressed review comments * comment out table cypress test * fix merge conflicts * comment out color picker tests Co-authored-by: Pawan Kumar <pawankumar@Pawans-MacBook-Pro.local> Co-authored-by: keyurparalkar <keyur@appsmith.com> Co-authored-by: Aswath K <aswath@appsmith.com> Co-authored-by: Nayan <nayan@appsmith.com> Co-authored-by: Ashit Rath <ashit@appsmith.com> Co-authored-by: balajisoundar <balaji@appsmith.com> Co-authored-by: albinAppsmith <87797149+albinAppsmith@users.noreply.github.com> Co-authored-by: Aishwarya UR <aishwarya@appsmith.com> Co-authored-by: apple <nandan@thinkify.io> Co-authored-by: Parthvi Goswami <parthvigoswami@Parthvis-MacBook-Pro.local>
262 lines
10 KiB
TypeScript
262 lines
10 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 Table {
|
|
public agHelper = ObjectsRegistry.AggregateHelper
|
|
public locator = ObjectsRegistry.CommonLocators
|
|
|
|
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-tablewidget .t--table-widget-next-page"
|
|
private _previousPage = ".t--widget-tablewidget .t--table-widget-prev-page"
|
|
private _pageNumber = ".t--widget-tablewidget .page-item"
|
|
private _pageNumberServerSideOff = ".t--widget-tablewidget .t--table-widget-page-input input"
|
|
_tableRow = (rowNum: number, colNum: number) => `.t--widget-tablewidget .tbody .td[data-rowindex=${rowNum}][data-colindex=${colNum}]`
|
|
_tableRowColumnData = (rowNum: number, colNum: number) => this._tableRow(rowNum, colNum) + ` div div`
|
|
_tableEmptyColumnData = `.t--widget-tablewidget .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"
|
|
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"
|
|
_columnSettings = (columnName: string) => "//input[@placeholder='Column Title'][@value='" + columnName + "']/parent::div/following-sibling::div[contains(@class, 't--edit-column-btn')]"
|
|
|
|
|
|
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: number = 0) {
|
|
cy.xpath(this._tableSelectedRow)
|
|
.invoke("attr", "data-rowindex")
|
|
.then($rowIndex => {
|
|
expect(Number($rowIndex)).to.eq(rowNum);
|
|
});
|
|
}
|
|
|
|
public SelectTableRow(rowIndex: number) {//0 for 1st row
|
|
cy.get(this._tableRow(rowIndex, 0)).first().click({ force: 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 FilterTable(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.agHelper.GetNClick(this._filterBtn)
|
|
|
|
this.agHelper.GetNClick(this._filterColumnsDropdown, index)
|
|
cy.get(this._dropdownText).contains(colName).click()
|
|
this.agHelper.GetNClick(this._filterConditionDropdown, index)
|
|
cy.get(this._dropdownText).contains(colCondition).click()
|
|
|
|
if (inputText)
|
|
this.agHelper.GetNClick(this._filterInputValue, index).type(inputText).wait(500)
|
|
|
|
this.agHelper.GetNClick(this._filterApplyBtn)
|
|
//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) {
|
|
let 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 AssertURLColumnNavigation(row: number, col: number, expectedURL: string) {
|
|
this.agHelper.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')
|
|
|
|
}
|
|
} |