Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: create storefront wishlist page and wishlist tasks #295

Merged
merged 13 commits into from
Feb 11, 2025
Merged
7 changes: 7 additions & 0 deletions src/page-objects/StorefrontPages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { CheckoutOrderEdit } from './storefront/CheckoutOrderEdit';
import { AccountAddressCreate } from './storefront/AccountAddresssCreate';
import { PageNotFound } from './storefront/PageNotFound';
import { ContactForm } from './storefront/ContactForm';
import { Wishlist } from './storefront/Wishlist';

export interface StorefrontPageTypes {
StorefrontHome: Home;
Expand All @@ -47,6 +48,7 @@ export interface StorefrontPageTypes {
StorefrontCheckoutOrderEdit: CheckoutOrderEdit;
StorefrontPageNotFound: PageNotFound;
StorefrontContactForm: ContactForm;
StorefrontWishlist: Wishlist;
}

export const StorefrontPageObjects = {
Expand All @@ -72,6 +74,7 @@ export const StorefrontPageObjects = {
CheckoutOrderEdit,
PageNotFound,
ContactForm,
Wishlist,
}

export const test = base.extend<FixtureTypes>({
Expand Down Expand Up @@ -163,4 +166,8 @@ export const test = base.extend<FixtureTypes>({
StorefrontContactForm: async ({ StorefrontPage, InstanceMeta }, use) => {
await use(new ContactForm(StorefrontPage, InstanceMeta));
},

StorefrontWishlist: async ({ StorefrontPage }, use) => {
await use(new Wishlist(StorefrontPage));
},
});
18 changes: 17 additions & 1 deletion src/page-objects/storefront/Home.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ export class Home implements PageObject {
public readonly mainNavigationLink: Locator;
public readonly contactFormLink: Locator;

//wishlist
public readonly wishlistIcon: Locator;
public readonly wishlistBasket: Locator;

constructor(public readonly page: Page) {
this.accountMenuButton = page.getByLabel('Your account');
this.closeGuestSessionButton = page.locator('.account-aside-btn');
Expand Down Expand Up @@ -67,6 +71,10 @@ export class Home implements PageObject {
this.offcanvasBackdrop = page.locator('.offcanvas-backdrop');
this.mainNavigationLink = page.locator('.main-navigation-link-text');
this.contactFormLink = this.page.getByRole('listitem').getByTitle('Contact form', { exact: true });

//wishlist
this.wishlistIcon = page.locator('.header-wishlist-icon');
this.wishlistBasket = page.locator('.header-wishlist-badge');
}

async getMenuItemByCategoryName(categoryName: string): Promise<Record<string, Locator>> {
Expand Down Expand Up @@ -107,6 +115,8 @@ export class Home implements PageObject {
const productListingPrice = listingItem.locator('.list-price-price');
const productListingPricePercentage = listingItem.locator('.list-price-percentage');
const productListingPriceBadge = listingItem.locator('.badge-discount');
const wishlistNotAddedIcon = listingItem.locator('.product-wishlist-not-added');
const wishlistAddedIcon = listingItem.locator('.product-wishlist-added');

return {
productImage: productImage,
Expand All @@ -121,6 +131,8 @@ export class Home implements PageObject {
productListingPrice: productListingPrice,
productListingPricePercentage: productListingPricePercentage,
productListingPriceBadge: productListingPriceBadge,
wishlistNotAddedIcon: wishlistNotAddedIcon,
wishlistAddedIcon: wishlistAddedIcon,
};
}

Expand All @@ -140,6 +152,8 @@ export class Home implements PageObject {
const productListingPrice = listingItem.locator('.list-price-price');
const productListingPricePercentage = listingItem.locator('.list-price-percentage');
const productListingPriceBadge = listingItem.locator('.badge-discount');
const wishlistNotAddedIcon = listingItem.locator('.product-wishlist-not-added');
const wishlistAddedIcon = listingItem.locator('.product-wishlist-added');

return {
productImage: productImage,
Expand All @@ -154,10 +168,12 @@ export class Home implements PageObject {
productListingPrice: productListingPrice,
productListingPricePercentage: productListingPricePercentage,
productListingPriceBadge: productListingPriceBadge,
wishlistNotAddedIcon: wishlistNotAddedIcon,
wishlistAddedIcon: wishlistAddedIcon,
};
}

url() {
return './';
}
}
}
4 changes: 4 additions & 0 deletions src/page-objects/storefront/OffCanvasCart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ export class OffCanvasCart implements PageObject {
const productUnitPriceValue = lineItem.locator('.line-item-unit-price-value');
const productTotalPriceValue = lineItem.locator('.line-item-total-price-value');
const removeButton = lineItem.locator('.line-item-remove-button');
const wishlistAddedButton = lineItem.locator('.product-wishlist-added');
const wishlistNotAddedButton = lineItem.locator('.product-wishlist-not-added');

return {
lineItemImage: lineItemImage,
Expand All @@ -56,6 +58,8 @@ export class OffCanvasCart implements PageObject {
productUnitPriceValue: productUnitPriceValue,
productTotalPriceValue: productTotalPriceValue,
removeButton: removeButton,
wishlistAddedButton: wishlistAddedButton,
wishlistNotAddedButton: wishlistNotAddedButton,
}
}
}
6 changes: 6 additions & 0 deletions src/page-objects/storefront/ProductDetail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ export class ProductDetail implements PageObject {
public readonly offCanvasSummaryTotalPrice: Locator;
public readonly offCanvas: Locator;

public readonly wishlistAddedButton: Locator;
public readonly wishlistNotAddedButton: Locator;

constructor(public readonly page: Page) {

this.addToCartButton = page.getByRole('button', { name: 'Add to shopping cart' });
Expand All @@ -37,6 +40,9 @@ export class ProductDetail implements PageObject {
this.offCanvasCartGoToCheckoutButton = page.getByRole('link', { name: 'Go to checkout' });
this.offCanvasLineItemImages = page.locator('.line-item-img-link');
this.offCanvasSummaryTotalPrice = page.locator('.offcanvas-summary').locator('dt:has-text("Subtotal") + dd');

this.wishlistAddedButton = page.locator('.product-wishlist-added');
this.wishlistNotAddedButton = page.locator('.product-wishlist-not-added');
}

url(productData: Product) {
Expand Down
31 changes: 31 additions & 0 deletions src/page-objects/storefront/Wishlist.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { Page, Locator } from '@playwright/test';
import type { PageObject } from '../../types/PageObject';
import { Home } from './Home';

export class Wishlist extends Home implements PageObject {
public readonly wishListHeader: Locator;
public readonly removeAlert: Locator;
public readonly emptyListing: Locator;

constructor(public readonly page: Page) {
super(page);
this.wishListHeader = page.locator('.wishlist-headline');
this.removeAlert = page.locator('.alert-success');
this.emptyListing = page.locator('.wishlist-listing-empty');
}

async getListingItemByProductName(productListingName: string): Promise<Record<string, Locator>> {
const baseItems = await super.getListingItemByProductName(productListingName);
const listingItem = this.page.getByRole('listitem').filter({ has: this.page.getByText(productListingName) });
const removeFromWishlistButton = listingItem.locator('.icon-wishlist-remove');

return {
...baseItems,
removeFromWishlistButton: removeFromWishlistButton,
};
}

url() {
return `wishlist`;
}
}
6 changes: 5 additions & 1 deletion src/tasks/shop-customer-tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { OpenSearchSuggestPage } from './shop-customer/Search/OpenSearchSuggestP
import { SearchForTerm } from './shop-customer/Search/SearchForTerm';

import { ValidateAccessibility } from './shop-customer/Accessibility/ValidateAccessibility';
import { AddProductToCartFromWishlist, AddProductToWishlist, RemoveProductFromWishlist } from './shop-customer/Wishlist/WishlistActions';

export const test = mergeTests(
Login,
Expand All @@ -47,5 +48,8 @@ export const test = mergeTests(
OpenSearchResultPage,
OpenSearchSuggestPage,
SearchForTerm,
ValidateAccessibility
ValidateAccessibility,
RemoveProductFromWishlist,
AddProductToCartFromWishlist,
AddProductToWishlist,
);
51 changes: 51 additions & 0 deletions src/tasks/shop-customer/Wishlist/WishlistActions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { test as base } from '@playwright/test';
import type { Task } from '../../../types/Task';
import type { FixtureTypes } from '../../../types/FixtureTypes';
import { Product } from '../../../types/ShopwareTypes';

export const AddProductToCartFromWishlist = base.extend<{ AddProductToCartFromWishlist: Task }, FixtureTypes>({
AddProductToCartFromWishlist: async ({ ShopCustomer, StorefrontWishlist, StorefrontOffCanvasCart }, use) => {
const task = (ProductData: Product) => {
return async function AddProductToCartFromWishlist() {
const listedItem = await StorefrontWishlist.getListingItemByProductName(ProductData.name);
await listedItem.productAddToShoppingCart.click();
await StorefrontWishlist.page.waitForResponse((response) => response.url().includes(`checkout/offcanvas`) && response.ok());
await ShopCustomer.expects(StorefrontOffCanvasCart.itemCount).toBeVisible();
const offcanvasItem = await StorefrontOffCanvasCart.getLineItemByProductNumber(ProductData.productNumber);
const itemsPrice = await offcanvasItem.productTotalPriceValue.innerText();
const expectedPrice = await listedItem.productPrice.innerText();
ShopCustomer.expects(itemsPrice).toBe(expectedPrice);
}
};

await use(task);
},
});

export const RemoveProductFromWishlist = base.extend<{ RemoveProductFromWishlist: Task }, FixtureTypes>({
RemoveProductFromWishlist: async ({ StorefrontHome , StorefrontWishlist}, use) => {
const task = (ProductData: Product) => {
return async function RemoveProductFromWishlist() {
const listedItem = await StorefrontHome.getListingItemByProductName(ProductData.name);
await listedItem.wishlistAddedIcon.click();
await StorefrontWishlist.page.waitForResponse((response) => response.url().includes(`remove/${ProductData.id}`) && response.ok());
}
};

await use(task);
},
});

export const AddProductToWishlist = base.extend<{ AddProductToWishlist: Task }, FixtureTypes>({
AddProductToWishlist: async ({ StorefrontHome , ShopCustomer}, use) => {
const task = (ProductData: Product) => {
return async function AddProductToWishlist() {
const listedItem = await StorefrontHome.getListingItemByProductName(ProductData.name);
await listedItem.wishlistNotAddedIcon.click();
await ShopCustomer.expects(listedItem.wishlistAddedIcon).toBeVisible();
}
};

await use(task);
},
});
Loading