|
| 1 | +import {type ProductAttribute, type ProductDetails} from '@data/types/product'; |
| 2 | +import {type FoModalQuickViewPageInterface} from '@interfaces/FO/modal/quickView'; |
| 3 | +import {type Page} from '@playwright/test'; |
| 4 | +import {QuickViewModal as QuickViewModalClassic} from '@versions/develop/pages/FO/classic/modal/quickView'; |
| 5 | + |
| 6 | +/** |
| 7 | + * Quick view modal, contains functions that can be used on the page |
| 8 | + * @class |
| 9 | + * @extends QuickViewModal |
| 10 | + */ |
| 11 | +class QuickViewModal extends QuickViewModalClassic implements FoModalQuickViewPageInterface { |
| 12 | + /** |
| 13 | + * @constructs |
| 14 | + * Setting up texts and selectors to use on home page |
| 15 | + */ |
| 16 | + constructor() { |
| 17 | + super('hummingbird'); |
| 18 | + |
| 19 | + // Quick view modal |
| 20 | + this.productRowQuantityUpDownButton = (direction: string) => `div.product-actions__quantity button.js-${direction}-button`; |
| 21 | + this.quickViewProductName = `${this.quickViewModalDiv} .h3`; |
| 22 | + this.quickViewRegularPrice = `${this.quickViewModalDiv} span.product__price-regular`; |
| 23 | + this.quickViewProductPrice = `${this.quickViewModalDiv} div.product__current-price`; |
| 24 | + this.quickViewDiscountPercentage = `${this.quickViewModalDiv} div.product__discount-percentage`; |
| 25 | + this.quickViewTaxShippingDeliveryLabel = `${this.quickViewModalDiv} div.product__tax-label`; |
| 26 | + this.quickViewCoverImage = `${this.quickViewModalDiv} #product-images div.carousel-item.active img.img-fluid`; |
| 27 | + this.quickViewThumbImage = `${this.quickViewModalDiv} div.thumbnails__container img.img-fluid`; |
| 28 | + this.quickViewProductVariants = `${this.quickViewModalDiv} div.js-product-variants`; |
| 29 | + this.quickViewProductDimension = `${this.quickViewProductVariants} select#group_3`; |
| 30 | + this.quickViewProductSize = `${this.quickViewProductVariants} select#group_1`; |
| 31 | + this.quickViewProductColor = `${this.quickViewProductVariants} ul#group_2`; |
| 32 | + this.quickViewCloseButton = `${this.quickViewModalDiv} button.btn-close`; |
| 33 | + } |
| 34 | + |
| 35 | + /** |
| 36 | + * Get product details from quick view modal |
| 37 | + * @param page {Page} Browser tab |
| 38 | + * @returns {Promise<ProductDetails>} |
| 39 | + */ |
| 40 | + async getProductDetailsFromQuickViewModal(page: Page): Promise<ProductDetails> { |
| 41 | + return { |
| 42 | + name: await this.getTextContent(page, this.quickViewProductName), |
| 43 | + price: parseFloat((await this.getTextContent(page, this.quickViewProductPrice)).replace('€', '')), |
| 44 | + taxShippingDeliveryLabel: await this.getTextContent(page, this.quickViewTaxShippingDeliveryLabel), |
| 45 | + shortDescription: await this.getTextContent(page, this.quickViewShortDescription), |
| 46 | + coverImage: await this.getAttributeContent(page, this.quickViewCoverImage, 'src'), |
| 47 | + thumbImage: await this.getAttributeContent(page, this.quickViewThumbImage, 'srcset'), |
| 48 | + }; |
| 49 | + } |
| 50 | + |
| 51 | + /** |
| 52 | + * Returns the URL of the main image in the quickview |
| 53 | + * @param page {Page} Browser tab |
| 54 | + * @returns {Promise<string|null>} |
| 55 | + */ |
| 56 | + async getQuickViewImageMain(page: Page): Promise<string | null> { |
| 57 | + return this.getAttributeContent(page, this.quickViewCoverImage, 'data-full-size-image-url'); |
| 58 | + } |
| 59 | + |
| 60 | + /** |
| 61 | + * Select thumb image |
| 62 | + * @param page {Page} Browser tab |
| 63 | + * @param position {number} Position of the image |
| 64 | + * @returns {Promise<string>} |
| 65 | + */ |
| 66 | + async selectThumbImage(page: Page, position: number): Promise<string> { |
| 67 | + await page.locator(this.quickViewThumbImagePosition(position)).click(); |
| 68 | + await page.waitForTimeout(2000); |
| 69 | + |
| 70 | + return this.getAttributeContent(page, this.quickViewCoverImage, 'src'); |
| 71 | + } |
| 72 | + |
| 73 | + /** |
| 74 | + * Change product attribute |
| 75 | + * @param page {Page} Browser tab |
| 76 | + * @param attributes {ProductAttribute} The attributes data (size, color, dimension) |
| 77 | + * @returns {Promise<void>} |
| 78 | + */ |
| 79 | + async setAttribute(page: Page, attributes: ProductAttribute): Promise<void> { |
| 80 | + switch (attributes.name) { |
| 81 | + case 'color': |
| 82 | + await Promise.all([ |
| 83 | + await this.waitForSelectorAndClick(page, `${this.quickViewProductColor} input[title='${attributes.value}'] + span`), |
| 84 | + await page.waitForResponse((response) => response.url().includes('product&token=')), |
| 85 | + ]); |
| 86 | + break; |
| 87 | + case 'dimension': |
| 88 | + await Promise.all([ |
| 89 | + page.waitForResponse((response) => response.url().includes('product&token=')), |
| 90 | + this.selectByVisibleText(page, this.quickViewProductDimension, attributes.value), |
| 91 | + ]); |
| 92 | + break; |
| 93 | + case 'size': |
| 94 | + await Promise.all([ |
| 95 | + page.waitForResponse((response) => response.url().includes('product&token=')), |
| 96 | + this.selectByVisibleText(page, this.quickViewProductSize, attributes.value), |
| 97 | + ]); |
| 98 | + break; |
| 99 | + default: |
| 100 | + throw new Error(`${attributes.name} has not being in defined in "changeAttributes"`); |
| 101 | + } |
| 102 | + } |
| 103 | +} |
| 104 | + |
| 105 | +module.exports = new QuickViewModal(); |
0 commit comments