Skip to content

Commit

Permalink
Add Commission tests (getdokan#2471)
Browse files Browse the repository at this point in the history
* add new commission tests

* Add commission tests
  • Loading branch information
shashwatahalder01 authored Dec 7, 2024
1 parent b44d4b3 commit e0ce1a0
Show file tree
Hide file tree
Showing 9 changed files with 354 additions and 28 deletions.
9 changes: 9 additions & 0 deletions tests/pw/feature-map/feature-map.yml
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,15 @@
admin can set commission to Dokan subscription product (category based): true
admin can set commission to Dokan subscription product (specific category based): true
admin can view commission meta-box on order details [lite]: true
admin can view sub orders meta-box on parent order details [lite]: true
admin can view related orders meta-box on child order details [lite]: true
admin can view commission on product list [lite]: true
admin can view commission on order list [lite]: true
vendor can view earning on product list [lite]: true
vendor can view earning on product add page [lite]: true
vendor can view earning on product edit page [lite]: true
vendor can view earning on order list [lite]: true
vendor can view earning on order details [lite]: true

- page: 'Withdraw'
features:
Expand Down
16 changes: 11 additions & 5 deletions tests/pw/pages/basePage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { expect, Page, BrowserContext, Cookie, Request, Response, Locator, Frame, FrameLocator, JSHandle, ElementHandle } from '@playwright/test';
import { data } from '@utils/testData';
import { selector } from '@pages/selectors';
import { helpers } from '@utils/helpers';

const { BASE_URL } = process.env;

Expand Down Expand Up @@ -210,8 +211,8 @@ export class BasePage {
}

// click & wait for load state to complete
async clickAndWaitForLoadState(selector: string): Promise<void> {
await Promise.all([this.waitForLoadState(), this.page.locator(selector).click()]);
async clickAndWaitForLoadState(selector: string, state: 'load' | 'domcontentloaded' | 'networkidle' = 'domcontentloaded', options?: { timeout?: number }): Promise<void> {
await Promise.all([this.waitForLoadState(state, options), this.page.locator(selector).click()]);
}

// click & wait for navigation to complete
Expand Down Expand Up @@ -1425,10 +1426,15 @@ export class BasePage {
}
}

// multiple elements to be visible
async multipleElementVisible(selectors: any) {
async multipleElementVisible(selectors: { [key: string]: any }) {
for (const selector in selectors) {
await this.toBeVisible(selectors[selector]);
if (helpers.isPlainObject(selectors[selector])) {
await this.multipleElementVisible(selectors[selector]);
} else if (typeof selectors[selector] === 'function') {
continue;
} else {
await this.toBeVisible(selectors[selector]);
}
}
}

Expand Down
110 changes: 107 additions & 3 deletions tests/pw/pages/commissionPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ const settingsAdmin = selector.admin.dokan.settings;
const vendors = selector.admin.dokan.vendors;
const productsAdmin = selector.admin.products;

const productsVendor = selector.vendor.product;
const ordersVendor = selector.vendor.orders;

export class CommissionPage extends AdminPage {
constructor(page: Page) {
super(page);
Expand Down Expand Up @@ -125,7 +128,6 @@ export class CommissionPage extends AdminPage {
// set commission for vendor
async setCommissionForVendor(sellerId: string, commission: commission) {
await this.gotoUntilNetworkidle(data.subUrls.backend.dokan.vendorDetailsEdit(sellerId));

await this.selectByValue(vendors.editVendor.commissionType, commission.commissionType);

// add commission
Expand Down Expand Up @@ -163,8 +165,6 @@ export class CommissionPage extends AdminPage {
// set commission to dokan subscription product
async setCommissionToDokanSubscriptionProduct(productId: string, commission: commission) {
await this.gotoUntilNetworkidle(data.subUrls.backend.wc.productDetails(productId));

// add commission
await this.click(productsAdmin.product.subMenus.commission);

// add commission
Expand All @@ -186,4 +186,108 @@ export class CommissionPage extends AdminPage {
// metabox elements are visible
await this.multipleElementVisible(selector.admin.wooCommerce.orders.commissionMetaBox);
}

// view suborders metabox
async viewSubOrdersMetaBox(orderId: string) {
await this.gotoUntilNetworkidle(data.subUrls.backend.orderDetails(orderId));

// metabox elements are visible
await this.multipleElementVisible(selector.admin.wooCommerce.orders.subOrdersMetaBox);
}

// view related orders metabox
async viewRelatedOrdersMetaBox(orderId: string) {
await this.gotoUntilNetworkidle(data.subUrls.backend.orderDetails(orderId));

// metabox elements are visible
await this.multipleElementVisible(selector.admin.wooCommerce.orders.relatedOrdersMetaBox);
}

// view commission on product list
async viewCommissionOnProductList() {
await this.gotoUntilNetworkidle(data.subUrls.backend.wc.products);
// commission column & value is visible
await this.toBeVisible(selector.admin.products.commissionColumn);
await this.toBeVisible(selector.admin.products.firstRowProductCommission);
}

// view commission on order list
async viewCommissionOnOrderList() {
await this.gotoUntilNetworkidle(data.subUrls.backend.wc.orders);
// commission column & value is visible
await this.toBeVisible(selector.admin.wooCommerce.orders.commissionColumn);
await this.toBeVisible(selector.admin.wooCommerce.orders.firstRowOrderCommission);
}

// vendor view earning on product list
async vendorViewEarningOnProductList() {
await this.goto(data.subUrls.frontend.vDashboard.products);

// earning column & value is visible
await this.toBeVisible(selector.vendor.product.table.earningColumn);
await this.toBeVisible(selector.vendor.product.firstRowProductEarning);
}

// vendor view earning on add product details
async vendorViewEarningOnAddProductDetails() {
await this.goIfNotThere(data.subUrls.frontend.vDashboard.products);
await this.clickAndWaitForLoadState(selector.vendor.product.addNewProduct);
await this.toBeVisible(selector.vendor.product.earning);
}

// vendor view earning on edit product details
async vendorViewEarningOnEditProductDetails(productName: string) {
await this.goToProductEdit(productName);
await this.toBeVisible(selector.vendor.product.earning);
}

// vendor view earning on order list
async vendorViewEarningOnOrderList() {
await this.goto(data.subUrls.frontend.vDashboard.orders);

// earning column & value is visible
await this.toBeVisible(selector.vendor.orders.table.earningColumn);
await this.toBeVisible(selector.vendor.orders.firstRowOrderEarning);
}

// vendor view earning on order list
async vendorViewEarningOnOrderDetails(orderNumber: string) {
await this.goToOrderDetails(orderNumber);
// earning column & value is visible
await this.toBeVisible(selector.vendor.orders.generalDetails.earningAmount);
}

// todo : remove below functions and call from the original class

async goToOrderDetails(orderNumber: string): Promise<void> {
await this.searchOrder(orderNumber);
await this.clickAndWaitForLoadState(ordersVendor.view(orderNumber));
await this.toContainText(ordersVendor.orderDetails.orderNumber, orderNumber);
}

async searchOrder(orderNumber: string): Promise<void> {
await this.goIfNotThere(data.subUrls.frontend.vDashboard.orders);

await this.clearAndType(ordersVendor.search.searchInput, orderNumber);
await this.clickAndWaitForResponse(data.subUrls.frontend.vDashboard.orders, ordersVendor.search.searchBtn);
await this.toHaveCount(ordersVendor.numberOfRowsFound, 1);
await this.toBeVisible(ordersVendor.orderLink(orderNumber));
}

// go to product edit
async goToProductEdit(productName: string): Promise<void> {
await this.searchProduct(productName);
await this.removeAttribute(productsVendor.rowActions(productName), 'class'); // forcing the row actions to be visible, to avoid flakiness
await this.hover(productsVendor.productCell(productName));
await this.clickAndWaitForResponseAndLoadStateUntilNetworkIdle(data.subUrls.frontend.vDashboard.products, productsVendor.editProduct(productName));
await this.toHaveValue(productsVendor.title, productName);
}

// search product vendor dashboard
async searchProduct(productName: string): Promise<void> {
await this.goIfNotThere(data.subUrls.frontend.vDashboard.products);
await this.clearAndType(productsVendor.search.searchInput, productName);
await this.clickAndWaitForResponse(data.subUrls.frontend.vDashboard.products, productsVendor.search.searchBtn);
await this.toBeVisible(productsVendor.productLink(productName));
}
}
9 changes: 9 additions & 0 deletions tests/pw/pages/productsPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ export class ProductsPage extends AdminPage {
super(page);
}

// admin search product
async adminSearchProduct(productName: string) {
await this.gotoUntilNetworkidle(data.subUrls.backend.wc.products);
await this.clearAndType(selector.admin.products.search.searchInput, productName);
await this.clickAndWaitForLoadState(selector.admin.products.search.searchButton, 'networkidle');
await this.toBeVisible(selector.admin.products.productRow(productName));
}

// admin add product category
async addCategory(categoryName: string) {
await this.goIfNotThere(data.subUrls.backend.wc.addNewCategories);
Expand Down Expand Up @@ -323,6 +331,7 @@ export class ProductsPage extends AdminPage {

// price
await this.toBeVisible(productsVendor.price);
await this.toBeVisible(productsVendor.earning);

// discount price & Schedule
await this.click(productsVendor.discount.schedule);
Expand Down
88 changes: 74 additions & 14 deletions tests/pw/pages/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2979,43 +2979,95 @@ export const selector = {
// orders
orders: {
//table
commissionColumn: 'th#admin_commission',
numberOfRowsFound: '(//span[@class="displaying-num"])[1]',
noRowsFound: '//td[normalize-space(text())="No items found."]',

firstRow: '(//tbody[@id="the-list"]//tr)[1]',
firstRowOrderCommission: '(//tbody[@id="the-list"]//tr[not(@style="display: none;")])[1]//td[@class="admin_commission column-admin_commission"]',

commissionMetaBox: {
metaBoxDiv: 'div#dokan_commission_box',
commissionsText: '//h2[normalize-space()="Commissions"]',
table: {
itemColumn: '//div[@id="dokan_commission_box"]//th[normalize-space()="Item"]',
typeColumn: '//div[@id="dokan_commission_box"]//th[normalize-space()="Type"]',
rateColumn: '//div[@id="dokan_commission_box"]//th[normalize-space()="Rate"]',
qtyColumn: '//div[@id="dokan_commission_box"]//th[normalize-space()="Qty"]',
commissionColumn: '//div[@id="dokan_commission_box"]//th[normalize-space()="Commission"]',
},
orderItemInfo: 'div#dokan_commission_box table.woocommerce_order_items',
orderTotalInfo: 'div#dokan_commission_box div.wc-order-totals-items',
},

subOrdersMetaBox: {
metaBoxDiv: 'div#dokan_sub_or_related_orders',
subOrdersText: '//h2[normalize-space()="Sub orders"]',
subOrdersItemInfo: 'div#dokan_sub_or_related_orders div#woocommerce-order-items',
table: {
orderColumn: '//div[@id="dokan_sub_or_related_orders"]//th[normalize-space()="Order"]',
dateColumn: '//div[@id="dokan_sub_or_related_orders"]//th[normalize-space()="Date"]',
statusColumn: '//div[@id="dokan_sub_or_related_orders"]//th[normalize-space()="Status"]',
totalColumn: '//div[@id="dokan_sub_or_related_orders"]//th[normalize-space()="Total"]',
vendorColumn: '//div[@id="dokan_sub_or_related_orders"]//th[normalize-space()="Vendor"]',
},
subOrderTable: 'div#dokan_sub_or_related_orders table.woocommerce_order_items',
},

relatedOrdersMetaBox: {
metaBoxDiv: 'div#dokan_sub_or_related_orders',
relatedOrdersText: '//h2[normalize-space()="Related orders"]',
relatedOrdersItemInfo: 'div#dokan_sub_or_related_orders div#woocommerce-order-items',
table: {
orderColumn: '//div[@id="dokan_sub_or_related_orders"]//th[normalize-space()="Order"]',
dateColumn: '//div[@id="dokan_sub_or_related_orders"]//th[normalize-space()="Date"]',
statusColumn: '//div[@id="dokan_sub_or_related_orders"]//th[normalize-space()="Status"]',
totalColumn: '//div[@id="dokan_sub_or_related_orders"]//th[normalize-space()="Total"]',
vendorColumn: '//div[@id="dokan_sub_or_related_orders"]//th[normalize-space()="Vendor"]',
},
relatedOrderTable: 'div#dokan_sub_or_related_orders table.woocommerce_order_items',
parentOrderRow: '//td[contains(.,"(Parent order)")]/..',
parentOrderVendor: '//td[contains(.,"(Parent order)")]/..//td[contains(.,"(no name)")]/..',
},
},
},

// Products
// products
products: {
// Products Menus
allProductsMenu: '//li[@id="menu-posts-product"]//a[text()="All Products"]',
addNewMenu: '//li[@id="menu-posts-product"]//a[text()="Add New"]',
categoriesMenu: '//li[@id="menu-posts-product"]//a[text()="Categories"]',
tagsMenu: '//li[@id="menu-posts-product"]//a[text()="Tags"]',
addOnsMenu: '//li[@id="menu-posts-product"]//a[text()="Add-ons"]',
attributesMenu: '//li[@id="menu-posts-product"]//a[text()="Attributes"]',
// products menus
menus: {
allProductsMenu: '//li[@id="menu-posts-product"]//a[text()="All Products"]',
addNewMenu: '//li[@id="menu-posts-product"]//a[text()="Add New"]',
categoriesMenu: '//li[@id="menu-posts-product"]//a[text()="Categories"]',
tagsMenu: '//li[@id="menu-posts-product"]//a[text()="Tags"]',
addOnsMenu: '//li[@id="menu-posts-product"]//a[text()="Add-ons"]',
attributesMenu: '//li[@id="menu-posts-product"]//a[text()="Attributes"]',
},

// search
search: {
searchInput: 'input#post-search-input',
searchButton: 'input#search-submit',
},

// table
commissionColumn: 'th#admin_commission',
numberOfRowsFound: '(//span[@class="displaying-num"])[1]',
noRowsFound: '//td[normalize-space(text())="No products found"]',
productRow: (productName: string) => `//a[@class="row-title" and normalize-space(text())='${productName}']/../../..`,
firstRowProductCommission: '(//tbody[@id="the-list"]//tr)[1]//td[@class="admin_commission column-admin_commission"]',
productCommission: (productName: string) => `//a[@class="row-title" and normalize-space(text())='${productName}']/../../..//td[@class="admin_commission column-admin_commission"]//bdi`,

// Product
// add new product
product: {
// Add New Product
productName: '#title',
// Product Data
// product data
productType: '#product-type',
virtual: '#\\_virtual',
downloadable: '#\\_downloadable',
// todo: group below locators

// Add New Product Sub Menus
// add new product sub menus
subMenus: {
general: '.general_options a',
inventory: '.inventory_options a',
Expand Down Expand Up @@ -3818,6 +3870,7 @@ export const selector = {
skuColumn: '//th[normalize-space()="SKU"]',
stockColumn: '//th[normalize-space()="Stock"]',
priceColumn: '//th[normalize-space()="Price"]',
earningColumn: '//th[normalize-space()="Earning"]',
typeColumn: '//th[normalize-space()="Type"]',
viewsColumn: '//th[normalize-space()="Views"]',
dateColumn: '//th[normalize-space()="Date"]',
Expand All @@ -3826,6 +3879,8 @@ export const selector = {
// product sub options
numberOfRowsFound: '#dokan-product-list-table tbody tr',
noProductsFound: '//td[normalize-space()="No product found"]',
firstRow: '(//table[@id="dokan-product-list-table"]//tbody//tr[not(@id="bulk-edit")])[1]',
firstRowProductEarning: '(//table[@id="dokan-product-list-table"]//tbody//tr[not(@id="bulk-edit")])[1]//td[@data-title="Earning"]',
productCell: (productName: string) => `//strong//a[contains(text(),'${productName}')]/../..`,
productLink: (productName: string) => `//strong//a[contains(text(),'${productName}')]`,
editProduct: (productName: string) => `//a[contains(text(),'${productName}')]/../..//span[@class="edit"]//a`,
Expand Down Expand Up @@ -3864,6 +3919,7 @@ export const selector = {
downloadable: '#\\_downloadable',
virtual: '#\\_virtual',
price: '#\\_regular_price',
earning: 'span.vendor-earning span.vendor-price',

// discount
discount: {
Expand Down Expand Up @@ -4250,6 +4306,8 @@ export const selector = {
},

numberOfRowsFound: '.dokan-table.dokan-table tbody tr',
firstRow: '(//table//tbody//tr)[1]',
firstRowOrderEarning: '(//table//tbody//tr)[1]//td[@class="dokan-order-earning"]',
// order details from table
orderTotalTable: (orderNumber: string) => `//strong[contains(text(),'Order ${orderNumber}')]/../../..//td[@class='dokan-order-total']//bdi`,
orderTotalAfterRefundTable: (orderNumber: string) => `///strong[contains(text(),'Order ${orderNumber}')]/../../..//td[@class='dokan-order-total']//ins//bdi`,
Expand Down Expand Up @@ -4283,8 +4341,10 @@ export const selector = {
// general details
generalDetails: {
generalDetailsDiv: '//strong[normalize-space()="General Details"]/../..',
orderDetails: '.list-unstyled.order-status',
customerDetails: '.list-unstyled.customer-details',
orderDetails: 'ul.list-unstyled.order-status',
earningFromOrder: 'li.earning-from-order',
earningAmount: 'li.earning-from-order span.amount',
customerDetails: 'ul.list-unstyled.customer-details',
},

// status
Expand Down
2 changes: 1 addition & 1 deletion tests/pw/pages/storeSupportsPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ export class StoreSupportsPage extends AdminPage {
if (ticketIsOpen) {
await this.toBeVisible(addReplyText);
} else {
await this.multipleElementVisible(closeTicketText);
await this.toBeVisible(closeTicketText);
}
await this.multipleElementVisible(replyBox);
}
Expand Down
Loading

0 comments on commit e0ce1a0

Please sign in to comment.