diff --git a/src/index.ts b/src/index.ts index 07c6b6e1..7f21b851 100644 --- a/src/index.ts +++ b/src/index.ts @@ -326,6 +326,7 @@ export {default as modAutoupgradeBoMain} from '@pages/BO/modules/autoupgrade'; export {default as modBlockwishlistBoMain} from '@pages/BO/modules/blockwishlist'; export {default as modBlockwishlistBoStatistics} from '@pages/BO/modules/blockwishlist/statistics'; export {default as modKeycloakConnectorDemoBoMain} from '@pages/BO/modules/keycloakConnectorDemo'; +export {default as modProductCommentsBoMain} from '@pages/BO/modules/productcomments'; export {default as modPsCategoryProductsBoMain} from '@pages/BO/modules/ps_categoryproducts'; export {default as modPsEmailAlertsBoMain} from '@pages/BO/modules/ps_emailalerts'; export {default as modPsEmailSubscriptionBoMain} from '@pages/BO/modules/ps_emailsubscription'; diff --git a/src/interfaces/BO/modules/autoupgrade/index.ts b/src/interfaces/BO/modules/autoupgrade/index.ts index 4ed1a8b9..50fa6cc6 100644 --- a/src/interfaces/BO/modules/autoupgrade/index.ts +++ b/src/interfaces/BO/modules/autoupgrade/index.ts @@ -2,10 +2,8 @@ import {ModuleConfigurationPageInterface} from '@interfaces/BO/modules/moduleCon import type {Page} from '@playwright/test'; export interface ModuleAutoupgradeMainPageInterface extends ModuleConfigurationPageInterface { - readonly pageTitle: string; - readonly checkRequirementSuccessMessage: string; - + readonly pageTitle: string; readonly updateSuccessMessage: string; cancelBackup(page:Page):Promise; diff --git a/src/interfaces/BO/modules/productcomments/index.ts b/src/interfaces/BO/modules/productcomments/index.ts new file mode 100644 index 00000000..f3612565 --- /dev/null +++ b/src/interfaces/BO/modules/productcomments/index.ts @@ -0,0 +1,5 @@ +import {ModuleConfigurationPageInterface} from '@interfaces/BO/modules/moduleConfiguration'; + +export interface ModuleProductCommentsBoMainPageInterface extends ModuleConfigurationPageInterface { + readonly pageTitle: string; +} diff --git a/src/pages/BO/modules/productcomments/index.ts b/src/pages/BO/modules/productcomments/index.ts new file mode 100644 index 00000000..a1e3d390 --- /dev/null +++ b/src/pages/BO/modules/productcomments/index.ts @@ -0,0 +1,9 @@ +import {type ModuleProductCommentsBoMainPageInterface} from '@interfaces/BO/modules/productcomments/index'; + +/* eslint-disable global-require, @typescript-eslint/no-require-imports */ +function requirePage(): ModuleProductCommentsBoMainPageInterface { + return require('@versions/develop/pages/BO/modules/productcomments/index'); +} +/* eslint-enable global-require, @typescript-eslint/no-require-imports */ + +export default requirePage(); diff --git a/src/versions/develop/pages/BO/modules/productcomments/index.ts b/src/versions/develop/pages/BO/modules/productcomments/index.ts new file mode 100644 index 00000000..b05dc1c9 --- /dev/null +++ b/src/versions/develop/pages/BO/modules/productcomments/index.ts @@ -0,0 +1,236 @@ +import {type ModuleProductCommentsBoMainPageInterface} from '@interfaces/BO/modules/productcomments'; +import ModuleConfiguration from '@pages/BO/modules/moduleConfiguration'; +import {type Page} from '@playwright/test'; + +/** + * Module configuration page for module : Product comments, contains selectors and functions for the page + * @class + * @extends ModuleConfiguration + */ +class ModuleProductCommentsBoMainPage extends ModuleConfiguration implements ModuleProductCommentsBoMainPageInterface { + public readonly pageTitle: string; + + private readonly reviewsTable: (table: string) => string; + + private readonly reviewsTableBody: (table: string) => string; + + private readonly reviewsTableRows: (table: string) => string; + + private readonly reviewsTableRow: (table: string, row: number) => string; + + private readonly reviewsTableColumn: (table: string, row: number, column: string) => string; + + private readonly reviewsTableEmptyRows: (table: string) => string; + + private readonly deleteReviewButton: (table: string, row: number) => string; + + private readonly toggleDropdownButton: (table: string, row: number) => string; + + private readonly approveWaitingReviewButton: (table: string, row: number) => string; + + private readonly confirmNotAbusiveReviewButton: (table: string, row: number) => string; + + private readonly confirmReviewDeletionButton: string; + + /** + * @constructs + * Setting selectors to use on product comments module configuration page + */ + constructor() { + super(); + this.pageTitle = 'Product Comments'; + + // Selectors + // Table Selectors + this.reviewsTable = (table: string) => `#table-${table}-productcomments-list`; + this.reviewsTableBody = (table: string) => `${this.reviewsTable(table)} tbody`; + this.reviewsTableRows = (table: string) => `${this.reviewsTableBody(table)} tr`; + this.reviewsTableRow = (table: string, row: number) => `${this.reviewsTableRows(table)}:nth-child(${row})`; + this.reviewsTableColumn = (table: string, row: number, column: string) => `${this.reviewsTableRow(table, row)}` + + ` td.product-comment-${column}`; + this.reviewsTableEmptyRows = (table: string) => `${this.reviewsTableRows(table)} td.list-empty`; + // Buttons Selectors + this.deleteReviewButton = (table: string, row: number) => `${this.reviewsTableRow(table, row)} .btn-group [title='Delete']`; + this.toggleDropdownButton = (table: string, row: number) => `${this.reviewsTableRow(table, row)} button.dropdown-toggle`; + // "Waiting for approval" buttons selectors + this.approveWaitingReviewButton = (table: string, row: number) => `${this.reviewsTableRow(table, row)} a.btn-success`; + // "Reported reviews" buttons selectors + this.confirmNotAbusiveReviewButton = (table: string, row: number) => `${this.reviewsTableRow(table, row)} .dropdown-toggle a`; + // Delete review confirmation modal selectors + this.confirmReviewDeletionButton = '#popup_ok'; + } + + /* Methods */ + + /** + * Get the review count for a table + * @param page {Page} Browser tab + * @param table {String} The review table (3 options available: 'waiting-approval', 'reported', 'approved') + * @returns {Promise} + */ + async getTableReviewCount(page: Page, table: string): Promise { + if (await this.elementVisible(page, this.reviewsTableEmptyRows(table), 3000)) { + return 0; + } + + return page.locator(this.reviewsTableRows(table)).count(); + } + + /** + * Get the review count for the 'waiting approval' table + * @param page {Page} Browser tab + * @returns {Promise} + */ + getWaitingApprovalReviewCount(page: Page): Promise { + return this.getTableReviewCount(page, 'waiting-approval'); + } + + /** + * Get the review count for the 'reported review' table + * @param page {Page} Browser tab + * @returns {Promise} + */ + getReportedReviewCount(page: Page): Promise { + return this.getTableReviewCount(page, 'reported'); + } + + /** + * Get the review count for the 'approved review' table + * @param page {Page} Browser tab + * @returns {Promise} + */ + getApprovedReviewCount(page: Page): Promise { + return this.getTableReviewCount(page, 'approved'); + } + + /** + * Open the button dropdown to perform some action + * @param page {Page} Browser tab + * @param table {String} The review table (2 options available: 'waiting-approval', 'reported') + * @param row {number} The review row + * @returns {Promise} + */ + async openProductReviewDropdown(page: Page, table: string, row: number = 1): Promise { + await this.waitForVisibleSelector(page, this.toggleDropdownButton(table, row)); + await page.locator(this.toggleDropdownButton(table, row)).click(); + } + + /** + * Get all the content for a review in review table + * @param page {Page} The browser tab + * @param table {String} The review table (3 options available: 'waiting-approval', 'reported', 'approved') + * @param row {number} The review row (default is set to 1) + * @returns {Promise<{id: string, title: string, content: string, rating: string, author: string, + * product: string, date: string}>} + */ + async getReviewDataFromTable(page: Page, table: string, row: number = 1) { + return { + id: await this.getTextContent(page, this.reviewsTableColumn(table, row, 'id')), + title: await this.getTextContent(page, this.reviewsTableColumn(table, row, 'title')), + content: await this.getTextContent(page, this.reviewsTableColumn(table, row, 'content')), + rating: await this.getTextContent(page, this.reviewsTableColumn(table, row, 'rating')), + author: await this.getTextContent(page, this.reviewsTableColumn(table, row, 'author')), + product: await this.getTextContent(page, this.reviewsTableColumn(table, row, 'product-name')), + date: await this.getTextContent(page, this.reviewsTableColumn(table, row, 'date')), + }; + } + + /** + * Get all the content for a review in 'waiting approval' table + * @param page {Page} Browser tab + * @returns {Promise<{id: string, title: string, content: string, rating: string, author: string, + * product: string, date: string}>} + */ + getReviewDataFromWaitingApprovalTable(page: Page) { + return this.getReviewDataFromTable(page, 'waiting-approval'); + } + + /** + * Get all the content for a review in 'reported review' table + * @param page {Page} Browser tab + * @returns {Promise<{id: string, title: string, content: string, rating: string, author: string, + * product: string, date: string}>} + */ + getReviewDataFromReportedReviewTable(page: Page) { + return this.getReviewDataFromTable(page, 'reported'); + } + + /** + * Get all the content for a review in 'approved review' table + * @param page {Page} Browser tab + * @returns {Promise<{id: string, title: string, content: string, rating: string, author: string, + * product: string, date: string}>} + */ + getReviewDataFromApprovedReviewTable(page: Page) { + return this.getReviewDataFromTable(page, 'approved'); + } + + /** + * Approve a review in the "waiting for approval table" + * @param page {Page} Browser tab + * @param row {number} The review row + * @returns {Promise} + */ + async approveReview(page: Page, row: number = 1): Promise { + await this.clickAndWaitForURL(page, this.approveWaitingReviewButton('waiting-approval', row)); + } + + /** + * Delete a review in a table + * @param page {Page} Browser tab + * @param table {String} The reviews table + * @param row {number} The review row + * @returns {Promise} + */ + async deleteReview(page: Page, table: string, row: number = 1): Promise { + await page.locator(this.deleteReviewButton(table, row)).click(); + await this.clickAndWaitForURL(page, this.confirmReviewDeletionButton); + } + + /** + * Delete a review in the "waiting approval" table + * @param page {Page} Browser tab + * @param row {number} The review row + * @returns {Promise} + */ + async deleteWaitingApprovalReview(page: Page, row: number = 1): Promise { + // Need to open dropdown before delete + await this.openProductReviewDropdown(page, 'waiting-approval', row); + await this.deleteReview(page, 'waiting-approval', row); + } + + /** + * Delete a review in the "reported review" table + * @param page {Page} Browser tab + * @param row {number} The review row + * @returns {Promise} + */ + async deleteReportedReview(page: Page, row: number = 1): Promise { + await this.deleteReview(page, 'reported', row); + } + + /** + * Delete a review in the "approved review" table + * @param page {Page} Browser tab + * @param row {number} The review row + * @returns {Promise} + */ + async deleteApprovedReview(page: Page, row: number = 1): Promise { + await this.deleteReview(page, 'approved', row); + } + + /** + * Confirm a review in the "reported review" table + * @param page {Page} Browser tab + * @param table {string} The review table + * @param row {number} The review row + * @returns {Promise} + */ + async confirmNotAbusiveReview(page: Page, table: string, row: number = 1): Promise { + await this.openProductReviewDropdown(page, 'reported', row); + await this.waitForVisibleSelector(page, this.confirmNotAbusiveReviewButton(table, row)); + await page.locator(this.confirmNotAbusiveReviewButton(table, row)).click(); + } +} + +module.exports = new ModuleProductCommentsBoMainPage();