/* eslint no-invalid-this: "off" */ let actions = { parsedUrl: async function() { return new URL(await this.url()); }, waitUntilNotPresent: async function(selector) { await this.wait(selector => { return document.querySelector(selector) == null; }, selector); }, changeLanguageToEnglish: async function() { let langSelector = '.user-popover vn-autocomplete[ng-model="$ctrl.lang"]'; await this.waitToClick('#user'); await this.wait(langSelector); let lang = await this.waitToGetProperty(`${langSelector} input`, 'value'); if (lang !== 'English') await this.autocompleteSearch(langSelector, 'English'); await this.waitFor(250); // tryed {visible: true}, page 'mutation' and waitForSelector unsuccessfully... await this.mouse.down(); await this.waitForSelector(langSelector, {hidden: true}); }, doLogin: async function(userName, password = 'nightmare') { await this.wait(`vn-login [name=user]`); await this.clearInput(`vn-login [name=user]`); await this.write(`vn-login [name=user]`, userName); await this.clearInput(`vn-login [name=password]`); await this.write(`vn-login [name=password]`, password); await this.click('vn-login button[type=submit]'); }, login: async function(userName) { await this.doLogin(userName); await this.wait(() => { return document.location.hash === '#!/'; }, {}); await this.changeLanguageToEnglish(); }, waitForLogin: async function(userName) { await this.login(userName); }, selectModule: async function(moduleName) { let snakeName = moduleName.replace(/[\w]([A-Z])/g, m => { return m[0] + '-' + m[1]; }).toLowerCase(); let selector = `vn-home a[ui-sref="${moduleName}.index"]`; await this.waitToClick(selector); await this.waitForURL(snakeName); }, loginAndModule: async function(userName, moduleName) { await this.login(userName); await this.selectModule(moduleName); }, datePicker: async function(selector, changeMonth, day) { let date = new Date(); if (changeMonth) date.setMonth(date.getMonth() + changeMonth); date.setDate(day ? day : 16); date = date.toISOString().substr(0, 10); await this.wait(selector); await this.evaluate((selector, date) => { let input = document.querySelector(selector).$ctrl.input; input.value = date; input.dispatchEvent(new Event('change')); }, selector, date); }, pickTime: async function(selector, time) { await this.wait(selector); await this.evaluate((selector, time) => { let input = document.querySelector(selector).$ctrl.input; input.value = time; input.dispatchEvent(new Event('change')); }, selector, time); }, clearTextarea: async function(selector) { await this.wait(selector); await this.input.evaluate(inputSelector => { return document.querySelector(inputSelector).value = ''; }, selector); }, clearInput: async function(selector) { await this.wait(selector); return await this.evaluate(selector => { let $ctrl = document.querySelector(selector).closest('.vn-field').$ctrl; $ctrl.field = null; $ctrl.$.$apply(); $ctrl.input.dispatchEvent(new Event('change')); }, selector); }, getProperty: async function(selector, property) { return await this.evaluate((selector, property) => { return document.querySelector(selector)[property].replace(/\s+/g, ' ').trim(); }, selector, property); }, waitPropertyLength: async function(selector, property, minLength) { await this.wait((selector, property, minLength) => { const element = document.querySelector(selector); return element && element[property] != null && element[property] !== '' && element[property].length >= minLength; }, {}, selector, property, minLength); return await this.getProperty(selector, property); }, waitPropertyValue: async function(selector, property, status) { await this.wait(selector); return await this.wait((selector, property, status) => { const element = document.querySelector(selector); return element[property] === status; }, {}, selector, property, status); }, waitToGetProperty: async function(selector, property) { await this.wait((selector, property) => { const element = document.querySelector(selector); return element && element[property] != null && element[property] !== ''; }, {}, selector, property); return await this.getProperty(selector, property); }, write: async function(selector, text) { await this.wait(selector); await this.type(selector, text); }, waitToClick: async function(selector) { await this.wait(selector); await this.click(selector); }, focusElement: async function(selector) { await this.wait(selector); return await this.evaluate(selector => { let element = document.querySelector(selector); element.focus(); }, selector); }, isVisible: async function(selector) { await this.wait(selector); return await this.evaluate(elementSelector => { let selectorMatches = document.querySelectorAll(elementSelector); let element = selectorMatches[0]; if (selectorMatches.length > 1) throw new Error(`Multiple matches of ${elementSelector} found`); let isVisible = false; if (element) { let eventHandler = event => { event.preventDefault(); isVisible = true; }; element.addEventListener('mouseover', eventHandler); let rect = element.getBoundingClientRect(); let x = rect.left + rect.width / 2; let y = rect.top + rect.height / 2; let elementInCenter = document.elementFromPoint(x, y); let elementInTopLeft = document.elementFromPoint(rect.left, rect.top); let elementInBottomRight = document.elementFromPoint(rect.right, rect.bottom); let e = new MouseEvent('mouseover', { view: window, bubbles: true, cancelable: true, }); if (elementInCenter) elementInCenter.dispatchEvent(e); if (elementInTopLeft) elementInTopLeft.dispatchEvent(e); if (elementInBottomRight) elementInBottomRight.dispatchEvent(e); element.removeEventListener('mouseover', eventHandler); } return isVisible; }, selector); }, waitImgLoad: async function(selector) { await this.wait(selector); return await this.wait(selector => { const imageReady = document.querySelector(selector).complete; return imageReady; }, selector); }, clickIfVisible: async function(selector) { await this.wait(selector); let isVisible = await this.isVisible(selector); if (isVisible) return await this.click(selector); throw new Error(`invisible selector: ${selector}`); }, countElement: async function(selector) { return await this.evaluate(selector => { return document.querySelectorAll(selector).length; }, selector); }, waitForNumberOfElements: async function(selector, count) { return await this.wait((selector, count) => { return document.querySelectorAll(selector).length === count; }, {}, selector, count); }, waitForClassNotPresent: async function(selector, className) { await this.wait(selector); return await this.wait((selector, className) => { if (!document.querySelector(selector).classList.contains(className)) return true; }, {}, selector, className); }, waitForClassPresent: async function(selector, className) { await this.wait(selector); return await this.wait((elementSelector, targetClass) => { if (document.querySelector(elementSelector).classList.contains(targetClass)) return true; }, {}, selector, className); }, waitForTextInElement: async function(selector, text) { await this.wait(selector); return await this.wait((selector, text) => { return document.querySelector(selector).innerText.toLowerCase().includes(text.toLowerCase()); }, {}, selector, text); }, waitForTextInInput: async function(selector, text) { await this.wait(selector); return await this.wait((selector, text) => { return document.querySelector(selector).value.toLowerCase().includes(text.toLowerCase()); }, {}, selector, text); }, waitForInnerText: async function(selector) { await this.wait(selector); await this.wait(selector => { const innerText = document.querySelector(selector).innerText; return innerText != null && innerText != ''; }, selector); return await this.evaluate(selector => { return document.querySelector(selector).innerText; }, selector); }, waitForEmptyInnerText: async function(selector) { return await this.wait(selector => { return document.querySelector(selector).innerText == ''; }, selector); }, waitForURL: async function(hashURL) { await this.wait(expectedHash => { return document.location.hash.includes(expectedHash); }, {}, hashURL); }, waitForShapes: async function(selector) { await this.wait(selector); return await this.evaluate(selector => { const shapes = document.querySelectorAll(selector); const shapesList = []; for (const shape of shapes) shapesList.push(shape.innerText); return shapesList; }, selector); }, waitForSnackbar: async function() { await this.wait(500); return await this.waitForShapes('vn-snackbar .shape .text'); }, waitForLastShape: async function(selector) { await this.wait(selector); return await this.evaluate(selector => { const shape = document.querySelector(selector); return shape.innerText; }, selector); }, waitForLastSnackbar: async function() { await this.wait(500); await this.waitForSpinnerLoad(); return await this.waitForLastShape('vn-snackbar .shape .text'); }, accessToSearchResult: async function(searchValue) { await this.clearInput('vn-searchbar input'); await this.write('vn-searchbar input', searchValue); await this.click('vn-searchbar vn-icon[icon="search"]'); await this.waitForNumberOfElements('.search-result', 1); let result = await this.evaluate(() => { return document.querySelector('ui-view vn-card vn-table') != null; }); if (result) return await this.waitToClick('ui-view vn-card vn-td'); return await this.waitToClick('ui-view vn-card a'); }, accessToSection: async function(sectionRoute) { await this.wait(`vn-left-menu`); letnested = await this.evaluate(sectionRoute => { return document.querySelector(`vn-left-menu li li > a[ui-sref="${sectionRoute}"]`) != null; }, sectionRoute); if (nested) { await this.waitToClick('vn-left-menu vn-item-section > vn-icon[icon=keyboard_arrow_down]'); await this.wait('vn-left-menu .expanded'); } await this.waitToClick(`vn-left-menu li > a[ui-sref="${sectionRoute}"]`); await this.waitForSpinnerLoad(); }, autocompleteSearch: async function(autocompleteSelector, searchValue) { await this.waitToClick(`${autocompleteSelector} input`); await this.write(`.vn-drop-down.shown input`, searchValue); await this.waitToClick(`.vn-drop-down.shown li.active`); await this.wait((autocompleteSelector, searchValue) => { return document.querySelector(`${autocompleteSelector} input`).value .toLowerCase() .includes(searchValue.toLowerCase()); }, {}, autocompleteSelector, searchValue); await this.wait(() => { return !document.querySelector('.vn-drop-down'); }, {}); }, reloadSection: async function(sectionRoute) { await this.waitToClick('vn-icon[icon="desktop_windows"]'); await this.wait('vn-card.summary'); await this.waitToClick(`vn-left-menu li > a[ui-sref="${sectionRoute}"]`); }, forceReloadSection: async function(sectionRoute) { await this.waitToClick('vn-icon[icon="desktop_windows"]'); await this.waitToClick('button[response="accept"]'); await this.wait('vn-card.summary'); await this.waitToClick(`vn-left-menu li > a[ui-sref="${sectionRoute}"]`); }, checkboxState: async function(selector) { await this.wait(selector); return await this.evaluate(selector => { let checkbox = document.querySelector(selector); switch (checkbox.$ctrl.field) { case null: return 'intermediate'; case true: return 'checked'; default: return 'unchecked'; } }, selector); }, isDisabled: async function(selector) { await this.wait(selector); return await this.evaluate(selector => { let element = document.querySelector(selector); return element.$ctrl.disabled; }, selector); }, waitForStylePresent: async function(selector, property, value) { return await this.wait((selector, property, value) => { const element = document.querySelector(selector); return element.style[property] == value; }, {}, selector, property, value); }, waitForSpinnerLoad: async function() { await this.waitUntilNotPresent('vn-topbar vn-spinner'); }, waitForWatcherData: async function(selector) { await this.wait(selector); await this.wait(selector => { const watcher = document.querySelector(selector); let orgData = watcher.$ctrl.orgData; return !angular.equals({}, orgData) && orgData != null; }, selector); await this.waitForSpinnerLoad(); } }; export function extendPage(page) { for (let name in actions) { page[name] = async(...args) => { return await actions[name].call(page, ...args); }; } page.wait = page.waitFor; return page; } export default actions;