diff --git a/.changeset/spotty-bulldogs-give.md b/.changeset/spotty-bulldogs-give.md new file mode 100644 index 00000000000..7e623df04ba --- /dev/null +++ b/.changeset/spotty-bulldogs-give.md @@ -0,0 +1,5 @@ +--- +"saleor-dashboard": minor +--- + +Adding e2e tests for bulk deleting shipping zones and updating one diff --git a/playwright/data/e2eTestData.ts b/playwright/data/e2eTestData.ts index f32975ec1d4..38f73cd0788 100644 --- a/playwright/data/e2eTestData.ts +++ b/playwright/data/e2eTestData.ts @@ -93,6 +93,19 @@ export const CHANNELS = { plnChannel: { id: "VGF4Q29uZmlndXJhdGlvbjox", }, + e2eChannelDoNotDelete: { + id: "Q2hhbm5lbDoyMzk0", + name: "e2e-channel-do-not-delete", + slug: "e2e-channel-do-not-delete", + }, + channelUSD: { + id: "Q2hhbm5lbDoyMjQz", + name: "Channel-USD", + }, + channelPLN: { + id: "Q2hhbm5lbDoyMjQ0", + name: "Channel-PLN", + }, }; export const GIFT_CARDS = { giftCardToBeEdited: { @@ -123,6 +136,22 @@ export const WAREHOUSES = { warehouseToBeDeleted: { name: "warehouseto be deleted", }, + warehouseEurope: { + id: "V2FyZWhvdXNlOjlkYjY4NWQxLWViMTktNDU2ZS05ODMyLTMxODA3ZWM0NDdhOQ==", + name: "Europe", + }, + warehouseAmericas: { + id: "V2FyZWhvdXNlOjdmZDA0OGI0LWYwNzItNDZmMi1iMDMyLTc3ZWU3MDNiMzM3Yg==", + name: "Americas", + }, + warehouseOceania: { + id: "V2FyZWhvdXNlOjc4OGUyMGRlLTlmYTAtNDI5My1iZDk2LWUwM2RjY2RhMzc0ZQ==", + name: "Oceania", + }, + warehouseAfrica: { + id: "V2FyZWhvdXNlOjk1NWY0ZDk2LWRmNTAtNGY0Zi1hOTM4LWM5MTYzYTA4YTViNg==", + name: "Africa", + }, }; export const PRODUCTS = { @@ -224,6 +253,26 @@ export const SHIPPING_METHODS = { id: "U2hpcHBpbmdab25lOjIzOTA%3D", info: "Shipping method that is used to add rates", }, + shippingMethodToBeUpdated: { + id: "U2hpcHBpbmdab25lOjIzOTI=", + info: "Shipping zone to be updated", + name: "e2e-test-shippingZone-to-be-updated", + }, + shippingMethodToBeBulkDeleted1: { + id: "U2hpcHBpbmdab25lOjIzOTM=", + info: "First shipping zone to be bulk deleted", + name: "e2e-test-shippingZone-to-be-bulk-deleted-1", + }, + shippingMethodToBeBulkDeleted2: { + id: "U2hpcHBpbmdab25lOjIzOTQ=", + info: "Second shipping zone to be bulk deleted", + name: "e2e-test-shippingZone-to-be-bulk-deleted-2", + }, + shippingMethodToBeBulkDeleted3: { + id: "U2hpcHBpbmdab25lOjIzOTU=", + info: "Third shipping zone to be bulk deleted", + name: "e2e-test-shippingZone-to-be-bulk-deleted-3", + }, shippingMethodWithRatesToBeDeleted: { id: "U2hpcHBpbmdab25lOjIzODk%3D", info: "Shipping zone with methods to be deleted", diff --git a/playwright/pages/pageElements/rightSideDetailsSection.ts b/playwright/pages/pageElements/rightSideDetailsSection.ts index 46015899afc..2edf22dd600 100644 --- a/playwright/pages/pageElements/rightSideDetailsSection.ts +++ b/playwright/pages/pageElements/rightSideDetailsSection.ts @@ -1,5 +1,5 @@ import { ChannelSelectDialog } from "@pages/dialogs/channelSelectDialog"; -import { expect, Page } from "@playwright/test"; +import { expect, Locator, Page } from "@playwright/test"; export class RightSideDetailsPage { readonly channelSelectDialog: ChannelSelectDialog; @@ -11,12 +11,13 @@ export class RightSideDetailsPage { "select-warehouse-for-shipping-method", ), readonly stockSettingsSection = page.getByTestId("stock-settings-section"), + readonly channelSection = page.getByTestId("channel-section"), + readonly warehouseSection = page.getByTestId("warehouse-section"), readonly selectChannelShippingPageButton = page.getByTestId( "select-channel-for-shipping-method", ), readonly pickupDisabledButton = page.getByTestId("DISABLED"), readonly pickupAllWarehousesButton = page.getByTestId("ALL"), - readonly categorySelectOption = page.locator( "[data-test-id*='select-option']", ), @@ -31,7 +32,6 @@ export class RightSideDetailsPage { ), readonly collectionInput = page.getByTestId("collections"), readonly autocompleteDropdown = page.getByTestId("autocomplete-dropdown"), - readonly manageChannelsButton = page.getByTestId( "channels-availability-manage-button", ), @@ -93,11 +93,14 @@ export class RightSideDetailsPage { async clickEditShippingAddressButton() { await this.editShippingAddressButton.click(); } - async clickWarehouseSelectShippingPage() { await this.selectWarehouseShippingMethodButton.click(); } - + async expectOptionsSelected(section: Locator, names: string[]) { + for (const name of names) { + await expect(section.getByText(name)).toBeVisible({timeout: 30000}); + } + } async typeAndSelectSingleWarehouseShippingPage(warehouse = "Europe") { await this.selectWarehouseShippingMethodButton .locator("input") @@ -107,7 +110,16 @@ export class RightSideDetailsPage { // below click hides prompted options this.clickWarehouseSelectShippingPage(); } + async typeAndSelectMultipleWarehousesShippingPage(warehouses: string[]) { + for (const warehouse of warehouses) { + await this.selectWarehouseShippingMethodButton + .locator("input") + .fill(warehouse); + await this.selectOption.filter({ hasText: warehouse }).first().click(); + } + this.clickWarehouseSelectShippingPage(); + } async clickChannelsSelectShippingPage() { await this.selectChannelShippingPageButton.click(); } @@ -116,11 +128,9 @@ export class RightSideDetailsPage { // below click hides prompted options this.clickChannelsSelectShippingPage(); } - async openChannelsDialog() { await this.manageChannelsButton.click(); } - async selectFirstCategory() { await this.categoryInput.click(); await this.categorySelectOption.first().click(); @@ -138,7 +148,6 @@ export class RightSideDetailsPage { await this.collectionInput.click(); await this.selectOption.first().click(); } - async clickEditCustomerButton() { await this.editCustomerButton.click(); } @@ -148,7 +157,6 @@ export class RightSideDetailsPage { async expandWarehousesSection() { await this.warehousesSection.locator(this.expandButton).click(); } - async clickSearchCustomerInput() { await this.searchCustomerInput.click(); } @@ -178,11 +186,9 @@ export class RightSideDetailsPage { await this.warehouseSelect.click(); await this.page.getByRole("option", { name: warehouseName }); } - async selectCustomer(customer = "allison.freeman@example.com") { await this.selectCustomerOption.locator(`text=${customer}`).click(); } - async selectOneChannelAsAvailableWhenMoreSelected(channel: string) { await this.manageChannelsButton.click(); await this.channelSelectDialog.clickAllChannelsCheckbox(); diff --git a/playwright/pages/shippingMethodsPage.ts b/playwright/pages/shippingMethodsPage.ts index 7f1c67b8bbc..0587982e990 100644 --- a/playwright/pages/shippingMethodsPage.ts +++ b/playwright/pages/shippingMethodsPage.ts @@ -5,12 +5,10 @@ import { AssignCountriesDialog } from "@pages/dialogs/assignCountriesDialog"; import { RightSideDetailsPage } from "@pages/pageElements/rightSideDetailsSection"; import type { Page } from "@playwright/test"; -export class ShippingMethodsPage { - readonly page: Page; - readonly basePage: BasePage; - readonly rightSideDetailsPage: RightSideDetailsPage; - readonly assignCountriesDialog: AssignCountriesDialog; - readonly deleteShippingMethodDialog: DeleteShippingMethodDialog; +export class ShippingMethodsPage extends BasePage { + rightSideDetailsPage: RightSideDetailsPage; + assignCountriesDialog: AssignCountriesDialog; + deleteShippingMethodDialog: DeleteShippingMethodDialog; constructor( @@ -31,8 +29,7 @@ export class ShippingMethodsPage { readonly priceBasedRatesSection = page.getByTestId("price-based-rates"), readonly weightBasedRatesSection = page.getByTestId("weight-based-rates"), ) { - this.page = page; - this.basePage = new BasePage(page); + super(page); this.rightSideDetailsPage = new RightSideDetailsPage(page); this.assignCountriesDialog = new AssignCountriesDialog(page); this.deleteShippingMethodDialog = new DeleteShippingMethodDialog(page); diff --git a/playwright/tests/shippingMethods.spec.ts b/playwright/tests/shippingMethods.spec.ts index a691078b91b..87d62809b2e 100644 --- a/playwright/tests/shippingMethods.spec.ts +++ b/playwright/tests/shippingMethods.spec.ts @@ -1,14 +1,19 @@ -import { SHIPPING_METHODS } from "@data/e2eTestData"; +import { CHANNELS, SHIPPING_METHODS, WAREHOUSES } from "@data/e2eTestData"; import { ShippingMethodsPage } from "@pages/shippingMethodsPage"; import { ShippingRatesPage } from "@pages/shippingRatesPage"; import { expect, test } from "@playwright/test"; test.use({ storageState: "playwright/.auth/admin.json" }); +let shippingMethodsPage: ShippingMethodsPage; +let shippingRatesPage: ShippingRatesPage; -test("TC: SALEOR_31 Create basic shipping method @shipping-method @e2e", async ({ - page, - }) => { - const shippingMethodsPage = new ShippingMethodsPage(page); + +test.beforeEach(({ page }) => { + shippingMethodsPage = new ShippingMethodsPage(page); + shippingRatesPage = new ShippingRatesPage(page); +}); + +test("TC: SALEOR_31 Create basic shipping method @shipping-method @e2e", async () => { await shippingMethodsPage.gotoListView(); await shippingMethodsPage.clickCreateShippingZoneButton(); @@ -17,21 +22,16 @@ test("TC: SALEOR_31 Create basic shipping method @shipping-method @e2e", async ( await shippingMethodsPage.clickAssignCountryButton(); await shippingMethodsPage.assignCountriesDialog.checkAndSaveSingleCountry(); await shippingMethodsPage.saveShippingZone(); - await shippingMethodsPage.basePage.expectSuccessBanner(); + await shippingMethodsPage.expectSuccessBanner(); await shippingMethodsPage.rightSideDetailsPage.clickChannelsSelectShippingPage(); await shippingMethodsPage.rightSideDetailsPage.selectSingleChannelShippingPage(); await shippingMethodsPage.rightSideDetailsPage.clickWarehouseSelectShippingPage(); await shippingMethodsPage.rightSideDetailsPage.typeAndSelectSingleWarehouseShippingPage(); await shippingMethodsPage.saveShippingZone(); - await shippingMethodsPage.basePage.expectSuccessBanner(); + await shippingMethodsPage.expectSuccessBanner(); }); -test("TC: SALEOR_32 Add price rate to shipping method - with excluded zip codes and excluded product @shipping-method @e2e", async ({ - page, - }) => { - const shippingMethodsPage = new ShippingMethodsPage(page); - const shippingRatesPage = new ShippingRatesPage(page); - +test("TC: SALEOR_32 Add price rate to shipping method - with excluded zip codes and excluded product @shipping-method @e2e", async () => { await shippingMethodsPage.gotoExistingShippingMethod( SHIPPING_METHODS.shippingMethodWithoutRates.id, ); @@ -55,11 +55,7 @@ test("TC: SALEOR_32 Add price rate to shipping method - with excluded zip codes 1, ); }); -test("TC: SALEOR_33 Add weight rate to shipping method - with included zip codes and excluded product @shipping-method @e2e", async ({ - page, - }) => { - const shippingMethodsPage = new ShippingMethodsPage(page); - const shippingRatesPage = new ShippingRatesPage(page); +test("TC: SALEOR_33 Add weight rate to shipping method - with included zip codes and excluded product @shipping-method @e2e", async () => { await shippingMethodsPage.gotoExistingShippingMethod( SHIPPING_METHODS.shippingMethodWithoutRates.id, @@ -86,27 +82,23 @@ test("TC: SALEOR_33 Add weight rate to shipping method - with included zip codes ); }); -test("TC: SALEOR_34 Delete a single shipping rate from the shipping zone details page @shipping-method @e2e", async ({ - page, - }) => { - const shippingMethodsPage = new ShippingMethodsPage(page); +test("TC: SALEOR_34 Delete a single shipping rate from the shipping zone details page @shipping-method @e2e", async () => { + await shippingMethodsPage.gotoExistingShippingMethod( SHIPPING_METHODS.shippingMethodWithRatesToBeDeleted.id, ); - await expect(shippingMethodsPage.basePage.pageHeader).toBeVisible(); + await expect(shippingMethodsPage.pageHeader).toBeVisible(); const priceBasedRate = SHIPPING_METHODS.shippingMethodWithRatesToBeDeleted.rates.priceBasedRateToBeDeleted.name; await expect(shippingMethodsPage.priceBasedRatesSection).toContainText(priceBasedRate); await shippingMethodsPage.clickDeletePriceBasedShippingMethod(); await shippingMethodsPage.deleteShippingMethodDialog.clickDeleteButton(); - await shippingMethodsPage.basePage.expectSuccessBanner(); + await shippingMethodsPage.expectSuccessBanner(); await expect(shippingMethodsPage.priceBasedRatesSection).toContainText("No shipping rates found"); await expect(shippingMethodsPage.priceBasedRatesSection).not.toContainText(priceBasedRate); }); -test("TC: SALEOR_35 Delete a single shipping rate from its details page @shipping-method @e2e", async ({ - page, - }) => { - const shippingMethodsPage = new ShippingMethodsPage(page); +test("TC: SALEOR_35 Delete a single shipping rate from its details page @shipping-method @e2e", async () => { + const shippingMethodId = SHIPPING_METHODS.shippingMethodWithRatesToBeDeleted.id; const shippingRateId = SHIPPING_METHODS.shippingMethodWithRatesToBeDeleted.rates.weightBasedRateToBeDeleted.id; const weightBasedRate = SHIPPING_METHODS.shippingMethodWithRatesToBeDeleted.rates.weightBasedRateToBeDeleted.name; @@ -114,7 +106,45 @@ test("TC: SALEOR_35 Delete a single shipping rate from its details page @shippin await shippingMethodsPage.gotoExistingShippingRate(shippingMethodId, shippingRateId); await shippingMethodsPage.clickDeleteShippingRateButton(); await shippingMethodsPage.deleteShippingMethodDialog.clickDeleteButton(); - await shippingMethodsPage.basePage.expectSuccessBanner(); + await shippingMethodsPage.expectSuccessBanner(); await expect(shippingMethodsPage.weightBasedRatesSection).toContainText("No shipping rates found"); await expect(shippingMethodsPage.weightBasedRatesSection).not.toContainText(weightBasedRate); }); + +test("TC: SALEOR_36 Delete shipping zones in bulk @shipping-method @e2e", async ({ + +}) => { + + const shippingZone1 = SHIPPING_METHODS.shippingMethodToBeBulkDeleted1.name; + const shippingZone2 = SHIPPING_METHODS.shippingMethodToBeBulkDeleted2.name; + const shippingZone3 = SHIPPING_METHODS.shippingMethodToBeBulkDeleted3.name; + + await shippingMethodsPage.gotoListView(); + await shippingMethodsPage.checkListRowsBasedOnContainingText([shippingZone1, shippingZone2, shippingZone3]); + await shippingMethodsPage.clickBulkDeleteGridRowsButton(); + await shippingMethodsPage.deleteShippingMethodDialog.clickDeleteButton(); + await shippingMethodsPage.expectSuccessBanner(); +}); + +test("TC: SALEOR_37 Update a shipping method @shipping-method @e2e", async () => { + const channelSection = shippingMethodsPage.rightSideDetailsPage.channelSection + const warehouseSection = shippingMethodsPage.rightSideDetailsPage.warehouseSection + const alreadyAssignedChannels = [CHANNELS.channelUSD.name]; + const channelsToBeAssigned = [CHANNELS.channelPLN.name]; + const alreadyAssignedWarehouses = [WAREHOUSES.warehouseOceania.name, WAREHOUSES.warehouseAfrica.name]; + const warehousesToBeAssigned = [WAREHOUSES.warehouseAmericas.name, WAREHOUSES.warehouseEurope.name]; + await shippingMethodsPage.gotoExistingShippingMethod( + SHIPPING_METHODS.shippingMethodToBeUpdated.id, + ); + await shippingMethodsPage.rightSideDetailsPage.clickChannelsSelectShippingPage(); + await shippingMethodsPage.rightSideDetailsPage.selectSingleChannelShippingPage() + await shippingMethodsPage.rightSideDetailsPage.clickWarehouseSelectShippingPage(); + await shippingMethodsPage.rightSideDetailsPage.typeAndSelectMultipleWarehousesShippingPage(warehousesToBeAssigned); + await shippingMethodsPage.saveShippingZone(); + await shippingMethodsPage.expectSuccessBanner(); + const updatedChannelsList = alreadyAssignedChannels.concat(channelsToBeAssigned); + await shippingMethodsPage.rightSideDetailsPage.expectOptionsSelected(channelSection,updatedChannelsList); + const updatedWarehousesList = alreadyAssignedWarehouses.concat(warehousesToBeAssigned); + await shippingMethodsPage.rightSideDetailsPage.expectOptionsSelected(warehouseSection,updatedWarehousesList); +}); + diff --git a/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx index 64986a604df..6f6138205f1 100644 --- a/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx +++ b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx @@ -231,7 +231,7 @@ const MultiAutocompleteSelectFieldComponent: React.FC< )} -
+
{displayValues.map(value => (
- + - +