diff --git a/tests/pw/pages/frontend/my-account/auth/my-account-auth.page.ts b/tests/pw/pages/frontend/my-account/auth/my-account-auth.page.ts new file mode 100644 index 0000000000..94d9c29b20 --- /dev/null +++ b/tests/pw/pages/frontend/my-account/auth/my-account-auth.page.ts @@ -0,0 +1,32 @@ +import { BasePage } from '@pages/basePage'; +import { Page } from '@playwright/test'; + +export default class MyAccountAuthPage extends BasePage { + constructor(page: Page) { + super(page); + } + + usernameInputField() { + return this.page.locator('#username'); + } + + passwordInputField() { + return this.page.locator('#password'); + } + + loginButton() { + return this.page.locator('//button[@name="login"]'); + } + + async enterUsername(username: string) { + await this.usernameInputField().fill(username); + } + + async enterPassword(password: string) { + await this.passwordInputField().fill(password); + } + + async clickOnLoginButton() { + await this.loginButton().click(); + } +} diff --git a/tests/pw/pages/frontend/my-orders/all-my-orders.page.ts b/tests/pw/pages/frontend/my-orders/all-my-orders.page.ts new file mode 100644 index 0000000000..a2118dcbf0 --- /dev/null +++ b/tests/pw/pages/frontend/my-orders/all-my-orders.page.ts @@ -0,0 +1,16 @@ +import { BasePage } from '@pages/basePage'; +import { Page } from '@playwright/test'; + +export default class AllMyOrdersPage extends BasePage { + constructor(page: Page) { + super(page); + } + + viewButtonByOrderId(orderId: string) { + return this.page.locator(`//td[@class="order-number"]/a[contains(text(), "${orderId}")]/../following-sibling::td[5]/a`); + } + + async clickOnViewButtonByOrderId(orderId: string) { + await this.viewButtonByOrderId(orderId).click(); + } +} diff --git a/tests/pw/pages/frontend/my-orders/customer-order-details.page.ts b/tests/pw/pages/frontend/my-orders/customer-order-details.page.ts new file mode 100644 index 0000000000..e84d425935 --- /dev/null +++ b/tests/pw/pages/frontend/my-orders/customer-order-details.page.ts @@ -0,0 +1,28 @@ +import { BasePage } from '@pages/basePage'; +import { Page } from '@playwright/test'; + +export default class CustomerOrderDetailsPage extends BasePage { + constructor(page: Page) { + super(page); + } + + orderReceivedButtonByShipmentNumber(shipmentNumber: string) { + return this.page.locator(`//h4[@class="shippments-tracking-title"]/strong[text()="Shipment ${shipmentNumber} "]/../../div[1]/strong[@class="customer-status"]`); + } + + trackingStatusByShipmentNumber(shipmentNumber: string) { + return this.page.locator(`//h4[@class="shippments-tracking-title"]/strong[text()="Shipment ${shipmentNumber} "]/../../div[1]/p/strong`); + } + + dialogueBoxOkButton() { + return this.page.locator('//div[@role="dialog"]/div[6]/button[text()="OK"]'); + } + + async markOrderAsReceived(shipmentNumber: string) { + await this.orderReceivedButtonByShipmentNumber(shipmentNumber).click(); + } + + async clickOnDialogBoxOkButton() { + await this.dialogueBoxOkButton().click(); + } +} diff --git a/tests/pw/pages/frontend/vendor-dashboard/common/vendor-sidebar.page.ts b/tests/pw/pages/frontend/vendor-dashboard/common/vendor-sidebar.page.ts new file mode 100644 index 0000000000..e87c7d707a --- /dev/null +++ b/tests/pw/pages/frontend/vendor-dashboard/common/vendor-sidebar.page.ts @@ -0,0 +1,16 @@ +import { BasePage } from '@pages/basePage'; +import { Page } from '@playwright/test'; + +export default class VendorDashboardSidebarPage extends BasePage { + constructor(page: Page) { + super(page); + } + + sidebarMenu(title: string) { + return this.page.locator(`//li[@class="${title}"]/a`); + } + + async clickOnOrdersTab() { + await this.sidebarMenu('orders').click(); + } +} diff --git a/tests/pw/pages/frontend/vendor-dashboard/orders/vendor-all-orders.page.ts b/tests/pw/pages/frontend/vendor-dashboard/orders/vendor-all-orders.page.ts new file mode 100644 index 0000000000..69acba6f78 --- /dev/null +++ b/tests/pw/pages/frontend/vendor-dashboard/orders/vendor-all-orders.page.ts @@ -0,0 +1,16 @@ +import { BasePage } from '@pages/basePage'; +import { Page } from '@playwright/test'; + +export default class VendorAllOrdersPage extends BasePage { + constructor(page: Page) { + super(page); + } + + orderTitleById(orderId: string) { + return this.page.locator(`//td[@data-title="Order"]/a/strong[text()="Order ${orderId}"]`); + } + + async clickOnOrderById(orderId: string) { + await this.orderTitleById(orderId).click(); + } +} diff --git a/tests/pw/pages/frontend/vendor-dashboard/orders/vendor-edit-order.page.ts b/tests/pw/pages/frontend/vendor-dashboard/orders/vendor-edit-order.page.ts new file mode 100644 index 0000000000..c754d2f257 --- /dev/null +++ b/tests/pw/pages/frontend/vendor-dashboard/orders/vendor-edit-order.page.ts @@ -0,0 +1,64 @@ +import { BasePage } from '@pages/basePage'; +import { Page } from '@playwright/test'; + +export default class VendorEditOrderPage extends BasePage { + constructor(page: Page) { + super(page); + } + + createNewShipmentButton() { + return this.page.locator('#create-tracking-status-action'); + } + + shipmentItemCheckboxByIndex(itemNumber: string) { + return this.page.locator(`//form[@id="add-shipping-tracking-status-form"]/div/table/tbody[@id="order_line_items"]/tr[${itemNumber}]/td[1]/label/input`); + } + + shippingStatusDropdown() { + return this.page.locator('#shipment-status'); + } + + shippingProviderDropdown() { + return this.page.locator('#shipping_status_provider'); + } + + shippingDateField() { + return this.page.locator('#shipped_status_date'); + } + + shippingTrackingNumberField() { + return this.page.locator('#tracking_status_number'); + } + + createShipmentButton() { + return this.page.locator('#add-tracking-status-details'); + } + + async clickOnCreateNewShipmentButton() { + await this.createNewShipmentButton().click(); + } + + async clickOnShipmentItemCheckboxByIndex(itemNumber: string) { + await this.shipmentItemCheckboxByIndex(itemNumber).click(); + } + + async selectShippingStatus(status: string) { + await this.shippingStatusDropdown().selectOption(status); + } + + async selectShippingProvider(providerName: string) { + await this.shippingProviderDropdown().selectOption(providerName); + } + + async enterShippingDate(date: string) { + await this.shippingDateField().fill(date); + } + + async enterShippingTrackingNumber(trackingNumber: string) { + await this.shippingTrackingNumberField().fill(trackingNumber); + } + + async clickOnCreateShipmentButton() { + await this.createShipmentButton().click(); + } +} diff --git a/tests/pw/pages/wp-admin/common/sidebar.page.ts b/tests/pw/pages/wp-admin/common/sidebar.page.ts new file mode 100644 index 0000000000..71e9eabc5c --- /dev/null +++ b/tests/pw/pages/wp-admin/common/sidebar.page.ts @@ -0,0 +1,16 @@ +import { BasePage } from '@pages/basePage'; +import { Page } from '@playwright/test'; + +export default class WpAdminSidebar extends BasePage { + constructor(page: Page) { + super(page); + } + + sideMenu(title: string) { + return this.page.locator('.wp-menu-name').getByText(title); + } + + async clickOnProductsLink() { + await this.sideMenu('Products').click(); + } +} diff --git a/tests/pw/pages/wp-admin/dokan/settings/shipping-status.page.ts b/tests/pw/pages/wp-admin/dokan/settings/shipping-status.page.ts new file mode 100644 index 0000000000..e4c3f57128 --- /dev/null +++ b/tests/pw/pages/wp-admin/dokan/settings/shipping-status.page.ts @@ -0,0 +1,54 @@ +import { BasePage } from '@pages/basePage'; +import { Page } from '@playwright/test'; + +export default class DokanShippingStatusPage extends BasePage { + constructor(page: Page) { + super(page); + } + + shippingStatusTab() { + return this.page.locator('//div[@class="nav-title"][text()="Shipping Status"]'); + } + + allowShipmentTrackingCheckbox() { + return this.page.locator('(//p/../following-sibling::div/label/label)[1]'); + } + + allowMarkAsReceivedCheckbox() { + return this.page.locator('(//p/../following-sibling::div/label/label)[2]'); + } + + async shippingStatusItem(status: string) { + const list = this.page.locator('//ul[@class="dokan-settings-repeatable-list"]/li').all(); + + let locator; + for (const item of await list) { + const text = await item.textContent(); + if (text?.includes(status)) { + locator = item; + } + } + + return locator; + } + + saveChangesButton() { + return this.page.locator('#submit'); + } + + async clickOnShippingStatusTab() { + await this.shippingStatusTab().click(); + } + + async clickOnAllowShipmentTrackingCheckbox() { + await this.allowShipmentTrackingCheckbox().click(); + } + + async clickOnAllowMarkAsReceivedCheckbox() { + await this.allowMarkAsReceivedCheckbox().click(); + } + + async clickOnSaveChangesButton() { + await this.saveChangesButton().click(); + } +} diff --git a/tests/pw/pages/wp-admin/products/all-products.page.ts b/tests/pw/pages/wp-admin/products/all-products.page.ts new file mode 100644 index 0000000000..5e39fd8b09 --- /dev/null +++ b/tests/pw/pages/wp-admin/products/all-products.page.ts @@ -0,0 +1,16 @@ +import { BasePage } from '@pages/basePage'; +import { Page } from '@playwright/test'; + +export default class AllProductsPage extends BasePage { + constructor(page: Page) { + super(page); + } + + productTitleById(productId: string) { + return this.page.locator(`//tr[@id="post-${productId}"]/td[2]/strong/a`); + } + + async clickOnProductTitleById(productId: string) { + await this.productTitleById(productId).click(); + } +} diff --git a/tests/pw/pages/wp-admin/products/edit-product.page.ts b/tests/pw/pages/wp-admin/products/edit-product.page.ts new file mode 100644 index 0000000000..1d504b94aa --- /dev/null +++ b/tests/pw/pages/wp-admin/products/edit-product.page.ts @@ -0,0 +1,16 @@ +import { BasePage } from '@pages/basePage'; +import { Page } from '@playwright/test'; + +export default class EditProductPage extends BasePage { + constructor(page: Page) { + super(page); + } + + publishButton() { + return this.page.locator('#publish'); + } + + async clickOnPublishButton() { + await this.publishButton().click(); + } +} diff --git a/tests/pw/tests/e2e/shipping-status/mark-order-as-received-01.spec.ts b/tests/pw/tests/e2e/shipping-status/mark-order-as-received-01.spec.ts new file mode 100644 index 0000000000..953384b2d3 --- /dev/null +++ b/tests/pw/tests/e2e/shipping-status/mark-order-as-received-01.spec.ts @@ -0,0 +1,30 @@ +import { LoginPage } from '@pages/loginPage'; +import DokanShippingStatusPage from '@pages/wp-admin/dokan/settings/shipping-status.page'; +import test, { expect } from '@playwright/test'; + +let baseUrl: string; +let loginPage: LoginPage; +let shippingStatusPage: DokanShippingStatusPage; + +test.describe('Mark Order As Received - 01', () => { + test.beforeEach(async ({ page }, testInfo) => { + loginPage = new LoginPage(page); + shippingStatusPage = new DokanShippingStatusPage(page); + + console.log(testInfo.project.use.baseURL); + baseUrl = testInfo.project.use.baseURL as string; + await page.goto(baseUrl); + }); + + test('Receive status is added when Mark received by Customer is enabled', async ({ page }) => { + await loginPage.adminLogin({ username: 'admin1', password: 'admin1@email.com' }); + await page.goto(baseUrl + '/wp-admin/admin.php?page=dokan#/settings'); + await shippingStatusPage.clickOnShippingStatusTab(); + await shippingStatusPage.clickOnAllowShipmentTrackingCheckbox(); + await shippingStatusPage.clickOnAllowMarkAsReceivedCheckbox(); + await shippingStatusPage.clickOnSaveChangesButton(); + + const status = await shippingStatusPage.shippingStatusItem('Received'); + expect(await status?.textContent()).toContain('Received'); + }); +}); diff --git a/tests/pw/tests/e2e/shipping-status/mark-order-as-received-02.spec.ts b/tests/pw/tests/e2e/shipping-status/mark-order-as-received-02.spec.ts new file mode 100644 index 0000000000..fec25a0216 --- /dev/null +++ b/tests/pw/tests/e2e/shipping-status/mark-order-as-received-02.spec.ts @@ -0,0 +1,168 @@ +import MyAccountAuthPage from '@pages/frontend/my-account/auth/my-account-auth.page'; +import AllMyOrdersPage from '@pages/frontend/my-orders/all-my-orders.page'; +import CustomerOrderDetailsPage from '@pages/frontend/my-orders/customer-order-details.page'; +import VendorDashboardSidebarPage from '@pages/frontend/vendor-dashboard/common/vendor-sidebar.page'; +import VendorAllOrdersPage from '@pages/frontend/vendor-dashboard/orders/vendor-all-orders.page'; +import VendorEditOrderPage from '@pages/frontend/vendor-dashboard/orders/vendor-edit-order.page'; +import { LoginPage } from '@pages/loginPage'; +import WpAdminSidebar from '@pages/wp-admin/common/sidebar.page'; +import AllProductsPage from '@pages/wp-admin/products/all-products.page'; +import EditProductPage from '@pages/wp-admin/products/edit-product.page'; +import test, { chromium, expect } from '@playwright/test'; +import { ApiUtils } from '@utils/apiUtils'; +import { payloads } from '@utils/payloads'; + +test.describe.only('Mark Order As Received - 02', () => { + test.beforeEach(async ({ page }, testInfo) => { + await page.goto(testInfo.project.use.baseURL as string); + }); + + test('Customer is able to mark order as received for single vendor shipments', async ({ page, request }) => { + const browserOptions = { headless: false }; + const api = new ApiUtils(request); + + // create customer + const customer = await api.createCustomer(payloads.createCustomer(), payloads.adminAuth); + const customerId = customer[0].id; + const customerEmail = customer[0].email; + + // // create vendor + const vendor = await api.createStore(payloads.createStore(), payloads.adminAuth); + const vendorId = vendor[0].id; + const vendorEmail = vendor[0].email; + + // // create product + const product = await api.createProduct( + { + name: `Automation Simple Product ${vendorId}`, + type: 'simple', + regular_price: '10', + status: 'publish', + post_author: `${vendorId}`, + categories: [ + { + name: 'Uncategorized', + slug: 'uncategorized', + }, + ], + description: '
test description
', + short_description: 'test short description
', + }, + payloads.adminAuth, + ); + + const productId = product[1]; + + const adminBrowser = await chromium.launch(browserOptions); + const adminPage = await adminBrowser.newPage(); + const adminLogin = new LoginPage(adminPage); + + const sidebar = new WpAdminSidebar(adminPage); + const allProductsPage = new AllProductsPage(adminPage); + const editProductPage = new EditProductPage(adminPage); + + // publish product + await adminLogin.adminLogin({ username: process.env.ADMIN, password: process.env.ADMIN_PASSWORD }); + await sidebar.clickOnProductsLink(); + await allProductsPage.clickOnProductTitleById(productId); + await editProductPage.clickOnPublishButton(); + + // close admin browser + await adminBrowser.close(); + + const payload = { + payment_method: 'bacs', + payment_method_title: 'Direct Bank Transfer', + set_paid: true, + customer_id: customerId, + billing: { + first_name: 'customer1', + last_name: 'c1', + address_1: 'abc street', + address_2: 'xyz street', + city: 'New York', + state: 'NY', + postcode: '10003', + country: 'US', + email: 'customer1@yopmail.com', + phone: '(555) 555-5555', + }, + + shipping: { + first_name: 'customer1', + last_name: 'c1', + address_1: 'abc street', + address_2: 'xyz street', + city: 'New York', + state: 'NY', + postcode: '10003', + country: 'US', + }, + + line_items: [ + { + product_id: '', + quantity: 1, + }, + ], + }; + + // create order + const orderResponse = await api.createOrder(productId, payload, payloads.adminAuth); + const orderId: number = orderResponse[1]['id']; + + const vendorBrowser = await chromium.launch(browserOptions); + const vendorPage = await vendorBrowser.newPage(); + + const vendorDashboardSidebarPage = new VendorDashboardSidebarPage(vendorPage); + const vendorAllOrdersPage = new VendorAllOrdersPage(vendorPage); + const vendorEditOrderPage = new VendorEditOrderPage(vendorPage); + const vendorMyAccountAuthPage = new MyAccountAuthPage(vendorPage); + + // vendor login + await vendorPage.goto('/dashboard/'); + await vendorMyAccountAuthPage.enterUsername(vendorEmail); + await vendorMyAccountAuthPage.enterPassword(process.env.USER_PASSWORD); + await vendorMyAccountAuthPage.clickOnLoginButton(); + + // create shipment + await vendorDashboardSidebarPage.clickOnOrdersTab(); + await vendorAllOrdersPage.clickOnOrderById(`${orderId}`); + await vendorEditOrderPage.clickOnCreateNewShipmentButton(); + await vendorEditOrderPage.clickOnShipmentItemCheckboxByIndex('1'); + + await vendorEditOrderPage.selectShippingStatus('Delivered'); + await vendorEditOrderPage.selectShippingProvider('Fedex'); + await vendorEditOrderPage.enterShippingDate('July 27, 2024'); + await vendorEditOrderPage.enterShippingTrackingNumber('#KDJNS93'); + await vendorEditOrderPage.clickOnCreateShipmentButton(); + + // close vendor browser + await vendorBrowser.close(); + + const customerBrowser = await chromium.launch(browserOptions); + const customerPage = await customerBrowser.newPage(); + + const customerMyAccountAuthPage = new MyAccountAuthPage(customerPage); + const allMyOrdersPage = new AllMyOrdersPage(customerPage); + const customerOrderDetailsPage = new CustomerOrderDetailsPage(customerPage); + + // customer login + await customerPage.goto('/my-account/'); + await customerMyAccountAuthPage.enterUsername(customerEmail); + await customerMyAccountAuthPage.enterPassword(process.env.USER_PASSWORD); + await customerMyAccountAuthPage.clickOnLoginButton(); + + // customer marks order as received + await customerPage.goto('/my-orders/'); + await allMyOrdersPage.clickOnViewButtonByOrderId(`${orderId}`); + await customerOrderDetailsPage.markOrderAsReceived('#1'); + await customerOrderDetailsPage.clickOnDialogBoxOkButton(); + + // temporary solution, will be replaced + await page.waitForTimeout(3000); + + const status = await customerOrderDetailsPage.trackingStatusByShipmentNumber('#1').textContent(); + expect(status?.trim()).toEqual('Received'); + }); +});