From 0342dba1616817fa45f260f20d61f0ec6be44f73 Mon Sep 17 00:00:00 2001 From: nesrineabdmouleh Date: Thu, 18 Apr 2024 10:34:46 +0200 Subject: [PATCH 1/4] Add new test to change quantity in product page classic theme --- .../02_productPage/02_changeQuantity.ts | 141 ++++++++++++++++++ .../02_productPage/02_changeQuantity.ts | 0 2 files changed, 141 insertions(+) create mode 100644 tests/UI/campaigns/functional/FO/classic/09_productPage/02_productPage/02_changeQuantity.ts create mode 100644 tests/UI/campaigns/functional/FO/hummingbird/09_productPage/02_productPage/02_changeQuantity.ts diff --git a/tests/UI/campaigns/functional/FO/classic/09_productPage/02_productPage/02_changeQuantity.ts b/tests/UI/campaigns/functional/FO/classic/09_productPage/02_productPage/02_changeQuantity.ts new file mode 100644 index 0000000000000..cfc27142ac2b3 --- /dev/null +++ b/tests/UI/campaigns/functional/FO/classic/09_productPage/02_productPage/02_changeQuantity.ts @@ -0,0 +1,141 @@ +// Import utils +import helper from '@utils/helpers'; +import testContext from '@utils/testContext'; + +// Import pages +import {homePage} from '@pages/FO/classic/home'; +import {productPage} from '@pages/FO/classic/product'; +import {blockCartModal} from '@pages/FO/classic/modal/blockCart'; +import {cartPage} from '@pages/FO/classic/cart'; + +// Import data +import Products from '@data/demo/products'; + +import {expect} from 'chai'; +import type {BrowserContext, Page} from 'playwright'; + +const baseContext: string = 'functional_FO_classic_productPage_productPage_changeQuantity'; + +/* +Scenario: +- Go to FO +- Go to the third product in the list +- Click up/down on quantity input +- Set quantity input (good/bad value) + */ +describe('FO - Product page : Change quantity', async () => { + let browserContext: BrowserContext; + let page: Page; + + // before and after functions + before(async function () { + browserContext = await helper.createBrowserContext(this.browser); + page = await helper.newTab(browserContext); + }); + + after(async () => { + await helper.closeBrowserContext(browserContext); + }); + + it('should go to FO home page', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'goToFo', baseContext); + + await homePage.goToFo(page); + + const isHomePage = await homePage.isHomePage(page); + expect(isHomePage).to.equal(true); + }); + + it('should go to the third product page', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'goToProductPage', baseContext); + + await homePage.goToProductPage(page, 3); + + const pageTitle = await productPage.getPageTitle(page); + expect(pageTitle.toUpperCase()).to.contains(Products.demo_6.name.toUpperCase()); + }); + + it('should change the quantity by using the arrow \'UP\' button', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'incrementQuantity', baseContext); + + await productPage.setQuantityByArrowUpDown(page, 5, 'up'); + + const productQuantity = await productPage.getProductQuantity(page); + expect(productQuantity).to.equal(5); + }); + + it('should change the quantity by using the arrow \'Down\' button', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'incrementQuantity2', baseContext); + + await productPage.setQuantityByArrowUpDown(page, 1, 'down'); + + const productQuantity = await productPage.getProductQuantity(page); + expect(productQuantity).to.equal(1); + }); + + it('should add quantity of the product by setting input value', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'updateQuantityByInput', baseContext); + + await productPage.setQuantity(page, 12); + await productPage.clickOnAddToCartButton(page); + + const isVisible = await blockCartModal.isBlockCartModalVisible(page); + expect(isVisible).to.equal(true); + }); + + it('should click on continue shopping and check that the modal is not visible', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'clickOnContinueShopping', baseContext); + + const isNotVisible = await blockCartModal.continueShopping(page); + expect(isNotVisible).to.equal(true); + }); + + it('should check the cart notifications number', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'checkNotificationsNumber', baseContext); + + const notificationsNumber = await productPage.getCartNotificationsNumber(page); + expect(notificationsNumber).to.equal(12); + }); + + it('should set \'-24\' in the quantity input', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'updateQuantityByInput2', baseContext); + + await productPage.setQuantity(page, '-24'); + await productPage.clickOnAddToCartButton(page); + + const isVisible = await blockCartModal.isBlockCartModalVisible(page); + expect(isVisible).to.equal(true); + }); + + it('should click on continue shopping and check that the modal is not visible', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'clickOnContinueShopping2', baseContext); + + const isNotVisible = await blockCartModal.continueShopping(page); + expect(isNotVisible).to.equal(true); + }); + + it('should check the cart notifications number', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'checkNotificationsNumber2', baseContext); + + const notificationsNumber = await homePage.getCartNotificationsNumber(page); + expect(notificationsNumber).to.equal(13); + }); + + it('should set \'Prestashop\' in the quantity input and proceed to checkout', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'updateQuantityByInput3', baseContext); + + await productPage.addProductToTheCart(page, 'Prestashop'); + + const notificationsNumber = await homePage.getCartNotificationsNumber(page); + expect(notificationsNumber).to.equal(14); + }); + + it('should remove product from shopping cart', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'removeProduct', baseContext); + + await cartPage.deleteProduct(page, 1); + + const notificationNumber = await cartPage.getCartNotificationsNumber(page); + expect(notificationNumber).to.equal(0); + }); +}); diff --git a/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/02_productPage/02_changeQuantity.ts b/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/02_productPage/02_changeQuantity.ts new file mode 100644 index 0000000000000..e69de29bb2d1d From 9ebd55f884077cd87629525b08b0505a1fd48854 Mon Sep 17 00:00:00 2001 From: nesrineabdmouleh Date: Thu, 18 Apr 2024 10:35:05 +0200 Subject: [PATCH 2/4] Add new test to change quantity in product page hummingbird theme --- .../02_productPage/02_changeQuantity.ts | 169 ++++++++++++++++++ tests/UI/pages/FO/classic/product/index.ts | 56 +++++- .../UI/pages/FO/hummingbird/product/index.ts | 2 + 3 files changed, 218 insertions(+), 9 deletions(-) diff --git a/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/02_productPage/02_changeQuantity.ts b/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/02_productPage/02_changeQuantity.ts index e69de29bb2d1d..0e164c6e18f6c 100644 --- a/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/02_productPage/02_changeQuantity.ts +++ b/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/02_productPage/02_changeQuantity.ts @@ -0,0 +1,169 @@ +// Import utils +import helper from '@utils/helpers'; +import testContext from '@utils/testContext'; + +// Import common tests +import {installHummingbird, uninstallHummingbird} from '@commonTests/BO/design/hummingbird'; + +// Import pages +import homePage from '@pages/FO/hummingbird/home'; +import productPage from '@pages/FO/hummingbird/product'; +import blockCartModal from '@pages/FO/hummingbird/modal/blockCart'; +import cartPage from '@pages/FO/hummingbird/cart'; + +// Import data +import Products from '@data/demo/products'; + +import {expect} from 'chai'; +import type {BrowserContext, Page} from 'playwright'; + +const baseContext: string = 'functional_FO_hummingbird_productPage_productPage_changeQuantity'; + +/* +Pre-condition: +- Install hummingbird theme +Scenario: +- Go to FO +- Go to the third product in the list +- Click up/down on quantity input +- Set quantity input (good/bad value) +Post-condition: +- Uninstall hummingbird theme + */ +describe('FO - Product page : Change quantity', async () => { + let browserContext: BrowserContext; + let page: Page; + + // Pre-condition : Install Hummingbird + installHummingbird(`${baseContext}_preTest`); + + // before and after functions + before(async function () { + browserContext = await helper.createBrowserContext(this.browser); + page = await helper.newTab(browserContext); + }); + + after(async () => { + await helper.closeBrowserContext(browserContext); + }); + + describe('Change quantity from product page', async () => { + it('should go to FO home page', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'goToFo', baseContext); + + await homePage.goToFo(page); + + const isHomePage = await homePage.isHomePage(page); + expect(isHomePage).to.equal(true); + }); + + it('should go to the third product page', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'goToProductPage', baseContext); + + await homePage.goToProductPage(page, 3); + + const pageTitle = await productPage.getPageTitle(page); + expect(pageTitle.toUpperCase()).to.contains(Products.demo_6.name.toUpperCase()); + }); + + it('should change the quantity by using the arrow \'Down\' button', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'decrement', baseContext); + + await productPage.setQuantityByArrowUpDown(page, 1, 'down'); + + const productQuantity = await productPage.getProductQuantity(page); + expect(productQuantity).to.equal(1); + }); + + it('should change the quantity by using the arrow \'UP\' button', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'incrementQuantity', baseContext); + + await productPage.setQuantityByArrowUpDown(page, 2, 'increment'); + + const productQuantity = await productPage.getProductQuantity(page); + expect(productQuantity).to.equal(2); + }); + + it('should click on add to cart button then on continue shopping button', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'clickOnAddToCartButton', baseContext); + + await productPage.clickOnAddToCartButton(page); + + const isNotVisible = await blockCartModal.continueShopping(page); + expect(isNotVisible).to.equal(true); + }); + + // @todo : https://github.com/PrestaShop/hummingbird/pull/600 + it.skip('should set the quantity 0 and check that the add to cart button is disabled', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'checkAddToCartButtonIsDisabled', baseContext); + + await productPage.setQuantity(page, 0); + + const isButtonDisabled = await productPage.isAddToCartButtonEnabled(page); + expect(isButtonDisabled).to.equal(false); + }); + + it('should add quantity of the product by setting input value', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'updateQuantityByInput', baseContext); + + // @todo : https://github.com/PrestaShop/hummingbird/issues/615 + await productPage.reloadPage(page); + + await productPage.setQuantity(page, 12); + await productPage.clickOnAddToCartButton(page); + + const isVisible = await blockCartModal.isBlockCartModalVisible(page); + expect(isVisible).to.equal(true); + }); + + it('should click on continue shopping and check that the modal is not visible', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'clickOnContinueShopping', baseContext); + + const isNotVisible = await blockCartModal.continueShopping(page); + expect(isNotVisible).to.equal(true); + }); + + it('should check the cart notifications number', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'checkNotificationsNumber', baseContext); + + const notificationsNumber = await productPage.getCartNotificationsNumber(page); + expect(notificationsNumber).to.equal(14); + }); + + // @todo : https://github.com/PrestaShop/hummingbird/pull/600 + it.skip('should set \'-24\' in the quantity input', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'updateQuantityByInput2', baseContext); + + await productPage.setQuantity(page, '-24'); + + const isButtonDisabled = await productPage.isAddToCartButtonEnabled(page); + expect(isButtonDisabled).to.equal(false); + }); + + it('should set \'Prestashop\' in the quantity input and proceed to checkout', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'updateQuantityByInput3', baseContext); + + // @todo : https://github.com/PrestaShop/hummingbird/issues/615 + await productPage.reloadPage(page); + + await productPage.setQuantity(page, 'Prestashop'); + await productPage.clickOnAddToCartButton(page); + + const errorAlert = await productPage.getWarningMessage(page); + expect(errorAlert).to.equal('Null quantity.'); + }); + + it('should remove product from shopping cart', async function () { + await testContext.addContextItem(this, 'testIdentifier', 'removeProduct', baseContext); + + await productPage.goToCartPage(page); + await cartPage.deleteProduct(page, 1); + + const notificationNumber = await cartPage.getCartNotificationsNumber(page); + expect(notificationNumber).to.equal(0); + }); + }); + + // Post-condition : Uninstall Hummingbird + uninstallHummingbird(`${baseContext}_postTest`); +}); diff --git a/tests/UI/pages/FO/classic/product/index.ts b/tests/UI/pages/FO/classic/product/index.ts index 2abe664f5d728..c45db6da935d7 100644 --- a/tests/UI/pages/FO/classic/product/index.ts +++ b/tests/UI/pages/FO/classic/product/index.ts @@ -21,7 +21,7 @@ class Product extends FOBasePage { public readonly messageAlertNotificationAlreadyRegistered: string; - private readonly warningMessage: string; + protected warningMessage: string; protected productFlags: string; @@ -37,6 +37,8 @@ class Product extends FOBasePage { private readonly productQuantity: string; + protected productRowQuantityUpDownButton: (direction: string) => string; + protected shortDescription: string; private readonly productDescription: string; @@ -193,6 +195,8 @@ class Product extends FOBasePage { this.thumbFirstImg = '#content li:nth-child(1) img.js-thumb'; this.thumbSecondImg = '#content li:nth-child(2) img.js-thumb'; this.productQuantity = '#quantity_wanted'; + this.productRowQuantityUpDownButton = (direction: string) => 'span.input-group-btn-vertical' + + ` button.bootstrap-touchspin-${direction}`; this.shortDescription = '#product-description-short'; this.productDescription = '#description'; this.customizationBlock = 'div.product-container div.product-information section.product-customization'; @@ -586,11 +590,11 @@ class Product extends FOBasePage { /** * Select product attributes * @param page {Page} Browser tab - * @param quantity {number} Quantity of the product that customer wants + * @param quantity {number|string} Quantity of the product that customer wants * @param attributes {ProductAttribute[]} Product's attributes data to select * @returns {Promise} */ - async selectAttributes(page: Page, quantity: number, attributes: ProductAttribute[]): Promise { + async selectAttributes(page: Page, quantity: number|string, attributes: ProductAttribute[]): Promise { if (attributes.length === 0) { return; } @@ -640,7 +644,7 @@ class Product extends FOBasePage { /** * Click on Add to cart button then on Proceed to checkout button in the modal * @param page {Page} Browser tab - * @param quantity {number} Quantity of the product that customer wants + * @param quantity {number|string} Quantity of the product that customer wants * @param combination {ProductAttribute[]} Product's combination data to add to cart * @param proceedToCheckout {boolean|null} True to click on proceed to checkout button on modal * @param customizedText {string} Value of customization @@ -648,7 +652,7 @@ class Product extends FOBasePage { */ async addProductToTheCart( page: Page, - quantity: number = 1, + quantity: number |string = 1, combination: ProductAttribute[] = [], proceedToCheckout: boolean | null = true, customizedText: string = 'text', @@ -738,11 +742,45 @@ class Product extends FOBasePage { /** * Set quantity * @param page {Page} Browser tab - * @param quantity {number} Quantity to set + * @param quantity {number|string} Quantity to set * @returns {Promise} */ - async setQuantity(page: Page, quantity: number): Promise { - await this.setValue(page, this.productQuantity, quantity.toString()); + async setQuantity(page: Page, quantity: number | string): Promise { + await this.setValue(page, this.productQuantity, quantity); + } + + /** + * Click on add to cart button + * @param page {Page} Browser tab + * @returns {Promise} + */ + async clickOnAddToCartButton(page: Page): Promise { + await this.waitForSelectorAndClick(page, this.addToCartButton); + } + + /** + * Get product quantity + * @param page {Page} Browser tab + * @returns {Promise} + */ + async getProductQuantity(page: Page): Promise { + return parseInt(await page.locator(this.productQuantity).evaluate((node: HTMLSelectElement) => node.value), 10); + } + + /** + * Update quantity value arrow up down in quick view modal + * @param page {Page} Browser tab + * @param quantityWanted {number} Value to add/subtract from quantity + * @param direction {string} Direction to click on + * @returns {Promise} + */ + async setQuantityByArrowUpDown(page: Page, quantityWanted: number, direction: string): Promise { + const inputValue = await this.getProductQuantity(page); + const nbClick: number = Math.abs(inputValue - quantityWanted); + + for (let i = 0; i < nbClick; i++) { + await page.locator(this.productRowQuantityUpDownButton(direction)).click(); + } } /** @@ -851,7 +889,7 @@ class Product extends FOBasePage { * @returns {Promise} */ async isAddToCartButtonEnabled(page: Page): Promise { - return this.elementNotVisible(page, `${this.addToCartButton}:disabled`, 1000); + return this.elementNotVisible(page, `${this.addToCartButton}:disabled`, 3000); } /** diff --git a/tests/UI/pages/FO/hummingbird/product/index.ts b/tests/UI/pages/FO/hummingbird/product/index.ts index 2925f5268ca01..a03a79ba67709 100644 --- a/tests/UI/pages/FO/hummingbird/product/index.ts +++ b/tests/UI/pages/FO/hummingbird/product/index.ts @@ -13,6 +13,8 @@ class ProductPage extends Product { constructor() { super('hummingbird'); + this.warningMessage = '#js-toast-container div.bg-danger div.toast-body'; + this.productRowQuantityUpDownButton = (direction: string) => `div.product-actions__quantity button.js-${direction}-button`; this.proceedToCheckoutButton = '#blockcart-modal div.cart-footer-actions a'; this.productName = '#content-wrapper h1.product__name'; this.shortDescription = 'div.product__description-short'; From 8c41535bbae4be781525afaab0503d1a965b51ba Mon Sep 17 00:00:00 2001 From: nesrineabdmouleh Date: Thu, 18 Apr 2024 10:35:18 +0200 Subject: [PATCH 3/4] Add some fixes --- .../hummingbird/09_productPage/02_productPage/01_addToCart.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/02_productPage/01_addToCart.ts b/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/02_productPage/01_addToCart.ts index 57483991612a6..00beaab48ebf6 100644 --- a/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/02_productPage/01_addToCart.ts +++ b/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/02_productPage/01_addToCart.ts @@ -1,7 +1,6 @@ // Import utils import helper from '@utils/helpers'; import testContext from '@utils/testContext'; -import files from '@utils/files'; // Import common tests import {installHummingbird, uninstallHummingbird} from '@commonTests/BO/design/hummingbird'; @@ -41,7 +40,6 @@ describe('FO - Product page - Product page : Add to cart', async () => { after(async () => { await helper.closeBrowserContext(browserContext); - await files.deleteFile('../../admin-dev/hummingbird.zip'); }); describe('Add to cart', async () => { From 2ef68464f4635bcfec97c2c8a68037118d633e14 Mon Sep 17 00:00:00 2001 From: nesrineabdmouleh Date: Mon, 22 Apr 2024 17:54:53 +0200 Subject: [PATCH 4/4] Fix review --- .../09_productPage/02_productPage/02_changeQuantity.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/02_productPage/02_changeQuantity.ts b/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/02_productPage/02_changeQuantity.ts index 0e164c6e18f6c..16f59869d188a 100644 --- a/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/02_productPage/02_changeQuantity.ts +++ b/tests/UI/campaigns/functional/FO/hummingbird/09_productPage/02_productPage/02_changeQuantity.ts @@ -94,9 +94,10 @@ describe('FO - Product page : Change quantity', async () => { }); // @todo : https://github.com/PrestaShop/hummingbird/pull/600 - it.skip('should set the quantity 0 and check that the add to cart button is disabled', async function () { + it('should set the quantity 0 and check that the add to cart button is disabled', async function () { await testContext.addContextItem(this, 'testIdentifier', 'checkAddToCartButtonIsDisabled', baseContext); + this.skip(); await productPage.setQuantity(page, 0); const isButtonDisabled = await productPage.isAddToCartButtonEnabled(page); @@ -131,9 +132,10 @@ describe('FO - Product page : Change quantity', async () => { }); // @todo : https://github.com/PrestaShop/hummingbird/pull/600 - it.skip('should set \'-24\' in the quantity input', async function () { + it('should set \'-24\' in the quantity input', async function () { await testContext.addContextItem(this, 'testIdentifier', 'updateQuantityByInput2', baseContext); + this.skip(); await productPage.setQuantity(page, '-24'); const isButtonDisabled = await productPage.isAddToCartButtonEnabled(page);