/* eslint no-invalid-this: "off" */ import config from './config.js'; import Nightmare from 'nightmare'; import {URL} from 'url'; Nightmare.action('login', function(userName, done) { this.goto(`${config.url}auth/?apiKey=salix`) .wait(`vn-login input[name=user]`) .write(`vn-login input[name=user]`, userName) .write(`vn-login input[name=password]`, 'nightmare') .click(`vn-login input[type=submit]`) // FIXME: Wait for dom to be ready: https://github.com/segmentio/nightmare/issues/481 .wait(1000) .then(done); }); Nightmare.action('changeLanguageToEnglish', function(done) { this.wait('#lang') .evaluate((selector) => { return document.querySelector(selector).title; }, '#lang') .then((title) => { if (title === 'Change language') this.then(done); else { this.click('#lang') .click('vn-main-menu [vn-id="langs-menu"] ul > li[name="en"]') .then(done); } }); }); Nightmare.action('waitForLogin', function(userName, done) { this.login(userName) .waitForURL('#!/') .url() .changeLanguageToEnglish() .then(done); }); Nightmare.action('parsedUrl', function(done) { this.url() .then((url) => { done(null, new URL(url)); }); }); Nightmare.action('getProperty', function(selector, property, done) { this.evaluate_now((selector, property) => { return document.querySelector(selector)[property].replace(/\s+/g, ' ').trim(); }, done, selector, property); }); Nightmare.action('waitPropertyLength', function(selector, property, minLength, done) { this.wait((selector, property, minLength) => { const element = document.querySelector(selector); return element && element[property] != null && element[property] !== '' && element[property].length >= minLength; }, selector, property, minLength) .getProperty(selector, property) .then((result) => done(null, result), done); }); Nightmare.action('waitProperty', function(selector, property, done) { this.wait((selector, property) => { const element = document.querySelector(selector); return element && element[property] != null && element[property] !== ''; }, selector, property) .getProperty(selector, property) .then((result) => done(null, result), done); }); Nightmare.action('getInnerText', function(selector, done) { this.wait(selector) .evaluate_now(function(elementToSelect) { return document.querySelector(elementToSelect).innerText; }, done, selector); }); Nightmare.action('getInputValue', function(selector, done) { this.wait(selector) .evaluate_now(function(elementToSelect) { return document.querySelector(elementToSelect).value; }, done, selector); }); Nightmare.action('clearInput', function(selector, done) { const backSpaces = []; for (let i = 0; i < 50; i += 1) backSpaces.push('\u0008'); this.wait(selector) .type(selector, backSpaces.join('')) .then(done); }); Nightmare.action('write', function(selector, text, done) { this.wait(selector) .type(selector, text) .then(done); }); Nightmare.action('waitToClick', function(selector, done) { this.wait(selector) .click(selector) .then(done); }); Nightmare.action('isVisible', function(selector, done) { this.wait(selector) .evaluate_now((elementSelector) => { const selectorMatches = document.querySelectorAll(elementSelector); const element = selectorMatches[0]; if (selectorMatches.length > 1) throw new Error(`multiple matches of ${elementSelector} found`); let isVisible = false; if (element) { const eventHandler = (event) => { event.preventDefault(); isVisible = true; }; element.addEventListener('mouseover', eventHandler); const elementBoundaries = element.getBoundingClientRect(); const x = elementBoundaries.left + element.offsetWidth / 2; const y = elementBoundaries.top + element.offsetHeight / 2; const elementInCenter = document.elementFromPoint(x, y); const elementInTopLeft = document.elementFromPoint(elementBoundaries.left, elementBoundaries.top); const elementInBottomRight = document.elementFromPoint(elementBoundaries.right, elementBoundaries.bottom); const 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; }, done, selector); }); Nightmare.action('selectText', function(selector, done) { this.wait(selector) .evaluate((elementToSelect) => { const range = document.createRange(); range.selectNodeContents(document.querySelector(elementToSelect)); const sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); }, selector) .mouseup(selector) .then(done); }); Nightmare.action('countElement', function(selector, done) { this.evaluate_now((selector) => { return document.querySelectorAll(selector).length; }, done, selector); }); Nightmare.action('waitForNumberOfElements', function(selector, count, done) { this.wait((resultSelector, expectedCount) => { return document.querySelectorAll(resultSelector).length === expectedCount; }, selector, count) .then(done); }); Nightmare.action('waitForClassNotPresent', function(selector, className, done) { this.wait(selector) .wait((resultSelector, targetClass) => { if (!document.querySelector(resultSelector).classList.contains(targetClass)) return true; }, selector, className) .then(done); }); Nightmare.action('waitForClassPresent', function(selector, className, done) { this.wait(selector) .wait((resultSelector, targetClass) => { if (document.querySelector(resultSelector).classList.contains(targetClass)) return true; }, selector, className) .then(done); }); Nightmare.action('waitForTextInElement', function(selector, name, done) { this.wait(selector) .wait((resultSelector, expectedText) => { return document.querySelector(resultSelector).innerText.toLowerCase().includes(expectedText.toLowerCase()); }, selector, name) .then(done); }); Nightmare.action('waitForTextInInput', function(selector, name, done) { this.wait(selector) .wait((resultSelector, expectedText) => { return document.querySelector(resultSelector).value.toLowerCase().includes(expectedText.toLowerCase()); }, selector, name) .then(done); }); Nightmare.action('waitForInnerText', function(selector, done) { this.wait(selector) .wait((selector) => { const innerText = document.querySelector(selector).innerText; return innerText != null && innerText != ''; }, selector) .evaluate_now((selector) => { return document.querySelector(selector).innerText; }, done, selector); }); Nightmare.action('waitForEmptyInnerText', function(selector, done) { this.wait((selector) => { return document.querySelector(selector).innerText == ''; }, selector) .then(done); }); Nightmare.action('waitForURL', function(hashURL, done) { this.wait((hash) => { return document.location.hash.includes(hash); }, hashURL) .then(done); }); Nightmare.action('waitForShapes', function(selector, done) { this.wait(selector) .evaluate_now((selector) => { const shapes = document.querySelectorAll(selector); const shapesList = []; for (const shape of shapes) shapesList.push(shape.innerText); return shapesList; }, done, selector); }); Nightmare.action('waitForSnackbar', function(done) { this.wait(500).waitForShapes('vn-snackbar .shape .text') .then((shapes) => { done(null, shapes); }); }); Nightmare.action('waitForLastShape', function(selector, done) { this.wait(selector) .evaluate_now((selector) => { const shape = document.querySelector(selector); return shape.innerText; }, done, selector); }); Nightmare.action('waitForLastSnackbar', function(done) { this.wait(500).waitForLastShape('vn-snackbar .shape .text') .then((shapes) => { done(null, shapes); }); });