diff --git a/src/data/demo/searchAliases.ts b/src/data/demo/searchAliases.ts index 163588e3..6b65d8e0 100644 --- a/src/data/demo/searchAliases.ts +++ b/src/data/demo/searchAliases.ts @@ -3,10 +3,10 @@ import FakerSearchAlias from '@data/faker/searchAlias'; export default { bloose: new FakerSearchAlias({ alias: 'bloose', - result: 'blouse', + search: 'blouse', }), blues: new FakerSearchAlias({ alias: 'blues', - result: 'blouse', + search: 'blouse', }), }; diff --git a/src/data/faker/searchAlias.ts b/src/data/faker/searchAlias.ts index 4f07d79d..5658a606 100644 --- a/src/data/faker/searchAlias.ts +++ b/src/data/faker/searchAlias.ts @@ -7,19 +7,19 @@ import {faker} from '@faker-js/faker'; * @class */ export default class FakerSearchAlias { - public readonly alias: string; + public readonly search: string; - public readonly result: string; + public readonly alias: string; /** * Constructor for class FakerSearchAlias * @param aliasToCreate {Object} Could be used to force the value of some members */ constructor(aliasToCreate: SearchAliasCreator = {}) { - /** @type {string} Name of the alias */ - this.alias = aliasToCreate.alias || `alias_${faker.lorem.word()}`; + /** @type {string} */ + this.search = aliasToCreate.search || `search_${faker.lorem.word()}`; - /** @type {string} Result to display on the search */ - this.result = aliasToCreate.result || `result_${faker.lorem.word()}`; + /** @type {string} */ + this.alias = aliasToCreate.alias || `alias_${faker.lorem.word()}`; } } diff --git a/src/data/types/searchAlias.ts b/src/data/types/searchAlias.ts index c3023701..f79c4ed3 100644 --- a/src/data/types/searchAlias.ts +++ b/src/data/types/searchAlias.ts @@ -1,6 +1,6 @@ type SearchAliasCreator = { + search?: string alias?: string - result?: string }; export default SearchAliasCreator; diff --git a/src/index.ts b/src/index.ts index b0ba5a74..9c899505 100644 --- a/src/index.ts +++ b/src/index.ts @@ -253,6 +253,7 @@ export {default as boQuickAccessPage} from '@pages/BO/quickAccess'; export {default as boRolesPage} from '@pages/BO/advancedParameters/team/roles'; export {default as boRolesCreatePage} from '@pages/BO/advancedParameters/team/roles/create'; export {default as boSearchPage} from '@pages/BO/shopParameters/search'; +export {default as boSearchAliasPage} from '@pages/BO/shopParameters/search/alias'; export {default as boSearchAliasCreatePage} from '@pages/BO/shopParameters/search/alias/create'; export {default as boShopParametersPage} from '@pages/BO/shopParameters/general'; export {default as boShoppingCartsPage} from '@pages/BO/orders/shoppingCarts'; diff --git a/src/interfaces/BO/shopParameters/search/alias/index.ts b/src/interfaces/BO/shopParameters/search/alias/index.ts new file mode 100644 index 00000000..7a53fc3f --- /dev/null +++ b/src/interfaces/BO/shopParameters/search/alias/index.ts @@ -0,0 +1,29 @@ +import {BOBasePagePageInterface} from '@interfaces/BO'; +import {type Page} from '@playwright/test'; + +export interface BOSearchAliasPageInterface extends BOBasePagePageInterface { + readonly errorFillFieldMessage: string; + readonly errorMaxWordLengthInvalidMessage: string; + readonly pageTitle: string; + readonly settingsUpdateMessage: string; + readonly successfulUpdateStatusMessage: string; + readonly updateSuccessMessage: string; + + bulkDeleteAliases(page: Page): Promise; + bulkSetStatus(page: Page, enable?: boolean): Promise; + deleteAlias(page: Page, row: number): Promise; + filterTable(page: Page, filterType: string, filterBy: string, value: string): Promise; + getAllRowsColumnContent(page: Page, columnName: string): Promise; + getNumberOfElementInGrid(page: Page): Promise; + getStatus(page: Page, row: number): Promise; + getTextColumn(page: Page, row: number, columnName: string): Promise; + goToAddNewAliasPage(page: Page): Promise; + gotoEditAliasPage(page: Page, row: number): Promise; + paginationNext(page: Page): Promise; + paginationPrevious(page: Page): Promise; + resetAndGetNumberOfLines(page: Page): Promise; + resetFilter(page: Page): Promise; + selectPaginationLimit(page: Page, number: number): Promise; + setStatus(page: Page, row: number, valueWanted?: boolean): Promise; + sortTable(page: Page, sortBy: string, sortDirection: string): Promise; +} diff --git a/src/interfaces/BO/shopParameters/search/index.ts b/src/interfaces/BO/shopParameters/search/index.ts index d74d7934..b63f5f3b 100644 --- a/src/interfaces/BO/shopParameters/search/index.ts +++ b/src/interfaces/BO/shopParameters/search/index.ts @@ -10,33 +10,19 @@ export interface BOSearchPageInterface extends BOBasePagePageInterface { readonly successfulUpdateStatusMessage: string; readonly updateSuccessMessage: string; - bulkDeleteAliases(page: Page): Promise; - bulkSetStatus(page: Page, enable?: boolean): Promise; - deleteAlias(page: Page, row: number): Promise; clickAddMissingProductsToIndex(page: Page): Promise; clickRebuildEntireIndex(page: Page): Promise; clickRebuildEntireIndexCronJobLink(page: Page): Promise; - filterTable(page: Page, filterType: string, filterBy: string, value: string): Promise; - getAllRowsColumnContent(page: Page, columnName: string): Promise; getBlacklistedWords(page: Page, idLang: number): Promise; getMaximumApproximateWords(page: Page): Promise; getMaximumWordLength(page: Page): Promise; getMinimumWordLength(page: Page): Promise; - getNumberOfElementInGrid(page: Page): Promise; getNumIndexedProducts(page: Page): Promise; getNumTotalProducts(page: Page): Promise; getSearchExactEndMatchStatus(page: Page): Promise; - getStatus(page: Page, row: number): Promise; - getTextColumn(page: Page, row: number, columnName: string): Promise; getWeightInputValue(page: Page, field: SearchWeight): Promise; - goToAddNewAliasPage(page: Page): Promise; - gotoEditAliasPage(page: Page, row: number): Promise; + goToAliasesPage(page: Page): Promise; goToTagsPage(page: Page): Promise; - paginationNext(page: Page): Promise; - paginationPrevious(page: Page): Promise; - resetAndGetNumberOfLines(page: Page): Promise; - resetFilter(page: Page): Promise; - selectPaginationLimit(page: Page, number: number): Promise; setBlacklistedWords(page: Page, idLang: number, words: string): Promise; setFuzzySearch(page: Page, toEnable?: boolean): Promise; setIndexing(page: Page, toEnable?: boolean): Promise; @@ -45,7 +31,5 @@ export interface BOSearchPageInterface extends BOBasePagePageInterface { setMinimumWordLength(page: Page, length: number): Promise; setSearchExactEndMatch(page: Page, toEnable?: boolean): Promise; setSearchWithinWord(page: Page, toEnable?: boolean): Promise; - setStatus(page: Page, row: number, valueWanted?: boolean): Promise; setWeightInputValue(page: Page, field: SearchWeight, value: number): Promise; - sortTable(page: Page, sortBy: string, sortDirection: string): Promise; } diff --git a/src/pages/BO/shopParameters/search/alias/create.ts b/src/pages/BO/shopParameters/search/alias/create.ts index 66b6b6ce..f95b4b1c 100644 --- a/src/pages/BO/shopParameters/search/alias/create.ts +++ b/src/pages/BO/shopParameters/search/alias/create.ts @@ -1,8 +1,15 @@ import type {BOAliasCreatePageInterface} from '@interfaces/BO/shopParameters/search/alias/create'; +import testContext from '@utils/test'; +import semver from 'semver'; + +const psVersion = testContext.getPSVersion(); /* eslint-disable global-require, @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */ function requirePage(): BOAliasCreatePageInterface { - return require('@versions/develop/pages/BO/shopParameters/search/alias/create'); + if (semver.lt(psVersion, '9.0.0')) { + return require('@versions/8.2/pages/BO/shopParameters/search/alias/create'); + } + return require('@versions/develop/pages/BO/shopParameters/search/alias/create').boSearchAliasCreatePage; } /* eslint-enable global-require, @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */ diff --git a/src/pages/BO/shopParameters/search/alias/index.ts b/src/pages/BO/shopParameters/search/alias/index.ts new file mode 100644 index 00000000..9e76604d --- /dev/null +++ b/src/pages/BO/shopParameters/search/alias/index.ts @@ -0,0 +1,16 @@ +import type {BOSearchAliasPageInterface} from '@interfaces/BO/shopParameters/search/alias'; +import testContext from '@utils/test'; +import semver from 'semver'; + +const psVersion = testContext.getPSVersion(); + +/* eslint-disable global-require, @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */ +function requirePage(): BOSearchAliasPageInterface { + if (semver.lt(psVersion, '9.0.0')) { + return require('@versions/8.2/pages/BO/shopParameters/search/alias'); + } + return require('@versions/develop/pages/BO/shopParameters/search/alias').boSearchAliasPage; +} +/* eslint-enable global-require, @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */ + +export default requirePage(); diff --git a/src/pages/BO/shopParameters/search/index.ts b/src/pages/BO/shopParameters/search/index.ts index faaa2305..cc313e14 100644 --- a/src/pages/BO/shopParameters/search/index.ts +++ b/src/pages/BO/shopParameters/search/index.ts @@ -1,8 +1,15 @@ import type {BOSearchPageInterface} from '@interfaces/BO/shopParameters/search'; +import testContext from '@utils/test'; +import semver from 'semver'; + +const psVersion = testContext.getPSVersion(); /* eslint-disable global-require, @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */ function requirePage(): BOSearchPageInterface { - return require('@versions/develop/pages/BO/shopParameters/search'); + if (semver.lt(psVersion, '9.0.0')) { + return require('@versions/8.2/pages/BO/shopParameters/search'); + } + return require('@versions/develop/pages/BO/shopParameters/search').boSearchPage; } /* eslint-enable global-require, @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */ diff --git a/src/versions/8.2/pages/BO/shopParameters/search/alias/create.ts b/src/versions/8.2/pages/BO/shopParameters/search/alias/create.ts new file mode 100644 index 00000000..75601e6d --- /dev/null +++ b/src/versions/8.2/pages/BO/shopParameters/search/alias/create.ts @@ -0,0 +1,44 @@ +import type FakerSearchAlias from '@data/faker/searchAlias'; +import {BOAliasCreatePageInterface} from '@interfaces/BO/shopParameters/search/alias/create'; +import { + BOSearchAliasCreatePage as BOSearchAliasCreatePageVersion, +} from '@versions/develop/pages/BO/shopParameters/search/alias/create'; +import type {Page} from 'playwright'; + +/** + * Search page, contains selectors and functions for the page + * @class + */ +class BOSearchAliasCreatePage extends BOSearchAliasCreatePageVersion implements BOAliasCreatePageInterface { + /** + * @constructs + * Setting up titles and selectors to use on search page + */ + constructor() { + super(); + + this.pageTitleCreate = 'Search > Add new •'; + this.pageTitleEdit = 'Search > Edit:'; + + // selectors + this.aliasInput = '#alias'; + this.resultInput = '#search'; + this.saveButton = '#alias_form_submit_btn'; + } + + /* Methods */ + /** + * Create/Edit alias + * @param page {Page} Browser tab + * @param aliasData {FakerSearchAlias} Data to set on alias form + * @returns {Promise} + */ + async setAlias(page: Page, aliasData: FakerSearchAlias): Promise { + await this.setValue(page, this.aliasInput, aliasData.search); + await this.setValue(page, this.resultInput, aliasData.alias); + await page.locator(this.saveButton).click(); + return this.getAlertSuccessBlockContent(page); + } +} + +module.exports = new BOSearchAliasCreatePage(); diff --git a/src/versions/8.2/pages/BO/shopParameters/search/alias/index.ts b/src/versions/8.2/pages/BO/shopParameters/search/alias/index.ts new file mode 100644 index 00000000..732c386d --- /dev/null +++ b/src/versions/8.2/pages/BO/shopParameters/search/alias/index.ts @@ -0,0 +1,263 @@ +import {BOSearchAliasPageInterface} from '@interfaces/BO/shopParameters/search/alias'; +import {BOSearchAliasPage as BOSearchAliasPageVersion} from '@versions/develop/pages/BO/shopParameters/search/alias'; +import type {Page} from 'playwright'; + +/** + * Search page, contains selectors and functions for the page + * @class + */ +class BOSearchAliasPage extends BOSearchAliasPageVersion implements BOSearchAliasPageInterface { + private readonly tableColumnStatus: (row: number) => string; + + private readonly tableColumnStatusEnabledIcon: (row: number) => string; + + private readonly tableColumnStatusDisabledIcon: (row: number) => string; + + private readonly paginationListOpen: string; + + private readonly paginationNumber: (number: number) => string; + + private readonly paginationRightBlock: string; + + private readonly bulkEnableButton: string; + + private readonly bulkDisableButton: string; + + private readonly sortColumnDivVersion: (column: string, direction: string) => string; + + /** + * @constructs + * Setting up titles and selectors to use on search page + */ + constructor() { + super(); + + this.updateSuccessMessage = 'Update successful'; + + // Selectors + // Header links + this.addNewAliasLink = 'a[data-role=page-header-desc-alias-link]'; + + // Form selectors + this.gridForm = '#form-alias'; + this.gridTableHeaderTitle = `${this.gridForm} .panel-heading`; + this.gridTableNumberOfTitlesSpan = `${this.gridTableHeaderTitle} span.badge`; + + // Table selectors + this.gridTable = '#table-alias'; + + // Filter selectors + this.filterRow = `${this.gridTable} tr.filter`; + this.filterColumn = (filterBy: string) => `${this.filterRow} [name='aliasFilter_${filterBy}']`; + this.filterSearchButton = '#submitFilterButtonalias'; + this.filterResetButton = 'button[name=\'submitResetalias\']'; + + // Row actions selectors + this.tableColumnActionsEditLink = (row: number) => `${this.tableColumnActions(row)} a.edit`; + this.tableColumnActionsToggleButton = (row: number) => `${this.tableColumnActions(row)} button.dropdown-toggle`; + this.tableColumnActionsDeleteLink = (row: number) => `${this.tableColumnActionsDropdownMenu(row)} a.delete`; + + // Confirmation modal + this.deleteModalButtonYes = '#popup_ok'; + + // Columns selectors + this.tableColumnStatus = (row: number) => `${this.tableBodyColumn(row)}:nth-child(4) a`; + this.tableColumnStatusEnabledIcon = (row: number) => `${this.tableColumnStatus(row)}.action-enabled`; + this.tableColumnStatusDisabledIcon = (row: number) => `${this.tableColumnStatus(row)}.action-disabled`; + + // Bulk actions selectors + this.bulkActionMenuButton = '#bulk_action_menu_alias'; + this.bulkActionBlock = 'div.bulk-actions'; + this.bulkActionDropdownMenu = `${this.bulkActionBlock} ul.dropdown-menu`; + this.selectAllLink = `${this.bulkActionDropdownMenu} li:nth-child(1)`; + this.bulkDeleteLink = `${this.bulkActionDropdownMenu} li:nth-child(7)`; + this.bulkEnableButton = `${this.bulkActionDropdownMenu} li:nth-child(4)`; + this.bulkDisableButton = `${this.bulkActionDropdownMenu} li:nth-child(5)`; + + // Pagination selectors + this.paginationLimitSelect = `${this.paginationDiv} button.dropdown-toggle`; + this.paginationListOpen = `${this.paginationDiv}.open`; + this.paginationNumber = (number: number) => `${this.gridForm} div.row li a[data-items='${number}']`; + this.paginationRightBlock = `${this.paginationDiv}.pull-right`; + this.paginationLabel = `${this.paginationRightBlock} li.active a`; + this.paginationNextLink = `${this.gridForm} i.icon-angle-right`; + this.paginationPreviousLink = `${this.gridForm} i.icon-angle-left`; + + // Sort Selectors + this.tableHead = `${this.gridTable} thead`; + this.sortColumnDivVersion = (column: string, direction: string) => `${this.tableHead + } a.${direction}-sort-column-${column}-link`; + } + + /** + * Reset all filters + * @param page {Page} Browser tab + * @return {Promise} + */ + async resetFilter(page: Page): Promise { + if (!(await this.elementNotVisible(page, this.filterResetButton, 2000))) { + await this.clickAndWaitForURL(page, this.filterResetButton); + } + await this.waitForVisibleSelector(page, this.filterSearchButton, 2000); + } + + /** + * Get text from column in table + * @param page {Page} Browser tab + * @param row {number} Row on table + * @param columnName {string} Column name of the value to return + * @return {Promise} + */ + async getTextColumn(page: Page, row: number, columnName: string): Promise { + let columnSelector; + + switch (columnName) { + case 'alias': + columnSelector = this.tableColumnAliases(row); + break; + + case 'search': + columnSelector = this.tableColumnSearch(row); + break; + + case 'active': + columnSelector = this.tableColumnStatus(row); + break; + + default: + throw new Error(`Column ${columnName} was not found`); + } + + if (columnName === 'active') { + return this.getAttributeContent(page, columnSelector, 'title'); + } + + return this.getTextContent(page, columnSelector); + } + + /** + * Get alias status + * @param page {Page} Browser tab + * @param row {number} Row on table + * @return {Promise} + */ + async getStatus(page: Page, row: number): Promise { + return this.elementVisible(page, this.tableColumnStatusEnabledIcon(row), 500); + } + + /** + * Quick edit toggle column value + * @param page {Page} Browser tab + * @param row {number} Row on table + * @param valueWanted {boolean} Value wanted in column + * @returns {Promise} return true if action is done, false otherwise + */ + async setStatus(page: Page, row: number, valueWanted: boolean = true): Promise { + await this.waitForVisibleSelector(page, this.tableColumnStatus(row), 2000); + if (await this.getStatus(page, row) !== valueWanted) { + await page.locator(this.tableColumnStatus(row)).click(); + await this.waitForVisibleSelector( + page, + (valueWanted ? this.tableColumnStatusEnabledIcon(row) : this.tableColumnStatusDisabledIcon(row)), + ); + return true; + } + return false; + } + + /** + * Delete alias from row + * @param page {Page} Browser tab + * @param row {number} Row on table + * @return {Promise} + */ + async deleteAlias(page: Page, row: number): Promise { + await Promise.all([ + page.locator(this.tableColumnActionsToggleButton(row)).click(), + this.waitForVisibleSelector(page, this.tableColumnActionsDeleteLink(row)), + ]); + + await page.locator(this.tableColumnActionsDeleteLink(row)).click(); + + // Confirm delete action + await this.clickAndWaitForURL(page, this.deleteModalButtonYes); + + // Get successful message + return this.getAlertSuccessBlockContent(page); + } + + /** + * Get pagination label + * @param page {Page} Browser tab + * @return {Promise} + */ + async getPaginationLabel(page: Page): Promise { + return this.getTextContent(page, this.paginationLabel); + } + + /** + * Select pagination limit + * @param page {Page} Browser tab + * @param number {number} Value of pagination limit to select + * @returns {Promise} + */ + async selectPaginationLimit(page: Page, number: number): Promise { + await page.locator(this.paginationLimitSelect).click(); + await this.waitForVisibleSelector(page, this.paginationListOpen); + await this.clickAndWaitForURL(page, this.paginationNumber(number)); + + return this.getPaginationLabel(page); + } + + /* Sort methods */ + /** + * Sort table + * @param page {Page} Browser tab + * @param sortBy {string} Column to sort with + * @param sortDirection {string} Sort direction asc or desc + * @return {Promise} + */ + async sortTable(page: Page, sortBy: string, sortDirection: string): Promise { + await this.clickAndWaitForURL(page, `${this.sortColumnDivVersion(sortBy, sortDirection)} i`); + } + + /** + * Delete by bulk action + * @param page {Page} Browser tab + * @returns {Promise} + */ + async bulkDeleteAliases(page: Page): Promise { + await this.dialogListener(page, true); + // Select all rows + await this.bulkSelectRows(page); + + // Click on Button Bulk actions + await page.locator(this.bulkActionMenuButton).click(); + + // Click on delete + await this.clickAndWaitForURL(page, this.bulkDeleteLink); + + return this.getAlertSuccessBlockContent(page); + } + + /** + * Enable / disable by Bulk Actions + * @param page {Page} Browser tab + * @param enable {boolean} True if we need to enable status + * @returns {Promise} + */ + async bulkSetStatus(page: Page, enable: boolean = true): Promise { + // Select all rows + await this.bulkSelectRows(page); + + // Click on Button Bulk actions + await page.locator(this.bulkActionMenuButton).click(); + + // Click on enable/Disable and wait for modal + await this.clickAndWaitForURL(page, enable ? this.bulkEnableButton : this.bulkDisableButton); + + return this.getTextContent(page, this.alertSuccessBlock); + } +} + +module.exports = new BOSearchAliasPage(); diff --git a/src/versions/8.2/pages/BO/shopParameters/search/index.ts b/src/versions/8.2/pages/BO/shopParameters/search/index.ts new file mode 100644 index 00000000..2960a8a2 --- /dev/null +++ b/src/versions/8.2/pages/BO/shopParameters/search/index.ts @@ -0,0 +1,19 @@ +import {type BOSearchPageInterface} from '@interfaces/BO/shopParameters/search'; +import {BOSearchPage as BOSearchPageVersion} from '@versions/develop/pages/BO/shopParameters/search'; + +/** + * Search page, contains selectors and functions for the page + * @class + * @extends BOBasePage + */ +class BOSearchPage extends BOSearchPageVersion implements BOSearchPageInterface { + /** + * Go to aliases page + * @returns {Promise} + */ + async goToAliasesPage(): Promise { + // No aliases tab before v9 + } +} + +module.exports = new BOSearchPage(); diff --git a/src/versions/develop/pages/BO/shopParameters/search/alias/create.ts b/src/versions/develop/pages/BO/shopParameters/search/alias/create.ts index 898b0e1d..512444a8 100644 --- a/src/versions/develop/pages/BO/shopParameters/search/alias/create.ts +++ b/src/versions/develop/pages/BO/shopParameters/search/alias/create.ts @@ -8,16 +8,16 @@ import {type Page} from '@playwright/test'; * @class * @extends BOBasePage */ -class AddAliasPage extends BOBasePage implements BOAliasCreatePageInterface { - public readonly pageTitleCreate: string; +class BOSearchAliasCreatePage extends BOBasePage implements BOAliasCreatePageInterface { + public pageTitleCreate: string; - public readonly pageTitleEdit: string; + public pageTitleEdit: string; - private readonly aliasInput: string; + protected aliasInput: string; - private readonly resultInput: string; + protected resultInput: string; - private readonly saveButton: string; + protected saveButton: string; /** * @constructs @@ -26,13 +26,13 @@ class AddAliasPage extends BOBasePage implements BOAliasCreatePageInterface { constructor() { super(); - this.pageTitleCreate = 'Search > Add new •'; - this.pageTitleEdit = 'Search > Edit:'; + this.pageTitleCreate = `New aliases • ${global.INSTALL.SHOP_NAME}`; + this.pageTitleEdit = 'Edit aliases for '; // selectors - this.aliasInput = '#alias'; - this.resultInput = '#search'; - this.saveButton = '#alias_form_submit_btn'; + this.aliasInput = '#search_term_search'; + this.resultInput = '#search_term_aliases_0_alias'; + this.saveButton = '#save-button'; } /* Methods */ @@ -43,11 +43,12 @@ class AddAliasPage extends BOBasePage implements BOAliasCreatePageInterface { * @returns {Promise} */ async setAlias(page: Page, aliasData: FakerSearchAlias): Promise { - await this.setValue(page, this.aliasInput, aliasData.alias); - await this.setValue(page, this.resultInput, aliasData.result); + await this.setValue(page, this.aliasInput, aliasData.search); + await this.setValue(page, this.resultInput, aliasData.alias); await page.locator(this.saveButton).click(); - return this.getAlertSuccessBlockContent(page); + return this.getAlertSuccessBlockParagraphContent(page); } } -module.exports = new AddAliasPage(); +const boSearchAliasCreatePage = new BOSearchAliasCreatePage(); +export {boSearchAliasCreatePage, BOSearchAliasCreatePage}; diff --git a/src/versions/develop/pages/BO/shopParameters/search/alias/index.ts b/src/versions/develop/pages/BO/shopParameters/search/alias/index.ts new file mode 100644 index 00000000..f477d8d8 --- /dev/null +++ b/src/versions/develop/pages/BO/shopParameters/search/alias/index.ts @@ -0,0 +1,462 @@ +import {BOSearchAliasPageInterface} from '@interfaces/BO/shopParameters/search/alias'; +import BOBasePage from '@pages/BO/BOBasePage'; +import type {Page} from 'playwright'; + +/** + * Search page, contains selectors and functions for the page + * @class + * @extends BOBasePage + */ +class BOSearchAliasPage extends BOBasePage implements BOSearchAliasPageInterface { + public readonly pageTitle: string; + + public readonly successfulUpdateStatusMessage: string; + + public readonly settingsUpdateMessage: string; + + public updateSuccessMessage: string; + + public readonly errorFillFieldMessage: string; + + public readonly errorMaxWordLengthInvalidMessage: string; + + protected addNewAliasLink: string; + + protected gridForm: string; + + protected gridTableHeaderTitle: string; + + protected gridTableNumberOfTitlesSpan: string; + + protected gridTable: string; + + protected filterRow: string; + + protected filterColumn: (filterBy: string) => string; + + protected filterSearchButton: string; + + protected filterResetButton: string; + + private readonly tableBody: string; + + private readonly tableBodyRows: string; + + private readonly tableBodyRow: (row: number) => string; + + protected tableBodyColumn: (row: number) => string; + + protected tableColumnActions: (row: number) => string; + + protected tableColumnActionsEditLink: (row: number) => string; + + protected tableColumnActionsToggleButton: (row: number) => string; + + protected tableColumnActionsDropdownMenu: (row: number) => string; + + protected tableColumnActionsDeleteLink: (row: number) => string; + + protected deleteModalButtonYes; + + protected tableColumnAliases: (row: number) => string; + + protected tableColumnSearch: (row: number) => string; + + protected bulkActionBlock: string; + + protected bulkActionMenuButton: string; + + protected bulkActionDropdownMenu: string; + + protected selectAllLink: string; + + protected bulkDeleteLink: string; + + private readonly confirmDeleteModal: string; + + private readonly confirmDeleteButton: string; + + protected paginationDiv: string; + + protected paginationLimitSelect: string; + + protected paginationLabel: string; + + protected paginationNextLink: string; + + protected paginationPreviousLink: string; + + protected tableHead: string; + + private readonly sortColumnDiv: (column: string) => string; + + private readonly sortColumnSpanButton: (column: string) => string; + + /** + * @constructs + * Setting up titles and selectors to use on search page + */ + constructor() { + super(); + + this.pageTitle = `Aliases • ${global.INSTALL.SHOP_NAME}`; + this.successfulCreationMessage = 'Successful creation'; + this.successfulUpdateStatusMessage = 'The status has been successfully updated.'; + this.updateSuccessMessage = 'Successful update'; + this.settingsUpdateMessage = 'The settings have been successfully updated.'; + this.errorFillFieldMessage = 'Please fill in this field.'; + this.errorMaxWordLengthInvalidMessage = 'The Maximum word length (in characters) field is invalid.'; + + // Selectors + // Header links + this.addNewAliasLink = 'a#page-header-desc-configuration-add'; + + // Form selectors + this.gridForm = '#alias_grid_panel'; + this.gridTableHeaderTitle = ''; + this.gridTableNumberOfTitlesSpan = `${this.gridForm} h3.card-header-title`; + + // Table selectors + this.gridTable = '#alias_grid_table'; + + // Filter selectors + this.filterRow = `${this.gridTable} tr.column-filters`; + this.filterColumn = (filterBy: string) => `${this.filterRow} [name='alias[${filterBy}]']`; + this.filterSearchButton = 'button.grid-search-button[name="alias[actions][search]"]'; + this.filterResetButton = 'button.js-reset-search[name="alias[actions][reset]"]'; + + // Table body selectors + this.tableBody = `${this.gridTable} tbody`; + this.tableBodyRows = `${this.tableBody} tr`; + this.tableBodyRow = (row: number) => `${this.tableBodyRows}:nth-child(${row})`; + this.tableBodyColumn = (row: number) => `${this.tableBodyRow(row)} td`; + + // Row actions selectors + this.tableColumnActions = (row: number) => `${this.tableBodyColumn(row)} .btn-group-action`; + this.tableColumnActionsEditLink = (row: number) => `${this.tableColumnActions(row)} a.grid-edit-row-link`; + this.tableColumnActionsToggleButton = (row: number) => `${this.tableColumnActions(row)} a.dropdown-toggle`; + this.tableColumnActionsDropdownMenu = (row: number) => `${this.tableColumnActions(row)} .dropdown-menu`; + this.tableColumnActionsDeleteLink = (row: number) => `${this.tableColumnActionsDropdownMenu(row)} a.grid-delete-row-link`; + + // Confirmation modal + this.deleteModalButtonYes = '#alias-grid-confirm-modal .modal-footer .btn-confirm-submit'; + + // Columns selectors + this.tableColumnAliases = (row: number) => `${this.tableBodyColumn(row)}.column-aliases`; + this.tableColumnSearch = (row: number) => `${this.tableBodyColumn(row)}.column-search`; + + // Bulk actions selectors + this.bulkActionBlock = 'div.bulk-actions'; + this.bulkActionMenuButton = '#alias_grid button.dropdown-toggle'; + this.bulkActionDropdownMenu = `${this.bulkActionBlock} ul.dropdown-menu`; + this.selectAllLink = `${this.gridForm} tr.column-filters .md-checkbox i`; + this.bulkDeleteLink = '#alias_grid_bulk_action_delete_selection'; + this.confirmDeleteModal = '#alias-grid-confirm-modal'; + this.confirmDeleteButton = `${this.confirmDeleteModal} button.btn-confirm-submit`; + + // Pagination selectors + this.paginationDiv = `${this.gridForm} .pagination`; + this.paginationLimitSelect = `${this.gridForm} #paginator_select_page_limit`; + this.paginationLabel = `${this.gridForm} .col-form-label`; + this.paginationNextLink = `${this.paginationDiv} a[data-role="next-page-link"]`; + this.paginationPreviousLink = `${this.paginationDiv} a[data-role="previous-page-link"]`; + + // Sort Selectors + this.tableHead = `${this.gridTable} thead`; + this.sortColumnDiv = (column: string) => `${this.tableHead} div.ps-sortable-column[data-sort-col-name='${column}']`; + this.sortColumnSpanButton = (column: string) => `${this.sortColumnDiv(column)} span.ps-sort`; + } + + /* + Methods + */ + + /* Header methods */ + /** + * Go to add new alias page + * @param page {Page} Browser tab + * @returns {Promise} + */ + async goToAddNewAliasPage(page: Page): Promise { + await this.clickAndWaitForURL(page, this.addNewAliasLink); + } + + /* Filter methods */ + /** + * Get number of lines + * @param page {Page} Browser tab + * @return {Promise} + */ + async getNumberOfElementInGrid(page: Page): Promise { + return this.getNumberFromText(page, this.gridTableNumberOfTitlesSpan); + } + + /** + * Reset all filters + * @param page {Page} Browser tab + * @return {Promise} + */ + async resetFilter(page: Page): Promise { + if (!(await this.elementNotVisible(page, this.filterResetButton, 2000))) { + await this.clickAndWaitForURL(page, this.filterResetButton); + } + } + + /** + * Reset and get number of lines + * @param page {Page} Browser tab + * @return {Promise} + */ + async resetAndGetNumberOfLines(page: Page): Promise { + await this.resetFilter(page); + return this.getNumberOfElementInGrid(page); + } + + /** + * Filter aliases + * @param page {Page} Browser tab + * @param filterType {string} Type of filter (input/select) + * @param filterBy {string} Column to filter with + * @param value {string} Value to filter + * @return {Promise} + */ + async filterTable(page: Page, filterType: string, filterBy: string, value: string): Promise { + let filterBySelector: string = ''; + + switch (filterType) { + case 'input': + switch (filterBy) { + case 'alias': + case 'search': + filterBySelector = filterBy; + break; + default: + throw new Error(`Column ${filterBy} was not found`); + } + await this.setValue(page, this.filterColumn(filterBySelector), value); + await this.clickAndWaitForURL(page, this.filterSearchButton); + break; + + default: + throw new Error(`Filter ${filterType} was not found`); + } + } + + /* Column methods */ + /** + * Go to edit page + * @param page {Page} Browser tab + * @param row {number} Row on table + * @return {Promise} + */ + async gotoEditAliasPage(page: Page, row: number): Promise { + await this.clickAndWaitForURL(page, this.tableColumnActionsEditLink(row)); + } + + /** + * Get text from column in table + * @param page {Page} Browser tab + * @param row {number} Row on table + * @param columnName {string} Column name of the value to return + * @return {Promise} + */ + async getTextColumn(page: Page, row: number, columnName: string): Promise { + let columnSelector; + + switch (columnName) { + case 'alias': + columnSelector = this.tableColumnAliases(row); + break; + + case 'search': + columnSelector = this.tableColumnSearch(row); + break; + + default: + throw new Error(`Column ${columnName} was not found`); + } + + return this.getTextContent(page, columnSelector); + } + + /** + * Get content from all rows + * @param page {Page} Browser tab + * @param columnName {string} Column name to get all text content + * @return {Promise>} + */ + async getAllRowsColumnContent(page: Page, columnName: string): Promise { + const rowsNumber = await this.getNumberOfElementInGrid(page); + const allRowsContentTable: string[] = []; + + for (let i = 1; i <= rowsNumber; i++) { + const rowContent = await this.getTextColumn(page, i, columnName); + allRowsContentTable.push(rowContent); + } + + return allRowsContentTable; + } + + /** + * Delete alias from row + * @param page {Page} Browser tab + * @param row {number} Row on table + * @return {Promise} + */ + async deleteAlias(page: Page, row: number): Promise { + await Promise.all([ + page.locator(this.tableColumnActionsToggleButton(row)).click(), + this.waitForVisibleSelector(page, this.tableColumnActionsDeleteLink(row)), + ]); + + await page.locator(this.tableColumnActionsDeleteLink(row)).click(); + + // Confirm delete action + await this.clickAndWaitForURL(page, this.deleteModalButtonYes); + + // Get successful message + return this.getAlertSuccessBlockParagraphContent(page); + } + + /* Bulk actions methods */ + /** + * Select all rows + * @param page {Page} Browser tab + * @return {Promise} + */ + async bulkSelectRows(page: Page): Promise { + await Promise.all([ + page.locator(this.selectAllLink).evaluate((el: HTMLElement) => el.click()), + this.waitForVisibleSelector(page, `${this.bulkActionMenuButton}:not([disabled])`), + ]); + } + + /** + * Delete by bulk action + * @param page {Page} Browser tab + * @returns {Promise} + */ + async bulkDeleteAliases(page: Page): Promise { + // Select all rows + await this.bulkSelectRows(page); + // Click on Button Bulk actions + await Promise.all([ + page.locator(this.bulkActionMenuButton).click(), + this.waitForVisibleSelector(page, `${this.bulkActionMenuButton}[aria-expanded='true']`), + ]); + // Click on delete and wait for modal + await Promise.all([ + page.locator(this.bulkDeleteLink).click(), + this.waitForVisibleSelector(page, `${this.confirmDeleteModal}.show`), + ]); + + await page.locator(this.confirmDeleteButton).click(); + await this.elementNotVisible(page, this.confirmDeleteButton, 2000); + + return this.getAlertSuccessBlockParagraphContent(page); + } + + /** + * Enable / disable by Bulk Actions + * @returns {Promise} + */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async bulkSetStatus(page: Page, enable: boolean = true): Promise { + return ''; + } + + /** + * Get alias status + * @return {Promise} + */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async getStatus(page: Page, row: number): Promise { + return true; + } + + /** + * Quick edit toggle column value + * @returns {Promise} return true if action is done, false otherwise + */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async setStatus(page: Page, row: number, valueWanted: boolean = true): Promise { + return true; + } + + /* Pagination methods */ + /** + * Get pagination label + * @param page {Page} Browser tab + * @return {Promise} + */ + async getPaginationLabel(page: Page): Promise { + const label: string = await this.getTextContent(page, this.paginationLabel); + const regexMatch: RegExpMatchArray | null = label.match(/\(page\s+(\d+)\s+\//); + + if (regexMatch === null) { + return ''; + } + + return regexMatch[1]; + } + + /** + * Select pagination limit + * @param page {Page} Browser tab + * @param number {number} Value of pagination limit to select + * @returns {Promise} + */ + async selectPaginationLimit(page: Page, number: number): Promise { + await page.locator(this.paginationLimitSelect).selectOption({ + value: number.toString(), + }); + + return this.getPaginationLabel(page); + } + + /** + * Click on next + * @param page {Page} Browser tab + * @returns {Promise} + */ + async paginationNext(page: Page): Promise { + await this.clickAndWaitForURL(page, this.paginationNextLink); + + return this.getPaginationLabel(page); + } + + /** + * Click on previous + * @param page {Page} Browser tab + * @returns {Promise} + */ + async paginationPrevious(page: Page): Promise { + await this.clickAndWaitForURL(page, this.paginationPreviousLink); + + return this.getPaginationLabel(page); + } + + /* Sort methods */ + /** + * Sort table + * @param page {Page} Browser tab + * @param sortBy {string} Column to sort with + * @param sortDirection {string} Sort direction asc or desc + * @return {Promise} + */ + async sortTable(page: Page, sortBy: string, sortDirection: string): Promise { + const sortColumnDiv = `${this.sortColumnDiv(sortBy)}[data-sort-direction='${sortDirection}']`; + const sortColumnSpanButton = this.sortColumnSpanButton(sortBy); + + let i: number = 0; + while (await this.elementNotVisible(page, sortColumnDiv, 2000) && i < 2) { + await this.clickAndWaitForURL(page, sortColumnSpanButton); + i += 1; + } + + await this.waitForVisibleSelector(page, sortColumnDiv, 20000); + } +} + +const boSearchAliasPage = new BOSearchAliasPage(); +export {boSearchAliasPage, BOSearchAliasPage}; diff --git a/src/versions/develop/pages/BO/shopParameters/search/index.ts b/src/versions/develop/pages/BO/shopParameters/search/index.ts index e41b3109..a87f8bdd 100644 --- a/src/versions/develop/pages/BO/shopParameters/search/index.ts +++ b/src/versions/develop/pages/BO/shopParameters/search/index.ts @@ -8,7 +8,7 @@ import type {Page} from 'playwright'; * @class * @extends BOBasePage */ -class SearchPage extends BOBasePage implements BOSearchPageInterface { +class BOSearchPage extends BOBasePage implements BOSearchPageInterface { public readonly pageTitle: string; public readonly successfulUpdateStatusMessage: string; @@ -21,90 +21,10 @@ class SearchPage extends BOBasePage implements BOSearchPageInterface { public readonly errorMaxWordLengthInvalidMessage: string; - private readonly addNewAliasLink: string; + private readonly aliasTabLink: string; private readonly tagsTabLink: string; - private readonly gridForm: string; - - private readonly gridTableHeaderTitle: string; - - private readonly gridTableNumberOfTitlesSpan: string; - - private readonly gridTable: string; - - private readonly filterRow: string; - - private readonly filterColumn: (filterBy: string) => string; - - private readonly filterSearchButton: string; - - private readonly filterResetButton: string; - - private readonly tableBody: string; - - private readonly tableBodyRows: string; - - private readonly tableBodyRow: (row: number) => string; - - private readonly tableBodyColumn: (row: number) => string; - - private readonly tableColumnActions: (row: number) => string; - - private readonly tableColumnActionsEditLink: (row: number) => string; - - private readonly tableColumnActionsToggleButton: (row: number) => string; - - private readonly tableColumnActionsDropdownMenu: (row: number) => string; - - private readonly tableColumnActionsDeleteLink: (row: number) => string; - - private readonly deleteModalButtonYes; - - private readonly tableColumnAliases: (row: number) => string; - - private readonly tableColumnSearch: (row: number) => string; - - private readonly tableColumnStatus: (row: number) => string; - - private readonly tableColumnStatusEnabledIcon: (row: number) => string; - - private readonly tableColumnStatusDisabledIcon: (row: number) => string; - - private readonly bulkActionBlock: string; - - private readonly bulkActionMenuButton: string; - - private readonly bulkActionDropdownMenu: string; - - private readonly selectAllLink: string; - - private readonly bulkDeleteLink: string; - - private readonly bulkEnableButton: string; - - private readonly bulkDisableButton: string; - - private readonly paginationDiv: string; - - private readonly paginationLimitSelect: string; - - private readonly paginationListOpen: string; - - private readonly paginationNumber: (number: number) => string; - - private readonly paginationRightBlock: string; - - private readonly paginationLabel: string; - - private readonly paginationNextLink: string; - - private readonly paginationPreviousLink: string; - - private readonly tableHead: string; - - private readonly sortColumnDiv: (column: string, direction: string) => string; - private readonly indexingForm: string; private readonly indexationLabel: (status: string) => string; @@ -157,72 +77,10 @@ class SearchPage extends BOBasePage implements BOSearchPageInterface { this.errorMaxWordLengthInvalidMessage = 'The Maximum word length (in characters) field is invalid.'; // Selectors - // Header links - this.addNewAliasLink = 'a[data-role=page-header-desc-alias-link]'; - // Tabs + this.aliasTabLink = '#subtab-AdminAliases'; this.tagsTabLink = '#subtab-AdminTags'; - // Form selectors - this.gridForm = '#form-alias'; - this.gridTableHeaderTitle = `${this.gridForm} .panel-heading`; - this.gridTableNumberOfTitlesSpan = `${this.gridTableHeaderTitle} span.badge`; - - // Table selectors - this.gridTable = '#table-alias'; - - // Filter selectors - this.filterRow = `${this.gridTable} tr.filter`; - this.filterColumn = (filterBy: string) => `${this.filterRow} [name='aliasFilter_${filterBy}']`; - this.filterSearchButton = '#submitFilterButtonalias'; - this.filterResetButton = 'button[name=\'submitResetalias\']'; - - // Table body selectors - this.tableBody = `${this.gridTable} tbody`; - this.tableBodyRows = `${this.tableBody} tr`; - this.tableBodyRow = (row: number) => `${this.tableBodyRows}:nth-child(${row})`; - this.tableBodyColumn = (row: number) => `${this.tableBodyRow(row)} td`; - - // Row actions selectors - this.tableColumnActions = (row: number) => `${this.tableBodyColumn(row)} .btn-group-action`; - this.tableColumnActionsEditLink = (row: number) => `${this.tableColumnActions(row)} a.edit`; - this.tableColumnActionsToggleButton = (row: number) => `${this.tableColumnActions(row)} button.dropdown-toggle`; - this.tableColumnActionsDropdownMenu = (row: number) => `${this.tableColumnActions(row)} .dropdown-menu`; - this.tableColumnActionsDeleteLink = (row: number) => `${this.tableColumnActionsDropdownMenu(row)} a.delete`; - - // Confirmation modal - this.deleteModalButtonYes = '#popup_ok'; - - // Columns selectors - this.tableColumnAliases = (row: number) => `${this.tableBodyColumn(row)}:nth-child(2)`; - this.tableColumnSearch = (row: number) => `${this.tableBodyColumn(row)}:nth-child(3)`; - this.tableColumnStatus = (row: number) => `${this.tableBodyColumn(row)}:nth-child(4) a`; - this.tableColumnStatusEnabledIcon = (row: number) => `${this.tableColumnStatus(row)}.action-enabled`; - this.tableColumnStatusDisabledIcon = (row: number) => `${this.tableColumnStatus(row)}.action-disabled`; - - // Bulk actions selectors - this.bulkActionBlock = 'div.bulk-actions'; - this.bulkActionMenuButton = '#bulk_action_menu_alias'; - this.bulkActionDropdownMenu = `${this.bulkActionBlock} ul.dropdown-menu`; - this.selectAllLink = `${this.bulkActionDropdownMenu} li:nth-child(1)`; - this.bulkDeleteLink = `${this.bulkActionDropdownMenu} li:nth-child(7)`; - this.bulkEnableButton = `${this.bulkActionDropdownMenu} li:nth-child(4)`; - this.bulkDisableButton = `${this.bulkActionDropdownMenu} li:nth-child(5)`; - - // Pagination selectors - this.paginationDiv = `${this.gridForm} .pagination`; - this.paginationLimitSelect = `${this.paginationDiv} button.dropdown-toggle`; - this.paginationListOpen = `${this.paginationDiv}.open`; - this.paginationNumber = (number: number) => `${this.gridForm} div.row li a[data-items='${number}']`; - this.paginationRightBlock = `${this.paginationDiv}.pull-right`; - this.paginationLabel = `${this.paginationRightBlock} li.active a`; - this.paginationNextLink = `${this.paginationRightBlock} i.icon-angle-right`; - this.paginationPreviousLink = `${this.paginationRightBlock} i.icon-angle-left`; - - // Sort Selectors - this.tableHead = `${this.gridTable} thead`; - this.sortColumnDiv = (column: string, direction: string) => `${this.tableHead} a.${direction}-sort-column-${column}-link`; - // Indexing form this.indexingForm = '#alias_fieldset_indexation'; this.indexationLabel = (status: string) => `#PS_SEARCH_INDEXATION_${status}`; @@ -257,12 +115,12 @@ class SearchPage extends BOBasePage implements BOSearchPageInterface { /* Header methods */ /** - * Go to add new alias page + * Go to aliases page * @param page {Page} Browser tab * @returns {Promise} */ - async goToAddNewAliasPage(page: Page): Promise { - await this.clickAndWaitForURL(page, this.addNewAliasLink); + async goToAliasesPage(page: Page): Promise { + await this.clickAndWaitForURL(page, this.aliasTabLink); } /** @@ -274,292 +132,6 @@ class SearchPage extends BOBasePage implements BOSearchPageInterface { await this.clickAndWaitForURL(page, this.tagsTabLink); } - /* Filter methods */ - /** - * Get number of lines - * @param page {Page} Browser tab - * @return {Promise} - */ - async getNumberOfElementInGrid(page: Page): Promise { - return this.getNumberFromText(page, this.gridTableNumberOfTitlesSpan); - } - - /** - * Reset all filters - * @param page {Page} Browser tab - * @return {Promise} - */ - async resetFilter(page: Page): Promise { - if (!(await this.elementNotVisible(page, this.filterResetButton, 2000))) { - await this.clickAndWaitForURL(page, this.filterResetButton); - } - await this.waitForVisibleSelector(page, this.filterSearchButton, 2000); - } - - /** - * Reset and get number of lines - * @param page {Page} Browser tab - * @return {Promise} - */ - async resetAndGetNumberOfLines(page: Page): Promise { - await this.resetFilter(page); - return this.getNumberOfElementInGrid(page); - } - - /** - * Filter aliases - * @param page {Page} Browser tab - * @param filterType {string} Type of filter (input/select) - * @param filterBy {string} Column to filter with - * @param value {string} Value to filter - * @return {Promise} - */ - async filterTable(page: Page, filterType: string, filterBy: string, value: string): Promise { - const currentUrl: string = page.url(); - - switch (filterType) { - case 'input': - await this.setValue(page, this.filterColumn(filterBy), value); - await this.clickAndWaitForURL(page, this.filterSearchButton); - break; - - case 'select': - await Promise.all([ - page.waitForURL((url: URL): boolean => url.toString() !== currentUrl, {waitUntil: 'networkidle'}), - this.selectByVisibleText(page, this.filterColumn(filterBy), value === '1' ? 'Yes' : 'No'), - ]); - break; - - default: - throw new Error(`Filter ${filterBy} was not found`); - } - } - - /* Column methods */ - /** - * Go to edit page - * @param page {Page} Browser tab - * @param row {number} Row on table - * @return {Promise} - */ - async gotoEditAliasPage(page: Page, row: number): Promise { - await this.clickAndWaitForURL(page, this.tableColumnActionsEditLink(row)); - } - - /** - * Get text from column in table - * @param page {Page} Browser tab - * @param row {number} Row on table - * @param columnName {string} Column name of the value to return - * @return {Promise} - */ - async getTextColumn(page: Page, row: number, columnName: string): Promise { - let columnSelector; - - switch (columnName) { - case 'alias': - columnSelector = this.tableColumnAliases(row); - break; - - case 'search': - columnSelector = this.tableColumnSearch(row); - break; - - case 'active': - columnSelector = this.tableColumnStatus(row); - break; - - default: - throw new Error(`Column ${columnName} was not found`); - } - - if (columnName === 'active') { - return this.getAttributeContent(page, columnSelector, 'title'); - } - - return this.getTextContent(page, columnSelector); - } - - /** - * Get content from all rows - * @param page {Page} Browser tab - * @param columnName {string} Column name to get all text content - * @return {Promise>} - */ - async getAllRowsColumnContent(page: Page, columnName: string): Promise { - const rowsNumber = await this.getNumberOfElementInGrid(page); - const allRowsContentTable: string[] = []; - - for (let i = 1; i <= rowsNumber; i++) { - const rowContent = await this.getTextColumn(page, i, columnName); - allRowsContentTable.push(rowContent); - } - - return allRowsContentTable; - } - - /** - * Delete alias from row - * @param page {Page} Browser tab - * @param row {number} Row on table - * @return {Promise} - */ - async deleteAlias(page: Page, row: number): Promise { - await Promise.all([ - page.locator(this.tableColumnActionsToggleButton(row)).click(), - this.waitForVisibleSelector(page, this.tableColumnActionsDeleteLink(row)), - ]); - - await page.locator(this.tableColumnActionsDeleteLink(row)).click(); - - // Confirm delete action - await this.clickAndWaitForURL(page, this.deleteModalButtonYes); - - // Get successful message - return this.getAlertSuccessBlockContent(page); - } - - /* Bulk actions methods */ - /** - * Select all rows - * @param page {Page} Browser tab - * @return {Promise} - */ - async bulkSelectRows(page: Page): Promise { - await page.locator(this.bulkActionMenuButton).click(); - - await Promise.all([ - page.locator(this.selectAllLink).click(), - this.waitForHiddenSelector(page, this.selectAllLink), - ]); - } - - /** - * Delete by bulk action - * @param page {Page} Browser tab - * @returns {Promise} - */ - async bulkDeleteAliases(page: Page): Promise { - await this.dialogListener(page, true); - // Select all rows - await this.bulkSelectRows(page); - - // Click on Button Bulk actions - await page.locator(this.bulkActionMenuButton).click(); - - // Click on delete - await this.clickAndWaitForURL(page, this.bulkDeleteLink); - - return this.getAlertSuccessBlockContent(page); - } - - /** - * Enable / disable by Bulk Actions - * @param page {Page} Browser tab - * @param enable {boolean} True if we need to enable status - * @returns {Promise} - */ - async bulkSetStatus(page: Page, enable: boolean = true): Promise { - // Select all rows - await this.bulkSelectRows(page); - - // Click on Button Bulk actions - await page.locator(this.bulkActionMenuButton).click(); - - // Click on enable/Disable and wait for modal - await this.clickAndWaitForURL(page, enable ? this.bulkEnableButton : this.bulkDisableButton); - - return this.getTextContent(page, this.alertSuccessBlock); - } - - /** - * Get alias status - * @param page {Page} Browser tab - * @param row {number} Row on table - * @return {Promise} - */ - async getStatus(page: Page, row: number): Promise { - return this.elementVisible(page, this.tableColumnStatusEnabledIcon(row), 500); - } - - /** - * Quick edit toggle column value - * @param page {Page} Browser tab - * @param row {number} Row on table - * @param valueWanted {boolean} Value wanted in column - * @returns {Promise} return true if action is done, false otherwise - */ - async setStatus(page: Page, row: number, valueWanted: boolean = true): Promise { - await this.waitForVisibleSelector(page, this.tableColumnStatus(row), 2000); - if (await this.getStatus(page, row) !== valueWanted) { - await page.locator(this.tableColumnStatus(row)).click(); - await this.waitForVisibleSelector( - page, - (valueWanted ? this.tableColumnStatusEnabledIcon(row) : this.tableColumnStatusDisabledIcon(row)), - ); - return true; - } - return false; - } - - /* Pagination methods */ - /** - * Get pagination label - * @param page {Page} Browser tab - * @return {Promise} - */ - async getPaginationLabel(page: Page): Promise { - return this.getTextContent(page, this.paginationLabel); - } - - /** - * Select pagination limit - * @param page {Page} Browser tab - * @param number {number} Value of pagination limit to select - * @returns {Promise} - */ - async selectPaginationLimit(page: Page, number: number): Promise { - await page.locator(this.paginationLimitSelect).click(); - await this.waitForVisibleSelector(page, this.paginationListOpen); - await this.clickAndWaitForURL(page, this.paginationNumber(number)); - - return this.getPaginationLabel(page); - } - - /** - * Click on next - * @param page {Page} Browser tab - * @returns {Promise} - */ - async paginationNext(page: Page): Promise { - await this.clickAndWaitForURL(page, this.paginationNextLink); - - return this.getPaginationLabel(page); - } - - /** - * Click on previous - * @param page {Page} Browser tab - * @returns {Promise} - */ - async paginationPrevious(page: Page): Promise { - await this.clickAndWaitForURL(page, this.paginationPreviousLink); - - return this.getPaginationLabel(page); - } - - /* Sort methods */ - /** - * Sort table - * @param page {Page} Browser tab - * @param sortBy {string} Column to sort with - * @param sortDirection {string} Sort direction asc or desc - * @return {Promise} - */ - async sortTable(page: Page, sortBy: string, sortDirection: string): Promise { - await this.clickAndWaitForURL(page, `${this.sortColumnDiv(sortBy, sortDirection)} i`); - } - // Methods for Indexing form /** * Returns the number of indexed products @@ -859,4 +431,5 @@ class SearchPage extends BOBasePage implements BOSearchPageInterface { } } -module.exports = new SearchPage(); +const boSearchPage = new BOSearchPage(); +export {boSearchPage, BOSearchPage};