diff --git a/tests/pw/feature-map/feature-map.yml b/tests/pw/feature-map/feature-map.yml index c83dd63d57..32eaf05a65 100644 --- a/tests/pw/feature-map/feature-map.yml +++ b/tests/pw/feature-map/feature-map.yml @@ -1324,5 +1324,73 @@ vendor can delete booking resource: true vendor can add booking for guest customer: true vendor can add booking for existing customer: true + vendor can update booking product title: true + vendor can add booking product accommodation booking option: true + vendor can update booking product accommodation booking option: true + vendor can remove booking product accommodation booking option: true + vendor can update booking product category (single): true + vendor can add booking product category (multiple): true + vendor can remove booking product category (multiple): true + vendor can add multi-step booking product category (last category): true + vendor can add multi-step booking product category (any category): true + vendor can't add multi-step booking product category (any category): true + vendor can add booking product tags: true + vendor can remove booking product tags: true + vendor can create booking product tags: true + vendor can add booking product cover image: true + vendor can update booking product cover image: true + vendor can remove booking product cover image: true + vendor can add booking product gallery image: true + vendor can update booking product gallery image: true + vendor can remove booking product gallery image: true + vendor can add booking product short description: true + vendor can update booking product short description: true + vendor can remove booking product short description: true + vendor can update booking product description: true + vendor can add booking product virtual option: true + vendor can remove booking product virtual option: true + vendor can add booking product inventory options (SKU): true + vendor can update booking product inventory options (SKU): true + vendor can remove booking product inventory options (SKU): true + vendor can add booking product inventory options (stock status): true + vendor can add booking product inventory options (stock management): true + vendor can update booking product inventory options (stock management): true + vendor can remove booking product inventory options (stock management): true + vendor can add booking product inventory options (allow single quantity): true + vendor can remove booking product inventory options (allow single quantity): true + vendor can add booking product other options (product status): true + vendor can add booking product other options (visibility): true + vendor can add booking product shipping: true + vendor can update booking product shipping: true + vendor can remove booking product shipping: true + vendor can add booking product tax: true + vendor can add booking product tax (with tax class): true + vendor can add booking product duration: true + vendor can update booking product duration: true + vendor can add booking product basic options: true + vendor can add booking product availability: true + vendor can update booking product availability: true + vendor can add booking product costs: true + vendor can update booking product costs: true + vendor can remove booking product costs: true + vendor can add booking product extra options (persons): true + vendor can add booking product extra options (person type): true + vendor can update booking product extra options (person type): true + vendor can remove booking product extra options (person type): true + vendor can add booking product extra options (resource): true + vendor can update booking product extra options (resource): true + vendor can remove booking product extra options (resource): true + vendor can add booking product attribute: true + vendor can't add already added booking product attribute: true + vendor can create booking product attribute term: true + vendor can remove booking product attribute: true + vendor can remove booking product attribute term: true + vendor can add booking product geolocation (individual): true + vendor can update booking product geolocation (individual): true + vendor can remove booking product geolocation (individual): true + vendor can add booking product addon: true + vendor can import booking product addon: true + vendor can export booking product addon: true + vendor can remove booking product addon: true customer: customer can buy bookable product: true diff --git a/tests/pw/pages/commissionPage.ts b/tests/pw/pages/commissionPage.ts index 49efd3325a..3f0dd3d204 100644 --- a/tests/pw/pages/commissionPage.ts +++ b/tests/pw/pages/commissionPage.ts @@ -17,17 +17,22 @@ export class CommissionPage extends AdminPage { // add commission async addCommission(commission: commission) { - await this.selectByValue(setupWizardAdmin.commissionType, commission.commissionType); if (commission.commissionType === 'fixed') { + await this.selectByValue(setupWizardAdmin.commissionType, commission.commissionType); + await this.clearAndType(setupWizardAdmin.percentage, commission.commissionPercentage); await this.clearAndType(setupWizardAdmin.fixed, commission.commissionFixed); } else { + await this.selectByValueAndWaitForResponse(data.subUrls.api.dokan.multistepCategories, setupWizardAdmin.commissionType, commission.commissionType); + if (commission.commissionCategory.allCategory) { await this.clearAndType(setupWizardAdmin.categoryPercentage(commission.commissionCategory.category), commission.commissionPercentage); await this.clearAndType(setupWizardAdmin.categoryFixed(commission.commissionCategory.category), commission.commissionFixed); } else { const categoryExpanded = await this.isVisible(setupWizardAdmin.expandedCategories); - if (!categoryExpanded) await this.clickIfVisible(setupWizardAdmin.expandCategories); + if (!categoryExpanded) { + await this.click(setupWizardAdmin.expandCategories); + } await this.clearAndType(setupWizardAdmin.categoryPercentageById(commission.commissionCategory.category), commission.commissionPercentage); await this.clearAndType(setupWizardAdmin.categoryFixedById(commission.commissionCategory.category), commission.commissionFixed); } @@ -45,7 +50,9 @@ export class CommissionPage extends AdminPage { await this.toHaveValue(settingsAdmin.selling.categoryFixed(commission.commissionCategory.category), commission.commissionFixed); } else { const categoryExpanded = await this.isVisible(setupWizardAdmin.expandedCategories); - if (!categoryExpanded) await this.clickIfVisible(setupWizardAdmin.expandCategories); + if (!categoryExpanded) { + await this.click(setupWizardAdmin.expandCategories); + } await this.toHaveValue(settingsAdmin.selling.categoryPercentageById(commission.commissionCategory.category), commission.commissionPercentage); await this.toHaveValue(settingsAdmin.selling.categoryFixedById(commission.commissionCategory.category), commission.commissionFixed); } @@ -80,7 +87,13 @@ export class CommissionPage extends AdminPage { // assert values await this.goToDokanSettings(); - await this.click(settingsAdmin.menus.sellingOptions); + + if (commission.commissionType === 'fixed') { + await this.click(settingsAdmin.menus.sellingOptions); + } else { + await this.clickAndAcceptAndWaitForResponse(data.subUrls.api.dokan.multistepCategories, settingsAdmin.menus.sellingOptions); + } + await this.assertCommission(commission); } @@ -104,12 +117,12 @@ export class CommissionPage extends AdminPage { // set commission for vendor async setCommissionForVendor(sellerId: string, commission: commission) { await this.goto(data.subUrls.backend.dokan.vendorDetailsEdit(sellerId)); - // await this.click(vendors.editVendor.editVendorIcon); await this.selectByValue(vendors.editVendor.commissionType, commission.commissionType); // add commission await this.addCommission(commission); + await this.wait(1); // todo: resolve in future; test failed for fixed commission await this.clickAndWaitForResponse(data.subUrls.api.dokan.stores, vendors.editVendor.saveChanges); await this.click(vendors.editVendor.closeUpdateSuccessModal); diff --git a/tests/pw/pages/customerPage.ts b/tests/pw/pages/customerPage.ts index c9d47fde07..45c02b8958 100644 --- a/tests/pw/pages/customerPage.ts +++ b/tests/pw/pages/customerPage.ts @@ -117,7 +117,9 @@ export class CustomerPage extends BasePage { await this.clearAndType(customerDashboard.bankIban, customerInfo.bankIban); } + // check if terms and conditions is visible await this.clickIfVisible(customerDashboard.termsAndConditions); + // purchase subscription pack if enabled const subscriptionPackIsVisible = await this.isVisible(customerDashboard.subscriptionPack); if (subscriptionPackIsVisible) await this.selectByLabel(selector.vendor.vRegistration.subscriptionPack, data.predefined.vendorSubscription.nonRecurring); await this.clickAndWaitForResponseAndLoadState(data.subUrls.frontend.becomeVendor, customerDashboard.becomeAVendor, 302); diff --git a/tests/pw/pages/selectors.ts b/tests/pw/pages/selectors.ts index 15dc8bca28..252b6e9320 100644 --- a/tests/pw/pages/selectors.ts +++ b/tests/pw/pages/selectors.ts @@ -692,8 +692,8 @@ export const selector = { expandedCategories: '(//i[contains(@class,"far fa-minus-square")]/..)[1]', categoryPercentage: (category: string) => `//p[contains(text(),'${category} ')]/../..//input[@id='percentage_commission']`, categoryFixed: (category: string) => `//p[contains(text(),'${category} ')]/../..//input[@id='fixed_commission']`, - categoryPercentageById: (category: string) => `//p[contains(text(), '(${category})')]/../..//input[@id='percentage_commission']`, - categoryFixedById: (category: string) => `//p[contains(text(), '(${category})')]/../..//input[@id='fixed_commission']`, + categoryPercentageById: (category: string) => `//span[contains(text(), '#${category}')]/../../..//input[@id='percentage_commission']`, + categoryFixedById: (category: string) => `//span[contains(text(), '#${category}')]/../../..//input[@id='fixed_commission']`, // Edit Options cancelEdit: '//div[contains(@class, "action-links footer")]//button[contains(text(),"Cancel")]', @@ -2072,8 +2072,8 @@ export const selector = { expandedCategories: '(//i[contains(@class,"far fa-minus-square")]/..)[1]', categoryPercentage: (category: string) => `//p[contains(text(),'${category}')]/../..//input[@id='percentage_commission']`, categoryFixed: (category: string) => `//p[contains(text(),'${category}')]/../..//input[@id='fixed_commission']`, - categoryPercentageById: (category: string) => `//p[contains(text(),'(${category})')]/../..//input[@id='percentage_commission']`, - categoryFixedById: (category: string) => `//p[contains(text(),'(${category})')]/../..//input[@id='fixed_commission']`, + categoryPercentageById: (category: string) => `//span[contains(text(), '#${category}')]/../../..//input[@id='percentage_commission']`, + categoryFixedById: (category: string) => `//span[contains(text(), '#${category}')]/../../..//input[@id='fixed_commission']`, shippingFeeRecipient: (feeReceiver: string) => `//label[contains(@for,'${feeReceiver}-shipping_fee_recipient')]`, productTaxFeeRecipient: (feeReceiver: string) => `//label[contains(@for,'${feeReceiver}-tax_fee_recipient')]`, shippingTaxFeeRecipient: (feeReceiver: string) => `//label[contains(@for,'${feeReceiver}-shipping_tax_fee_recipient')]`, @@ -2628,8 +2628,8 @@ export const selector = { expandedCategories: '(//i[contains(@class,"far fa-minus-square")]/..)[1]', categoryPercentage: (category: string) => `//p[text()='${category}']/../..//input[@id='percentage_commission']`, categoryFixed: (category: string) => `//p[text()='${category}']/../..//input[@id='fixed_commission']`, - categoryPercentageById: (category: string) => `//p[contains(text(), '(${category})')]/../..//input[@id='percentage_commission']`, - categoryFixedById: (category: string) => `//p[contains(text(), '(${category})')]/../..//input[@id='fixed_commission']`, + categoryPercentageById: (category: string) => `//span[contains(text(), '#${category}')]/../../..//input[@id='percentage_commission']`, + categoryFixedById: (category: string) => `//span[contains(text(), '#${category}')]/../../..//input[@id='fixed_commission']`, // Withdraw payPal: '//label[@for="withdraw_methods[paypal]" and @class="switch-label"]', @@ -3159,8 +3159,8 @@ export const selector = { expandedCategories: '(//i[contains(@class,"far fa-minus-square")]/..)[1]', categoryPercentage: (category: string) => `//p[text()='${category}']/../..//input[@id='percentage_commission']`, categoryFixed: (category: string) => `//p[text()='${category}']/../..//input[@id='fixed_commission']`, - categoryPercentageById: (category: string) => `//p[contains(text(), '(${category})')]/../..//input[@id='percentage_commission']`, - categoryFixedById: (category: string) => `//p[contains(text(), '(${category})')]/../..//input[@id='fixed_commission']`, + categoryPercentageById: (category: string) => `//span[contains(text(), '#${category}')]/../../..//input[@id='percentage_commission']`, + categoryFixedById: (category: string) => `//span[contains(text(), '#${category}')]/../../..//input[@id='fixed_commission']`, }, // Vendor @@ -5222,27 +5222,33 @@ export const selector = { // Create Booking Product booking: { - viewProduct: '.view-product', + viewProduct: 'a.view-product', productName: '#post_title', - ProductImage: '.dokan-feat-image-btn', - virtual: '#\\_virtual', - accommodationBooking: '#\\_is_dokan_accommodation', + ProductImage: 'a.dokan-feat-image-btn', + virtual: 'input#\\_virtual', + accommodationBooking: 'input#\\_is_dokan_accommodation', productCategory: '#select2-product_cat-container', productCategoryInput: '.select2-search--dropdown > .select2-search__field', - tags: '.select2-search__field', + // tags + tags: { + tagInput: '//select[@id="product_tag"]/..//input[@class="select2-search__field"]', + searchedTag: (tagName: string) => `//li[@class="select2-results__option select2-results__option--highlighted" and normalize-space(text())="${tagName}"]`, + selectedTags: (tagName: string) => `//li[@class="select2-selection__choice" and contains(., "${tagName}")]`, + removeSelectedTags: (tagName: string) => `//li[@class="select2-selection__choice" and contains(., "${tagName}")]//span[@class="select2-selection__choice__remove"]`, + }, // Accommodation Booking Options - minimumNumberOfNightsAllowedInABooking: '#\\_wc_booking_min_duration', - maximumNumberOfNightsAllowedInABooking: '#\\_wc_booking_max_duration', - checkInTime: '#\\_dokan_accommodation_checkin_time', - checkOutTime: '#\\_dokan_accommodation_checkout_time', + minimumNumberOfNightsAllowed: 'input#\\_wc_booking_min_duration', + maximumNumberOfNightsAllowed: 'input#\\_wc_booking_max_duration', + checkInTime: 'input#\\_dokan_accommodation_checkin_time', + checkOutTime: 'input#\\_dokan_accommodation_checkout_time', // General Booking Options bookingDurationType: '#\\_wc_booking_duration_type', bookingDuration: 'input#\\_wc_booking_duration', + bookingDurationUnit: '#\\_wc_booking_duration_unit', bookingDurationMin: 'input#\\_wc_booking_min_duration', bookingDurationMax: 'input#\\_wc_booking_max_duration', - bookingDurationUnit: '#\\_wc_booking_duration_unit', calendarDisplayMode: '#\\_wc_booking_calendar_display_mode', @@ -5274,7 +5280,7 @@ export const selector = { maximumBookingWindowIntoTheFutureDateUnit: '#\\_wc_booking_max_date_unit', requireABufferPeriodOfMonthsBetweenBookings: '#\\_wc_booking_buffer_period', adjacentBuffering: '#\\_wc_booking_apply_adjacent_buffer', - allDatesAre: '#\\_wc_booking_default_date_availability', + allDatesAvailability: '#\\_wc_booking_default_date_availability', checkRulesAgainst: '#\\_wc_booking_check_availability_against', restrictStartAndEndDays: '#dokan_booking_has_restricted_days_field', sunday: '#\\_wc_booking_restricted_days\\[0\\]', @@ -5313,34 +5319,38 @@ export const selector = { // Extra Options // Has Persons - hasPersons: '#\\_wc_booking_has_persons', - minPersons: '#\\_wc_booking_min_persons_group', - maxPersons: '#\\_wc_booking_max_persons_group', - multiplyAllCostsByPersonCount: '#\\_wc_booking_person_cost_multiplier', - countPersonsAsBookings: '#\\_wc_booking_person_qty_multiplier', - enablePersonTypes: '#\\_wc_booking_has_person_types', + hasPersons: 'input#\\_wc_booking_has_persons', + minPersons: 'div#bookings_persons #\\_wc_booking_min_persons_group', + maxPersons: 'div#bookings_persons #\\_wc_booking_max_persons_group', + multiplyAllCostsByPersonCount: 'div#bookings_persons #\\_wc_booking_person_cost_multiplier', + countPersonsAsBookings: 'div#bookings_persons #\\_wc_booking_person_qty_multiplier', + enablePersonTypes: 'div#bookings_persons #\\_wc_booking_has_person_types', // Add Person - addPersonType: '.add_person', - personTypeName: '//label[contains(text(),"Person Type Name:")]/..//input', - personBaseCost: '//label[contains(text(),"Base Cost:")]/..//input', - personBlockCost: '//label[contains(text(),"Block Cost:")]/..//input', - description: '.person_description', - min: '//label[contains(text(),"Min:")]/..//input', - max: '//label[contains(text(),"Max:")]/..//input', - unlink: '.unlink_booking_person', // invokes default js alert + addPersonType: 'button.add_person', + person: { + typeName: '//div[@id="bookings_persons"]//label[contains(text(),"Person Type Name:")]/..//input', + baseCost: '//div[@id="bookings_persons"]//label[contains(text(),"Base Cost:")]/..//input', + blockCost: '//div[@id="bookings_persons"]//label[contains(text(),"Block Cost:")]/..//input', + description: 'input.person_description', + min: '//div[@id="bookings_persons"]//label[contains(text(),"Min:")]/..//input', + max: '//div[@id="bookings_persons"]//label[contains(text(),"Max:")]/..//input', + }, + unlink: 'button.unlink_booking_person', // invokes default js alert + remove: 'button.remove_booking_person', + confirmRemove: 'button.swal2-confirm', // Has Resources - hasResources: '#\\_wc_booking_has_resources', + hasResources: 'input#\\_wc_booking_has_resources', // Add Resource - label: '#\\_wc_booking_resource_label', - resourcesAre: '#\\_wc_booking_resources_assignment', - addResourceId: '.add_resource_id', - addResource: '.add_resource', - resourceBaseCost: '//label[contains(text(),"Base Cost:")]/..//input', - resourceBlockCost: '//label[contains(text(),"Block Cost:")]/..//input', - removeResource: '.remove_booking_resource.button', // invokes default js alert + label: 'div#bookings_resources input#\\_wc_booking_resource_label', + resourcesAllocation: 'div#bookings_resources select#\\_wc_booking_resources_assignment', + addResourceId: 'div#bookings_resources select.add_resource_id', + addResource: 'button.add_resource', + resourceBaseCost: '//div[@id="bookings_resources"]//label[contains(text(),"Base Cost:")]/..//input', + resourceBlockCost: '//div[@id="bookings_resources"]//label[contains(text(),"Block Cost:")]/..//input', + removeResource: 'button.remove_booking_resource', // invokes default js alert // Short Description shortDescriptionIframe: '.dokan-product-short-description iframe', @@ -5702,8 +5712,10 @@ export const selector = { // tags tags: { tagInput: '//div[@class="dokan-form-group dokan-auction-tags"]//input[@class="select2-search__field"]', - searchedTag: (tagName: string) => `//li[contains(@class,"select2-results__option") and contains(@id, "select2-product_tag-result") and normalize-space(text())="${tagName}"]`, - nonCreatedTag: (tagName: string) => `//li[@class="select2-results__option select2-results__option--highlighted" and normalize-space(text())="${tagName}"]`, + // todo: remove below lines if the behavior is actually changed + // searchedTag: (tagName: string) => `//li[contains(@class,"select2-results__option") and contains(@id, "select2-product_tag-result") and normalize-space(text())="${tagName}"]`, + // nonCreatedTag: (tagName: string) => `//li[@class="select2-results__option select2-results__option--highlighted" and normalize-space(text())="${tagName}"]`, + searchedTag: (tagName: string) => `//li[@class="select2-results__option select2-results__option--highlighted" and normalize-space(text())="${tagName}"]`, selectedTags: (tagName: string) => `//li[@class="select2-selection__choice" and contains(., "${tagName}")]`, removeSelectedTags: (tagName: string) => `//li[@class="select2-selection__choice" and contains(., "${tagName}")]//span[@class="select2-selection__choice__remove"]`, }, diff --git a/tests/pw/pages/settingsPage.ts b/tests/pw/pages/settingsPage.ts index 4cd275bd81..a1006db8b9 100644 --- a/tests/pw/pages/settingsPage.ts +++ b/tests/pw/pages/settingsPage.ts @@ -3,7 +3,6 @@ import { AdminPage } from '@pages/adminPage'; import { selector } from '@pages/selectors'; import { data } from '@utils/testData'; import { dokanSettings } from '@utils/interfaces'; -import { helpers } from '@utils/helpers'; const { DOKAN_PRO } = process.env; @@ -142,8 +141,8 @@ export class SettingsPage extends AdminPage { // save settings await this.clickAndWaitForResponseAndLoadState(data.subUrls.ajax, settingsAdmin.saveChanges); - await this.toHaveValue(settingsAdmin.selling.percentage, helpers.priceStringWithDecimal(Number(selling.commission.commissionPercentage), 'ES')); - await this.toHaveValue(settingsAdmin.selling.fixed, helpers.priceStringWithDecimal(Number(selling.commission.commissionFixed), 'ES')); + await this.toHaveValue(settingsAdmin.selling.percentage, selling.commission.commissionPercentage); + await this.toHaveValue(settingsAdmin.selling.fixed, selling.commission.commissionFixed); } // Admin Set Dokan Withdraw Settings diff --git a/tests/pw/pages/vendorAuctionsPage.ts b/tests/pw/pages/vendorAuctionsPage.ts index b03aca0d78..ec9bf05def 100644 --- a/tests/pw/pages/vendorAuctionsPage.ts +++ b/tests/pw/pages/vendorAuctionsPage.ts @@ -324,16 +324,23 @@ export class AuctionsPage extends VendorPage { } // add product tags - async addProductTags(productName: string, tags: string[], create = false): Promise { + async addProductTags(productName: string, tags: string[]): Promise { + // async addProductTags(productName: string, tags: string[], create = false): Promise { await this.goToAuctionProductEditById(productName); for (const tag of tags) { await this.clearAndType(auctionProductsVendor.auction.tags.tagInput, tag); - if (create) { - await this.click(auctionProductsVendor.auction.tags.nonCreatedTag(tag)); - } else { - await this.click(auctionProductsVendor.auction.tags.searchedTag(tag)); - } + await this.toBeVisible(auctionProductsVendor.auction.tags.searchedTag(tag)); + await this.click(auctionProductsVendor.auction.tags.searchedTag(tag)); await this.toBeVisible(auctionProductsVendor.auction.tags.selectedTags(tag)); + + // todo: remove below lines if the behavior is actually changed + // await this.clearAndType(auctionProductsVendor.auction.tags.tagInput, tag); + // if (create) { + // await this.click(auctionProductsVendor.auction.tags.nonCreatedTag(tag)); + // } else { + // await this.click(auctionProductsVendor.auction.tags.searchedTag(tag)); + // } + // await this.toBeVisible(auctionProductsVendor.auction.tags.selectedTags(tag)); } await this.saveProduct(); @@ -585,6 +592,7 @@ export class AuctionsPage extends VendorPage { await this.toBeVisible(productsVendor.attribute.savedAttribute(attribute.attributeName)); } + // can't add already added attribute async cantAddAlreadyAddedAttribute(productName: string, attributeName: string): Promise { await this.goToAuctionProductEditById(productName); await this.toBeVisible(productsVendor.attribute.savedAttribute(attributeName)); diff --git a/tests/pw/pages/vendorBookingPage.ts b/tests/pw/pages/vendorBookingPage.ts index 6107160c08..0fa8ba0cdc 100644 --- a/tests/pw/pages/vendorBookingPage.ts +++ b/tests/pw/pages/vendorBookingPage.ts @@ -6,9 +6,12 @@ import { data } from '@utils/testData'; import { helpers } from '@utils/helpers'; import { product, bookings, bookingResource } from '@utils/interfaces'; +const { DOKAN_PRO } = process.env; + // selectors const bookingProductsAdmin = selector.admin.products; const bookingProductsVendor = selector.vendor.vBooking; +const productsVendor = selector.vendor.product; export class BookingPage extends VendorPage { constructor(page: Page) { @@ -27,14 +30,14 @@ export class BookingPage extends VendorPage { await this.clearAndType(bookingProductsAdmin.product.productName, product.productName()); await this.selectByValue(bookingProductsAdmin.product.productType, product.productType); await this.click(bookingProductsAdmin.product.subMenus.general); - await this.selectByValue(bookingProductsAdmin.product.bookingDurationType, product.bookingDurationType); - await this.clearAndType(bookingProductsAdmin.product.bookingDurationMax, product.bookingDurationMax); + await this.selectByValue(bookingProductsAdmin.product.bookingDurationType, product.duration.bookingDurationType); + await this.clearAndType(bookingProductsAdmin.product.bookingDurationMax, product.duration.bookingDurationMax); await this.selectByValue(bookingProductsAdmin.product.calendarDisplayMode, product.calendarDisplayMode); // Costs await this.click(bookingProductsAdmin.product.subMenus.bookingCosts); - await this.clearAndType(bookingProductsAdmin.product.baseCost, product.baseCost); - await this.clearAndType(bookingProductsAdmin.product.blockCost, product.blockCost); + await this.clearAndType(bookingProductsAdmin.product.baseCost, product.costs.baseCost); + await this.clearAndType(bookingProductsAdmin.product.blockCost, product.costs.blockCost); // Category await this.click(bookingProductsAdmin.product.category(product.category)); @@ -58,6 +61,10 @@ export class BookingPage extends VendorPage { await this.toHaveValue(bookingProductsVendor.booking.productName, productName); } + async goToBookingProductEditById(productId: string): Promise { + await this.gotoUntilNetworkidle(data.subUrls.frontend.vDashboard.bookingProductEdit(productId)); + } + // vendor booking render properly async vendorBookingRenderProperly() { await this.goIfNotThere(data.subUrls.frontend.vDashboard.booking); @@ -147,23 +154,23 @@ export class BookingPage extends VendorPage { async updateBookingProductFields(product: product['booking']) { await this.clearAndType(bookingProductsVendor.booking.productName, product.name); // await this.addProductCategory(product.category); - // general booking options - await this.selectByValue(bookingProductsVendor.booking.bookingDurationType, product.bookingDurationType); - await this.clearAndType(bookingProductsVendor.booking.bookingDurationMin, product.bookingDurationMin); - await this.clearAndType(bookingProductsVendor.booking.bookingDurationMax, product.bookingDurationMax); - await this.selectByValue(bookingProductsVendor.booking.bookingDurationUnit, product.bookingDurationUnit); + // booking duration options + await this.selectByValue(bookingProductsVendor.booking.bookingDurationType, product.duration.bookingDurationType); + await this.clearAndType(bookingProductsVendor.booking.bookingDurationMin, product.duration.bookingDurationMin); + await this.clearAndType(bookingProductsVendor.booking.bookingDurationMax, product.duration.bookingDurationMax); + await this.selectByValue(bookingProductsVendor.booking.bookingDurationUnit, product.duration.bookingDurationUnit); // calendar display mode await this.selectByValue(bookingProductsVendor.booking.calendarDisplayMode, product.calendarDisplayMode); await this.check(bookingProductsVendor.booking.enableCalendarRangePicker); // availability - await this.clearAndType(bookingProductsVendor.booking.maxBookingsPerBlock, product.maxBookingsPerBlock); - await this.clearAndType(bookingProductsVendor.booking.minimumBookingWindowIntoTheFutureDate, product.minimumBookingWindowIntoTheFutureDate); - await this.selectByValue(bookingProductsVendor.booking.minimumBookingWindowIntoTheFutureDateUnit, product.minimumBookingWindowIntoTheFutureDateUnit); - await this.clearAndType(bookingProductsVendor.booking.maximumBookingWindowIntoTheFutureDate, product.maximumBookingWindowIntoTheFutureDate); - await this.selectByValue(bookingProductsVendor.booking.maximumBookingWindowIntoTheFutureDateUnit, product.maximumBookingWindowIntoTheFutureDateUnit); + await this.clearAndType(bookingProductsVendor.booking.maxBookingsPerBlock, product.availability.maxBookingsPerBlock); + await this.clearAndType(bookingProductsVendor.booking.minimumBookingWindowIntoTheFutureDate, product.availability.minimumBookingWindowIntoTheFutureDate); + await this.selectByValue(bookingProductsVendor.booking.minimumBookingWindowIntoTheFutureDateUnit, product.availability.minimumBookingWindowIntoTheFutureDateUnit); + await this.clearAndType(bookingProductsVendor.booking.maximumBookingWindowIntoTheFutureDate, product.availability.maximumBookingWindowIntoTheFutureDate); + await this.selectByValue(bookingProductsVendor.booking.maximumBookingWindowIntoTheFutureDateUnit, product.availability.maximumBookingWindowIntoTheFutureDateUnit); // costs - await this.clearAndType(bookingProductsVendor.booking.baseCost, product.baseCost); - await this.clearAndType(bookingProductsVendor.booking.blockCost, product.blockCost); + await this.clearAndType(bookingProductsVendor.booking.baseCost, product.costs.baseCost); + await this.clearAndType(bookingProductsVendor.booking.blockCost, product.costs.blockCost); // todo: add more fields } @@ -312,4 +319,782 @@ export class BookingPage extends VendorPage { await this.clickAndWaitForResponse(data.subUrls.frontend.productDetails(helpers.slugify(productName)), selector.customer.cBookings.bookNow); await this.customerPage.placeOrder(); } + + // save product + async saveProduct() { + await this.clickAndWaitForResponseAndLoadState(data.subUrls.frontend.vDashboard.booking, bookingProductsVendor.booking.saveProduct, 302); + await this.toContainText(selector.vendor.product.updatedSuccessMessage, 'Success! The product has been saved successfully.'); + } + + // add product title + async addProductTitle(productName: string, title: string): Promise { + await this.goToBookingProductEditById(productName); + await this.clearAndType(bookingProductsVendor.booking.productName, title); + await this.saveProduct(); + await this.toHaveValue(bookingProductsVendor.booking.productName, title); + } + + // add product accommodation booking options + async addProductAccommodationBookingOptions(productName: string, accommodationBookingOptions: product['booking']['accommodationBookingOptions']): Promise { + await this.goToBookingProductEditById(productName); + await this.check(bookingProductsVendor.booking.accommodationBooking); + await this.clearAndType(bookingProductsVendor.booking.minimumNumberOfNightsAllowed, accommodationBookingOptions.minimumNumberOfNightsAllowed); + await this.clearAndType(bookingProductsVendor.booking.maximumNumberOfNightsAllowed, accommodationBookingOptions.maximumNumberOfNightsAllowed); + await this.clearAndType(bookingProductsVendor.booking.checkInTime, accommodationBookingOptions.checkInTime); + await this.clearAndType(bookingProductsVendor.booking.checkOutTime, accommodationBookingOptions.checkOutTime); + + await this.saveProduct(); + await this.toBeChecked(bookingProductsVendor.booking.accommodationBooking); + await this.toHaveValue(bookingProductsVendor.booking.minimumNumberOfNightsAllowed, accommodationBookingOptions.minimumNumberOfNightsAllowed); + await this.toHaveValue(bookingProductsVendor.booking.maximumNumberOfNightsAllowed, accommodationBookingOptions.maximumNumberOfNightsAllowed); + await this.toHaveValue(bookingProductsVendor.booking.checkInTime, accommodationBookingOptions.checkInTime); + await this.toHaveValue(bookingProductsVendor.booking.checkOutTime, accommodationBookingOptions.checkOutTime); + } + + // remove product accommodation booking options + async removeProductAccommodationBookingOptions(productName: string): Promise { + await this.goToBookingProductEditById(productName); + await this.uncheck(bookingProductsVendor.booking.accommodationBooking); + + await this.saveProduct(); + await this.notToBeChecked(bookingProductsVendor.booking.accommodationBooking); + await this.notToBeVisible(bookingProductsVendor.booking.minimumNumberOfNightsAllowed); + await this.notToBeVisible(bookingProductsVendor.booking.maximumNumberOfNightsAllowed); + await this.notToBeVisible(bookingProductsVendor.booking.checkInTime); + await this.notToBeVisible(bookingProductsVendor.booking.checkOutTime); + } + + // vendor add product category + async vendorAddProductCategory(category: string, multiple: boolean, neg?: boolean): Promise { + if (!multiple) { + await this.click(productsVendor.category.openCategoryModal); + } else { + await this.click(productsVendor.category.addNewCategory); + await this.click(productsVendor.category.selectACategory); + } + await this.toBeVisible(productsVendor.category.categoryModal); + await this.type(productsVendor.category.searchInput, category); + await this.toContainText(productsVendor.category.searchedResultText, category); + await this.click(productsVendor.category.searchedResult); + await this.click(productsVendor.category.categoryOnList(category)); + if (neg) { + await this.toBeDisabled(productsVendor.category.done); + return; + } + await this.click(productsVendor.category.done); + + const categoryAlreadySelectedPopup = await this.isVisible(productsVendor.category.categoryAlreadySelectedPopup); + if (categoryAlreadySelectedPopup) { + await this.click(productsVendor.category.categoryAlreadySelectedPopup); + await this.click(productsVendor.category.categoryModalClose); + } + await this.toBeVisible(productsVendor.category.selectedCategory(category)); + } + + // add product category + async addProductCategory(productName: string, categories: string[], multiple: boolean = false): Promise { + await this.goToBookingProductEditById(productName); + for (const category of categories) { + await this.vendorAddProductCategory(category, multiple); + } + await this.saveProduct(); + for (const category of categories) { + await this.toBeVisible(productsVendor.category.selectedCategory(category)); + } + } + + // remove product category + async removeProductCategory(productName: string, categories: string[]): Promise { + await this.goToBookingProductEditById(productName); + for (const category of categories) { + await this.click(productsVendor.category.removeSelectedCategory(category)); + await this.notToBeVisible(productsVendor.category.selectedCategory(category)); + } + await this.saveProduct(); + for (const category of categories) { + await this.notToBeVisible(productsVendor.category.selectedCategory(category)); + } + } + + // can't add product category + async cantAddCategory(productName: string, category: string): Promise { + await this.goToBookingProductEditById(productName); + await this.vendorAddProductCategory(category, false, true); + } + + // add product tags + async addProductTags(productName: string, tags: string[]): Promise { + await this.goToBookingProductEditById(productName); + for (const tag of tags) { + await this.clearAndType(bookingProductsVendor.booking.tags.tagInput, tag); + await this.toBeVisible(bookingProductsVendor.booking.tags.searchedTag(tag)); + await this.click(bookingProductsVendor.booking.tags.searchedTag(tag)); + await this.toBeVisible(bookingProductsVendor.booking.tags.selectedTags(tag)); + } + await this.saveProduct(); + for (const tag of tags) { + await this.toBeVisible(bookingProductsVendor.booking.tags.selectedTags(tag)); + } + } + + // remove product tags + async removeProductTags(productName: string, tags: string[]): Promise { + await this.goToBookingProductEditById(productName); + for (const tag of tags) { + await this.click(productsVendor.tags.removeSelectedTags(tag)); + await this.press('Escape'); // shift focus from element + } + await this.saveProduct(); + + for (const tag of tags) { + await this.notToBeVisible(productsVendor.tags.selectedTags(tag)); + } + } + + // add product cover image + async addProductCoverImage(productName: string, coverImage: string, removePrevious: boolean = false): Promise { + await this.goToBookingProductEditById(productName); + // remove previous cover image + if (removePrevious) { + await this.hover(productsVendor.image.coverImageDiv); + await this.click(productsVendor.image.removeFeatureImage); + await this.toBeVisible(productsVendor.image.uploadImageText); + } + await this.click(productsVendor.image.cover); + await this.uploadMedia(coverImage); + await this.saveProduct(); + await this.toHaveAttribute(productsVendor.image.uploadedFeatureImage, 'src', /.+/); // Ensures 'src' has any non-falsy value + await this.notToBeVisible(productsVendor.image.uploadImageText); + } + + // remove product cover image + async removeProductCoverImage(productName: string): Promise { + await this.goToBookingProductEditById(productName); + await this.hover(productsVendor.image.coverImageDiv); + await this.click(productsVendor.image.removeFeatureImage); + await this.saveProduct(); + await this.toHaveAttribute(productsVendor.image.uploadedFeatureImage, 'src', /^$/); + await this.toBeVisible(productsVendor.image.uploadImageText); + } + + // add product gallery images + async addProductGalleryImages(productName: string, galleryImages: string[], removePrevious: boolean = false): Promise { + await this.goToBookingProductEditById(productName); + // remove previous gallery images + if (removePrevious) { + const imageCount = await this.getElementCount(productsVendor.image.uploadedGalleryImage); + for (let i = 0; i < imageCount; i++) { + await this.hover(productsVendor.image.galleryImageDiv); + await this.click(productsVendor.image.removeGalleryImage); + } + await this.toHaveCount(productsVendor.image.uploadedGalleryImage, 0); + } + + for (const galleryImage of galleryImages) { + await this.click(productsVendor.image.gallery); + await this.uploadMedia(galleryImage); + } + await this.saveProduct(); + await this.toHaveCount(productsVendor.image.uploadedGalleryImage, galleryImages.length); + } + + // remove product gallery images + async removeProductGalleryImages(productName: string): Promise { + await this.goToBookingProductEditById(productName); + const imageCount = await this.getElementCount(productsVendor.image.uploadedGalleryImage); + for (let i = 0; i < imageCount; i++) { + await this.hover(productsVendor.image.galleryImageDiv); + await this.click(productsVendor.image.removeGalleryImage); + } + await this.saveProduct(); + await this.toHaveCount(productsVendor.image.uploadedGalleryImage, 0); + } + + // add product short description + async addProductShortDescription(productName: string, shortDescription: string): Promise { + await this.goToBookingProductEditById(productName); + await this.typeFrameSelector(productsVendor.shortDescription.shortDescriptionIframe, productsVendor.shortDescription.shortDescriptionHtmlBody, shortDescription); + await this.saveProduct(); + await this.toContainTextFrameLocator(productsVendor.shortDescription.shortDescriptionIframe, productsVendor.shortDescription.shortDescriptionHtmlBody, shortDescription); + } + + // add product description + async addProductDescription(productName: string, description: string): Promise { + await this.goToBookingProductEditById(productName); + await this.typeFrameSelector(productsVendor.description.descriptionIframe, productsVendor.description.descriptionHtmlBody, description); + await this.saveProduct(); + await this.toContainTextFrameLocator(productsVendor.description.descriptionIframe, productsVendor.description.descriptionHtmlBody, description); + } + + // add product virtual option + async addProductVirtualOption(productName: string, enable: boolean): Promise { + await this.goToBookingProductEditById(productName); + if (enable) { + await this.check(productsVendor.virtual); + } else { + await this.focus(productsVendor.virtual); + await this.uncheck(productsVendor.virtual); + } + await this.saveProduct(); + if (enable) { + await this.toBeChecked(productsVendor.virtual); + if (DOKAN_PRO) { + await this.notToBeVisible(productsVendor.shipping.shippingContainer); + } + } else { + await this.notToBeChecked(productsVendor.virtual); + } + } + + // add product inventory + async addProductInventory(productName: string, inventory: product['productInfo']['inventory'], choice: string): Promise { + await this.goToBookingProductEditById(productName); + + switch (choice) { + case 'sku': + await this.clearAndType(productsVendor.inventory.sku, inventory.sku); + break; + case 'stock-status': + await this.selectByValue(productsVendor.inventory.stockStatus, inventory.stockStatus); + break; + case 'stock-management': + await this.check(productsVendor.inventory.enableStockManagement); + await this.clearAndType(productsVendor.inventory.stockQuantity, inventory.stockQuantity); + await this.clearAndType(productsVendor.inventory.lowStockThreshold, inventory.lowStockThreshold); + await this.selectByValue(productsVendor.inventory.allowBackorders, inventory.backorders); + break; + case 'one-quantity': + if (inventory.oneQuantity) { + await this.check(productsVendor.inventory.allowOnlyOneQuantity); + } else { + await this.uncheck(productsVendor.inventory.allowOnlyOneQuantity); + } + break; + default: + break; + } + + await this.saveProduct(); + + // todo: replace switch with all method action and assertion as object member and loop through to call them + + switch (choice) { + case 'sku': + await this.toHaveValue(productsVendor.inventory.sku, inventory.sku); + break; + case 'stock-status': + await this.toHaveSelectedValue(productsVendor.inventory.stockStatus, inventory.stockStatus); + break; + case 'stock-management': + await this.toBeChecked(productsVendor.inventory.enableStockManagement); + await this.toHaveValue(productsVendor.inventory.stockQuantity, inventory.stockQuantity); + await this.toHaveValue(productsVendor.inventory.lowStockThreshold, inventory.lowStockThreshold); + await this.toHaveSelectedValue(productsVendor.inventory.allowBackorders, inventory.backorders); + await this.notToBeVisible(productsVendor.inventory.stockStatus); + break; + case 'one-quantity': + if (inventory.oneQuantity) { + await this.toBeChecked(productsVendor.inventory.allowOnlyOneQuantity); + } else { + await this.notToBeChecked(productsVendor.inventory.allowOnlyOneQuantity); + } + break; + default: + break; + } + } + // remove product inventory [stock management] + async removeProductInventory(productName: string): Promise { + await this.goToBookingProductEditById(productName); + await this.uncheck(productsVendor.inventory.enableStockManagement); + await this.saveProduct(); + await this.notToBeChecked(productsVendor.inventory.enableStockManagement); + } + + // add product other options (product status, visibility, purchase note, reviews) + async addProductOtherOptions(productName: string, otherOption: product['productInfo']['otherOptions'], choice: string): Promise { + await this.goToBookingProductEditById(productName); + + switch (choice) { + case 'status': + await this.selectByValue(productsVendor.otherOptions.productStatus, otherOption.status); + break; + case 'visibility': + await this.selectByValue(productsVendor.otherOptions.visibility, otherOption.visibility); + break; + case 'purchaseNote': + await this.clearAndType(productsVendor.otherOptions.purchaseNote, otherOption.purchaseNote); + break; + case 'reviews': + if (otherOption.enableReview) { + await this.check(productsVendor.otherOptions.enableProductReviews); + } else { + await this.uncheck(productsVendor.otherOptions.enableProductReviews); + } + break; + default: + break; + } + + await this.saveProduct(); + + switch (choice) { + case 'status': + await this.toHaveSelectedValue(productsVendor.otherOptions.productStatus, otherOption.status); + break; + case 'visibility': + await this.toHaveSelectedValue(productsVendor.otherOptions.visibility, otherOption.visibility); + break; + case 'purchaseNote': + await this.toHaveValue(productsVendor.otherOptions.purchaseNote, otherOption.purchaseNote); + break; + case 'reviews': + if (otherOption.enableReview) { + await this.toBeChecked(productsVendor.otherOptions.enableProductReviews); + } else { + await this.notToBeChecked(productsVendor.otherOptions.enableProductReviews); + } + break; + default: + break; + } + } + + // add product catalog mode + async addProductCatalogMode(productName: string, hidePrice: boolean = false): Promise { + await this.goToBookingProductEditById(productName); + await this.check(productsVendor.catalogMode.removeAddToCart); + if (hidePrice) await this.check(productsVendor.catalogMode.hideProductPrice); + await this.saveProduct(); + await this.toBeChecked(productsVendor.catalogMode.removeAddToCart); + if (hidePrice) await this.toBeChecked(productsVendor.catalogMode.hideProductPrice); + } + + // remove product catalog mode + async removeProductCatalogMode(productName: string, onlyPrice: boolean = false): Promise { + await this.goToBookingProductEditById(productName); + + if (onlyPrice) { + await this.uncheck(productsVendor.catalogMode.hideProductPrice); + } else { + await this.uncheck(productsVendor.catalogMode.removeAddToCart); + } + + await this.saveProduct(); + + if (onlyPrice) { + await this.notToBeChecked(productsVendor.catalogMode.hideProductPrice); + } else { + await this.notToBeChecked(productsVendor.catalogMode.removeAddToCart); + } + } + + // dokan pro features + + // add product shipping + async addProductShipping(productName: string, shipping: product['productInfo']['shipping']): Promise { + await this.goToBookingProductEditById(productName); + await this.check(productsVendor.shipping.requiresShipping); + await this.clearAndType(productsVendor.shipping.weight, shipping.weight); + await this.clearAndType(productsVendor.shipping.length, shipping.length); + await this.clearAndType(productsVendor.shipping.width, shipping.width); + await this.clearAndType(productsVendor.shipping.height, shipping.height); + await this.selectByLabel(productsVendor.shipping.shippingClass, shipping.shippingClass); + await this.saveProduct(); + await this.toBeChecked(productsVendor.shipping.requiresShipping); + await this.toHaveValue(productsVendor.shipping.weight, shipping.weight); + await this.toHaveValue(productsVendor.shipping.length, shipping.length); + await this.toHaveValue(productsVendor.shipping.width, shipping.width); + await this.toHaveValue(productsVendor.shipping.height, shipping.height); + await this.toHaveSelectedLabel(productsVendor.shipping.shippingClass, shipping.shippingClass); + } + // add product shipping + async removeProductShipping(productName: string): Promise { + await this.goToBookingProductEditById(productName); + await this.uncheck(productsVendor.shipping.requiresShipping); + await this.saveProduct(); + await this.notToBeChecked(productsVendor.shipping.requiresShipping); + } + + // add product tax + async addProductTax(productName: string, tax: product['productInfo']['tax'], hasClass: boolean = false): Promise { + await this.goToBookingProductEditById(productName); + await this.selectByValue(productsVendor.tax.status, tax.status); + if (hasClass) await this.selectByValue(productsVendor.tax.class, tax.class); + await this.saveProduct(); + await this.toHaveSelectedValue(productsVendor.tax.status, tax.status); + if (hasClass) await this.toHaveSelectedValue(productsVendor.tax.class, tax.class); + } + + // add product duration + async addProductDuration(productName: string, duration: product['booking']['duration']): Promise { + await this.goToBookingProductEditById(productName); + await this.selectByValue(bookingProductsVendor.booking.bookingDurationType, duration.bookingDurationType); + await this.clearAndType(bookingProductsVendor.booking.bookingDuration, duration.bookingDuration); + await this.selectByValue(bookingProductsVendor.booking.bookingDurationUnit, duration.bookingDurationUnit); + await this.clearAndType(bookingProductsVendor.booking.bookingDurationMin, duration.bookingDurationMin); + await this.clearAndType(bookingProductsVendor.booking.bookingDurationMax, duration.bookingDurationMax); + + await this.saveProduct(); + + await this.toHaveSelectedValue(bookingProductsVendor.booking.bookingDurationType, duration.bookingDurationType); + await this.toHaveValue(bookingProductsVendor.booking.bookingDuration, duration.bookingDuration); + await this.toHaveSelectedValue(bookingProductsVendor.booking.bookingDurationUnit, duration.bookingDurationUnit); + await this.toHaveValue(bookingProductsVendor.booking.bookingDurationMin, duration.bookingDurationMin); + await this.toHaveValue(bookingProductsVendor.booking.bookingDurationMax, duration.bookingDurationMax); + } + + // add product basic options + async addProductBasicOptions(productName: string, product: product['booking']): Promise { + await this.goToBookingProductEditById(productName); + await this.selectByValue(bookingProductsVendor.booking.calendarDisplayMode, product.calendarDisplayMode); + await this.check(bookingProductsVendor.booking.enableCalendarRangePicker); + await this.check(bookingProductsVendor.booking.requiresConfirmation); + await this.check(bookingProductsVendor.booking.canBeCancelled); + + await this.saveProduct(); + + await this.toHaveSelectedValue(bookingProductsVendor.booking.calendarDisplayMode, product.calendarDisplayMode); + await this.toBeChecked(bookingProductsVendor.booking.enableCalendarRangePicker); + await this.toBeChecked(bookingProductsVendor.booking.requiresConfirmation); + await this.toBeChecked(bookingProductsVendor.booking.canBeCancelled); + } + + // add product availability options + async addProductAvailability(productName: string, availability: product['booking']['availability']): Promise { + await this.goToBookingProductEditById(productName); + await this.clearAndType(bookingProductsVendor.booking.maxBookingsPerBlock, availability.maxBookingsPerBlock); + await this.clearAndType(bookingProductsVendor.booking.minimumBookingWindowIntoTheFutureDate, availability.minimumBookingWindowIntoTheFutureDate); + await this.selectByValue(bookingProductsVendor.booking.minimumBookingWindowIntoTheFutureDateUnit, availability.minimumBookingWindowIntoTheFutureDateUnit); + await this.clearAndType(bookingProductsVendor.booking.maximumBookingWindowIntoTheFutureDate, availability.maximumBookingWindowIntoTheFutureDate); + await this.selectByValue(bookingProductsVendor.booking.maximumBookingWindowIntoTheFutureDateUnit, availability.maximumBookingWindowIntoTheFutureDateUnit); + await this.clearAndType(bookingProductsVendor.booking.requireABufferPeriodOfMonthsBetweenBookings, availability.requireABufferPeriodOfMonthsBetweenBookings); + await this.check(bookingProductsVendor.booking.adjacentBuffering); + await this.selectByValue(bookingProductsVendor.booking.allDatesAvailability, availability.allDatesAvailability); + await this.selectByValue(bookingProductsVendor.booking.checkRulesAgainst, availability.checkRulesAgainst); + + await this.saveProduct(); + + await this.toHaveValue(bookingProductsVendor.booking.maxBookingsPerBlock, availability.maxBookingsPerBlock); + await this.toHaveValue(bookingProductsVendor.booking.minimumBookingWindowIntoTheFutureDate, availability.minimumBookingWindowIntoTheFutureDate); + await this.toHaveSelectedValue(bookingProductsVendor.booking.minimumBookingWindowIntoTheFutureDateUnit, availability.minimumBookingWindowIntoTheFutureDateUnit); + await this.toHaveValue(bookingProductsVendor.booking.maximumBookingWindowIntoTheFutureDate, availability.maximumBookingWindowIntoTheFutureDate); + await this.toHaveSelectedValue(bookingProductsVendor.booking.maximumBookingWindowIntoTheFutureDateUnit, availability.maximumBookingWindowIntoTheFutureDateUnit); + await this.toHaveValue(bookingProductsVendor.booking.requireABufferPeriodOfMonthsBetweenBookings, availability.requireABufferPeriodOfMonthsBetweenBookings); + await this.toBeChecked(bookingProductsVendor.booking.adjacentBuffering); + await this.toHaveSelectedValue(bookingProductsVendor.booking.allDatesAvailability, availability.allDatesAvailability); + await this.toHaveSelectedValue(bookingProductsVendor.booking.checkRulesAgainst, availability.checkRulesAgainst); + } + + // add product costs + async addProductCosts(productName: string, costs: product['booking']['costs']): Promise { + await this.goToBookingProductEditById(productName); + await this.clearAndType(bookingProductsVendor.booking.baseCost, costs.baseCost); + await this.clearAndType(bookingProductsVendor.booking.blockCost, costs.blockCost); + await this.clearAndType(bookingProductsVendor.booking.displayCost, costs.displayCost); + await this.saveProduct(); + await this.toHaveValue(bookingProductsVendor.booking.baseCost, costs.baseCost); + await this.toHaveValue(bookingProductsVendor.booking.blockCost, costs.blockCost); + await this.toHaveValue(bookingProductsVendor.booking.displayCost, costs.displayCost); + } + + // add product extra options + + // persons + async addProductPersons(productName: string, extraOptions: product['booking']['extraOptions']): Promise { + await this.goToBookingProductEditById(productName); + await this.focus(bookingProductsVendor.booking.hasPersons); + await this.check(bookingProductsVendor.booking.hasPersons); + await this.clearAndType(bookingProductsVendor.booking.minPersons, extraOptions.minPersons); + await this.clearAndType(bookingProductsVendor.booking.maxPersons, extraOptions.maxPersons); + await this.check(bookingProductsVendor.booking.multiplyAllCostsByPersonCount); + await this.check(bookingProductsVendor.booking.countPersonsAsBookings); + await this.saveProduct(); + await this.toBeChecked(bookingProductsVendor.booking.hasPersons); + await this.toHaveValue(bookingProductsVendor.booking.minPersons, extraOptions.minPersons); + await this.toHaveValue(bookingProductsVendor.booking.maxPersons, extraOptions.maxPersons); + await this.toBeChecked(bookingProductsVendor.booking.multiplyAllCostsByPersonCount); + await this.toBeChecked(bookingProductsVendor.booking.countPersonsAsBookings); + } + + // add person type + async addProductPersonType(productName: string, extraOptions: product['booking']['extraOptions']): Promise { + await this.goToBookingProductEditById(productName); + await this.focus(bookingProductsVendor.booking.hasPersons); + await this.check(bookingProductsVendor.booking.hasPersons); + await this.check(bookingProductsVendor.booking.enablePersonTypes); + await this.clickAndWaitForResponse(data.subUrls.ajax, bookingProductsVendor.booking.addPersonType); + await this.clearAndType(bookingProductsVendor.booking.person.typeName, extraOptions.person.typeName); + await this.clearAndType(bookingProductsVendor.booking.person.baseCost, extraOptions.person.baseCost); + await this.clearAndType(bookingProductsVendor.booking.person.blockCost, extraOptions.person.blockCost); + await this.clearAndType(bookingProductsVendor.booking.person.description, extraOptions.person.description); + await this.clearAndType(bookingProductsVendor.booking.person.min, extraOptions.person.min); + await this.clearAndType(bookingProductsVendor.booking.person.max, extraOptions.person.max); + + await this.saveProduct(); + + await this.toBeChecked(bookingProductsVendor.booking.hasPersons); + await this.toBeChecked(bookingProductsVendor.booking.enablePersonTypes); + await this.toHaveValue(bookingProductsVendor.booking.person.typeName, extraOptions.person.typeName); + await this.toHaveValue(bookingProductsVendor.booking.person.baseCost, extraOptions.person.baseCost); + await this.toHaveValue(bookingProductsVendor.booking.person.blockCost, extraOptions.person.blockCost); + await this.toHaveValue(bookingProductsVendor.booking.person.description, extraOptions.person.description); + await this.toHaveValue(bookingProductsVendor.booking.person.min, extraOptions.person.min); + await this.toHaveValue(bookingProductsVendor.booking.person.max, extraOptions.person.max); + } + + // remove product person + async removeProductPersonType(productName: string): Promise { + await this.goToBookingProductEditById(productName); + await this.focus(bookingProductsVendor.booking.remove); + await this.click(bookingProductsVendor.booking.remove); + await this.clickAndWaitForResponse(data.subUrls.ajax, bookingProductsVendor.booking.confirmRemove); + await this.notToBeVisible(bookingProductsVendor.booking.remove); //todo: replace with person id + } + + // resources + + // add product resource + async addProductResources(productName: string, extraOptions: product['booking']['extraOptions']): Promise { + await this.goToBookingProductEditById(productName); + await this.focus(bookingProductsVendor.booking.hasResources); + await this.check(bookingProductsVendor.booking.hasResources); + await this.clearAndType(bookingProductsVendor.booking.label, extraOptions.label); + await this.selectByValue(bookingProductsVendor.booking.resourcesAllocation, extraOptions.resourcesAllocation); + await this.selectByValue(bookingProductsVendor.booking.addResourceId, extraOptions.addResourceId); + await this.clickAndWaitForResponse(data.subUrls.ajax, bookingProductsVendor.booking.addResource); + await this.clearAndType(bookingProductsVendor.booking.resourceBaseCost, extraOptions.resource.baseCost); + await this.clearAndType(bookingProductsVendor.booking.resourceBlockCost, extraOptions.resource.blockCost); + + await this.saveProduct(); + + await this.toBeChecked(bookingProductsVendor.booking.hasResources); + await this.toHaveValue(bookingProductsVendor.booking.label, extraOptions.label); + await this.toHaveSelectedValue(bookingProductsVendor.booking.resourcesAllocation, extraOptions.resourcesAllocation); + await this.toHaveValue(bookingProductsVendor.booking.resourceBaseCost, extraOptions.resource.baseCost); + await this.toHaveValue(bookingProductsVendor.booking.resourceBlockCost, extraOptions.resource.blockCost); + } + + // remove product resource + async removeProductResource(productName: string): Promise { + await this.goToBookingProductEditById(productName); + await this.focus(bookingProductsVendor.booking.removeResource); + await this.clickAndAcceptAndWaitForResponse(data.subUrls.ajax, bookingProductsVendor.booking.removeResource); + await this.notToBeVisible(bookingProductsVendor.booking.removeResource); //todo: replace with resource id + } + + // add product linked products + async addProductLinkedProducts(productName: string, linkedProducts: product['productInfo']['linkedProducts'], choice: string): Promise { + await this.goToBookingProductEditById(productName); + switch (choice) { + case 'up-sells': + for (const linkedProduct of linkedProducts.upSells) { + await this.typeAndWaitForResponse(data.subUrls.ajax, productsVendor.linkedProducts.upSells, linkedProduct); + await this.click(productsVendor.linkedProducts.searchedResult(linkedProduct)); + await this.toBeVisible(productsVendor.linkedProducts.selectedUpSellProduct(linkedProduct)); + } + break; + case 'cross-sells': + for (const linkedProduct of linkedProducts.crossSells) { + await this.typeAndWaitForResponse(data.subUrls.ajax, productsVendor.linkedProducts.crossSells, linkedProduct); + await this.click(productsVendor.linkedProducts.searchedResult(linkedProduct)); + await this.toBeVisible(productsVendor.linkedProducts.selectedCrossSellProduct(linkedProduct)); + } + break; + default: + break; + } + + await this.saveProduct(); + + switch (choice) { + case 'up-sells': + for (const linkedProduct of linkedProducts.upSells) { + await this.toBeVisible(productsVendor.linkedProducts.selectedUpSellProduct(linkedProduct)); + } + break; + case 'cross-sells': + for (const linkedProduct of linkedProducts.crossSells) { + await this.toBeVisible(productsVendor.linkedProducts.selectedCrossSellProduct(linkedProduct)); + } + break; + default: + break; + } + } + + // add product linked products + async removeProductLinkedProducts(productName: string, linkedProducts: product['productInfo']['linkedProducts'], choice: string): Promise { + await this.goToBookingProductEditById(productName); + switch (choice) { + case 'up-sells': + for (const linkedProduct of linkedProducts.upSells) { + await this.click(productsVendor.linkedProducts.removeSelectedUpSellProduct(linkedProduct)); + await this.press('Escape'); // shift focus from element + } + break; + case 'cross-sells': + for (const linkedProduct of linkedProducts.crossSells) { + await this.click(productsVendor.linkedProducts.removeSelectedCrossSellProduct(linkedProduct)); + await this.press('Escape'); // shift focus from element + } + break; + default: + break; + } + + await this.saveProduct(); + + switch (choice) { + case 'up-sells': + for (const linkedProduct of linkedProducts.upSells) { + await this.notToBeVisible(productsVendor.linkedProducts.selectedUpSellProduct(linkedProduct)); + } + break; + case 'cross-sells': + for (const linkedProduct of linkedProducts.crossSells) { + await this.notToBeVisible(productsVendor.linkedProducts.selectedCrossSellProduct(linkedProduct)); + } + break; + default: + break; + } + } + + // add product attribute + async addProductAttribute(productName: string, attribute: product['productInfo']['attribute'], addTerm: boolean = false): Promise { + await this.goToBookingProductEditById(productName); + await this.selectByLabel(productsVendor.attribute.customAttribute, attribute.attributeName); + await this.clickAndWaitForResponse(data.subUrls.ajax, productsVendor.attribute.addAttribute); + await this.check(productsVendor.attribute.visibleOnTheProductPage); + await this.click(productsVendor.attribute.selectAll); + await this.notToHaveCount(productsVendor.attribute.attributeTerms, 0); + if (addTerm) { + await this.click(productsVendor.attribute.addNew); + await this.clearAndType(productsVendor.attribute.attributeTermInput, attribute.attributeTerm); + await this.clickAndWaitForResponse(data.subUrls.ajax, productsVendor.attribute.confirmAddAttributeTerm); + await this.toBeVisible(productsVendor.attribute.selectedAttributeTerm(attribute.attributeTerm)); + } + await this.clickAndWaitForResponse(data.subUrls.ajax, productsVendor.attribute.saveAttribute); + await this.saveProduct(); + await this.toBeVisible(productsVendor.attribute.savedAttribute(attribute.attributeName)); + } + + // can't add already added attribute + async cantAddAlreadyAddedAttribute(productName: string, attributeName: string): Promise { + await this.goToBookingProductEditById(productName); + await this.toBeVisible(productsVendor.attribute.savedAttribute(attributeName)); + await this.toHaveAttribute(productsVendor.attribute.disabledAttribute(attributeName), 'disabled', 'disabled'); + } + + // remove product attribute + async removeProductAttribute(productName: string, attribute: string): Promise { + await this.goToBookingProductEditById(productName); + await this.click(productsVendor.attribute.removeAttribute(attribute)); + await this.click(productsVendor.attribute.confirmRemoveAttribute); + await this.notToBeVisible(productsVendor.attribute.savedAttribute(attribute)); + await this.saveProduct(); + await this.notToBeVisible(productsVendor.attribute.savedAttribute(attribute)); + } + + // remove product attribute term + async removeProductAttributeTerm(productName: string, attribute: string, attributeTerm: string): Promise { + await this.goToBookingProductEditById(productName); + await this.click(productsVendor.attribute.savedAttribute(attribute)); + await this.click(productsVendor.attribute.removeSelectedAttributeTerm(attributeTerm)); + await this.press('Escape'); // shift focus from element + await this.notToBeVisible(productsVendor.attribute.selectedAttributeTerm(attributeTerm)); + await this.clickAndWaitForResponse(data.subUrls.ajax, productsVendor.attribute.saveAttribute); + await this.saveProduct(); + await this.click(productsVendor.attribute.savedAttribute(attribute)); + await this.notToBeVisible(productsVendor.attribute.selectedAttributeTerm(attributeTerm)); + } + + // dokan pro modules + + // add product geolocation + async addProductGeolocation(productName: string, location: string): Promise { + await this.goToBookingProductEditById(productName); + await this.uncheck(productsVendor.geolocation.sameAsStore); + await this.typeAndWaitForResponse(data.subUrls.gmap, productsVendor.geolocation.productLocation, location); + await this.press(data.key.arrowDown); + await this.press(data.key.enter); + await this.saveProduct(); + await this.notToBeChecked(productsVendor.geolocation.sameAsStore); + await this.toHaveValue(productsVendor.geolocation.productLocation, location); + } + + // remove product geolocation + async removeProductGeolocation(productName: string): Promise { + await this.goToBookingProductEditById(productName); + await this.check(productsVendor.geolocation.sameAsStore); + await this.saveProduct(); + await this.toBeChecked(productsVendor.geolocation.sameAsStore); + } + + // add product addons + async addProductAddon(productName: string, addon: product['productInfo']['addon']): Promise { + await this.goToBookingProductEditById(productName); + await this.toPass(async () => { + await this.clickAndWaitForResponse(data.subUrls.ajax, productsVendor.addon.addField); + await this.toBeVisible(productsVendor.addon.addonForm); + }); + + await this.selectByValue(productsVendor.addon.type, addon.type); + await this.selectByValue(productsVendor.addon.displayAs, addon.displayAs); + await this.clearAndType(productsVendor.addon.titleRequired, addon.title); + await this.selectByValue(productsVendor.addon.formatTitle, addon.formatTitle); + await this.check(productsVendor.addon.addDescription); + await this.clearAndType(productsVendor.addon.descriptionInput, addon.addDescription); + await this.check(productsVendor.addon.requiredField); + // option + await this.clearAndType(productsVendor.addon.option.enterAnOption, addon.enterAnOption); + await this.selectByValue(productsVendor.addon.option.optionPriceType, addon.optionPriceType); + await this.clearAndType(productsVendor.addon.option.optionPriceInput, addon.optionPriceInput); + await this.check(productsVendor.addon.excludeAddons); + + await this.saveProduct(); + + await this.toBeVisible(productsVendor.addon.addonRow(addon.title)); + await this.click(productsVendor.addon.addonRow(addon.title)); + + await this.toHaveSelectedValue(productsVendor.addon.type, addon.type); + await this.toHaveSelectedValue(productsVendor.addon.displayAs, addon.displayAs); + await this.toHaveValue(productsVendor.addon.titleRequired, addon.title); + await this.toHaveSelectedValue(productsVendor.addon.formatTitle, addon.formatTitle); + await this.toBeChecked(productsVendor.addon.addDescription); + await this.toHaveValue(productsVendor.addon.descriptionInput, addon.addDescription); + await this.toBeChecked(productsVendor.addon.requiredField); + // option + await this.toHaveValue(productsVendor.addon.option.enterAnOption, addon.enterAnOption); + await this.toHaveSelectedValue(productsVendor.addon.option.optionPriceType, addon.optionPriceType); + await this.toHaveValue(productsVendor.addon.option.optionPriceInput, addon.optionPriceInput); + await this.toBeChecked(productsVendor.addon.excludeAddons); + } + + // import addon + async importAddon(productName: string, addon: string, addonTitle: string): Promise { + await this.goToBookingProductEditById(productName); + await this.click(productsVendor.addon.import); + await this.clearAndType(productsVendor.addon.importInput, addon); + await this.saveProduct(); + await this.toBeVisible(productsVendor.addon.addonRow(addonTitle)); + } + + // export addon + async exportAddon(productName: string, addon: string): Promise { + await this.goToBookingProductEditById(productName); + await this.click(productsVendor.addon.export); + await this.toContainText(productsVendor.addon.exportInput, addon); + } + + // delete addon + async removeAddon(productName: string, addonName: string): Promise { + await this.goToBookingProductEditById(productName); + await this.click(productsVendor.addon.removeAddon(addonName)); + await this.click(productsVendor.addon.confirmRemove); + await this.notToBeVisible(productsVendor.addon.addonRow(addonName)); + await this.saveProduct(); + await this.notToBeVisible(productsVendor.addon.addonRow(addonName)); + } } diff --git a/tests/pw/playwright.config.ts b/tests/pw/playwright.config.ts index 0d3c3481bf..8e397b2483 100644 --- a/tests/pw/playwright.config.ts +++ b/tests/pw/playwright.config.ts @@ -1,7 +1,7 @@ import { defineConfig, devices, expect } from '@playwright/test'; import { customExpect } from '@utils/pwMatchers'; // import 'dotenv/config'; -const { CI, NON_HEADLESS, BASE_URL, SLOWMO, ADMIN, ADMIN_PASSWORD } = process.env; +const { CI, NON_HEADLESS, BASE_URL, SLOWMO } = process.env; export default defineConfig({ testDir: './tests/', @@ -101,7 +101,7 @@ export default defineConfig({ /* api request headers */ extraHTTPHeaders: { Accept: '*/*', - Authorization: 'Basic ' + Buffer.from(ADMIN + ':' + ADMIN_PASSWORD).toString('base64'), + // Authorization: 'Basic ' + Buffer.from(ADMIN + ':' + ADMIN_PASSWORD).toString('base64'), }, }, diff --git a/tests/pw/tests/e2e/commission.spec.ts b/tests/pw/tests/e2e/commission.spec.ts index 54f17f9813..910078a14b 100644 --- a/tests/pw/tests/e2e/commission.spec.ts +++ b/tests/pw/tests/e2e/commission.spec.ts @@ -6,7 +6,7 @@ import { payloads } from '@utils/payloads'; import { dbUtils } from '@utils/dbUtils'; import { dbData } from '@utils/dbData'; -const { DOKAN_PRO } = process.env; +// const { DOKAN_PRO } = process.env; test.describe('Commission test', () => { let admin: CommissionPage; @@ -22,61 +22,63 @@ test.describe('Commission test', () => { apiUtils = new ApiUtils(await request.newContext()); - if (DOKAN_PRO) { - // enable dokan subscription - // await dbUtils.updateOptionValue(dbData.dokan.optionName.vendorSubscription, { ...dbData.dokan.vendorSubscriptionSettings, enable_pricing: 'on', enable_subscription_pack_in_reg: 'on' }); - await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { ...dbData.dokan.sellingSettings, enable_min_max_quantity: 'off', enable_min_max_amount: 'off' }); //todo: after dokan issue fixed, remove this line - // [subscriptionProductId] = await createDokanSubscriptionProduct(); - } + await dbUtils.setOptionValue(dbData.dokan.optionName.selling, dbData.dokan.sellingSettings); + + // if (DOKAN_PRO) { + // enable dokan subscription + // await dbUtils.updateOptionValue(dbData.dokan.optionName.vendorSubscription, { ...dbData.dokan.vendorSubscriptionSettings, enable_pricing: 'on', enable_subscription_pack_in_reg: 'on' }); + // [subscriptionProductId] = await createDokanSubscriptionProduct(); + // } [, sellerId] = await apiUtils.createStore(payloads.createStore(), payloads.adminAuth); }); test.afterAll(async () => { - if (DOKAN_PRO) { - // await dbUtils.updateOptionValue(dbData.dokan.optionName.vendorSubscription, { ...dbData.dokan.vendorSubscriptionSettings, enable_pricing: 'off', enable_subscription_pack_in_reg: 'off' }); - await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { ...dbData.dokan.sellingSettings, enable_min_max_quantity: 'on', enable_min_max_amount: 'on' }); //todo: after dokan issue fixed, remove this line - } + // if (DOKAN_PRO) { + // await dbUtils.updateOptionValue(dbData.dokan.optionName.vendorSubscription, { ...dbData.dokan.vendorSubscriptionSettings, enable_pricing: 'off', enable_subscription_pack_in_reg: 'off' }); + // } + await dbUtils.setOptionValue(dbData.dokan.optionName.selling, dbData.dokan.sellingSettings); await aPage.close(); await apiUtils.dispose(); }); - test('admin can set commission on Dokan setup wizard (fixed)', { tag: ['@pro', '@admin'] }, async () => { + test('admin can set commission on Dokan setup wizard (fixed)', { tag: ['@lite', '@admin'] }, async () => { await admin.setCommissionOnDokanSetupWizard(data.commission.fixed); }); - test('admin can set commission on Dokan setup wizard (category based)', { tag: ['@pro', '@admin'] }, async () => { + test('admin can set commission on Dokan setup wizard (category based)', { tag: ['@lite', '@admin'] }, async () => { await admin.setCommissionOnDokanSetupWizard(data.commission.allCategory); }); - test('admin can set commission on Dokan setup wizard (specific category based)', { tag: ['@pro', '@admin'] }, async () => { - await admin.setCommissionOnDokanSetupWizard(data.commission.specficCategory); + test('admin can set commission on Dokan setup wizard (specific category based)', { tag: ['@lite', '@admin'] }, async () => { + await admin.setCommissionOnDokanSetupWizard(data.commission.specificCategory); }); - test('admin can set commission on Dokan selling settings (fixed)', { tag: ['@pro', '@admin'] }, async () => { + test('admin can set commission on Dokan selling settings (fixed)', { tag: ['@lite', '@admin'] }, async () => { await admin.setCommissionOnDokanSellingSettings(data.commission.fixed); }); - test('admin can set commission on Dokan selling settings (category based)', { tag: ['@pro', '@admin'] }, async () => { + test('admin can set commission on Dokan selling settings (category based)', { tag: ['@lite', '@admin'] }, async () => { await admin.setCommissionOnDokanSellingSettings(data.commission.allCategory); }); - test('admin can set commission on Dokan selling settings (specific category based)', { tag: ['@pro', '@admin'] }, async () => { - await admin.setCommissionOnDokanSellingSettings(data.commission.specficCategory); + test('admin can set commission on Dokan selling settings (specific category based)', { tag: ['@lite', '@admin'] }, async () => { + await admin.setCommissionOnDokanSellingSettings(data.commission.specificCategory); }); - test('admin can set commission for vendor (fixed)', { tag: ['@pro', '@admin'] }, async () => { + test('admin can set commission for vendor (fixed)', { tag: ['@lite', '@admin'] }, async () => { await admin.setCommissionForVendor(sellerId, data.commission.fixed); }); - test('admin can set commission for vendor (category based)', { tag: ['@pro', '@admin'] }, async () => { + test('admin can set commission for vendor (category based)', { tag: ['@lite', '@admin'] }, async () => { await admin.setCommissionForVendor(sellerId, data.commission.allCategory); }); - test('admin can set commission for vendor (specific category based)', { tag: ['@pro', '@admin'] }, async () => { - await admin.setCommissionForVendor(sellerId, data.commission.specficCategory); + test('admin can set commission for vendor (specific category based)', { tag: ['@lite', '@admin'] }, async () => { + await admin.setCommissionForVendor(sellerId, data.commission.specificCategory); }); - test('admin can set commission for a product (fixed)', { tag: ['@pro', '@admin'] }, async () => { + test('admin can set commission for a product (fixed)', { tag: ['@lite', '@admin'] }, async () => { + test.skip(true, 'dokan issue, decimal separator , becomes .'); const [, productId] = await apiUtils.createProduct(payloads.createProduct(), payloads.vendorAuth); await admin.setCommissionForProduct(productId, data.commission.fixed); }); @@ -93,6 +95,6 @@ test.describe('Commission test', () => { test('admin can set commission to Dokan subscription product (specific category based)', { tag: ['@pro', '@admin'] }, async () => { test.skip(true, 'Need to implement createDokanSubscriptionProduct function'); - await admin.setCommissionToDokanSubscriptionProduct(subscriptionProductId, data.commission.specficCategory); + await admin.setCommissionToDokanSubscriptionProduct(subscriptionProductId, data.commission.specificCategory); }); }); diff --git a/tests/pw/tests/e2e/productsDetails.spec.ts b/tests/pw/tests/e2e/productsDetails.spec.ts index b28cb694b4..b0134db2d4 100644 --- a/tests/pw/tests/e2e/productsDetails.spec.ts +++ b/tests/pw/tests/e2e/productsDetails.spec.ts @@ -16,8 +16,8 @@ test.describe('Product details functionality test', () => { let apiUtils: ApiUtils; let productResponseBody: responseBody; let productId: string; - let productName: string; // has all fields - let productName1: string; // has only required fields + let productNameFull: string; // has all fields + let productNameBasic: string; // has only required fields test.beforeAll(async ({ browser }) => { const vendorContext = await browser.newContext(data.auth.vendorAuth); @@ -26,11 +26,11 @@ test.describe('Product details functionality test', () => { apiUtils = new ApiUtils(await request.newContext()); // product with only required fields - [, , productName1] = await apiUtils.createProduct(payloads.createProductRequiredFields(), payloads.vendorAuth); + [, , productNameBasic] = await apiUtils.createProduct(payloads.createProductRequiredFields(), payloads.vendorAuth); // product with all fields // const [, , mediaUrl] = await apiUtils.uploadMedia(data.image.avatar, payloads.mimeTypes.png, payloads.vendorAuth); - // [productResponseBody, productId, productName] = await apiUtils.createProductWc({ ...payloads.createProductAllFields(), images: [{ src: mediaUrl }, { src: mediaUrl }] }, payloads.vendorAuth); // todo: mediaUrl is not working on git action - [productResponseBody, productId, productName] = await apiUtils.createProductWc(payloads.createProductAllFields(), payloads.vendorAuth); + // [productResponseBody, productId, productNameFull] = await apiUtils.createProductWc({ ...payloads.createProductAllFields(), images: [{ src: mediaUrl }, { src: mediaUrl }] }, payloads.vendorAuth); // todo: mediaUrl is not working on git action + [productResponseBody, productId, productNameFull] = await apiUtils.createProductWc(payloads.createProductAllFields(), payloads.vendorAuth); await apiUtils.updateProduct( productId, { @@ -61,43 +61,43 @@ test.describe('Product details functionality test', () => { // product permalink test('vendor can update product permalink', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductPermalink(productName, data.product.productInfo.permalink); + await vendor.addProductPermalink(productNameFull, data.product.productInfo.permalink); }); // product price test('vendor can add product price', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addPrice(productName1, data.product.productInfo.price()); + await vendor.addPrice(productNameBasic, data.product.productInfo.price()); }); test('vendor can update product price', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addPrice(productName, data.product.productInfo.price()); + await vendor.addPrice(productNameFull, data.product.productInfo.price()); }); test('vendor can remove product price', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.removePrice(productName); + await vendor.removePrice(productNameFull); }); // product discount price test('vendor can add product discount price', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addDiscount(productName1, data.product.productInfo.discount); + await vendor.addDiscount(productNameBasic, data.product.productInfo.discount); }); test('vendor can add product discount price (with schedule)', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addDiscount(productName1, data.product.productInfo.discount, true); + await vendor.addDiscount(productNameBasic, data.product.productInfo.discount, true); }); test('vendor can update product discount price', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addDiscount(productName, { ...data.product.productInfo.discount, regularPrice: productResponseBody.price }); + await vendor.addDiscount(productNameFull, { ...data.product.productInfo.discount, regularPrice: productResponseBody.price }); }); test('vendor can update product discount price (with schedule)', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addDiscount(productName, { ...data.product.productInfo.discount, regularPrice: productResponseBody.price }, true, true); + await vendor.addDiscount(productNameFull, { ...data.product.productInfo.discount, regularPrice: productResponseBody.price }, true, true); }); test("vendor can't add product discount price higher than price", { tag: ['@lite', '@vendor'] }, async () => { - await vendor.cantAddGreaterDiscount(productName, { ...data.product.productInfo.discount, regularPrice: productResponseBody.price }); + await vendor.cantAddGreaterDiscount(productNameFull, { ...data.product.productInfo.discount, regularPrice: productResponseBody.price }); }); test('vendor can remove product discount price', { tag: ['@lite', '@vendor'] }, async () => { @@ -113,12 +113,12 @@ test.describe('Product details functionality test', () => { // product category test('vendor can update product category (single)', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductCategory(productName, [data.product.category.clothings]); + await vendor.addProductCategory(productNameFull, [data.product.category.clothings]); }); test('vendor can add product category (multiple)', { tag: ['@pro', '@vendor'] }, async () => { await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { product_category_style: 'multiple' }); - await vendor.addProductCategory(productName1, data.product.category.categories, true); + await vendor.addProductCategory(productNameBasic, data.product.category.categories, true); }); test('vendor can remove product category (multiple)', { tag: ['@pro', '@vendor'] }, async () => { @@ -130,104 +130,104 @@ test.describe('Product details functionality test', () => { test('vendor can add multi-step product category (last category)', { tag: ['@lite', '@vendor'] }, async () => { await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { product_category_style: 'single' }); - await vendor.addProductCategory(productName1, [data.product.category.multistepCategories.at(-1)!]); + await vendor.addProductCategory(productNameBasic, [data.product.category.multistepCategories.at(-1)!]); }); test('vendor can add multi-step product category (any category)', { tag: ['@lite', '@vendor'] }, async () => { await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { dokan_any_category_selection: 'on' }); - await vendor.addProductCategory(productName, [data.product.category.multistepCategories.at(-2)!]); + await vendor.addProductCategory(productNameFull, [data.product.category.multistepCategories.at(-2)!]); }); test("vendor can't add multi-step product category (any category)", { tag: ['@lite', '@vendor'] }, async () => { await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { dokan_any_category_selection: 'off' }); - await vendor.cantAddCategory(productName, data.product.category.multistepCategories.at(-2)!); + await vendor.cantAddCategory(productNameFull, data.product.category.multistepCategories.at(-2)!); }); // product tags test('vendor can add product tags', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductTags(productName1, data.product.productInfo.tags.tags); + await vendor.addProductTags(productNameBasic, data.product.productInfo.tags.tags); }); test('vendor can remove product tags', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.removeProductTags(productName, data.product.productInfo.tags.tags); + await vendor.removeProductTags(productNameFull, data.product.productInfo.tags.tags); }); test('vendor can create product tags', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductTags(productName, data.product.productInfo.tags.randomTags); + await vendor.addProductTags(productNameFull, data.product.productInfo.tags.randomTags); }); // product cover image test('vendor can add product cover image', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductCoverImage(productName1, data.product.productInfo.images.cover); + await vendor.addProductCoverImage(productNameBasic, data.product.productInfo.images.cover); }); test('vendor can update product cover image', { tag: ['@lite', '@vendor'] }, async () => { // todo: need a product with cover image - await vendor.addProductCoverImage(productName, data.product.productInfo.images.cover); - await vendor.addProductCoverImage(productName, data.product.productInfo.images.cover, true); + await vendor.addProductCoverImage(productNameFull, data.product.productInfo.images.cover); + await vendor.addProductCoverImage(productNameFull, data.product.productInfo.images.cover, true); }); test('vendor can remove product cover image', { tag: ['@lite', '@vendor'] }, async () => { // todo: need a product with cover image - await vendor.addProductCoverImage(productName, data.product.productInfo.images.cover, true); - await vendor.removeProductCoverImage(productName); + await vendor.addProductCoverImage(productNameFull, data.product.productInfo.images.cover, true); + await vendor.removeProductCoverImage(productNameFull); }); // product gallery image test('vendor can add product gallery image', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductGalleryImages(productName1, data.product.productInfo.images.gallery); + await vendor.addProductGalleryImages(productNameBasic, data.product.productInfo.images.gallery); }); test('vendor can update product gallery image', { tag: ['@lite', '@vendor'] }, async () => { // todo: need a product with gallery images - await vendor.addProductGalleryImages(productName, data.product.productInfo.images.gallery); - await vendor.addProductGalleryImages(productName, data.product.productInfo.images.gallery, true); + await vendor.addProductGalleryImages(productNameFull, data.product.productInfo.images.gallery); + await vendor.addProductGalleryImages(productNameFull, data.product.productInfo.images.gallery, true); }); test('vendor can remove product gallery image', { tag: ['@lite', '@vendor'] }, async () => { // todo: need a product with gallery images - await vendor.addProductGalleryImages(productName, data.product.productInfo.images.gallery, true); - await vendor.removeProductGalleryImages(productName); + await vendor.addProductGalleryImages(productNameFull, data.product.productInfo.images.gallery, true); + await vendor.removeProductGalleryImages(productNameFull); }); // product short description test('vendor can add product short description', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductShortDescription(productName1, data.product.productInfo.description.shortDescription); + await vendor.addProductShortDescription(productNameBasic, data.product.productInfo.description.shortDescription); }); test('vendor can update product short description', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductShortDescription(productName, data.product.productInfo.description.shortDescription); + await vendor.addProductShortDescription(productNameFull, data.product.productInfo.description.shortDescription); }); test('vendor can remove product short description', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductShortDescription(productName, ''); + await vendor.addProductShortDescription(productNameFull, ''); }); // product description test('vendor can update product description', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductDescription(productName, data.product.productInfo.description.description); + await vendor.addProductDescription(productNameFull, data.product.productInfo.description.description); }); // product downloadable options test('vendor can add product downloadable options', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductDownloadableOptions(productName1, data.product.productInfo.downloadableOptions); + await vendor.addProductDownloadableOptions(productNameBasic, data.product.productInfo.downloadableOptions); }); test('vendor can update product downloadable options', { tag: ['@lite', '@vendor'] }, async () => { // todo: need a product with downloadable file - await vendor.addProductDownloadableOptions(productName, data.product.productInfo.downloadableOptions); + await vendor.addProductDownloadableOptions(productNameFull, data.product.productInfo.downloadableOptions); }); test('vendor can remove product downloadable file', { tag: ['@lite', '@vendor'] }, async () => { // todo: need a product with downloadable file - await vendor.addProductDownloadableOptions(productName, data.product.productInfo.downloadableOptions); - await vendor.removeDownloadableFile(productName, { ...data.product.productInfo.downloadableOptions, downloadLimit: '', downloadExpiry: '' }); + await vendor.addProductDownloadableOptions(productNameFull, data.product.productInfo.downloadableOptions); + await vendor.removeDownloadableFile(productNameFull, { ...data.product.productInfo.downloadableOptions, downloadLimit: '', downloadExpiry: '' }); }); // product virtual options @@ -245,69 +245,69 @@ test.describe('Product details functionality test', () => { // product inventory options test('vendor can add product inventory options (SKU)', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductInventory(productName1, data.product.productInfo.inventory(), 'sku'); + await vendor.addProductInventory(productNameBasic, data.product.productInfo.inventory(), 'sku'); }); test('vendor can update product inventory options (SKU)', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductInventory(productName, data.product.productInfo.inventory(), 'sku'); + await vendor.addProductInventory(productNameFull, data.product.productInfo.inventory(), 'sku'); }); test('vendor can remove product inventory options (SKU)', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductInventory(productName, { ...data.product.productInfo.inventory(), sku: '' }, 'sku'); + await vendor.addProductInventory(productNameFull, { ...data.product.productInfo.inventory(), sku: '' }, 'sku'); }); test('vendor can add product inventory options (stock status)', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductInventory(productName1, data.product.productInfo.inventory(), 'stock-status'); + await vendor.addProductInventory(productNameBasic, data.product.productInfo.inventory(), 'stock-status'); }); test('vendor can add product inventory options (stock management)', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductInventory(productName1, data.product.productInfo.inventory(), 'stock-management'); + await vendor.addProductInventory(productNameBasic, data.product.productInfo.inventory(), 'stock-management'); }); test('vendor can update product inventory options (stock management)', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductInventory(productName1, data.product.productInfo.inventory(), 'stock-management'); + await vendor.addProductInventory(productNameBasic, data.product.productInfo.inventory(), 'stock-management'); }); test('vendor can remove product inventory options (stock management)', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.removeProductInventory(productName); + await vendor.removeProductInventory(productNameFull); }); test('vendor can add product inventory options (allow single quantity)', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductInventory(productName1, data.product.productInfo.inventory(), 'one-quantity'); + await vendor.addProductInventory(productNameBasic, data.product.productInfo.inventory(), 'one-quantity'); }); test('vendor can remove product inventory options (allow single quantity)', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductInventory(productName, { ...data.product.productInfo.inventory(), oneQuantity: false }, 'one-quantity'); + await vendor.addProductInventory(productNameFull, { ...data.product.productInfo.inventory(), oneQuantity: false }, 'one-quantity'); }); // product other options test('vendor can add product other options (product status)', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductOtherOptions(productName1, data.product.productInfo.otherOptions, 'status'); + await vendor.addProductOtherOptions(productNameBasic, data.product.productInfo.otherOptions, 'status'); }); test('vendor can add product other options (visibility)', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductOtherOptions(productName1, data.product.productInfo.otherOptions, 'visibility'); + await vendor.addProductOtherOptions(productNameBasic, data.product.productInfo.otherOptions, 'visibility'); }); test('vendor can add product other options (purchase note)', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductOtherOptions(productName1, data.product.productInfo.otherOptions, 'purchaseNote'); + await vendor.addProductOtherOptions(productNameBasic, data.product.productInfo.otherOptions, 'purchaseNote'); }); test('vendor can update product other options (purchase note)', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductOtherOptions(productName, data.product.productInfo.otherOptions, 'purchaseNote'); + await vendor.addProductOtherOptions(productNameFull, data.product.productInfo.otherOptions, 'purchaseNote'); }); test('vendor can remove product other options (purchase note)', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductOtherOptions(productName, { ...data.product.productInfo.otherOptions, purchaseNote: '' }, 'purchaseNote'); + await vendor.addProductOtherOptions(productNameFull, { ...data.product.productInfo.otherOptions, purchaseNote: '' }, 'purchaseNote'); }); test('vendor can add product other options (product review)', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductOtherOptions(productName1, data.product.productInfo.otherOptions, 'reviews'); + await vendor.addProductOtherOptions(productNameBasic, data.product.productInfo.otherOptions, 'reviews'); }); test('vendor can remove product other options (product review)', { tag: ['@lite', '@vendor'] }, async () => { - await vendor.addProductOtherOptions(productName, { ...data.product.productInfo.otherOptions, enableReview: false }, 'reviews'); + await vendor.addProductOtherOptions(productNameFull, { ...data.product.productInfo.otherOptions, enableReview: false }, 'reviews'); }); // catalog mode @@ -316,137 +316,138 @@ test.describe('Product details functionality test', () => { test('vendor can add product catalog mode', { tag: ['@lite', '@vendor'] }, async () => { await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { catalog_mode_hide_add_to_cart_button: 'on' }); - await vendor.addProductCatalogMode(productName1); + await vendor.addProductCatalogMode(productNameBasic); }); test('vendor can add product catalog mode (with price hidden)', { tag: ['@lite', '@vendor'] }, async () => { await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { catalog_mode_hide_add_to_cart_button: 'on', catalog_mode_hide_product_price: 'on' }); - await vendor.addProductCatalogMode(productName1, true); + await vendor.addProductCatalogMode(productNameBasic, true); }); test('vendor can remove product catalog mode', { tag: ['@lite', '@vendor'] }, async () => { await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { catalog_mode_hide_add_to_cart_button: 'on', catalog_mode_hide_product_price: 'on' }); - await vendor.removeProductCatalogMode(productName); + await vendor.removeProductCatalogMode(productNameFull); }); test('vendor can remove product catalog mode (price hidden option)', { tag: ['@lite', '@vendor'] }, async () => { await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { catalog_mode_hide_add_to_cart_button: 'on', catalog_mode_hide_product_price: 'on' }); - await vendor.removeProductCatalogMode(productName, true); + await vendor.removeProductCatalogMode(productNameFull, true); }); // shipping and tax test('vendor can add product shipping', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductShipping(productName1, data.product.productInfo.shipping); + await vendor.addProductShipping(productNameBasic, data.product.productInfo.shipping); }); test('vendor can update product shipping', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductShipping(productName, data.product.productInfo.shipping); + await vendor.addProductShipping(productNameFull, data.product.productInfo.shipping); }); test('vendor can remove product shipping', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.removeProductShipping(productName); + await vendor.removeProductShipping(productNameFull); }); test('vendor can add product tax', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductTax(productName1, data.product.productInfo.tax); + await vendor.addProductTax(productNameBasic, data.product.productInfo.tax); }); test('vendor can add product tax (with tax class)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductTax(productName1, data.product.productInfo.tax, true); + await vendor.addProductTax(productNameBasic, data.product.productInfo.tax, true); }); // linked products test('vendor can add product linked products (up-sells)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductLinkedProducts(productName1, data.product.productInfo.linkedProducts, 'up-sells'); + await vendor.addProductLinkedProducts(productNameBasic, data.product.productInfo.linkedProducts, 'up-sells'); }); test('vendor can add product linked products (cross-sells)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductLinkedProducts(productName1, data.product.productInfo.linkedProducts, 'cross-sells'); + await vendor.addProductLinkedProducts(productNameBasic, data.product.productInfo.linkedProducts, 'cross-sells'); }); test('vendor can remove product linked products (up-sells)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.removeProductLinkedProducts(productName, data.product.productInfo.linkedProducts, 'up-sells'); + await vendor.removeProductLinkedProducts(productNameFull, data.product.productInfo.linkedProducts, 'up-sells'); }); test('vendor can remove product linked products (cross-sells)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.removeProductLinkedProducts(productName, data.product.productInfo.linkedProducts, 'cross-sells'); + await vendor.removeProductLinkedProducts(productNameFull, data.product.productInfo.linkedProducts, 'cross-sells'); }); // attribute test('vendor can add product attribute', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductAttribute(productName1, data.product.productInfo.attribute); + await vendor.addProductAttribute(productNameBasic, data.product.productInfo.attribute); }); test("vendor can't add already added product attribute", { tag: ['@pro', '@vendor'] }, async () => { - await vendor.cantAddAlreadyAddedAttribute(productName, data.product.productInfo.attribute.attributeName); + await vendor.cantAddAlreadyAddedAttribute(productNameFull, data.product.productInfo.attribute.attributeName); }); // todo: refactor below tests + test('vendor can create product attribute term', { tag: ['@pro', '@vendor'] }, async () => { const [, , , attributeName] = await apiUtils.createAttributeTerm(payloads.createAttribute(), payloads.createAttributeTerm(), payloads.adminAuth); - const [, , productName] = await apiUtils.createProduct(payloads.createProduct(), payloads.vendorAuth); - await vendor.addProductAttribute(productName, { ...data.product.productInfo.attribute, attributeName: attributeName }, true); + const [, , productId] = await apiUtils.createProduct(payloads.createProduct(), payloads.vendorAuth); + await vendor.addProductAttribute(productId, { ...data.product.productInfo.attribute, attributeName: attributeName }, true); }); test('vendor can remove product attribute', { tag: ['@pro', '@vendor'] }, async () => { const [, attributeId, , attributeName, attributeTerm] = await apiUtils.createAttributeTerm(payloads.createAttribute(), payloads.createAttributeTerm(), payloads.adminAuth); const attributes = { id: attributeId, name: attributeName, options: [attributeTerm] }; - const [, , productName] = await apiUtils.createProduct({ ...payloads.createProduct(), attributes: [attributes] }, payloads.vendorAuth); - await vendor.removeProductAttribute(productName, attributeName); + const [, , productId] = await apiUtils.createProduct({ ...payloads.createProduct(), attributes: [attributes] }, payloads.vendorAuth); + await vendor.removeProductAttribute(productId, attributeName); }); test('vendor can remove product attribute term', { tag: ['@pro', '@vendor'] }, async () => { const [, attributeId, , attributeName, attributeTerm] = await apiUtils.createAttributeTerm(payloads.createAttribute(), payloads.createAttributeTerm(), payloads.adminAuth); const [, , , , attributeTerm2] = await apiUtils.createAttributeTerm(payloads.createAttribute(), payloads.createAttributeTerm(), payloads.adminAuth); const attributes = { id: attributeId, name: attributeName, options: [attributeTerm, attributeTerm2] }; - const [, , productName] = await apiUtils.createProduct({ ...payloads.createProduct(), attributes: [attributes] }, payloads.vendorAuth); - await vendor.removeProductAttributeTerm(productName, attributeName, attributeTerm2); + const [, , productId] = await apiUtils.createProduct({ ...payloads.createProduct(), attributes: [attributes] }, payloads.vendorAuth); + await vendor.removeProductAttributeTerm(productId, attributeName, attributeTerm2); }); // discount options test('vendor can add product bulk discount options', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductBulkDiscountOptions(productName1, data.product.productInfo.quantityDiscount); + await vendor.addProductBulkDiscountOptions(productNameBasic, data.product.productInfo.quantityDiscount); }); test('vendor can update product bulk discount options', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductBulkDiscountOptions(productName, data.product.productInfo.quantityDiscount); + await vendor.addProductBulkDiscountOptions(productNameFull, data.product.productInfo.quantityDiscount); }); test('vendor can remove product bulk discount options', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.removeProductBulkDiscountOptions(productName); + await vendor.removeProductBulkDiscountOptions(productNameFull); }); // geolocation test('vendor can add product geolocation (individual)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductGeolocation(productName1, data.product.productInfo.geolocation); + await vendor.addProductGeolocation(productNameBasic, data.product.productInfo.geolocation); }); test('vendor can update product geolocation (individual)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductGeolocation(productName, data.product.productInfo.geolocation); + await vendor.addProductGeolocation(productNameFull, data.product.productInfo.geolocation); }); test('vendor can remove product geolocation (individual)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.removeProductGeolocation(productName); + await vendor.removeProductGeolocation(productNameFull); }); // EU compliance options // todo: duplicate test from euCompliance test.skip('vendor can add product EU compliance data', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductEuCompliance(productName1, data.product.productInfo.euCompliance); + await vendor.addProductEuCompliance(productNameBasic, data.product.productInfo.euCompliance); }); test.skip('vendor can update product EU compliance data', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductEuCompliance(productName, data.product.productInfo.euCompliance); + await vendor.addProductEuCompliance(productNameFull, data.product.productInfo.euCompliance); }); test.skip('vendor can remove product EU compliance data', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductEuCompliance(productName, { ...data.product.productInfo.euCompliance, productUnits: '', basePriceUnits: '', freeShipping: false, regularUnitPrice: '', saleUnitPrice: '', optionalMiniDescription: '' }); + await vendor.addProductEuCompliance(productNameFull, { ...data.product.productInfo.euCompliance, productUnits: '', basePriceUnits: '', freeShipping: false, regularUnitPrice: '', saleUnitPrice: '', optionalMiniDescription: '' }); }); // addon @@ -454,12 +455,12 @@ test.describe('Product details functionality test', () => { test('vendor can add product addon', { tag: ['@pro', '@vendor'] }, async () => { test.slow(); - await vendor.addProductAddon(productName1, data.product.productInfo.addon); + await vendor.addProductAddon(productNameBasic, data.product.productInfo.addon); }); test('vendor can import product addon', { tag: ['@pro', '@vendor'] }, async () => { const addon = payloads.createProductAddon(); - await vendor.importAddon(productName1, serialize([addon]), addon.name); + await vendor.importAddon(productNameBasic, serialize([addon]), addon.name); }); test('vendor can export product addon', { tag: ['@pro', '@vendor'] }, async () => { @@ -468,64 +469,64 @@ test.describe('Product details functionality test', () => { }); test('vendor can remove product addon', { tag: ['@pro', '@vendor'] }, async () => { - const [, , productName, addonNames] = await apiUtils.createProductWithAddon(payloads.createProduct(), [payloads.createProductAddon()], payloads.vendorAuth); - await vendor.removeAddon(productName, addonNames[0] as string); + const [, , productId, addonNames] = await apiUtils.createProductWithAddon(payloads.createProduct(), [payloads.createProductAddon()], payloads.vendorAuth); + await vendor.removeAddon(productId, addonNames[0] as string); }); // rma options test('vendor can add product rma options (no warranty)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductRmaOptions(productName1, { ...data.vendor.rma, type: 'no_warranty' }); + await vendor.addProductRmaOptions(productNameBasic, { ...data.vendor.rma, type: 'no_warranty' }); }); test('vendor can add product rma options (warranty included limited)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductRmaOptions(productName1, data.vendor.rma); + await vendor.addProductRmaOptions(productNameBasic, data.vendor.rma); }); test('vendor can add product rma options (warranty included lifetime)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductRmaOptions(productName1, { ...data.vendor.rma, length: 'lifetime' }); + await vendor.addProductRmaOptions(productNameBasic, { ...data.vendor.rma, length: 'lifetime' }); }); test('vendor can add product rma options (warranty as addon)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductRmaOptions(productName1, { ...data.vendor.rma, type: 'addon_warranty' }); + await vendor.addProductRmaOptions(productNameBasic, { ...data.vendor.rma, type: 'addon_warranty' }); }); //todo: add update rma options tests test('vendor can remove product rma options', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.removeProductRmaOptions(productName); + await vendor.removeProductRmaOptions(productNameFull); }); // wholesale options test('vendor can add product wholesale options', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductWholesaleOptions(productName1, data.product.productInfo.wholesaleOption); + await vendor.addProductWholesaleOptions(productNameBasic, data.product.productInfo.wholesaleOption); }); test('vendor can update product wholesale options', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductWholesaleOptions(productName, data.product.productInfo.wholesaleOption); + await vendor.addProductWholesaleOptions(productNameFull, data.product.productInfo.wholesaleOption); }); test('vendor can remove product wholesale options', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.removeProductWholesaleOptions(productName); + await vendor.removeProductWholesaleOptions(productNameFull); }); // mix-max options test('vendor can add product min-max options', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductMinMaxOptions(productName1, data.product.productInfo.minMax); + await vendor.addProductMinMaxOptions(productNameBasic, data.product.productInfo.minMax); }); test('vendor can update product min-max options', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductMinMaxOptions(productName, data.product.productInfo.minMax); + await vendor.addProductMinMaxOptions(productNameFull, data.product.productInfo.minMax); }); test("vendor can't add product min limit grater than max limit", { tag: ['@pro', '@vendor'] }, async () => { - await vendor.cantAddGreaterMin(productName, { minimumProductQuantity: '100', maximumProductQuantity: '50' }); + await vendor.cantAddGreaterMin(productNameFull, { minimumProductQuantity: '100', maximumProductQuantity: '50' }); }); test('vendor can remove product min-max options', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.removeProductMinMaxOptions(productName, { minimumProductQuantity: '', maximumProductQuantity: '' }); + await vendor.removeProductMinMaxOptions(productNameFull, { minimumProductQuantity: '', maximumProductQuantity: '' }); }); // todo: advertising diff --git a/tests/pw/tests/e2e/productsDetailsAuction.spec.ts b/tests/pw/tests/e2e/productsDetailsAuction.spec.ts index 45867f858f..4d8a8d119b 100644 --- a/tests/pw/tests/e2e/productsDetailsAuction.spec.ts +++ b/tests/pw/tests/e2e/productsDetailsAuction.spec.ts @@ -13,8 +13,8 @@ test.describe('Auction Product details functionality test', () => { let vendor: AuctionsPage; let vPage: Page; let apiUtils: ApiUtils; - let productId: string; // has all fields - let productId1: string; // has only required fields + let productIdFull: string; // has all fields + let productIdBasic: string; // has only required fields test.beforeAll(async ({ browser }) => { const vendorContext = await browser.newContext(data.auth.vendorAuth); @@ -24,10 +24,10 @@ test.describe('Auction Product details functionality test', () => { apiUtils = new ApiUtils(await request.newContext()); // product with only required fields - [, productId1] = await apiUtils.createProduct(payloads.createAuctionProductRequiredFields(), payloads.vendorAuth); + [, productIdBasic] = await apiUtils.createProduct(payloads.createAuctionProductRequiredFields(), payloads.vendorAuth); // product with all fields - [, productId] = await apiUtils.createProduct(payloads.createAuctionProduct(), payloads.vendorAuth); //todo: need to add all fields + [, productIdFull] = await apiUtils.createProduct(payloads.createAuctionProduct(), payloads.vendorAuth); //todo: need to add all fields }); test.afterAll(async () => { @@ -48,12 +48,12 @@ test.describe('Auction Product details functionality test', () => { // product category test('vendor can update auction product category (single)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductCategory(productId, [data.product.category.clothings]); + await vendor.addProductCategory(productIdFull, [data.product.category.clothings]); }); test('vendor can add auction product category (multiple)', { tag: ['@pro', '@vendor'] }, async () => { await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { product_category_style: 'multiple' }); - await vendor.addProductCategory(productId1, data.product.category.categories, true); + await vendor.addProductCategory(productIdBasic, data.product.category.categories, true); }); test('vendor can remove auction product category (multiple)', { tag: ['@pro', '@vendor'] }, async () => { @@ -65,105 +65,107 @@ test.describe('Auction Product details functionality test', () => { test('vendor can add multi-step auction product category (last category)', { tag: ['@pro', '@vendor'] }, async () => { await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { product_category_style: 'single' }); - await vendor.addProductCategory(productId1, [data.product.category.multistepCategories.at(-1)!]); + await vendor.addProductCategory(productIdBasic, [data.product.category.multistepCategories.at(-1)!]); }); test('vendor can add multi-step auction product category (any category)', { tag: ['@pro', '@vendor'] }, async () => { await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { dokan_any_category_selection: 'on' }); - await vendor.addProductCategory(productId, [data.product.category.multistepCategories.at(-2)!]); + await vendor.addProductCategory(productIdFull, [data.product.category.multistepCategories.at(-2)!]); }); test("vendor can't add multi-step product category (any category)", { tag: ['@pro', '@vendor'] }, async () => { await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { dokan_any_category_selection: 'off' }); - await vendor.cantAddCategory(productId, data.product.category.multistepCategories.at(-2)!); + await vendor.cantAddCategory(productIdFull, data.product.category.multistepCategories.at(-2)!); }); // product tags test('vendor can add auction product tags', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductTags(productId1, data.product.productInfo.tags.tags); + test.skip(true, 'dokan issue option does not work'); + await vendor.addProductTags(productIdBasic, data.product.productInfo.tags.tags); }); test('vendor can remove auction product tags', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.removeProductTags(productId, data.product.productInfo.tags.tags); + await vendor.removeProductTags(productIdFull, data.product.productInfo.tags.tags); }); test('vendor can create auction product tags', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductTags(productId, data.product.productInfo.tags.randomTags, true); + // await vendor.addProductTags(productIdFull, data.product.productInfo.tags.randomTags, true); + await vendor.addProductTags(productIdFull, data.product.productInfo.tags.randomTags); }); // product cover image test('vendor can add auction product cover image', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductCoverImage(productId1, data.product.productInfo.images.cover); + await vendor.addProductCoverImage(productIdBasic, data.product.productInfo.images.cover); }); test('vendor can update auction product cover image', { tag: ['@pro', '@vendor'] }, async () => { // todo: need a product with cover image - await vendor.addProductCoverImage(productId, data.product.productInfo.images.cover); - await vendor.addProductCoverImage(productId, data.product.productInfo.images.cover, true); + await vendor.addProductCoverImage(productIdFull, data.product.productInfo.images.cover); + await vendor.addProductCoverImage(productIdFull, data.product.productInfo.images.cover, true); }); test('vendor can remove auction product cover image', { tag: ['@pro', '@vendor'] }, async () => { // todo: need a product with cover image - await vendor.addProductCoverImage(productId, data.product.productInfo.images.cover, true); - await vendor.removeProductCoverImage(productId); + await vendor.addProductCoverImage(productIdFull, data.product.productInfo.images.cover, true); + await vendor.removeProductCoverImage(productIdFull); }); // product gallery image test('vendor can add auction product gallery image', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductGalleryImages(productId1, data.product.productInfo.images.gallery); + await vendor.addProductGalleryImages(productIdBasic, data.product.productInfo.images.gallery); }); test('vendor can update auction product gallery image', { tag: ['@pro', '@vendor'] }, async () => { // todo: need a product with gallery images - await vendor.addProductGalleryImages(productId, data.product.productInfo.images.gallery); - await vendor.addProductGalleryImages(productId, data.product.productInfo.images.gallery, true); + await vendor.addProductGalleryImages(productIdFull, data.product.productInfo.images.gallery); + await vendor.addProductGalleryImages(productIdFull, data.product.productInfo.images.gallery, true); }); test('vendor can remove auction product gallery image', { tag: ['@pro', '@vendor'] }, async () => { // todo: need a product with gallery images - await vendor.addProductGalleryImages(productId, data.product.productInfo.images.gallery, true); - await vendor.removeProductGalleryImages(productId); + await vendor.addProductGalleryImages(productIdFull, data.product.productInfo.images.gallery, true); + await vendor.removeProductGalleryImages(productIdFull); }); // product short description test('vendor can add auction product short description', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductShortDescription(productId1, data.product.productInfo.description.shortDescription); + await vendor.addProductShortDescription(productIdBasic, data.product.productInfo.description.shortDescription); }); test('vendor can update auction product short description', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductShortDescription(productId, data.product.productInfo.description.shortDescription); + await vendor.addProductShortDescription(productIdFull, data.product.productInfo.description.shortDescription); }); test('vendor can remove auction product short description', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductShortDescription(productId, ''); + await vendor.addProductShortDescription(productIdFull, ''); }); // product description test('vendor can update auction product description', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductDescription(productId, data.product.productInfo.description.description); + await vendor.addProductDescription(productIdFull, data.product.productInfo.description.description); }); // product downloadable options test.skip('vendor can add auction product downloadable options', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductDownloadableOptions(productId1, data.product.productInfo.downloadableOptions); + await vendor.addProductDownloadableOptions(productIdBasic, data.product.productInfo.downloadableOptions); }); test.skip('vendor can update auction product downloadable options', { tag: ['@pro', '@vendor'] }, async () => { // todo: need a product with downloadable file - await vendor.addProductDownloadableOptions(productId, data.product.productInfo.downloadableOptions); + await vendor.addProductDownloadableOptions(productIdFull, data.product.productInfo.downloadableOptions); }); test.skip('vendor can remove auction product downloadable file', { tag: ['@pro', '@vendor'] }, async () => { // todo: need a product with downloadable file - test.skip(true, 'Has Dokan Issue download limit & expiry doesnt reset'); - await vendor.addProductDownloadableOptions(productId, data.product.productInfo.downloadableOptions); - await vendor.removeDownloadableFile(productId, { ...data.product.productInfo.downloadableOptions, downloadLimit: '', downloadExpiry: '' }); + test.skip(true, 'Has Dokan Issue download limit & expiry does not reset'); + await vendor.addProductDownloadableOptions(productIdFull, data.product.productInfo.downloadableOptions); + await vendor.removeDownloadableFile(productIdFull, { ...data.product.productInfo.downloadableOptions, downloadLimit: '', downloadExpiry: '' }); }); // product virtual options @@ -179,69 +181,70 @@ test.describe('Auction Product details functionality test', () => { }); test('vendor can update product general options', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductGeneralOption(productId1, { ...data.product.auction, itemCondition: 'used', auctionType: 'reverse' }); + await vendor.addProductGeneralOption(productIdBasic, { ...data.product.auction, itemCondition: 'used', auctionType: 'reverse' }); }); // product inventory options test('vendor can add auction product inventory options (SKU)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductInventory(productId1, data.product.productInfo.inventory()); + await vendor.addProductInventory(productIdBasic, data.product.productInfo.inventory()); }); test('vendor can update auction product inventory options (SKU)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductInventory(productId, data.product.productInfo.inventory()); + await vendor.addProductInventory(productIdFull, data.product.productInfo.inventory()); }); test('vendor can remove auction product inventory options (SKU)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductInventory(productId, { ...data.product.productInfo.inventory(), sku: '' }); + await vendor.addProductInventory(productIdFull, { ...data.product.productInfo.inventory(), sku: '' }); }); // product other options test('vendor can add auction product other options (product status)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductOtherOptions(productId1, data.product.productInfo.otherOptions, 'status'); + await vendor.addProductOtherOptions(productIdBasic, data.product.productInfo.otherOptions, 'status'); }); test('vendor can add auction product other options (visibility)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductOtherOptions(productId1, data.product.productInfo.otherOptions, 'visibility'); + await vendor.addProductOtherOptions(productIdBasic, data.product.productInfo.otherOptions, 'visibility'); }); // shipping and tax test('vendor can add auction product shipping', { tag: ['@pro', '@vendor'] }, async () => { test.skip(true, 'has dokan issue, php notice'); - await vendor.addProductShipping(productId1, data.product.productInfo.shipping); + await vendor.addProductShipping(productIdBasic, data.product.productInfo.shipping); }); test('vendor can update auction product shipping', { tag: ['@pro', '@vendor'] }, async () => { test.skip(true, 'has dokan issue, php notice'); - await vendor.addProductShipping(productId, data.product.productInfo.shipping); + await vendor.addProductShipping(productIdFull, data.product.productInfo.shipping); }); test('vendor can remove auction product shipping', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.removeProductShipping(productId); + await vendor.removeProductShipping(productIdFull); }); test('vendor can add auction product tax', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductTax(productId1, data.product.productInfo.tax); + await vendor.addProductTax(productIdBasic, data.product.productInfo.tax); }); test('vendor can add auction product tax (with tax class)', { tag: ['@pro', '@vendor'] }, async () => { test.skip(true, 'Has Dokan Issue'); - await vendor.addProductTax(productId1, data.product.productInfo.tax, true); + await vendor.addProductTax(productIdBasic, data.product.productInfo.tax, true); }); // attribute test('vendor can add auction product attribute', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductAttribute(productId1, data.product.productInfo.attribute); + await vendor.addProductAttribute(productIdBasic, data.product.productInfo.attribute); }); test("vendor can't add already added auction product attribute", { tag: ['@pro', '@vendor'] }, async () => { - await vendor.cantAddAlreadyAddedAttribute(productId, data.product.productInfo.attribute.attributeName); + await vendor.cantAddAlreadyAddedAttribute(productIdFull, data.product.productInfo.attribute.attributeName); }); // todo: refactor below tests + test('vendor can create auction product attribute term', { tag: ['@pro', '@vendor'] }, async () => { const [, , , attributeName] = await apiUtils.createAttributeTerm(payloads.createAttribute(), payloads.createAttributeTerm(), payloads.adminAuth); const [, productId] = await apiUtils.createProduct(payloads.createAuctionProductRequiredFields(), payloads.vendorAuth); @@ -266,29 +269,29 @@ test.describe('Auction Product details functionality test', () => { // geolocation test('vendor can add auction product geolocation (individual)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductGeolocation(productId1, data.product.productInfo.geolocation); + await vendor.addProductGeolocation(productIdBasic, data.product.productInfo.geolocation); }); test('vendor can update auction product geolocation (individual)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.addProductGeolocation(productId, data.product.productInfo.geolocation); + await vendor.addProductGeolocation(productIdFull, data.product.productInfo.geolocation); }); test('vendor can remove auction product geolocation (individual)', { tag: ['@pro', '@vendor'] }, async () => { - await vendor.removeProductGeolocation(productId); + await vendor.removeProductGeolocation(productIdFull); }); // addon test('vendor can add product addon', { tag: ['@pro', '@vendor'] }, async () => { test.slow(); - await vendor.addProductAddon(productId1, data.product.productInfo.addon); + await vendor.addProductAddon(productIdBasic, data.product.productInfo.addon); }); // todo: add update product addon test in all product edit test files test('vendor can import auction product addon', { tag: ['@pro', '@vendor'] }, async () => { const addon = payloads.createProductAddon(); - await vendor.importAddon(productId1, serialize([addon]), addon.name); + await vendor.importAddon(productIdBasic, serialize([addon]), addon.name); }); test('vendor can export auction product addon', { tag: ['@pro', '@vendor'] }, async () => { diff --git a/tests/pw/tests/e2e/productsDetailsBookings.spec.ts b/tests/pw/tests/e2e/productsDetailsBookings.spec.ts new file mode 100644 index 0000000000..460ed23418 --- /dev/null +++ b/tests/pw/tests/e2e/productsDetailsBookings.spec.ts @@ -0,0 +1,406 @@ +import { test, request, Page } from '@playwright/test'; +import { BookingPage } from '@pages/vendorBookingPage'; +import { ApiUtils } from '@utils/apiUtils'; +import { dbUtils } from '@utils/dbUtils'; +import { data } from '@utils/testData'; +import { dbData } from '@utils/dbData'; +import { payloads } from '@utils/payloads'; +import { serialize } from 'php-serialize'; + +const { CATEGORY_ID } = process.env; + +test.describe('Booking Product details functionality test', () => { + let vendor: BookingPage; + let vPage: Page; + let apiUtils: ApiUtils; + let productIdFull: string; // has all fields + let productIdBasic: string; // has only required fields + + test.beforeAll(async ({ browser }) => { + const vendorContext = await browser.newContext(data.auth.vendorAuth); + vPage = await vendorContext.newPage(); + vendor = new BookingPage(vPage); + + apiUtils = new ApiUtils(await request.newContext()); + + // product with only required fields + [, productIdBasic] = await apiUtils.createBookableProduct(payloads.createBookableProductRequiredFields(), payloads.vendorAuth); + + // product with all fields + [, productIdFull] = await apiUtils.createBookableProduct(payloads.createBookableProduct(), payloads.vendorAuth); //todo: need to add all fields + }); + + test.afterAll(async () => { + // await apiUtils.deleteAllProducts(payloads.vendorAuth); + await vPage.close(); + await apiUtils.dispose(); + }); + + // vendor + + // product title + + test('vendor can update booking product title', { tag: ['@pro', '@vendor'] }, async () => { + const [, productId] = await apiUtils.createBookableProduct(payloads.createBookableProduct(), payloads.vendorAuth); + await vendor.addProductTitle(productId, data.product.productInfo.title); + }); + + // product virtual options + + test('vendor can add booking product accommodation booking option', { tag: ['@pro', '@vendor'] }, async () => { + const [, productId] = await apiUtils.createProduct(payloads.createBookableProductRequiredFields(), payloads.vendorAuth); + await vendor.addProductAccommodationBookingOptions(productId, data.product.booking.accommodationBookingOptions); + }); + + test('vendor can update booking product accommodation booking option', { tag: ['@pro', '@vendor'] }, async () => { + test.skip(true, 'need min & max duration'); // todo: need to add min & max duration + const [, productId] = await apiUtils.createProduct({ ...payloads.createBookableProductWithAccommodation() }, payloads.vendorAuth); + await vendor.addProductAccommodationBookingOptions(productId, { minimumNumberOfNightsAllowed: '1', maximumNumberOfNightsAllowed: '5', checkInTime: '1:00 am', checkOutTime: '1:00 am' }); + }); + + test('vendor can remove booking product accommodation booking option', { tag: ['@pro', '@vendor'] }, async () => { + const [, productId] = await apiUtils.createProduct({ ...payloads.createBookableProductWithAccommodation() }, payloads.vendorAuth); + await vendor.removeProductAccommodationBookingOptions(productId); + }); + + // product category + + test('vendor can update booking product category (single)', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductCategory(productIdFull, [data.product.category.clothings]); + }); + + test('vendor can add booking product category (multiple)', { tag: ['@pro', '@vendor'] }, async () => { + await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { product_category_style: 'multiple' }); + await vendor.addProductCategory(productIdBasic, data.product.category.categories, true); + }); + + test('vendor can remove booking product category (multiple)', { tag: ['@pro', '@vendor'] }, async () => { + await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { product_category_style: 'multiple' }); + const uncategorizedId = await apiUtils.getCategoryId('Uncategorized', payloads.adminAuth); + const [, productId] = await apiUtils.createProduct({ ...payloads.createBookableProduct(), categories: [{ id: uncategorizedId }, { id: CATEGORY_ID }] }, payloads.vendorAuth); // need multiple categories + await vendor.removeProductCategory(productId, [data.product.category.clothings]); + }); + + test('vendor can add multi-step booking product category (last category)', { tag: ['@pro', '@vendor'] }, async () => { + await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { product_category_style: 'single' }); + await vendor.addProductCategory(productIdBasic, [data.product.category.multistepCategories.at(-1)!]); + }); + + test('vendor can add multi-step booking product category (any category)', { tag: ['@pro', '@vendor'] }, async () => { + await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { dokan_any_category_selection: 'on' }); + await vendor.addProductCategory(productIdFull, [data.product.category.multistepCategories.at(-2)!]); + }); + + test("vendor can't add multi-step booking product category (any category)", { tag: ['@pro', '@vendor'] }, async () => { + await dbUtils.updateOptionValue(dbData.dokan.optionName.selling, { dokan_any_category_selection: 'off' }); + await vendor.cantAddCategory(productIdFull, data.product.category.multistepCategories.at(-2)!); + }); + + // product tags + + test('vendor can add booking product tags', { tag: ['@pro', '@vendor'] }, async () => { + test.skip(true, 'dokan issue option does not work'); + await vendor.addProductTags(productIdBasic, data.product.productInfo.tags.tags); + }); + + test('vendor can remove booking product tags', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.removeProductTags(productIdFull, data.product.productInfo.tags.tags); + }); + + test('vendor can create booking product tags', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductTags(productIdFull, data.product.productInfo.tags.randomTags); + }); + + // product cover image + + test('vendor can add booking product cover image', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductCoverImage(productIdBasic, data.product.productInfo.images.cover); + }); + + test('vendor can update booking product cover image', { tag: ['@pro', '@vendor'] }, async () => { + // todo: need a product with cover image + await vendor.addProductCoverImage(productIdFull, data.product.productInfo.images.cover); + await vendor.addProductCoverImage(productIdFull, data.product.productInfo.images.cover, true); + }); + + test('vendor can remove booking product cover image', { tag: ['@pro', '@vendor'] }, async () => { + // todo: need a product with cover image + await vendor.addProductCoverImage(productIdFull, data.product.productInfo.images.cover, true); + await vendor.removeProductCoverImage(productIdFull); + }); + + // product gallery image + + test('vendor can add booking product gallery image', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductGalleryImages(productIdBasic, data.product.productInfo.images.gallery); + }); + + test('vendor can update booking product gallery image', { tag: ['@pro', '@vendor'] }, async () => { + // todo: need a product with gallery images + await vendor.addProductGalleryImages(productIdFull, data.product.productInfo.images.gallery); + await vendor.addProductGalleryImages(productIdFull, data.product.productInfo.images.gallery, true); + }); + + test('vendor can remove booking product gallery image', { tag: ['@pro', '@vendor'] }, async () => { + // todo: need a product with gallery images + await vendor.addProductGalleryImages(productIdFull, data.product.productInfo.images.gallery, true); + await vendor.removeProductGalleryImages(productIdFull); + }); + + // product short description + test('vendor can add booking product short description', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductShortDescription(productIdBasic, data.product.productInfo.description.shortDescription); + }); + + test('vendor can update booking product short description', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductShortDescription(productIdFull, data.product.productInfo.description.shortDescription); + }); + + test('vendor can remove booking product short description', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductShortDescription(productIdFull, ''); + }); + + // product description + + test('vendor can update booking product description', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductDescription(productIdFull, data.product.productInfo.description.description); + }); + + // product virtual options + + test('vendor can add booking product virtual option', { tag: ['@pro', '@vendor'] }, async () => { + const [, productId] = await apiUtils.createProduct(payloads.createBookableProductRequiredFields(), payloads.vendorAuth); + await vendor.addProductVirtualOption(productId, true); + }); + + test('vendor can remove booking product virtual option', { tag: ['@pro', '@vendor'] }, async () => { + const [, productId] = await apiUtils.createProduct({ ...payloads.createBookableProductRequiredFields(), virtual: true }, payloads.vendorAuth); + await vendor.addProductVirtualOption(productId, false); + }); + + // product inventory options + + test('vendor can add booking product inventory options (SKU)', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductInventory(productIdBasic, data.product.productInfo.inventory(), 'sku'); + }); + + test('vendor can update booking product inventory options (SKU)', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductInventory(productIdFull, data.product.productInfo.inventory(), 'sku'); + }); + + test('vendor can remove booking product inventory options (SKU)', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductInventory(productIdFull, { ...data.product.productInfo.inventory(), sku: '' }, 'sku'); + }); + + test('vendor can add booking product inventory options (stock status)', { tag: ['@pro', '@vendor'] }, async () => { + test.skip(true, 'dokan issue option does not work'); + await vendor.addProductInventory(productIdBasic, data.product.productInfo.inventory(), 'stock-status'); + }); + + test('vendor can add booking product inventory options (stock management)', { tag: ['@pro', '@vendor'] }, async () => { + test.skip(true, 'dokan issue option does not work'); + await vendor.addProductInventory(productIdBasic, data.product.productInfo.inventory(), 'stock-management'); + }); + + test('vendor can update booking product inventory options (stock management)', { tag: ['@pro', '@vendor'] }, async () => { + test.skip(true, 'dokan issue option does not work'); + await vendor.addProductInventory(productIdBasic, data.product.productInfo.inventory(), 'stock-management'); + }); + + test('vendor can remove booking product inventory options (stock management)', { tag: ['@pro', '@vendor'] }, async () => { + test.skip(true, 'dokan issue option does not work'); + await vendor.removeProductInventory(productIdFull); + }); + + test('vendor can add booking product inventory options (allow single quantity)', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductInventory(productIdBasic, data.product.productInfo.inventory(), 'one-quantity'); + }); + + test('vendor can remove booking product inventory options (allow single quantity)', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductInventory(productIdFull, { ...data.product.productInfo.inventory(), oneQuantity: false }, 'one-quantity'); + }); + + // product other options + + test('vendor can add booking product other options (product status)', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductOtherOptions(productIdBasic, data.product.productInfo.otherOptions, 'status'); + }); + + test('vendor can add booking product other options (visibility)', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductOtherOptions(productIdBasic, data.product.productInfo.otherOptions, 'visibility'); + }); + + // shipping and tax + + test('vendor can add booking product shipping', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductShipping(productIdBasic, data.product.productInfo.shipping); + }); + + test('vendor can update booking product shipping', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductShipping(productIdFull, data.product.productInfo.shipping); + }); + + test('vendor can remove booking product shipping', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.removeProductShipping(productIdFull); + }); + + test('vendor can add booking product tax', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductTax(productIdBasic, data.product.productInfo.tax); + }); + + test('vendor can add booking product tax (with tax class)', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductTax(productIdBasic, data.product.productInfo.tax, true); + }); + + // booking duration + + test('vendor can add booking product duration', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductDuration(productIdBasic, data.product.booking.duration); + }); + + test('vendor can update booking product duration', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductDuration(productIdBasic, { bookingDurationType: 'customer', bookingDuration: '3', bookingDurationUnit: 'month', bookingDurationMin: '2', bookingDurationMax: '30' }); + }); + + test('vendor can add booking product basic options', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductBasicOptions(productIdBasic, data.product.booking); + }); + + // availability + + test('vendor can add booking product availability', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductAvailability(productIdBasic, data.product.booking.availability); + }); + + test('vendor can update booking product availability', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductAvailability(productIdBasic, { + maxBookingsPerBlock: '10', + minimumBookingWindowIntoTheFutureDate: '1', + minimumBookingWindowIntoTheFutureDateUnit: 'week', + maximumBookingWindowIntoTheFutureDate: '10', + maximumBookingWindowIntoTheFutureDateUnit: 'week', + requireABufferPeriodOfMonthsBetweenBookings: '2', + allDatesAvailability: 'non-available', + checkRulesAgainst: 'start', + }); + }); + + // costs + + test('vendor can add booking product costs', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductCosts(productIdBasic, data.product.booking.costs); + }); + + test('vendor can update booking product costs', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductCosts(productIdFull, { baseCost: '10', blockCost: '20', displayCost: '30' }); + }); + + test('vendor can remove booking product costs', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductCosts(productIdFull, { baseCost: '0', blockCost: '0', displayCost: '0' }); + }); + + // extra options + + test('vendor can add booking product extra options (persons)', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductPersons(productIdBasic, data.product.booking.extraOptions); + }); + + test('vendor can add booking product extra options (person type)', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductPersonType(productIdFull, data.product.booking.extraOptions); + }); + + test.skip('vendor can update booking product extra options (person type)', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductPersonType(productIdFull, data.product.booking.extraOptions); + }); + + test.skip('vendor can remove booking product extra options (person type)', { tag: ['@pro', '@vendor'] }, async () => { + // todo: need a product with person + await vendor.addProductPersons(productIdFull, data.product.booking.extraOptions); + await vendor.removeProductPersonType(productIdFull); + }); + + test.skip('vendor can add booking product extra options (resource)', { tag: ['@pro', '@vendor'] }, async () => { + // todo: need a product with resource + await vendor.addProductResources(productIdBasic, data.product.booking.extraOptions); + }); + + test.skip('vendor can update booking product extra options (resource)', { tag: ['@pro', '@vendor'] }, async () => { + // todo: need a product with resource + await vendor.addProductResources(productIdFull, data.product.booking.extraOptions); + }); + + test.skip('vendor can remove booking product extra options (resource)', { tag: ['@pro', '@vendor'] }, async () => { + // todo: need a product with resource + await vendor.addProductResources(productIdFull, data.product.booking.extraOptions); + await vendor.removeProductResource(productIdFull); + }); + + // attribute + + test('vendor can add booking product attribute', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductAttribute(productIdBasic, data.product.productInfo.attribute); + }); + + test("vendor can't add already added booking product attribute", { tag: ['@pro', '@vendor'] }, async () => { + await vendor.cantAddAlreadyAddedAttribute(productIdFull, data.product.productInfo.attribute.attributeName); + }); + + // todo: refactor below tests + + test('vendor can create booking product attribute term', { tag: ['@pro', '@vendor'] }, async () => { + const [, , , attributeName] = await apiUtils.createAttributeTerm(payloads.createAttribute(), payloads.createAttributeTerm(), payloads.adminAuth); + const [, productId] = await apiUtils.createProduct(payloads.createBookableProductRequiredFields(), payloads.vendorAuth); + await vendor.addProductAttribute(productId, { ...data.product.productInfo.attribute, attributeName: attributeName }, true); + }); + + test('vendor can remove booking product attribute', { tag: ['@pro', '@vendor'] }, async () => { + const [, attributeId, , attributeName, attributeTerm] = await apiUtils.createAttributeTerm(payloads.createAttribute(), payloads.createAttributeTerm(), payloads.adminAuth); + const attributes = { id: attributeId, name: attributeName, options: [attributeTerm] }; + const [, productId] = await apiUtils.createProduct({ ...payloads.createBookableProduct(), attributes: [attributes] }, payloads.vendorAuth); + await vendor.removeProductAttribute(productId, attributeName); + }); + + test('vendor can remove booking product attribute term', { tag: ['@pro', '@vendor'] }, async () => { + const [, attributeId, , attributeName, attributeTerm] = await apiUtils.createAttributeTerm(payloads.createAttribute(), payloads.createAttributeTerm(), payloads.adminAuth); + const [, , , , attributeTerm2] = await apiUtils.createAttributeTerm(payloads.createAttribute(), payloads.createAttributeTerm(), payloads.adminAuth); + const attributes = { id: attributeId, name: attributeName, options: [attributeTerm, attributeTerm2] }; + const [, productId] = await apiUtils.createProduct({ ...payloads.createBookableProduct(), attributes: [attributes] }, payloads.vendorAuth); + await vendor.removeProductAttributeTerm(productId, attributeName, attributeTerm2); + }); + + // geolocation + + test('vendor can add booking product geolocation (individual)', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductGeolocation(productIdBasic, data.product.productInfo.geolocation); + }); + + test('vendor can update booking product geolocation (individual)', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.addProductGeolocation(productIdFull, data.product.productInfo.geolocation); + }); + + test('vendor can remove booking product geolocation (individual)', { tag: ['@pro', '@vendor'] }, async () => { + await vendor.removeProductGeolocation(productIdFull); + }); + + // addon + + test('vendor can add booking product addon', { tag: ['@pro', '@vendor'] }, async () => { + test.slow(); + await vendor.addProductAddon(productIdBasic, data.product.productInfo.addon); + }); + + test('vendor can import booking product addon', { tag: ['@pro', '@vendor'] }, async () => { + const addon = payloads.createProductAddon(); + await vendor.importAddon(productIdBasic, serialize([addon]), addon.name); + }); + + test('vendor can export booking product addon', { tag: ['@pro', '@vendor'] }, async () => { + const [responseBody, productId] = await apiUtils.createProductWithAddon(payloads.createBookableProduct(), [payloads.createProductAddon()], payloads.vendorAuth); + await vendor.exportAddon(productId, serialize(apiUtils.getMetaDataValue(responseBody.meta_data, '_product_addons'))); + }); + + test('vendor can remove booking product addon', { tag: ['@pro', '@vendor'] }, async () => { + const [, productId, , addonNames] = await apiUtils.createProductWithAddon(payloads.createBookableProduct(), [payloads.createProductAddon()], payloads.vendorAuth); + await vendor.removeAddon(productId, addonNames[0] as string); + }); +}); diff --git a/tests/pw/tests/e2e/storelisting.spec.ts b/tests/pw/tests/e2e/storelisting.spec.ts index 292d443992..b61454c97b 100644 --- a/tests/pw/tests/e2e/storelisting.spec.ts +++ b/tests/pw/tests/e2e/storelisting.spec.ts @@ -55,6 +55,7 @@ test.describe('Store list functionality test', () => { }); test('customer can view stores on map', { tag: ['@pro', '@customer'] }, async () => { + // test.skip(true, '@todo fix this test'); await customer.storeOnMap(); }); diff --git a/tests/pw/tests/e2e/vendorBooking.spec.ts b/tests/pw/tests/e2e/vendorBooking.spec.ts index 2b94993b70..f8761054d8 100644 --- a/tests/pw/tests/e2e/vendorBooking.spec.ts +++ b/tests/pw/tests/e2e/vendorBooking.spec.ts @@ -31,6 +31,7 @@ test.describe('Booking Product test', () => { apiUtils = new ApiUtils(await request.newContext()); [, , bookableProductName] = await apiUtils.createBookableProduct(payloads.createBookableProduct(), payloads.vendorAuth); + // disable vendor global rma settings await dbUtils.setUserMeta(VENDOR_ID, '_dokan_rma_settings', dbData.testData.dokan.rmaSettings, true); }); diff --git a/tests/pw/utils/interfaces.ts b/tests/pw/utils/interfaces.ts index 7f0a35c054..cd5cfcc2e7 100644 --- a/tests/pw/utils/interfaces.ts +++ b/tests/pw/utils/interfaces.ts @@ -252,19 +252,59 @@ export interface product { name: string; productType: string; category: string; - bookingDurationType: string; - bookingDuration: string; - bookingDurationMin: string; - bookingDurationMax: string; - bookingDurationUnit: string; + accommodationBookingOptions: { + minimumNumberOfNightsAllowed: string; + maximumNumberOfNightsAllowed: string; + checkInTime: string; + checkOutTime: string; + }; + duration: { + bookingDurationType: string; + bookingDuration: string; + bookingDurationUnit: string; + bookingDurationMin: string; + bookingDurationMax: string; + }; + calendarDisplayMode: string; - maxBookingsPerBlock: string; - minimumBookingWindowIntoTheFutureDate: string; - minimumBookingWindowIntoTheFutureDateUnit: string; - maximumBookingWindowIntoTheFutureDate: string; - maximumBookingWindowIntoTheFutureDateUnit: string; - baseCost: string; - blockCost: string; + + availability: { + maxBookingsPerBlock: string; + minimumBookingWindowIntoTheFutureDate: string; + minimumBookingWindowIntoTheFutureDateUnit: string; + maximumBookingWindowIntoTheFutureDate: string; + maximumBookingWindowIntoTheFutureDateUnit: string; + requireABufferPeriodOfMonthsBetweenBookings: string; + allDatesAvailability: string; + checkRulesAgainst: string; + }; + costs: { + baseCost: string; + blockCost: string; + displayCost: string; + }; + + extraOptions: { + minPersons: string; + maxPersons: string; + person: { + typeName: string; + baseCost: string; + blockCost: string; + description: string; + min: string; + max: string; + }; + + label: string; + resourcesAllocation: string; + addResourceId: string; + resource: { + baseCost: string; + blockCost: string; + }; + }; + storeName: string; saveSuccessMessage: string; }; diff --git a/tests/pw/utils/payloads.ts b/tests/pw/utils/payloads.ts index f92468e116..0f486e0d09 100644 --- a/tests/pw/utils/payloads.ts +++ b/tests/pw/utils/payloads.ts @@ -962,7 +962,7 @@ export const payloads = { ], }), - createBookableProduct: () => ({ + createBookableProductRequiredFields: () => ({ name: `${faker.commerce.productName()}_${faker.string.nanoid(5)} (Bookable)`, status: 'publish', featured: true, @@ -976,11 +976,59 @@ export const payloads = { max_duration: 10, calendar_display_mode: 'always_visible', enable_range_picker: true, - requires_confirmations: false, + requires_confirmation: false, + can_be_cancelled: false, + default_date_availability: 'available', + block_cost: 5, + cost: 10, + has_persons: false, + has_resources: false, + qty: 100, + // min_date_value : 10, + // min_date_unit : 'day', + // max_date_value : 11, + // max_date_unit : 'month' + }), + + createBookableProduct: () => ({ + name: `${faker.commerce.productName()}_${faker.string.nanoid(5)} (Bookable)`, + status: 'publish', + featured: true, + description: '

test description

', + short_description: '

test short description

', + // categories + categories: [ + {}, + // { + // id: CATEGORY_ID, + // }, + ], + // tags + tags: [{ id: TAG_ID }], + // attributes + attributes: [ + { + id: ATTRIBUTE_ID, + name: 'sizes', + position: 0, + visible: true, + variation: true, + options: ['s', 'l', 'm'], + }, + ], + duration_type: 'customer', + duration_unit: 'day', + duration: 1, + min_duration: 1, + max_duration: 10, + calendar_display_mode: 'always_visible', + enable_range_picker: true, + requires_confirmation: false, can_be_cancelled: false, default_date_availability: 'available', block_cost: 5, cost: 10, + display_cost: '15', has_persons: false, has_resources: false, qty: 100, @@ -990,6 +1038,70 @@ export const payloads = { // max_date_unit : 'month' }), + createBookableProductWithAccommodation: () => ({ + name: `${faker.commerce.productName()}_${faker.string.nanoid(5)} (Bookable)`, + status: 'publish', + featured: true, + description: '

test description

', + short_description: '

test short description

', + // categories + categories: [ + {}, + // { + // id: CATEGORY_ID, + // }, + ], + // tags + tags: [{ id: TAG_ID }], + // attributes + attributes: [ + { + id: ATTRIBUTE_ID, + name: 'sizes', + position: 0, + visible: true, + variation: true, + options: ['s', 'l', 'm'], + }, + ], + duration_type: 'customer', + duration_unit: 'day', + duration: 1, + min_duration: 1, + max_duration: 10, + // min_duration: 88, + // max_duration: 89, + calendar_display_mode: 'always_visible', + enable_range_picker: true, + requires_confirmation: false, + can_be_cancelled: false, + default_date_availability: 'available', + block_cost: 5, + cost: 10, + display_cost: '15', + has_persons: false, + has_resources: false, + qty: 100, + // min_date_value : 10, + // min_date_unit : 'day', + // max_date_value : 11, + // max_date_unit : 'month' + meta_data: [ + { + key: '_dokan_is_accommodation_booking', + value: 'yes', + }, + { + key: '_dokan_accommodation_checkin_time', + value: '12:00 am', + }, + { + key: '_dokan_accommodation_checkout_time', + value: '12:00 am', + }, + ], + }), + createBookingResource: () => ({ name: `resource_${faker.string.nanoid(10)}`, qty: '1', @@ -1035,6 +1147,7 @@ export const payloads = { ], // tags tags: [{ id: TAG_ID }], + // attributes attributes: [ { id: ATTRIBUTE_ID, diff --git a/tests/pw/utils/testData.ts b/tests/pw/utils/testData.ts index 4f2865ca88..b55f30d9c2 100644 --- a/tests/pw/utils/testData.ts +++ b/tests/pw/utils/testData.ts @@ -363,19 +363,59 @@ export const data = { name: '', productType: 'booking', category: 'Uncategorized', - bookingDurationType: 'customer', // 'fixed', 'customer' - bookingDuration: '2', - bookingDurationMin: '1', - bookingDurationMax: '20', - bookingDurationUnit: 'day', // 'month', 'day', 'hour', 'minute' + accommodationBookingOptions: { + minimumNumberOfNightsAllowed: '1', + maximumNumberOfNightsAllowed: '5', + checkInTime: '12:00 am', + checkOutTime: '12:00 am', + }, + duration: { + bookingDurationType: 'customer', // 'fixed', 'customer' + bookingDuration: '2', + bookingDurationUnit: 'day', // 'month', 'day', 'hour', 'minute' + bookingDurationMin: '1', + bookingDurationMax: '20', + }, calendarDisplayMode: 'always_visible', // '', 'always_visible' - maxBookingsPerBlock: '5', - minimumBookingWindowIntoTheFutureDate: '0', - minimumBookingWindowIntoTheFutureDateUnit: 'month', - maximumBookingWindowIntoTheFutureDate: '5', - maximumBookingWindowIntoTheFutureDateUnit: 'month', - baseCost: '20', - blockCost: '10', + availability: { + maxBookingsPerBlock: '5', + minimumBookingWindowIntoTheFutureDate: '0', + minimumBookingWindowIntoTheFutureDateUnit: 'month', // 'month', 'week', 'day', 'hour', + maximumBookingWindowIntoTheFutureDate: '5', + maximumBookingWindowIntoTheFutureDateUnit: 'month', + requireABufferPeriodOfMonthsBetweenBookings: '1', + allDatesAvailability: 'available', // 'available', 'non-available' + checkRulesAgainst: 'start', // 'start' + }, + costs: { + baseCost: '5', + blockCost: '10', + displayCost: '15', + }, + + extraOptions: { + // persons + minPersons: '1', + maxPersons: '5', + person: { + typeName: 'children', + baseCost: '5', + blockCost: '5', + description: '1-5 years old', + min: '1', + max: '5', + }, + + // resource + label: 'test resource label', + resourcesAllocation: 'customer', // 'customer', 'automatic' + addResourceId: '427', //todo: need actual resource id + resource: { + baseCost: '5', + blockCost: '5', + }, + }, + storeName: `${VENDOR}store`, saveSuccessMessage: 'Success! The product has been saved successfully.', @@ -574,8 +614,8 @@ export const data = { commission: { commissionType: 'fixed', // 'fixed','category_based' [category commission will only be applicable to dokan subscription product] - commissionPercentage: '2', - commissionFixed: '2', + commissionPercentage: helpers.priceStringWithDecimal(2, 'ES'), + commissionFixed: helpers.priceStringWithDecimal(2, 'ES'), commissionCategory: { allCategory: true, // true for all category, false for specific category category: 'All Categories', @@ -868,8 +908,8 @@ export const data = { commission: { fixed: { commissionType: 'fixed', // 'fixed','category_based' - commissionPercentage: '10', - commissionFixed: '10', + commissionPercentage: helpers.priceStringWithDecimal(10, 'ES'), + commissionFixed: helpers.priceStringWithDecimal(0, 'ES'), commissionCategory: { allCategory: true, // true for all category, false for specific category category: 'All Categories', @@ -878,18 +918,18 @@ export const data = { allCategory: { commissionType: 'category_based', // 'fixed','category_based' - commissionPercentage: '5', - commissionFixed: '5', + commissionPercentage: helpers.priceStringWithDecimal(5, 'US'), // todo: change to ES when issue is fixed + commissionFixed: helpers.priceStringWithDecimal(5, 'US'), // todo: change to ES when issue is fixed commissionCategory: { allCategory: true, // true for all category, false for specific category category: 'All Categories', }, }, - specficCategory: { + specificCategory: { commissionType: 'category_based', // 'fixed','category_based' - commissionPercentage: '2', - commissionFixed: '2', + commissionPercentage: helpers.priceStringWithDecimal(2, 'US'), // todo: change to ES when issue is fixed + commissionFixed: helpers.priceStringWithDecimal(2, 'US'), // todo: change to ES when issue is fixed commissionCategory: { allCategory: false, // true for all category, false for specific category category: CATEGORY_ID, @@ -907,8 +947,8 @@ export const data = { sellingProductTypes: 'sell_both', // 'physical', 'digital', 'sell_both', commission: { commissionType: 'fixed', // 'fixed','category_based' - commissionPercentage: '10', - commissionFixed: '0', + commissionPercentage: helpers.priceStringWithDecimal(10, 'ES'), + commissionFixed: helpers.priceStringWithDecimal(0, 'ES'), commissionCategory: { allCategory: true, // true for all category, false for specific category category: 'All Categories', @@ -1117,6 +1157,7 @@ export const data = { followers: 'dashboard/followers', booking: 'dashboard/booking', addBookingProduct: 'dashboard/booking/new-product', + bookingProductEdit: (productId: string) => `dashboard/booking/edit/?product_id=${productId}`, addBooking: 'dashboard/booking/add-booking', manageBooking: 'dashboard/booking/my-bookings', bookingCalendar: 'dashboard/booking/calendar', @@ -1295,8 +1336,8 @@ export const data = { // commission commission: { commissionType: 'fixed', // 'fixed','category_based' - commissionPercentage: '5', - commissionFixed: '5', + commissionPercentage: helpers.priceStringWithDecimal(5, 'ES'), + commissionFixed: helpers.priceStringWithDecimal(5, 'ES'), commissionCategory: { allCategory: true, // true for all category, false for specific category category: 'All Categories', @@ -2136,8 +2177,8 @@ export const data = { settingTitle: 'Selling Option Settings', commission: { commissionType: 'fixed', // 'fixed','category_based' - commissionPercentage: '10', - commissionFixed: '0', + commissionPercentage: helpers.priceStringWithDecimal(10, 'ES'), + commissionFixed: helpers.priceStringWithDecimal(0, 'ES'), commissionCategory: { allCategory: true, // true for all category, false for specific category category: 'All Categories',