From 10216205bb5006df8f78bb2df89b7224c1b972ed Mon Sep 17 00:00:00 2001 From: Orkun Cavli Date: Tue, 28 Jan 2025 17:06:01 +0100 Subject: [PATCH 1/9] fix: add wishlist page and related tasks --- src/page-objects/StorefrontPages.ts | 7 +++++++ src/page-objects/storefront/Home.ts | 14 +++++++++++++- src/tasks/shop-customer-tasks.ts | 6 +++++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/page-objects/StorefrontPages.ts b/src/page-objects/StorefrontPages.ts index 2a9ed20..6fb31c5 100644 --- a/src/page-objects/StorefrontPages.ts +++ b/src/page-objects/StorefrontPages.ts @@ -21,6 +21,7 @@ import { SearchSuggest } from './storefront/SearchSuggest'; import { CustomRegister } from './storefront/CustomRegister'; import { CheckoutOrderEdit } from './storefront/CheckoutOrderEdit'; import { AccountAddressCreate } from './storefront/AccountAddresssCreate'; +import { Wishlist } from './storefront/Wishlist'; export interface StorefrontPageTypes { StorefrontHome: Home; @@ -43,6 +44,7 @@ export interface StorefrontPageTypes { StorefrontSearchSuggest: SearchSuggest; StorefrontCustomRegister: CustomRegister; StorefrontCheckoutOrderEdit: CheckoutOrderEdit; + StorefrontWishlist: Wishlist; } export const StorefrontPageObjects = { @@ -66,6 +68,7 @@ export const StorefrontPageObjects = { SearchSuggest, CustomRegister, CheckoutOrderEdit, + Wishlist, } export const test = base.extend({ @@ -150,4 +153,8 @@ export const test = base.extend({ StorefrontCheckoutOrderEdit: async ({ StorefrontPage }, use) => { await use(new CheckoutOrderEdit(StorefrontPage)); }, + + StorefrontWishlist: async ({ StorefrontPage }, use) => { + await use(new Wishlist(StorefrontPage)); + }, }); diff --git a/src/page-objects/storefront/Home.ts b/src/page-objects/storefront/Home.ts index ea862f8..d7949d4 100644 --- a/src/page-objects/storefront/Home.ts +++ b/src/page-objects/storefront/Home.ts @@ -28,6 +28,10 @@ export class Home implements PageObject { public readonly consentCookieBannerContainer: Locator; public readonly offcanvasBackdrop: 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'); @@ -63,6 +67,10 @@ export class Home implements PageObject { exact: true, }); this.offcanvasBackdrop = page.locator('.offcanvas-backdrop'); + + //wishlist + this.wishlistIcon = page.locator('.header-wishlist-icon'); + this.wishlistBasket = page.locator('.header-wishlist-badge'); } async getMenuItemByCategoryName(categoryName: string): Promise> { @@ -97,6 +105,8 @@ export class Home implements PageObject { const productAddToShoppingCart = listingItem.getByRole('button', { name: 'Add to shopping cart', }); + const wishlistNotAddedIcon = listingItem.locator('.product-wishlist-not-added'); + const wishlistAddedIcon = listingItem.locator('.product-wishlist-added'); return { productImage: productImage, @@ -108,10 +118,12 @@ export class Home implements PageObject { productPrice: productPrice, productName: productName, productAddToShoppingCart: productAddToShoppingCart, + wishlistNotAddedIcon: wishlistNotAddedIcon, + wishlistAddedIcon: wishlistAddedIcon, }; } url() { return './'; } -} +} \ No newline at end of file diff --git a/src/tasks/shop-customer-tasks.ts b/src/tasks/shop-customer-tasks.ts index 9607263..97d4178 100644 --- a/src/tasks/shop-customer-tasks.ts +++ b/src/tasks/shop-customer-tasks.ts @@ -24,6 +24,8 @@ import { OpenSearchSuggestPage } from './shop-customer/Search/OpenSearchSuggestP import { SearchForTerm } from './shop-customer/Search/SearchForTerm'; import { ValidateAccessibility } from './shop-customer/Accessibility/ValidateAccessibility'; +import { AddProductToWishlist } from './shop-customer/Wishlist/addProductToWishlist'; +import { RemoveProductFromWishlist } from './shop-customer/Wishlist/RemoveProductFromWishlist'; export const test = mergeTests( Login, @@ -45,5 +47,7 @@ export const test = mergeTests( OpenSearchResultPage, OpenSearchSuggestPage, SearchForTerm, - ValidateAccessibility + ValidateAccessibility, + AddProductToWishlist, + RemoveProductFromWishlist ); From 0ccc4e75b7364da2c3fb87dae33b1c2463eca7c0 Mon Sep 17 00:00:00 2001 From: Orkun Cavli Date: Thu, 30 Jan 2025 13:53:16 +0100 Subject: [PATCH 2/9] feat: add wishlist page and related tasks --- src/page-objects/storefront/Home.ts | 2 ++ src/page-objects/storefront/Wishlist.ts | 34 +++++++++++++++++++ src/tasks/shop-customer-tasks.ts | 8 +++-- .../Wishlist/AddProductToCartFromWishlist.ts | 20 +++++++++++ .../Wishlist/AddProductToWishlist.ts | 18 ++++++++++ .../Wishlist/RemoveProductFromWishlist.ts | 18 ++++++++++ 6 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 src/page-objects/storefront/Wishlist.ts create mode 100644 src/tasks/shop-customer/Wishlist/AddProductToCartFromWishlist.ts create mode 100644 src/tasks/shop-customer/Wishlist/AddProductToWishlist.ts create mode 100644 src/tasks/shop-customer/Wishlist/RemoveProductFromWishlist.ts diff --git a/src/page-objects/storefront/Home.ts b/src/page-objects/storefront/Home.ts index d7949d4..f4538aa 100644 --- a/src/page-objects/storefront/Home.ts +++ b/src/page-objects/storefront/Home.ts @@ -107,6 +107,7 @@ export class Home implements PageObject { }); const wishlistNotAddedIcon = listingItem.locator('.product-wishlist-not-added'); const wishlistAddedIcon = listingItem.locator('.product-wishlist-added'); + const removeProductFromWishlist = listingItem.locator('.icon-wishlist-remove'); return { productImage: productImage, @@ -120,6 +121,7 @@ export class Home implements PageObject { productAddToShoppingCart: productAddToShoppingCart, wishlistNotAddedIcon: wishlistNotAddedIcon, wishlistAddedIcon: wishlistAddedIcon, + removeFromWishlistXButton: removeProductFromWishlist, }; } diff --git a/src/page-objects/storefront/Wishlist.ts b/src/page-objects/storefront/Wishlist.ts new file mode 100644 index 0000000..41e402b --- /dev/null +++ b/src/page-objects/storefront/Wishlist.ts @@ -0,0 +1,34 @@ +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; + + public readonly offCanvas: Locator; + public readonly offCanvasCartTitle: Locator; + public readonly offCanvasCart: Locator; + public readonly offCanvasCartGoToCheckoutButton: Locator; + public readonly offCanvasLineItemImages: Locator; + public readonly offCanvasSummaryTotalPrice: Locator; + + constructor(public readonly page: Page) { + super(page); + this.wishListHeader = page.locator('.wishlist-headline'); + this.removeAlert = page.locator('.alert-content'); + this.emptyListing = page.locator('.wishlist-listing-empty'); + + this.offCanvas = page.locator('offcanvas-body'); + this.offCanvasCartTitle = page.getByText('Shopping cart', { exact: true }); + this.offCanvasCart = page.getByRole('dialog'); + 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'); + } + + url() { + return `wishlist`; + } +} \ No newline at end of file diff --git a/src/tasks/shop-customer-tasks.ts b/src/tasks/shop-customer-tasks.ts index 97d4178..f390f5c 100644 --- a/src/tasks/shop-customer-tasks.ts +++ b/src/tasks/shop-customer-tasks.ts @@ -24,8 +24,9 @@ import { OpenSearchSuggestPage } from './shop-customer/Search/OpenSearchSuggestP import { SearchForTerm } from './shop-customer/Search/SearchForTerm'; import { ValidateAccessibility } from './shop-customer/Accessibility/ValidateAccessibility'; -import { AddProductToWishlist } from './shop-customer/Wishlist/addProductToWishlist'; import { RemoveProductFromWishlist } from './shop-customer/Wishlist/RemoveProductFromWishlist'; +import { AddProductToCartFromWishlist } from './shop-customer/Wishlist/AddProductToCartFromWishlist'; +import { AddProductToWishlist } from './shop-customer/Wishlist/AddProductToWishlist'; export const test = mergeTests( Login, @@ -48,6 +49,7 @@ export const test = mergeTests( OpenSearchSuggestPage, SearchForTerm, ValidateAccessibility, - AddProductToWishlist, - RemoveProductFromWishlist + RemoveProductFromWishlist, + AddProductToCartFromWishlist, + AddProductToWishlist ); diff --git a/src/tasks/shop-customer/Wishlist/AddProductToCartFromWishlist.ts b/src/tasks/shop-customer/Wishlist/AddProductToCartFromWishlist.ts new file mode 100644 index 0000000..4e11c3f --- /dev/null +++ b/src/tasks/shop-customer/Wishlist/AddProductToCartFromWishlist.ts @@ -0,0 +1,20 @@ +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 }, use) => { + const task = (ProductData: Product) => { + return async function AddProductToCart() { + const listedItem = await StorefrontWishlist.getListingItemByProductId(ProductData.id); + await listedItem.productAddToShoppingCart.click(); + await StorefrontWishlist.page.waitForResponse((response) => response.url().includes(`checkout/offcanvas`) && response.ok()); + await ShopCustomer.expects(StorefrontWishlist.offCanvasCartTitle).toBeVisible(); + await ShopCustomer.expects(StorefrontWishlist.offCanvasCart.getByText(ProductData.name)).toBeVisible(); + } + }; + + await use(task); + }, +}); \ No newline at end of file diff --git a/src/tasks/shop-customer/Wishlist/AddProductToWishlist.ts b/src/tasks/shop-customer/Wishlist/AddProductToWishlist.ts new file mode 100644 index 0000000..a9ca593 --- /dev/null +++ b/src/tasks/shop-customer/Wishlist/AddProductToWishlist.ts @@ -0,0 +1,18 @@ +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 AddProductToWishlist = base.extend<{ AddProductToWishlist: Task }, FixtureTypes>({ + AddProductToWishlist: async ({ StorefrontHome , StorefrontWishlist, ShopCustomer}, use) => { + const task = (ProductData: Product) => { + return async function AddProductToWishlist() { + const listedItem = await StorefrontHome.getListingItemByProductId(ProductData.id); + await listedItem.wishlistNotAddedIcon.click(); + await ShopCustomer.expects(listedItem.wishlistAddedIcon).toBeVisible(); + } + }; + + await use(task); + }, +}); \ No newline at end of file diff --git a/src/tasks/shop-customer/Wishlist/RemoveProductFromWishlist.ts b/src/tasks/shop-customer/Wishlist/RemoveProductFromWishlist.ts new file mode 100644 index 0000000..dcc8826 --- /dev/null +++ b/src/tasks/shop-customer/Wishlist/RemoveProductFromWishlist.ts @@ -0,0 +1,18 @@ +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 RemoveProductFromWishlist = base.extend<{ RemoveProductFromWishlist: Task }, FixtureTypes>({ + RemoveProductFromWishlist: async ({ StorefrontHome , StorefrontWishlist}, use) => { + const task = (ProductData: Product) => { + return async function AddProductToWishlist() { + const listedItem = await StorefrontHome.getListingItemByProductId(ProductData.id); + await listedItem.wishlistAddedIcon.click(); + await StorefrontWishlist.page.waitForResponse((response) => response.url().includes(`remove/${ProductData.id}`) && response.ok()); + } + }; + + await use(task); + }, +}); \ No newline at end of file From ee0719093334108e911514872f3d3808fb7c4b82 Mon Sep 17 00:00:00 2001 From: Orkun Cavli Date: Tue, 4 Feb 2025 08:06:28 +0100 Subject: [PATCH 3/9] feat: rebase to trunk --- src/page-objects/StorefrontPages.ts | 8 ++- src/page-objects/storefront/AccountLogin.ts | 13 +++++ src/page-objects/storefront/ContactForm.ts | 57 +++++++++++++++++++ src/page-objects/storefront/Home.ts | 3 + src/services/TestDataService.ts | 45 ++++++++++++++- src/types/ShopwareTypes.ts | 4 ++ tests/TestDataService/TestDataService.spec.ts | 9 +++ 7 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 src/page-objects/storefront/ContactForm.ts diff --git a/src/page-objects/StorefrontPages.ts b/src/page-objects/StorefrontPages.ts index 6fb31c5..6a00b1e 100644 --- a/src/page-objects/StorefrontPages.ts +++ b/src/page-objects/StorefrontPages.ts @@ -22,6 +22,7 @@ import { CustomRegister } from './storefront/CustomRegister'; import { CheckoutOrderEdit } from './storefront/CheckoutOrderEdit'; import { AccountAddressCreate } from './storefront/AccountAddresssCreate'; import { Wishlist } from './storefront/Wishlist'; +import { ContactForm } from './storefront/ContactForm'; export interface StorefrontPageTypes { StorefrontHome: Home; @@ -45,6 +46,7 @@ export interface StorefrontPageTypes { StorefrontCustomRegister: CustomRegister; StorefrontCheckoutOrderEdit: CheckoutOrderEdit; StorefrontWishlist: Wishlist; + StorefrontContactForm: ContactForm; } export const StorefrontPageObjects = { @@ -69,6 +71,7 @@ export const StorefrontPageObjects = { CustomRegister, CheckoutOrderEdit, Wishlist, + ContactForm, } export const test = base.extend({ @@ -147,7 +150,6 @@ export const test = base.extend({ StorefrontCustomRegister: async ({ StorefrontPage }, use) => { await use(new CustomRegister(StorefrontPage)); - }, StorefrontCheckoutOrderEdit: async ({ StorefrontPage }, use) => { @@ -157,4 +159,8 @@ export const test = base.extend({ StorefrontWishlist: async ({ StorefrontPage }, use) => { await use(new Wishlist(StorefrontPage)); }, + + StorefrontContactForm: async ({ StorefrontPage }, use) => { + await use(new ContactForm(StorefrontPage)); + }, }); diff --git a/src/page-objects/storefront/AccountLogin.ts b/src/page-objects/storefront/AccountLogin.ts index ab92621..f5d5df0 100644 --- a/src/page-objects/storefront/AccountLogin.ts +++ b/src/page-objects/storefront/AccountLogin.ts @@ -29,6 +29,13 @@ export class AccountLogin implements PageObject { public readonly postalCodeInput: Locator; public readonly registerButton: Locator; + // Inputs for reCaptcha + public readonly greCaptchaV2Container: Locator; + public readonly greCaptchaV2Input: Locator; + public readonly greCaptchaV3Input: Locator; + public readonly greCaptchaProtectionInformation: Locator; + public readonly greCaptchaBadge: Locator; + constructor(public readonly page: Page) { this.emailInput = page.getByLabel('Your email address'); this.passwordInput = page.getByLabel('Your password'); @@ -56,6 +63,12 @@ export class AccountLogin implements PageObject { this.logoutLink = page.getByRole('link', { name: 'Log out'}); this.successAlert = page.getByText('Successfully logged out.'); this.passwordUpdatedAlert = page.getByText('Your password has been updated.'); + + this.greCaptchaV2Container = this.page.locator('.grecaptcha-v2-container'); + this.greCaptchaV2Input = this.page.locator('.grecaptcha-v2-input'); + this.greCaptchaV3Input = this.page.locator('.grecaptcha_v3-input'); + this.greCaptchaProtectionInformation = this.page.locator('.grecaptcha-protection-information'); + this.greCaptchaBadge = this.page.locator('.grecaptcha-badge'); } url() { diff --git a/src/page-objects/storefront/ContactForm.ts b/src/page-objects/storefront/ContactForm.ts new file mode 100644 index 0000000..f6a19fe --- /dev/null +++ b/src/page-objects/storefront/ContactForm.ts @@ -0,0 +1,57 @@ +import type { Page, Locator } from '@playwright/test'; +import type { PageObject } from '../../types/PageObject'; +import { Home } from './Home'; + +export class ContactForm extends Home implements PageObject { + public readonly contactModal: Locator; + public readonly contactSuccessModal: Locator; + public readonly salutationSelect: Locator; + public readonly firstNameInput: Locator; + public readonly lastNameInput: Locator; + public readonly emailInput: Locator; + public readonly phoneInput: Locator; + public readonly subjectInput: Locator; + public readonly commentInput: Locator; + public readonly privacyPolicyCheckbox: Locator; + public readonly submitButton: Locator; + public readonly contactSuccessMessage: Locator; + public readonly cardTitle: Locator; + /** + * Captcha locators + */ + public readonly basicCaptcha: Locator; + public readonly basicCaptchaImage: Locator; + public readonly basicCaptchaRefreshButton: Locator; + public readonly basicCaptchaInput: Locator; + public readonly greCaptchaV2Container: Locator; + public readonly greCaptchaV2Input: Locator; + public readonly greCaptchaProtectionInformation: Locator; + + constructor(public readonly page: Page) { + super(page); + this.contactModal = this.page.getByRole('dialog').filter({ has: this.page.getByLabel('Contact', { exact: true }) }); + this.salutationSelect = this.contactModal.getByLabel('Salutation*'); + this.firstNameInput = this.contactModal.getByLabel('First name*'); + this.lastNameInput = this.contactModal.getByLabel('Last name*'); + this.emailInput = this.contactModal.getByLabel('Your email address*'); + this.phoneInput = this.contactModal.getByLabel('Phone*'); + this.subjectInput = this.contactModal.getByLabel('Subject*'); + this.commentInput = this.contactModal.getByLabel('Comment*'); + this.privacyPolicyCheckbox = this.contactModal.getByRole('checkbox', { name: 'By selecting continue you confirm that you have read and agree to our' }); + this.submitButton = this.contactModal.getByRole('button', { name: 'Submit' }); + this.contactSuccessModal = this.page.getByRole('dialog').filter({ has: this.page.locator('.confirm-message') }); + this.contactSuccessMessage = this.contactSuccessModal.locator('.confirm-message'); + this.cardTitle = this.contactModal.locator('.card-title'); + this.basicCaptcha = this.contactModal.locator('.basic-captcha'); + this.basicCaptchaImage = this.basicCaptcha.locator('img'); + this.basicCaptchaRefreshButton = this.basicCaptcha.locator('.basic-captcha-content-refresh-icon'); + this.basicCaptchaInput = this.basicCaptcha.locator('input[name="shopware_basic_captcha_confirm"]'); + this.greCaptchaV2Container = this.contactModal.locator('.grecaptcha-v2-container'); + this.greCaptchaV2Input = this.contactModal.locator('.grecaptcha-v2-input'); + this.greCaptchaProtectionInformation = this.contactModal.locator('.grecaptcha-protection-information'); +} + + url() { + return new Error('Function not implemented, because it is a modal page object').message; + } +} diff --git a/src/page-objects/storefront/Home.ts b/src/page-objects/storefront/Home.ts index f4538aa..dcff327 100644 --- a/src/page-objects/storefront/Home.ts +++ b/src/page-objects/storefront/Home.ts @@ -18,6 +18,8 @@ export class Home implements PageObject { public readonly consentDialog: Locator; public readonly consentDialogTechnicallyRequiredCheckbox: Locator; public readonly consentDialogStatisticsCheckbox: Locator; + public readonly contactFormLink: Locator; + /** * @deprecated Use 'consentDialogMarketingCheckbox' instead */ @@ -71,6 +73,7 @@ export class Home implements PageObject { //wishlist this.wishlistIcon = page.locator('.header-wishlist-icon'); this.wishlistBasket = page.locator('.header-wishlist-badge'); + this.contactFormLink = this.page.getByRole('listitem').getByTitle('Contact form', { exact: true }); } async getMenuItemByCategoryName(categoryName: string): Promise> { diff --git a/src/services/TestDataService.ts b/src/services/TestDataService.ts index f6b0baf..e418a8b 100644 --- a/src/services/TestDataService.ts +++ b/src/services/TestDataService.ts @@ -33,6 +33,7 @@ import type { CustomFieldSet, CustomField, Tax, + ProductCrossSelling, } from '../types/ShopwareTypes'; import { expect } from '@playwright/test'; @@ -100,7 +101,7 @@ export class TestDataService { * * @private */ - private highPriorityEntities = ['order', 'product', 'landing_page', 'shipping_method', 'sales_channel_domain', 'sales_channel_currency', 'sales_channel_country', 'customer']; + private highPriorityEntities = ['order', 'product_cross_selling' , 'product', 'landing_page', 'shipping_method', 'sales_channel_domain', 'sales_channel_currency', 'sales_channel_country', 'customer']; /** * A registry of all created records. @@ -475,6 +476,27 @@ export class TestDataService { return propertyGroup; } + /** + * Creates a basic product cross-selling entity without products. + * + * @param productId - The uuid of the product to which the pproduct cross-selling should be assigned. + * @param overrides - Specific data overrides that will be applied to the property group data struct. + */ + async createProductCrossSelling(productId: string, overrides: Partial = {}): Promise { + const crossSellingStruct = this.getBasicCrossSellingStruct(productId, overrides); + + const response = await this.AdminApiClient.post('product-cross-selling?_response=detail', { + data: crossSellingStruct, + }); + expect(response.ok()).toBeTruthy(); + + const { data: productCrossSelling } = (await response.json()) as { data: ProductCrossSelling }; + + this.addCreatedRecord('product_cross_selling', productCrossSelling.id); + + return productCrossSelling; + } + /** * Creates a new tag which can be assigned to other entities. * @@ -1640,7 +1662,6 @@ export class TestDataService { deleteOperations[`delete-${record.resource}`].payload.push(record.payload); } }); - await this.AdminApiClient.post('_action/sync', { data: priorityDeleteOperations, }); @@ -2516,4 +2537,24 @@ export class TestDataService { return Object.assign({}, basicTaxStruct, overrides); } + + getBasicCrossSellingStruct(productId: string, overrides: Partial = {}) { + + const { id: productCrossSellingId, uuid: productCrossSellingUuid } = this.IdProvider.getIdPair(); + const productCrossSellingName = `${this.namePrefix}ProductCrossSelling-${productCrossSellingId}${this.nameSuffix}`; + + const defaultCrossSelling = { + id: productCrossSellingUuid, + productId: productId, + name: productCrossSellingName, + type: 'product_list', + position: 1, + active: true, + productStreamId: null, + sortingType: 'name', + limit: 10, + sortBy: 'name', + } + return Object.assign({}, defaultCrossSelling, overrides); + } } diff --git a/src/types/ShopwareTypes.ts b/src/types/ShopwareTypes.ts index 35b3e83..9a093aa 100644 --- a/src/types/ShopwareTypes.ts +++ b/src/types/ShopwareTypes.ts @@ -200,6 +200,10 @@ export type SalesChannelAnalytics = components['schemas']['SalesChannelAnalytics id: string, }; +export type ProductCrossSelling = components['schemas']['ProductCrossSelling'] & { + id: string, +}; + export interface RegistrationData { isCommercial: boolean; isGuest: boolean; diff --git a/tests/TestDataService/TestDataService.spec.ts b/tests/TestDataService/TestDataService.spec.ts index f2b88d9..3330db0 100644 --- a/tests/TestDataService/TestDataService.spec.ts +++ b/tests/TestDataService/TestDataService.spec.ts @@ -15,6 +15,7 @@ import { APIResponse, SalesChannelAnalytics, Tax, + ProductCrossSelling, } from '../../src'; test('Data Service', async ({ @@ -93,6 +94,10 @@ test('Data Service', async ({ const taxRate21 = await TestDataService.createTaxRate({ taxRate: 21.0 }); expect(taxRate21.taxRate).toEqual(21.0); + const crossSellingProduct = await TestDataService.createBasicProduct(); + const productCrossSelling = await TestDataService.createProductCrossSelling(crossSellingProduct.id, { name: 'Custom cross selling' }); + expect(productCrossSelling.name).toEqual('Custom cross selling'); + // Test data clean-up with deactivated cleansing process TestDataService.setCleanUp(false); const cleanUpFalseResponse = await TestDataService.cleanUp(); @@ -150,6 +155,10 @@ test('Data Service', async ({ const { data: databaseTaxRate21 } = (await taxRate21Response.json()) as { data: Tax }; expect(databaseTaxRate21.id).toBe(taxRate21.id); + const crossSellingProductResponse = await AdminApiContext.get(`./product-cross-selling/${productCrossSelling.id}?_response=detail`); + const { data: databaseCrossSellingProduct } = (await crossSellingProductResponse.json()) as { data: ProductCrossSelling }; + expect(databaseCrossSellingProduct.id).toBe(productCrossSelling.id); + // Test data clean-up with activated cleansing process TestDataService.setCleanUp(true); const cleanUpDeleteOperationsResponse = await TestDataService.cleanUp() as APIResponse; From fb67c27a219c4d987b1eae581239c252afe893b8 Mon Sep 17 00:00:00 2001 From: Orkun Cavli Date: Tue, 4 Feb 2025 08:18:07 +0100 Subject: [PATCH 4/9] feat: rebase to trunk fix conflict on testdataservice --- src/page-objects/StorefrontPages.ts | 1 + src/page-objects/storefront/AccountLogin.ts | 13 ----- src/page-objects/storefront/ContactForm.ts | 57 ------------------- src/page-objects/storefront/Home.ts | 2 - src/services/TestDataService.ts | 47 ++------------- src/types/ShopwareTypes.ts | 4 -- tests/TestDataService/TestDataService.spec.ts | 9 --- 7 files changed, 6 insertions(+), 127 deletions(-) delete mode 100644 src/page-objects/storefront/ContactForm.ts diff --git a/src/page-objects/StorefrontPages.ts b/src/page-objects/StorefrontPages.ts index 6a00b1e..0907779 100644 --- a/src/page-objects/StorefrontPages.ts +++ b/src/page-objects/StorefrontPages.ts @@ -150,6 +150,7 @@ export const test = base.extend({ StorefrontCustomRegister: async ({ StorefrontPage }, use) => { await use(new CustomRegister(StorefrontPage)); + }, StorefrontCheckoutOrderEdit: async ({ StorefrontPage }, use) => { diff --git a/src/page-objects/storefront/AccountLogin.ts b/src/page-objects/storefront/AccountLogin.ts index f5d5df0..ab92621 100644 --- a/src/page-objects/storefront/AccountLogin.ts +++ b/src/page-objects/storefront/AccountLogin.ts @@ -29,13 +29,6 @@ export class AccountLogin implements PageObject { public readonly postalCodeInput: Locator; public readonly registerButton: Locator; - // Inputs for reCaptcha - public readonly greCaptchaV2Container: Locator; - public readonly greCaptchaV2Input: Locator; - public readonly greCaptchaV3Input: Locator; - public readonly greCaptchaProtectionInformation: Locator; - public readonly greCaptchaBadge: Locator; - constructor(public readonly page: Page) { this.emailInput = page.getByLabel('Your email address'); this.passwordInput = page.getByLabel('Your password'); @@ -63,12 +56,6 @@ export class AccountLogin implements PageObject { this.logoutLink = page.getByRole('link', { name: 'Log out'}); this.successAlert = page.getByText('Successfully logged out.'); this.passwordUpdatedAlert = page.getByText('Your password has been updated.'); - - this.greCaptchaV2Container = this.page.locator('.grecaptcha-v2-container'); - this.greCaptchaV2Input = this.page.locator('.grecaptcha-v2-input'); - this.greCaptchaV3Input = this.page.locator('.grecaptcha_v3-input'); - this.greCaptchaProtectionInformation = this.page.locator('.grecaptcha-protection-information'); - this.greCaptchaBadge = this.page.locator('.grecaptcha-badge'); } url() { diff --git a/src/page-objects/storefront/ContactForm.ts b/src/page-objects/storefront/ContactForm.ts deleted file mode 100644 index f6a19fe..0000000 --- a/src/page-objects/storefront/ContactForm.ts +++ /dev/null @@ -1,57 +0,0 @@ -import type { Page, Locator } from '@playwright/test'; -import type { PageObject } from '../../types/PageObject'; -import { Home } from './Home'; - -export class ContactForm extends Home implements PageObject { - public readonly contactModal: Locator; - public readonly contactSuccessModal: Locator; - public readonly salutationSelect: Locator; - public readonly firstNameInput: Locator; - public readonly lastNameInput: Locator; - public readonly emailInput: Locator; - public readonly phoneInput: Locator; - public readonly subjectInput: Locator; - public readonly commentInput: Locator; - public readonly privacyPolicyCheckbox: Locator; - public readonly submitButton: Locator; - public readonly contactSuccessMessage: Locator; - public readonly cardTitle: Locator; - /** - * Captcha locators - */ - public readonly basicCaptcha: Locator; - public readonly basicCaptchaImage: Locator; - public readonly basicCaptchaRefreshButton: Locator; - public readonly basicCaptchaInput: Locator; - public readonly greCaptchaV2Container: Locator; - public readonly greCaptchaV2Input: Locator; - public readonly greCaptchaProtectionInformation: Locator; - - constructor(public readonly page: Page) { - super(page); - this.contactModal = this.page.getByRole('dialog').filter({ has: this.page.getByLabel('Contact', { exact: true }) }); - this.salutationSelect = this.contactModal.getByLabel('Salutation*'); - this.firstNameInput = this.contactModal.getByLabel('First name*'); - this.lastNameInput = this.contactModal.getByLabel('Last name*'); - this.emailInput = this.contactModal.getByLabel('Your email address*'); - this.phoneInput = this.contactModal.getByLabel('Phone*'); - this.subjectInput = this.contactModal.getByLabel('Subject*'); - this.commentInput = this.contactModal.getByLabel('Comment*'); - this.privacyPolicyCheckbox = this.contactModal.getByRole('checkbox', { name: 'By selecting continue you confirm that you have read and agree to our' }); - this.submitButton = this.contactModal.getByRole('button', { name: 'Submit' }); - this.contactSuccessModal = this.page.getByRole('dialog').filter({ has: this.page.locator('.confirm-message') }); - this.contactSuccessMessage = this.contactSuccessModal.locator('.confirm-message'); - this.cardTitle = this.contactModal.locator('.card-title'); - this.basicCaptcha = this.contactModal.locator('.basic-captcha'); - this.basicCaptchaImage = this.basicCaptcha.locator('img'); - this.basicCaptchaRefreshButton = this.basicCaptcha.locator('.basic-captcha-content-refresh-icon'); - this.basicCaptchaInput = this.basicCaptcha.locator('input[name="shopware_basic_captcha_confirm"]'); - this.greCaptchaV2Container = this.contactModal.locator('.grecaptcha-v2-container'); - this.greCaptchaV2Input = this.contactModal.locator('.grecaptcha-v2-input'); - this.greCaptchaProtectionInformation = this.contactModal.locator('.grecaptcha-protection-information'); -} - - url() { - return new Error('Function not implemented, because it is a modal page object').message; - } -} diff --git a/src/page-objects/storefront/Home.ts b/src/page-objects/storefront/Home.ts index dcff327..81d066c 100644 --- a/src/page-objects/storefront/Home.ts +++ b/src/page-objects/storefront/Home.ts @@ -18,8 +18,6 @@ export class Home implements PageObject { public readonly consentDialog: Locator; public readonly consentDialogTechnicallyRequiredCheckbox: Locator; public readonly consentDialogStatisticsCheckbox: Locator; - public readonly contactFormLink: Locator; - /** * @deprecated Use 'consentDialogMarketingCheckbox' instead */ diff --git a/src/services/TestDataService.ts b/src/services/TestDataService.ts index e418a8b..ee7d2d1 100644 --- a/src/services/TestDataService.ts +++ b/src/services/TestDataService.ts @@ -33,7 +33,6 @@ import type { CustomFieldSet, CustomField, Tax, - ProductCrossSelling, } from '../types/ShopwareTypes'; import { expect } from '@playwright/test'; @@ -101,7 +100,11 @@ export class TestDataService { * * @private */ +<<<<<<< HEAD private highPriorityEntities = ['order', 'product_cross_selling' , 'product', 'landing_page', 'shipping_method', 'sales_channel_domain', 'sales_channel_currency', 'sales_channel_country', 'customer']; +======= + private highPriorityEntities = ['order', 'product', 'landing_page', 'shipping_method', 'sales_channel_domain', 'sales_channel_currency', 'sales_channel_country', 'sales_channel_payment_method', 'customer']; +>>>>>>> 12996cb (feat: rebase trunk) /** * A registry of all created records. @@ -476,27 +479,6 @@ export class TestDataService { return propertyGroup; } - /** - * Creates a basic product cross-selling entity without products. - * - * @param productId - The uuid of the product to which the pproduct cross-selling should be assigned. - * @param overrides - Specific data overrides that will be applied to the property group data struct. - */ - async createProductCrossSelling(productId: string, overrides: Partial = {}): Promise { - const crossSellingStruct = this.getBasicCrossSellingStruct(productId, overrides); - - const response = await this.AdminApiClient.post('product-cross-selling?_response=detail', { - data: crossSellingStruct, - }); - expect(response.ok()).toBeTruthy(); - - const { data: productCrossSelling } = (await response.json()) as { data: ProductCrossSelling }; - - this.addCreatedRecord('product_cross_selling', productCrossSelling.id); - - return productCrossSelling; - } - /** * Creates a new tag which can be assigned to other entities. * @@ -1662,6 +1644,7 @@ export class TestDataService { deleteOperations[`delete-${record.resource}`].payload.push(record.payload); } }); + await this.AdminApiClient.post('_action/sync', { data: priorityDeleteOperations, }); @@ -2537,24 +2520,4 @@ export class TestDataService { return Object.assign({}, basicTaxStruct, overrides); } - - getBasicCrossSellingStruct(productId: string, overrides: Partial = {}) { - - const { id: productCrossSellingId, uuid: productCrossSellingUuid } = this.IdProvider.getIdPair(); - const productCrossSellingName = `${this.namePrefix}ProductCrossSelling-${productCrossSellingId}${this.nameSuffix}`; - - const defaultCrossSelling = { - id: productCrossSellingUuid, - productId: productId, - name: productCrossSellingName, - type: 'product_list', - position: 1, - active: true, - productStreamId: null, - sortingType: 'name', - limit: 10, - sortBy: 'name', - } - return Object.assign({}, defaultCrossSelling, overrides); - } } diff --git a/src/types/ShopwareTypes.ts b/src/types/ShopwareTypes.ts index 9a093aa..35b3e83 100644 --- a/src/types/ShopwareTypes.ts +++ b/src/types/ShopwareTypes.ts @@ -200,10 +200,6 @@ export type SalesChannelAnalytics = components['schemas']['SalesChannelAnalytics id: string, }; -export type ProductCrossSelling = components['schemas']['ProductCrossSelling'] & { - id: string, -}; - export interface RegistrationData { isCommercial: boolean; isGuest: boolean; diff --git a/tests/TestDataService/TestDataService.spec.ts b/tests/TestDataService/TestDataService.spec.ts index 3330db0..f2b88d9 100644 --- a/tests/TestDataService/TestDataService.spec.ts +++ b/tests/TestDataService/TestDataService.spec.ts @@ -15,7 +15,6 @@ import { APIResponse, SalesChannelAnalytics, Tax, - ProductCrossSelling, } from '../../src'; test('Data Service', async ({ @@ -94,10 +93,6 @@ test('Data Service', async ({ const taxRate21 = await TestDataService.createTaxRate({ taxRate: 21.0 }); expect(taxRate21.taxRate).toEqual(21.0); - const crossSellingProduct = await TestDataService.createBasicProduct(); - const productCrossSelling = await TestDataService.createProductCrossSelling(crossSellingProduct.id, { name: 'Custom cross selling' }); - expect(productCrossSelling.name).toEqual('Custom cross selling'); - // Test data clean-up with deactivated cleansing process TestDataService.setCleanUp(false); const cleanUpFalseResponse = await TestDataService.cleanUp(); @@ -155,10 +150,6 @@ test('Data Service', async ({ const { data: databaseTaxRate21 } = (await taxRate21Response.json()) as { data: Tax }; expect(databaseTaxRate21.id).toBe(taxRate21.id); - const crossSellingProductResponse = await AdminApiContext.get(`./product-cross-selling/${productCrossSelling.id}?_response=detail`); - const { data: databaseCrossSellingProduct } = (await crossSellingProductResponse.json()) as { data: ProductCrossSelling }; - expect(databaseCrossSellingProduct.id).toBe(productCrossSelling.id); - // Test data clean-up with activated cleansing process TestDataService.setCleanUp(true); const cleanUpDeleteOperationsResponse = await TestDataService.cleanUp() as APIResponse; From e00afd28eac105a8ac6b084ebf07f86a38c7a3c5 Mon Sep 17 00:00:00 2001 From: Orkun Cavli Date: Tue, 4 Feb 2025 08:21:29 +0100 Subject: [PATCH 5/9] feat: fix conflixt on testdataservice --- src/services/TestDataService.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/services/TestDataService.ts b/src/services/TestDataService.ts index ee7d2d1..c7e1e25 100644 --- a/src/services/TestDataService.ts +++ b/src/services/TestDataService.ts @@ -100,11 +100,7 @@ export class TestDataService { * * @private */ -<<<<<<< HEAD - private highPriorityEntities = ['order', 'product_cross_selling' , 'product', 'landing_page', 'shipping_method', 'sales_channel_domain', 'sales_channel_currency', 'sales_channel_country', 'customer']; -======= - private highPriorityEntities = ['order', 'product', 'landing_page', 'shipping_method', 'sales_channel_domain', 'sales_channel_currency', 'sales_channel_country', 'sales_channel_payment_method', 'customer']; ->>>>>>> 12996cb (feat: rebase trunk) + private highPriorityEntities = ['order', 'product_cross_selling' , 'product', 'landing_page', 'shipping_method', 'sales_channel_domain', 'sales_channel_currency', 'sales_channel_country', 'sales_channel_payment_method', 'customer']; /** * A registry of all created records. From 123b09a0c38da67f2fc617f48e1502978125caf6 Mon Sep 17 00:00:00 2001 From: Orkun Cavli Date: Tue, 4 Feb 2025 08:43:26 +0100 Subject: [PATCH 6/9] feat: remove contact form --- src/page-objects/StorefrontPages.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/page-objects/StorefrontPages.ts b/src/page-objects/StorefrontPages.ts index 0907779..aa848ea 100644 --- a/src/page-objects/StorefrontPages.ts +++ b/src/page-objects/StorefrontPages.ts @@ -22,7 +22,6 @@ import { CustomRegister } from './storefront/CustomRegister'; import { CheckoutOrderEdit } from './storefront/CheckoutOrderEdit'; import { AccountAddressCreate } from './storefront/AccountAddresssCreate'; import { Wishlist } from './storefront/Wishlist'; -import { ContactForm } from './storefront/ContactForm'; export interface StorefrontPageTypes { StorefrontHome: Home; @@ -46,7 +45,6 @@ export interface StorefrontPageTypes { StorefrontCustomRegister: CustomRegister; StorefrontCheckoutOrderEdit: CheckoutOrderEdit; StorefrontWishlist: Wishlist; - StorefrontContactForm: ContactForm; } export const StorefrontPageObjects = { @@ -71,7 +69,6 @@ export const StorefrontPageObjects = { CustomRegister, CheckoutOrderEdit, Wishlist, - ContactForm, } export const test = base.extend({ @@ -150,7 +147,6 @@ export const test = base.extend({ StorefrontCustomRegister: async ({ StorefrontPage }, use) => { await use(new CustomRegister(StorefrontPage)); - }, StorefrontCheckoutOrderEdit: async ({ StorefrontPage }, use) => { @@ -160,8 +156,4 @@ export const test = base.extend({ StorefrontWishlist: async ({ StorefrontPage }, use) => { await use(new Wishlist(StorefrontPage)); }, - - StorefrontContactForm: async ({ StorefrontPage }, use) => { - await use(new ContactForm(StorefrontPage)); - }, }); From 468d1bf97082d37de396819211f3fe5f7263e619 Mon Sep 17 00:00:00 2001 From: Orkun Cavli Date: Tue, 4 Feb 2025 13:24:37 +0100 Subject: [PATCH 7/9] feat: fix wishlist actions --- .../Wishlist/AddProductToCartFromWishlist.ts | 20 -------- .../Wishlist/AddProductToWishlist.ts | 18 ------- .../Wishlist/RemoveProductFromWishlist.ts | 18 ------- .../shop-customer/Wishlist/WishlistActions.ts | 48 +++++++++++++++++++ 4 files changed, 48 insertions(+), 56 deletions(-) delete mode 100644 src/tasks/shop-customer/Wishlist/AddProductToCartFromWishlist.ts delete mode 100644 src/tasks/shop-customer/Wishlist/AddProductToWishlist.ts delete mode 100644 src/tasks/shop-customer/Wishlist/RemoveProductFromWishlist.ts create mode 100644 src/tasks/shop-customer/Wishlist/WishlistActions.ts diff --git a/src/tasks/shop-customer/Wishlist/AddProductToCartFromWishlist.ts b/src/tasks/shop-customer/Wishlist/AddProductToCartFromWishlist.ts deleted file mode 100644 index 4e11c3f..0000000 --- a/src/tasks/shop-customer/Wishlist/AddProductToCartFromWishlist.ts +++ /dev/null @@ -1,20 +0,0 @@ -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 }, use) => { - const task = (ProductData: Product) => { - return async function AddProductToCart() { - const listedItem = await StorefrontWishlist.getListingItemByProductId(ProductData.id); - await listedItem.productAddToShoppingCart.click(); - await StorefrontWishlist.page.waitForResponse((response) => response.url().includes(`checkout/offcanvas`) && response.ok()); - await ShopCustomer.expects(StorefrontWishlist.offCanvasCartTitle).toBeVisible(); - await ShopCustomer.expects(StorefrontWishlist.offCanvasCart.getByText(ProductData.name)).toBeVisible(); - } - }; - - await use(task); - }, -}); \ No newline at end of file diff --git a/src/tasks/shop-customer/Wishlist/AddProductToWishlist.ts b/src/tasks/shop-customer/Wishlist/AddProductToWishlist.ts deleted file mode 100644 index a9ca593..0000000 --- a/src/tasks/shop-customer/Wishlist/AddProductToWishlist.ts +++ /dev/null @@ -1,18 +0,0 @@ -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 AddProductToWishlist = base.extend<{ AddProductToWishlist: Task }, FixtureTypes>({ - AddProductToWishlist: async ({ StorefrontHome , StorefrontWishlist, ShopCustomer}, use) => { - const task = (ProductData: Product) => { - return async function AddProductToWishlist() { - const listedItem = await StorefrontHome.getListingItemByProductId(ProductData.id); - await listedItem.wishlistNotAddedIcon.click(); - await ShopCustomer.expects(listedItem.wishlistAddedIcon).toBeVisible(); - } - }; - - await use(task); - }, -}); \ No newline at end of file diff --git a/src/tasks/shop-customer/Wishlist/RemoveProductFromWishlist.ts b/src/tasks/shop-customer/Wishlist/RemoveProductFromWishlist.ts deleted file mode 100644 index dcc8826..0000000 --- a/src/tasks/shop-customer/Wishlist/RemoveProductFromWishlist.ts +++ /dev/null @@ -1,18 +0,0 @@ -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 RemoveProductFromWishlist = base.extend<{ RemoveProductFromWishlist: Task }, FixtureTypes>({ - RemoveProductFromWishlist: async ({ StorefrontHome , StorefrontWishlist}, use) => { - const task = (ProductData: Product) => { - return async function AddProductToWishlist() { - const listedItem = await StorefrontHome.getListingItemByProductId(ProductData.id); - await listedItem.wishlistAddedIcon.click(); - await StorefrontWishlist.page.waitForResponse((response) => response.url().includes(`remove/${ProductData.id}`) && response.ok()); - } - }; - - await use(task); - }, -}); \ No newline at end of file diff --git a/src/tasks/shop-customer/Wishlist/WishlistActions.ts b/src/tasks/shop-customer/Wishlist/WishlistActions.ts new file mode 100644 index 0000000..b0aca1e --- /dev/null +++ b/src/tasks/shop-customer/Wishlist/WishlistActions.ts @@ -0,0 +1,48 @@ +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 }, use) => { + const task = (ProductData: Product) => { + return async function AddProductToCart() { + const listedItem = await StorefrontWishlist.getListingItemByProductId(ProductData.id); + await listedItem.productAddToShoppingCart.click(); + await StorefrontWishlist.page.waitForResponse((response) => response.url().includes(`checkout/offcanvas`) && response.ok()); + await ShopCustomer.expects(StorefrontWishlist.offCanvasCartTitle).toBeVisible(); + await ShopCustomer.expects(StorefrontWishlist.offCanvasCart.getByText(ProductData.name)).toBeVisible(); + } + }; + + await use(task); + }, +}); + +export const RemoveProductFromWishlist = base.extend<{ RemoveProductFromWishlist: Task }, FixtureTypes>({ + RemoveProductFromWishlist: async ({ StorefrontHome , StorefrontWishlist}, use) => { + const task = (ProductData: Product) => { + return async function AddProductToWishlist() { + const listedItem = await StorefrontHome.getListingItemByProductId(ProductData.id); + 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.getListingItemByProductId(ProductData.id); + await listedItem.wishlistNotAddedIcon.click(); + await ShopCustomer.expects(listedItem.wishlistAddedIcon).toBeVisible(); + } + }; + + await use(task); + }, +}); \ No newline at end of file From bdf0226b014012467b23b49891b468c428fb9b47 Mon Sep 17 00:00:00 2001 From: Orkun Cavli Date: Tue, 4 Feb 2025 13:44:51 +0100 Subject: [PATCH 8/9] feat: remove testdataservice from MR --- src/services/TestDataService.ts | 35 ++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/services/TestDataService.ts b/src/services/TestDataService.ts index c7e1e25..cc838b5 100644 --- a/src/services/TestDataService.ts +++ b/src/services/TestDataService.ts @@ -100,7 +100,7 @@ export class TestDataService { * * @private */ - private highPriorityEntities = ['order', 'product_cross_selling' , 'product', 'landing_page', 'shipping_method', 'sales_channel_domain', 'sales_channel_currency', 'sales_channel_country', 'sales_channel_payment_method', 'customer']; + private highPriorityEntities = ['order', 'product', 'landing_page', 'shipping_method', 'sales_channel_domain', 'sales_channel_currency', 'sales_channel_country', 'sales_channel_payment_method', 'customer']; /** * A registry of all created records. @@ -1212,6 +1212,39 @@ export class TestDataService { return salesChannel; } + /** + * Assigns a payment method to a sales channel. + * + * @param salesChannelId - The uuid of the sales channel. + * @param paymentMethodId - The uuid of the currency. + */ + async assignSalesChannelPaymentMethod(salesChannelId: string, paymentMethodId: string) { + const syncSalesChannelResponse = await this.AdminApiClient.post('./_action/sync', { + data: { + 'write-sales-channel-payment-method': { + entity: 'sales_channel_payment_method', + action: 'upsert', + payload: [ + { + salesChannelId: salesChannelId, + paymentMethodId: paymentMethodId, + }, + ], + }, + }, + }); + expect(syncSalesChannelResponse.ok()).toBeTruthy(); + + const { data: salesChannel } = await syncSalesChannelResponse.json(); + + this.addCreatedRecord('sales_channel_payment_method', { + salesChannelId: salesChannelId, + paymentMethodId: paymentMethodId, + }); + + return salesChannel; + } + /** * Assigns a media resource to a payment method as a logo. * From 15799d3ec0869e5c903b72ed66078ff7981cdfe9 Mon Sep 17 00:00:00 2001 From: Orkun Cavli Date: Tue, 4 Feb 2025 14:06:18 +0100 Subject: [PATCH 9/9] feat: fix shopcustomer tasks --- src/tasks/shop-customer-tasks.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/tasks/shop-customer-tasks.ts b/src/tasks/shop-customer-tasks.ts index f390f5c..ccf55ac 100644 --- a/src/tasks/shop-customer-tasks.ts +++ b/src/tasks/shop-customer-tasks.ts @@ -24,9 +24,7 @@ import { OpenSearchSuggestPage } from './shop-customer/Search/OpenSearchSuggestP import { SearchForTerm } from './shop-customer/Search/SearchForTerm'; import { ValidateAccessibility } from './shop-customer/Accessibility/ValidateAccessibility'; -import { RemoveProductFromWishlist } from './shop-customer/Wishlist/RemoveProductFromWishlist'; -import { AddProductToCartFromWishlist } from './shop-customer/Wishlist/AddProductToCartFromWishlist'; -import { AddProductToWishlist } from './shop-customer/Wishlist/AddProductToWishlist'; +import { AddProductToCartFromWishlist, AddProductToWishlist, RemoveProductFromWishlist } from './shop-customer/Wishlist/WishlistActions'; export const test = mergeTests( Login,