Skip to content

Commit

Permalink
add live chat module tests (#2426)
Browse files Browse the repository at this point in the history
* Add live chat settings

* Add action secret reference

* Fix live chat tests

* Fix pr reviews
  • Loading branch information
shashwatahalder01 authored Nov 1, 2024
1 parent f31aa2c commit d96222c
Show file tree
Hide file tree
Showing 18 changed files with 346 additions and 52 deletions.
19 changes: 11 additions & 8 deletions tests/pw/feature-map/feature-map.yml
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,7 @@
admin can set Dokan social api settings: true
admin can set Dokan shipping status settings: true
admin can set Dokan quote settings: true
admin can set Dokan live chat settings: true
admin can set Dokan rma settings: true
admin can set Dokan wholesale settings: true
admin can set Dokan eu compliance settings: true
Expand Down Expand Up @@ -762,16 +763,18 @@
- page: 'Live Chat'
features:
admin:
admin can set chat provider: false
admin can enable chat button on vendor page: false
admin can enable chat button on product page: false
# admin can set Dokan live chat settings [duplicate]: true
admin can enable chat button on vendor page: true
admin can disable chat button on vendor page: true
admin can enable chat button on product page (above_tab): true
admin can enable chat button on product page (inside_tab): true
admin can disable chat button on product page: true
vendor:
# vendor can set live chat settings [duplicate]: false
vendor can set inbox menu page: false
vendor can view inbox menu page: false
vendor can chat with customer: false
# vendor can set live chat settings [duplicate]: true
vendor can view inbox menu page: true
vendor can reply to customer message: true
customer:
customer can chat with vendor: false
customer can send message to vendor: true

- page: 'Live Search'
features:
Expand Down
14 changes: 13 additions & 1 deletion tests/pw/pages/basePage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,12 @@ export class BasePage {
// await locator.pressSequentially(text);
}

async clickFrameSelectorAndWaitForResponse(frame: string, subUrl: string, frameSelector: string, code = 200): Promise<Response> {
const locator = this.page.frameLocator(frame).locator(frameSelector);
const [response] = await Promise.all([this.page.waitForResponse(resp => resp.url().includes(subUrl) && resp.status() === code), locator.click()]);
return response;
}

/**
* Locator methods [using playwright locator class]
*/
Expand Down Expand Up @@ -1553,7 +1559,13 @@ export class BasePage {
}, options);
}

// assert element to contain text
// assert frame element to be visible
async toBeVisibleFrameLocator(frame: string, frameSelector: string, options?: { timeout?: number; visible?: boolean } | undefined) {
const locator = this.page.frameLocator(frame).locator(frameSelector);
await expect(locator).toBeVisible(options);
}

// assert frame element to contain text
async toContainTextFrameLocator(frame: string, frameSelector: string, text: string | RegExp, options?: { timeout?: number; intervals?: number[] }): Promise<void> {
await this.toPass(async () => {
const locator = this.page.frameLocator(frame).locator(frameSelector);
Expand Down
94 changes: 94 additions & 0 deletions tests/pw/pages/liveChatPage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { Page } from '@playwright/test';
import { BasePage } from '@pages/basePage';
import { selector } from '@pages/selectors';
import { data } from '@utils/testData';
import { helpers } from '@utils/helpers';

// selectors
const liveChatVendor = selector.vendor.vInbox;
const liveChatCustomer = selector.customer.cLiveChat;
const singleStoreCustomer = selector.customer.cSingleStore;
const singleProductCustomer = selector.customer.cSingleProduct;

export class LiveChatPage extends BasePage {
constructor(page: Page) {
super(page);
}

async gotoSingleStore(storeName: string, force = false): Promise<void> {
await this.goIfNotThere(data.subUrls.frontend.vendorDetails(helpers.slugify(storeName)), 'networkidle', force);
}

async goToProductDetails(productName: string, force = false): Promise<void> {
await this.goIfNotThere(data.subUrls.frontend.productDetails(helpers.slugify(productName)), 'domcontentloaded', force);
}

// vendor

// vendor inbox render properly
async vendorInboxRenderProperly(): Promise<void> {
await this.goIfNotThere(data.subUrls.frontend.vDashboard.inbox);

// chat persons, chat box, chat text box, send button is visible
await this.toBeVisibleFrameLocator(liveChatVendor.liveChatIframe, liveChatVendor.chatPersons);
await this.toBeVisibleFrameLocator(liveChatVendor.liveChatIframe, liveChatVendor.chatBox);
await this.toBeVisibleFrameLocator(liveChatVendor.liveChatIframe, liveChatVendor.chatTextBox);
await this.toBeVisibleFrameLocator(liveChatVendor.liveChatIframe, liveChatVendor.sendButton);
}

// vendor send message to customer
async sendMessageToCustomer(chatPerson: string, message: string): Promise<void> {
await this.goIfNotThere(data.subUrls.frontend.vDashboard.inbox);
await this.clickFrameSelector(liveChatVendor.liveChatIframe, liveChatVendor.chatPerson(chatPerson));
await this.typeFrameSelector(liveChatVendor.liveChatIframe, liveChatVendor.chatTextBox, message);
await this.clickFrameSelectorAndWaitForResponse(liveChatVendor.liveChatIframe, data.subUrls.frontend.talkjs, liveChatVendor.sendButton);
await this.toBeVisibleFrameLocator(liveChatVendor.liveChatIframe, liveChatVendor.sentMessage(message));
}

// customer

// customer send message to vendor
async sendMessageToVendor(storename: string, message: string): Promise<void> {
await this.gotoSingleStore(storename, true);
await this.click(singleStoreCustomer.storeTabs.chatNow);
await this.toBeVisible(liveChatCustomer.liveChatIframe);
await this.typeFrameSelector(liveChatCustomer.liveChatIframe, liveChatCustomer.chatTextBox, message);
await this.clickFrameSelectorAndWaitForResponse(liveChatCustomer.liveChatIframe, data.subUrls.frontend.talkjs, liveChatCustomer.sendButton);
await this.toBeVisibleFrameLocator(liveChatCustomer.liveChatIframe, liveChatCustomer.sentMessage(message));
}

// view chat button on vendor page
async viewLiveChatButtonOnStore(storename: string, disable = false): Promise<void> {
await this.gotoSingleStore(storename, true);
if (!disable) {
await this.toBeVisible(singleStoreCustomer.storeTabs.chatNow);
} else {
await this.notToBeVisible(singleStoreCustomer.storeTabs.chatNow);
}
}

// view chat button on product page
async viewLiveChatButtonOnProduct(productName: string, option: 'above-tab' | 'inside-tab' | 'dont-show'): Promise<void> {
await this.goToProductDetails(productName, true);

switch (option) {
case 'above-tab':
await this.toBeVisible(singleProductCustomer.productDetails.chatNow);
break;

case 'inside-tab':
await this.click(singleProductCustomer.menus.vendorInfo);
await this.toBeVisible(singleProductCustomer.productDetails.chatNow);
break;

case 'dont-show':
await this.notToBeVisible(singleProductCustomer.productDetails.chatNow);
await this.click(singleProductCustomer.menus.vendorInfo);
await this.notToBeVisible(singleProductCustomer.productDetails.chatNow);
break;

default:
break;
}
}
}
2 changes: 1 addition & 1 deletion tests/pw/pages/productsPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ export class ProductsPage extends AdminPage {
await this.hover(productsVendor.productCell(productName));
await this.clickAndWaitForLoadState(productsVendor.view(productName));
await expect(this.page).toHaveURL(data.subUrls.frontend.productDetails(helpers.slugify(productName)) + '/');
const { quantity, addToCart, viewCart, euComplianceData, productAddedSuccessMessage, productWithQuantityAddedSuccessMessage, ...productDetails } = selector.customer.cSingleProduct.productDetails;
const { quantity, addToCart, viewCart, chatNow, euComplianceData, productAddedSuccessMessage, productWithQuantityAddedSuccessMessage, ...productDetails } = selector.customer.cSingleProduct.productDetails;
await this.multipleElementVisible(productDetails);
}

Expand Down
81 changes: 53 additions & 28 deletions tests/pw/pages/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2417,25 +2417,22 @@ export const selector = {

// Live Chat
liveChat: {
enableLiveChat: '#dokan_live_chat\\[enable\\]',
chatProviderFacebookMessenger: '#dokan_live_chat\\[provider\\]\\[messenger\\]',
chatProviderTalkJs: '#dokan_live_chat\\[provider\\]\\[talkjs\\]',
chatProviderTawkTo: '#dokan_live_chat\\[provider\\]\\[tawkto\\]',
chatProviderWhatsApp: '#dokan_live_chat\\[provider\\]\\[whatsapp\\]',
enableLiveChat: '//label[@for="dokan_live_chat[enable]"]',
chatProvider: (provider: string) => `//label[contains(@for,'${provider}-provider')]`,

// Fb
messengerColor: '.button > span',
messengerColor: 'div.color-picker-container span.dashicons',

// Talkjs
talkJsAppId: '#dokan_live_chat\\[app_id\\]',
talkJsAppSecret: '#dokan_live_chat\\[app_secret\\]',
talkJsAppId: 'input#dokan_live_chat\\[app_id\\]',
talkJsAppSecret: 'input#dokan_live_chat\\[app_secret\\]',

// Whatsapp
openingPattern: '#dokan_live_chat\\[wa_opening_method\\]',
preFilledMessage: '#dokan_live_chat\\[wa_pre_filled_message\\]',
openingPattern: 'select#dokan_live_chat\\[wa_opening_method\\]',
preFilledMessage: 'textarea#dokan_live_chat\\[wa_pre_filled_message\\]',

// Chat Button
chatButtonOnVendorPage: '#dokan_live_chat\\[chat_button_seller_page\\]',
chatButtonOnVendorPage: '//label[@for="dokan_live_chat[chat_button_seller_page]"]',
chatButtonOnProductPage: '#dokan_live_chat\\[chat_button_product_page\\]',
liveChatSaveChanges: '#submit',
},
Expand Down Expand Up @@ -5913,7 +5910,7 @@ export const selector = {
},
},

// Settings
// settings
vSettings: {
store: '.store > a',
addons: '.product-addon > a',
Expand All @@ -5927,12 +5924,25 @@ export const selector = {
storeSEO: '.seo > a',
},

// Store Settings
// inbox
vInbox: {
chatPersons: 'div#hub',
chatPerson: (personName: string) => `//div[@class="ConversationListItem__conversation-name" and normalize-space(text())="${personName}"]/../../..`,
liveChatIframe: '(//iframe[@name="____talkjs__chat__ui_internal"])[last()]',
liveChatLauncher: 'a#__talkjs_launcher',

chatBox: 'div#chat-box',
chatTextBox: '//div[@role="textbox"]',
sendButton: 'button.send-button',
sentMessage: (message: string) => `//div[@id="chat-box"]//span[@class="EntityTreeRenderer" and normalize-space(text())="${message}"]`,
},

// store settings
vStoreSettings: {
settingsText: '.dokan-settings-content h1',
visitStore: '//a[normalize-space()="Visit Store"]',

// Wp Image Upload
// wp image upload
wpUploadFiles: '#menu-item-upload',
uploadedMedia: '.attachment-preview',
selectFiles: '//div[@class="supports-drag-drop" and @style="position: relative;"]//button[@class="browser button button-hero"]',
Expand All @@ -5950,7 +5960,7 @@ export const selector = {
uploadedProfilePicture: 'div#dokan-profile-picture-wrapper div.gravatar-wrap',
removeProfilePictureImage: '.dokan-close.dokan-remove-gravatar-image',

// Basic Store Info
// basic store Info
storeName: '#dokan_store_name',
phoneNo: '#setting_phone',

Expand All @@ -5967,7 +5977,7 @@ export const selector = {
editLocation: '.store-pickup-location-edit-btn',
locationName: '#store-location-name-input',

// Address
// address
address: {
street: '#dokan_address\\[street_1\\]',
street2: '#dokan_address\\[street_2\\]',
Expand All @@ -5980,7 +5990,7 @@ export const selector = {
deleteSaveLocation: '.store-pickup-location-delete-btn',
},

// Company Info
// company info
companyInfo: {
companyName: '#settings_dokan_company_name',
companyId: '#settings_dokan_company_id_number',
Expand All @@ -5989,18 +5999,18 @@ export const selector = {
bankIban: '#setting_bank_iban',
},

// Email
// email
email: '//label[contains(text(), "Email")]/..//input[@type="checkbox"]',

// Map
// map
map: '#dokan-map-add',

// Terms and Conditions
// terms and conditions
termsAndConditions: '//label[contains(text(), "Terms and Conditions")]/..//input[@type="checkbox"]',
termsAndConditionsIframe: '#dokan_tnc_text iframe',
termsAndConditionsHtmlBody: '#tinymce',

// Store Opening Closing Time
// store opening closing time
storeOpeningClosingTime: '#dokan-store-time-enable',

// lite locators
Expand All @@ -6021,7 +6031,7 @@ export const selector = {
storeOpenNotice: '//input[@name="dokan_store_open_notice"]',
storeCloseNotice: '//input[@name="dokan_store_close_notice"]',

// Vacation
// vacation
goToVacation: '#dokan-seller-vacation-activate',
closingStyle: 'label .form-control',
setVacationMessageInstantly: '//textarea[@id="dokan-seller-vacation-message" and @name="setting_vacation_message"]',
Expand All @@ -6043,21 +6053,24 @@ export const selector = {
hideProductPrice: 'input#catalog_mode_hide_product_price',
enableRequestQuoteSupport: 'input#catalog_mode_request_a_quote_support',

// Discount
// discount
enableStoreWideDiscount: '#lbl_setting_minimum_quantity',
minimumOrderAmount: '#setting_minimum_order_amount',
percentage: '#setting_order_percentage',

// Biography
// biography
biographyIframe: '#wp-vendor_biography-wrap iframe',
biographyHtmlBody: '#tinymce',

// Store Support
// store support
showSupportButtonInStore: '#support_checkbox',
showSupportButtonInSingleProduct: '#support_checkbox_product',
supportButtonText: '#dokan_support_btn_name',

// Min-Max
// live chat
liveChat: 'input#live_chat',

// min-max
minMax: {
minimumAmountToPlaceAnOrder: 'input#min_amount_to_order',
maximumAmountToPlaceAnOrder: 'input#max_amount_to_order',
Expand Down Expand Up @@ -6962,6 +6975,7 @@ export const selector = {
price: '//div[@class="summary entry-summary"]//p[@class="price"]',
quantity: 'div.quantity input.qty',
addToCart: 'button.single_add_to_cart_button',
chatNow: 'button.dokan-live-chat',
viewCart: '.woocommerce .woocommerce-message > .button',
category: '.product_meta .posted_in',

Expand Down Expand Up @@ -7310,9 +7324,10 @@ export const selector = {

// Store Tabs
storeTabs: {
follow: '.dokan-follow-store-button',
follow: 'button.dokan-follow-store-button',
getSupport: 'button.dokan-store-support-btn',
share: '.dokan-share-btn',
chatNow: 'button.dokan-live-chat',
share: 'button.dokan-share-btn',

products: '//div[@class="dokan-store-tabs"]//a[contains(text(),"Products")]',
toc: '//div[@class="dokan-store-tabs"]//a[contains(text(),"Terms and Conditions")]',
Expand Down Expand Up @@ -7801,6 +7816,16 @@ export const selector = {
searchResultWithCategory: (productName: string, category: string) => `//div[@id="dokan-ajax-search-suggestion-result"]//h3[normalize-space(text())='${productName}']//..//span[normalize-space(text())='${category}']`,
},

cLiveChat: {
liveChatIframe: '(//div[ contains(@id, "__talkjs_popup_container") and not (@style="display: none;") ]//iframe[@name="____talkjs__chat__ui_internal"])[last()]',
// liveChatIframe: '(//iframe[@name="____talkjs__chat__ui_internal"])[last()]',
liveChatLauncher: 'a#__talkjs_launcher',
chatBox: 'div#chat-box',
chatTextBox: '//div[@role="textbox"]',
sendButton: 'button.send-button',
sentMessage: (message: string) => `//span[@class="EntityTreeRenderer" and normalize-space(text())="${message}"]`,
},

cOrderReceived: {
orderReceivedHeading: '//h1[normalize-space()="Order received"]',
orderReceivedSuccessMessage: '.woocommerce-notice.woocommerce-notice--success.woocommerce-thankyou-order-received',
Expand Down
24 changes: 24 additions & 0 deletions tests/pw/pages/settingsPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,30 @@ export class SettingsPage extends AdminPage {
await this.toContainText(settingsAdmin.dokanUpdateSuccessMessage, quote.saveSuccessMessage);
}

// Admin Set Dokan live chat Settings
async setDokanLiveChatSettings(liveChat: dokanSettings['liveChat']) {
await this.goToDokanSettings();
await this.click(settingsAdmin.menus.liveChat);

// liveChat Settings
await this.enableSwitcher(settingsAdmin.liveChat.enableLiveChat);
await this.click(settingsAdmin.liveChat.chatProvider(liveChat.chatProvider));
await this.clearAndType(settingsAdmin.liveChat.talkJsAppId, liveChat.talkJsAppId);
await this.clearAndType(settingsAdmin.liveChat.talkJsAppSecret, liveChat.talkJsAppSecret);
await this.enableSwitcher(settingsAdmin.liveChat.chatButtonOnVendorPage);
await this.selectByValue(settingsAdmin.liveChat.chatButtonOnProductPage, liveChat.chatButtonPosition);

// save settings
await this.clickAndWaitForResponseAndLoadState(data.subUrls.ajax, settingsAdmin.liveChat.liveChatSaveChanges);

await this.toHaveBackgroundColor(settingsAdmin.liveChat.enableLiveChat + '//span', 'rgb(0, 144, 255)');
await this.toHaveClass(settingsAdmin.liveChat.chatProvider(liveChat.chatProvider), 'checked');
await this.toHaveValue(settingsAdmin.liveChat.talkJsAppId, liveChat.talkJsAppId);
await this.toHaveValue(settingsAdmin.liveChat.talkJsAppSecret, liveChat.talkJsAppSecret);
await this.toHaveBackgroundColor(settingsAdmin.liveChat.chatButtonOnVendorPage + '//span', 'rgb(0, 144, 255)');
await this.toHaveSelectedValue(settingsAdmin.liveChat.chatButtonOnProductPage, liveChat.chatButtonPosition);
}

// Admin Set Dokan Rma Settings
async setDokanRmaSettings(rma: dokanSettings['rma']) {
await this.goToDokanSettings();
Expand Down
Loading

0 comments on commit d96222c

Please sign in to comment.