Skip to content

Commit 002ca30

Browse files
authored
Merge pull request #80 from Progi1984/pages/FO/classic/myAccount/myWishlists
Migrate `@pages/FO/{classic|hummingbird}/myAccount/myWishlists` from Core
2 parents 1f50fc6 + 1c3f641 commit 002ca30

File tree

9 files changed

+361
-0
lines changed

9 files changed

+361
-0
lines changed

src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,16 @@ export {default as foClassicLoginPage} from '@pages/FO/classic/login';
224224
export {default as foClassicModalBlockCartPage} from '@pages/FO/classic/modal/blockCart';
225225
export {default as foClassicModalQuickViewPage} from '@pages/FO/classic/modal/quickView';
226226
export {default as foClassicModalWishlistPage} from '@pages/FO/classic/modal/wishlist';
227+
export {default as foClassicMyWishlistsPage} from '@pages/FO/classic/myAccount/myWishlists';
228+
export {default as foClassicMyWishlistsViewPage} from '@pages/FO/classic/myAccount/myWishlists/view';
227229
export {default as foClassicProductPage} from '@pages/FO/classic/product';
228230
export {default as foClassicSearchResultsPage} from '@pages/FO/classic/searchResults';
229231
// Export Pages FO/Hummingbird
230232
export {default as foHummingbirdAboutUsPage} from '@pages/FO/hummingbird/aboutUs';
231233
export {default as foHummingbirdCategoryPage} from '@pages/FO/hummingbird/category';
232234
export {default as foHummingbirdLoginPage} from '@pages/FO/hummingbird/login';
233235
export {default as foHummingbirdModalQuickViewPage} from '@pages/FO/hummingbird/modal/quickView';
236+
export {default as foHummingbirdMyWishlistsPage} from '@pages/FO/hummingbird/myAccount/myWishlists';
234237
export {default as foHummingbirdSearchResultsPage} from '@pages/FO/hummingbird/searchResults';
235238

236239
// Export Modules
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import {FOBasePagePageInterface} from '@interfaces/FO';
2+
import type {Page} from '@playwright/test';
3+
4+
export interface FoMyWishlistsPageInterface extends FOBasePagePageInterface {
5+
readonly pageTitle: string;
6+
7+
countWishlists(page: Page): Promise<number>;
8+
getWishlistName(page: Page, nth: number): Promise<string>;
9+
goToWishlistPage(page: Page, nth: number): Promise<void>;
10+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import {FOBasePagePageInterface} from '@interfaces/FO';
2+
import type {Page} from '@playwright/test';
3+
4+
export interface FoMyWishlistsViewPageInterface extends FOBasePagePageInterface {
5+
readonly messageSuccessfullyRemoved: string;
6+
7+
countProducts(page: Page): Promise<number>;
8+
getProductAttribute(page: Page, nth: number, attribute: string): Promise<string|null>;
9+
getProductName(page: Page, nth: number): Promise<string>;
10+
getProductQuantity(page: Page, nth: number): Promise<number>;
11+
hasButtonAddToCartDisabled(page: Page, nth: number): Promise<boolean>;
12+
isProductLastItemsInStock(page: Page, nth: number): Promise<boolean>;
13+
isProductOutOfStock(page: Page, nth: number): Promise<boolean>;
14+
removeProduct(page: Page, nth: number): Promise<string>;
15+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import type {FoMyWishlistsPageInterface} from '@interfaces/FO/myAccount/myWishlists';
2+
3+
/* eslint-disable global-require, @typescript-eslint/no-var-requires */
4+
function requirePage(): FoMyWishlistsPageInterface {
5+
return require('@versions/develop/pages/FO/classic/myAccount/myWishlists').myWishlistsPage;
6+
}
7+
/* eslint-enable global-require, @typescript-eslint/no-var-requires */
8+
9+
export default requirePage();
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import type {FoMyWishlistsViewPageInterface} from '@interfaces/FO/myAccount/myWishlists/view';
2+
3+
/* eslint-disable global-require */
4+
function requirePage(): FoMyWishlistsViewPageInterface {
5+
return require('@versions/develop/pages/FO/classic/myAccount/myWishlists/view');
6+
}
7+
/* eslint-enable global-require */
8+
9+
export default requirePage();
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import type {FoMyWishlistsPageInterface} from '@interfaces/FO/myAccount/myWishlists';
2+
3+
/* eslint-disable global-require */
4+
function requirePage(): FoMyWishlistsPageInterface {
5+
return require('@versions/develop/pages/FO/hummingbird/myAccount/myWishlists');
6+
}
7+
/* eslint-enable global-require */
8+
9+
export default requirePage();
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import {type FoMyWishlistsPageInterface} from '@interfaces/FO/myAccount/myWishlists';
2+
import FOBasePage from '@pages/FO/FOBasePage';
3+
import type {Page} from 'playwright';
4+
5+
/**
6+
* My Wishlists page, contains functions that can be used on the page
7+
* @class
8+
* @extends FOBasePage
9+
*/
10+
class MyWishlistsPage extends FOBasePage implements FoMyWishlistsPageInterface {
11+
public readonly pageTitle: string;
12+
13+
private readonly headerTitle: string;
14+
15+
private readonly wishlistList: string;
16+
17+
private readonly wishlistListItem: string;
18+
19+
private readonly wishlistListItemNth: (nth: number) => string;
20+
21+
private readonly wishlistListItemNthLink: (nth: number) => string;
22+
23+
private readonly wishlistListItemNthTitle: (nth: number) => string;
24+
25+
/**
26+
* @constructs
27+
* Setting up texts and selectors to use on My Wishlists page
28+
*/
29+
constructor(theme: string = 'classic') {
30+
super(theme);
31+
32+
this.pageTitle = 'My wishlists';
33+
34+
// Selectors
35+
this.headerTitle = '#content-wrapper h1';
36+
this.wishlistList = '.wishlist-list';
37+
this.wishlistListItem = `${this.wishlistList} .wishlist-list-item`;
38+
this.wishlistListItemNth = (nth: number) => `${this.wishlistListItem}:nth-child(${nth})`;
39+
this.wishlistListItemNthLink = (nth: number) => `${this.wishlistListItemNth(nth)} a.wishlist-list-item-link`;
40+
this.wishlistListItemNthTitle = (nth: number) => `${this.wishlistListItemNth(nth)} p.wishlist-list-item-title`;
41+
}
42+
43+
/*
44+
Methods
45+
*/
46+
/**
47+
* @override
48+
* Get the page title from the main section
49+
* @param page {Page} Browser tab
50+
* @returns {Promise<string>}
51+
*/
52+
async getPageTitle(page: Page): Promise<string> {
53+
return this.getTextContent(page, this.headerTitle);
54+
}
55+
56+
/**
57+
* Returns the number of wishlists
58+
* @param page {Page} Browser tab
59+
* @returns {Promise<number>}
60+
*/
61+
async countWishlists(page: Page): Promise<number> {
62+
return page.locator(this.wishlistListItem).count();
63+
}
64+
65+
/**
66+
* Click and go to a specific wishlist
67+
* @param page {Page} Browser tab
68+
* @param nth {number} Nth of the wishlist
69+
* @returns {Promise<number>}
70+
*/
71+
async goToWishlistPage(page: Page, nth: number): Promise<void> {
72+
await page.locator(this.wishlistListItemNthLink(nth)).click();
73+
}
74+
75+
/**
76+
* Returns the name of a specific wishlist
77+
* @param page {Page} Browser tab
78+
* @param nth {number} Nth of the wishlist
79+
* @returns {Promise<string>}
80+
*/
81+
async getWishlistName(page: Page, nth: number): Promise<string> {
82+
const textContent = await this.getTextContent(page, this.wishlistListItemNthTitle(nth));
83+
84+
return textContent
85+
.substring(
86+
0,
87+
textContent.search(/\(/),
88+
)
89+
.trim();
90+
}
91+
}
92+
93+
const myWishlistsPage = new MyWishlistsPage();
94+
export {myWishlistsPage, MyWishlistsPage};
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
import {type FoMyWishlistsViewPageInterface} from '@interfaces/FO/myAccount/myWishlists/view';
2+
import FOBasePage from '@pages/FO/FOBasePage';
3+
4+
import type {Page} from 'playwright';
5+
6+
/**
7+
* My Wishlists View page, contains functions that can be used on the page
8+
* @class
9+
* @extends FOBasePage
10+
*/
11+
class WishlistPage extends FOBasePage implements FoMyWishlistsViewPageInterface {
12+
public readonly messageSuccessfullyRemoved: string;
13+
14+
private readonly headerTitle: string;
15+
16+
private readonly productList: string;
17+
18+
private readonly productListItem: string;
19+
20+
private readonly productListItemNth: (nth: number) => string;
21+
22+
private readonly productListItemNthTitle: (nth: number) => string;
23+
24+
private readonly productListItemNthCombinations: (nth: number) => string;
25+
26+
private readonly productListItemNthUnavailable: (nth: number) => string;
27+
28+
private readonly productListItemNthBtnAddToCart: (nth: number) => string;
29+
30+
private readonly productListItemNthBtnDelete: (nth: number) => string;
31+
32+
private readonly modalDelete: string;
33+
34+
private readonly modalDeleteBtnRemove: string;
35+
36+
private readonly toastText: string;
37+
38+
/**
39+
* @constructs
40+
* Setting up texts and selectors to use on My Wishlists View page
41+
*/
42+
constructor(theme: string = 'classic') {
43+
super(theme);
44+
45+
// Message
46+
this.messageSuccessfullyRemoved = 'Product successfully removed';
47+
48+
// Selectors
49+
this.headerTitle = '#content-wrapper h1';
50+
this.productList = '.wishlist-products-list';
51+
this.productListItem = `${this.productList} .wishlist-products-item`;
52+
this.productListItemNth = (nth: number) => `${this.productListItem}:nth-child(${nth})`;
53+
this.productListItemNthTitle = (nth: number) => `${this.productListItemNth(nth)} .wishlist-product-title`;
54+
this.productListItemNthCombinations = (nth: number) => `${this.productListItemNth(nth)} .wishlist-product-combinations-text`;
55+
this.productListItemNthUnavailable = (nth: number) => `${this.productListItemNth(nth)} .wishlist-product-availability`;
56+
this.productListItemNthBtnAddToCart = (nth: number) => `${this.productListItemNth(nth)} .wishlist-product-addtocart`;
57+
this.productListItemNthBtnDelete = (nth: number) => `${this.productListItemNth(nth)} .wishlist-button-add`;
58+
59+
// Modal "Delete"
60+
this.modalDelete = '.wishlist-delete .wishlist-modal.show';
61+
this.modalDeleteBtnRemove = `${this.modalDelete} div.modal-footer button.btn-primary`;
62+
63+
// Toast
64+
this.toastText = '.wishlist-toast .wishlist-toast-text';
65+
}
66+
67+
/*
68+
Methods
69+
*/
70+
/**
71+
* @override
72+
* Get the page title from the main section
73+
* @param page {Page} Browser tab
74+
* @returns {Promise<string>}
75+
*/
76+
async getPageTitle(page: Page): Promise<string> {
77+
return this.getTextContent(page, this.headerTitle);
78+
}
79+
80+
/**
81+
* Returns the number of product
82+
* @param page {Page} Browser tab
83+
* @returns {Promise<number>}
84+
*/
85+
async countProducts(page: Page): Promise<number> {
86+
return page.locator(this.productListItem).count();
87+
}
88+
89+
/**
90+
* Returns the name of a specific product
91+
* @param page {Page} Browser tab
92+
* @param nth {number} Nth of the wishlist
93+
* @returns {Promise<string>}
94+
*/
95+
async getProductName(page: Page, nth: number): Promise<string> {
96+
return this.getTextContent(page, this.productListItemNthTitle(nth));
97+
}
98+
99+
/**
100+
* @param page {Page} Browser tab
101+
* @param nth {number} Nth of the wishlist
102+
* @returns {Promise<string|null>}
103+
*/
104+
private async getProductCombinationValue(page: Page, nth: number, key: string): Promise<string|null> {
105+
const text = await this.getTextContent(page, this.productListItemNthCombinations(nth));
106+
107+
const regexResult: RegExpMatchArray[] = [...text.matchAll(/([A-Za-z]+)\s:\s([A-Za-z0-9]+)/g)];
108+
109+
// eslint-disable-next-line no-restricted-syntax
110+
for (const regexResultItem of regexResult) {
111+
if (regexResultItem[1].toLowerCase() === key) {
112+
return regexResultItem[2];
113+
}
114+
}
115+
116+
return null;
117+
}
118+
119+
/**
120+
* Returns the quantity of a specific product
121+
* @param page {Page} Browser tab
122+
* @param nth {number} Nth of the wishlist
123+
* @returns {Promise<string>}
124+
*/
125+
async getProductQuantity(page: Page, nth: number): Promise<number> {
126+
const result: string|null = await this.getProductCombinationValue(page, nth, 'quantity');
127+
128+
return result ? parseInt(result, 10) : 0;
129+
}
130+
131+
/**
132+
* Returns the value of an attribute of a specific product
133+
* @param page {Page} Browser tab
134+
* @param nth {number} Nth of the wishlist
135+
* @param attribute {string} Attribute name
136+
* @returns {Promise<string|null>}
137+
*/
138+
async getProductAttribute(page: Page, nth: number, attribute: string): Promise<string|null> {
139+
return this.getProductCombinationValue(page, nth, attribute.toLowerCase());
140+
}
141+
142+
/**
143+
* Returns if the product has a label Out-of-Stock
144+
* @param page {Page} Browser tab
145+
* @param nth {number} Nth of the wishlist
146+
* @returns {Promise<boolean>}
147+
*/
148+
async isProductOutOfStock(page: Page, nth: number): Promise<boolean> {
149+
return (await this.elementVisible(page, this.productListItemNthUnavailable(nth), 3000))
150+
&& (await this.getTextContent(page, this.productListItemNthUnavailable(nth)) === 'block Out-of-Stock');
151+
}
152+
153+
/**
154+
* Returns if the product has a label Last items in stock
155+
* @param page {Page} Browser tab
156+
* @param nth {number} Nth of the wishlist
157+
* @returns {Promise<boolean>}
158+
*/
159+
async isProductLastItemsInStock(page: Page, nth: number): Promise<boolean> {
160+
return (await this.elementVisible(page, this.productListItemNthUnavailable(nth), 3000))
161+
&& (await this.getTextContent(page, this.productListItemNthUnavailable(nth)) === 'warning Last items in stock');
162+
}
163+
164+
/**
165+
* Returns if the product has the button "Add to cart" disabled
166+
* @param page {Page} Browser tab
167+
* @param nth {number} Nth of the wishlist
168+
* @returns {Promise<boolean>}
169+
*/
170+
async hasButtonAddToCartDisabled(page: Page, nth: number): Promise<boolean> {
171+
return page.locator(this.productListItemNthBtnAddToCart(nth)).isDisabled();
172+
}
173+
174+
/**
175+
* Remove the nth Product of the wishlist
176+
* @param page {Page} Browser tab
177+
* @param nth {number} Nth of the wishlist
178+
* @returns {Promise<string>}
179+
*/
180+
async removeProduct(page: Page, nth: number): Promise<string> {
181+
await page.locator(this.productListItemNthBtnDelete(nth)).click();
182+
183+
// Wait for the modal
184+
await this.elementVisible(page, this.modalDelete, 3000);
185+
// Click on the first wishlist
186+
await page.locator(this.modalDeleteBtnRemove).click();
187+
// Wait for the toast
188+
await this.elementVisible(page, this.toastText, 3000);
189+
190+
return this.getTextContent(page, this.toastText);
191+
}
192+
}
193+
194+
module.exports = new WishlistPage();
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import {type FoMyWishlistsPageInterface} from '@interfaces/FO/myAccount/myWishlists';
2+
import {MyWishlistsPage as MyWishlistsPageVersion} from '@versions/develop/pages/FO/classic/myAccount/myWishlists';
3+
4+
/**
5+
* @class
6+
* @extends FOBasePage
7+
*/
8+
class MyWishlistsPage extends MyWishlistsPageVersion implements FoMyWishlistsPageInterface {
9+
/**
10+
* @constructs
11+
* Setting up texts and selectors to use
12+
*/
13+
constructor() {
14+
super('hummingbird');
15+
}
16+
}
17+
18+
module.exports = new MyWishlistsPage();

0 commit comments

Comments
 (0)