src/page_objects/web/general/globalSearch.page.js
import BasePage from "../../base.page.js";
/**
* GlobalSearchSection
* @extends BasePage
*/
class GlobalSearchPage extends BasePage {
/**
* @param {*} browser Browser from controller
*/
constructor(browser) {
super(browser);
}
// PAGE ELEMENTS
/* eslint-disable require-jsdoc */
searchInput() {
return this.element("#globalSearch");
}
scrollDivision() {
return this.element("[class*='GlobalSearch__infiniteScroll']");
}
contactListElements() {
return this.elements("[class*='GlobalSearch__contactListItem']");
}
emptyMessage() {
return this.element("[class*='components-EmptyMessage']");
}
/* eslint-enable require-jsodoc */
/**
* Internal function to scroll the scrolling division to an offset
* @param {Number} offset offset to scroll, by default scrolls to top
*/
async _scrollContainerToPosition(offset = 0) {
const element = this.scrollDivision();
await element.waitForVisible();
await this.browser.execute(
(selector, offset) => {
// eslint-disable-next-line
var ele = document.querySelector(selector);
ele.scrollTop = offset;
},
element.selector,
offset
);
await this.browser.pause(1000);
}
/**
* Internal function that gives if the scroll division is at bottom
* @return {Boolean} scroll division at bottom or not
*/
async _isBottomOfScroll() {
const element = this.scrollDivision();
await element.waitForVisible();
const result = await this.browser.execute(selector => {
// eslint-disable-next-line
var ele = document.querySelector(selector);
return ele.scrollHeight - ele.offsetHeight === ele.scrollTop;
}, element.selector);
return result.value;
}
/**
* Internal function to scroll contact to the top in scroll division
* @param {PageElement} contactElement Contact element to scroll to
*/
async _scrollToContact(contactElement) {
const elementOffset = await contactElement.getAttribute("offsetTop");
await this._scrollContainerToPosition(elementOffset);
}
/**
* Internal function that returns the name selector within an element
* @param {String} name name of the contact
* @return {String} selector for name of the contact
*/
_nameSelector(name) {
// eslint-disable-next-line
return `.//div[contains(@class,'ContactListItem__overflowContainer') and string()='${name}']`;
}
/**
* Internal method that checks if the name element is found in parent element
* @param {PageElement} parentElement parent element to llok for
* @param {String} name name to be searched within parentElement
* @return {Boolean} element found or not
*/
async _isContactFoundInElement(parentElement, name) {
let subElement;
try {
subElement = await parentElement.element(this._nameSelector(name));
} catch (error) {
if (error.message.includes("Unable to locate sub-element")) return false;
throw error;
}
return await subElement.isVisible();
}
/**
* Internal method to find and return contact element
* @param {String} name name of the contact
* @return {PageElement} Contact list element
*/
async _findContact(name) {
// Search for the element within container
// to avoid looping for each list element
// if not load the next set of elements by scrolling
if (!await this._isContactFoundInElement(this.scrollDivision(), name)) {
if (await this._isBottomOfScroll()) return null;
const lastContact = await this.contactListElements().last();
await this._scrollToContact(lastContact);
return await this._findContact(name);
} else {
return await this._getContactElementFromList(name);
}
}
/**
* Internal method to get contacts from the list of visible entries
* @param {String} name Name of the contact
* @return {PageElement} PageElement of the contact or null
*/
async _getContactElementFromList(name) {
const contactElements = await this.contactListElements().all();
let contactElement = null;
for (const eachElement of contactElements) {
if (await this._isContactFoundInElement(eachElement, name)) {
contactElement = eachElement;
await this._scrollToContact(contactElement);
}
}
return contactElement;
}
/**
* Type in global search field
* @param {String} name Name to search for
*/
async typeInSearchField(name) {
await this.searchInput().setValue(name);
}
/**
* Scroll and find contact in global search dropdown
* @param {String} name name of the contact to search for
* @return {PageElement} contact PageElement
*/
async scrollAndfindContact(name) {
await this._scrollContainerToPosition(0); // scrolls to top of the container
return await this._findContact(name);
}
/**
* Search and return contact element if found
* @param {name} name Name of the contact to search for
* @return {PageElement} contact page element
*/
async searchContact(name) {
await this.typeInSearchField(name);
const contact = await this.scrollAndfindContact(name);
return contact;
}
/**
* Search and select a contact from global search
* @param {String} name name of the contact
*/
async selectContact(name) {
const contact = await this.searchContact(name);
await contact.click();
}
/**
* Checks if chat icon is available within the contact element
* @param {String} name name of the contact
* @return {Boolean} whether chat icon exists or not
*/
async isContactChattable(name) {
const contact = await this.searchContact(name);
await contact.hover();
try {
await contact.element("button.icon-chat");
return true;
} catch (error) {
if (error.message.includes("Unable to locate sub-element")) return false;
throw error;
}
}
}
export default GlobalSearchPage;