UNPKG

cabbie-sync

Version:
315 lines (281 loc) 9.8 kB
/** * @flow * This file is generated automatically, run npm run build to re-generate. **/ import type { SelectorType } from './enums/selector-types'; import type Driver from './driver'; import type { Options } from './flow-types/options'; import depd from 'depd'; import { resolve } from 'url'; import Alert from './alert'; import addDebugging from './add-debugging'; import Element from './element'; import Frame from './frame'; import GlobalMouse from './global-mouse'; import GlobalTouch from './global-touch'; import Navigator from './navigator'; import SelectorTypes from './enums/selector-types'; import BaseWindow from './base-window'; import WindowHandle from './window-handle'; import waitFor from './utils/wait-for'; const deprecate = depd('cabbie'); /* * This is an object representing the currently active window. You can access the navigation for that window, * touch and mouse objects for interacting via screen coordinates, and (most imporatantly) getElement and getElements. */ class ActiveWindow extends BaseWindow { /* * The global-touch object. */ touch: GlobalTouch; /* * Get the global-mouse object. */ mouse: GlobalMouse; /* * Get the Navigator object. * * @private */ navigator: Navigator; /* * Get the Frame object. */ frame: Frame; /* * Get the Alert object. */ alert: Alert; _options: Options; constructor(driver: Driver, options: Options) { super(driver, 'current'); this.touch = new GlobalTouch(this.driver); this.mouse = new GlobalMouse(this.driver); this.navigator = new Navigator(this.driver, options); this.frame = new Frame(this.driver); this.alert = new Alert(this.driver); this._options = options; deprecate.property(this, 'navigator', 'All properties of navigator are now directly available on the ActiveWindow object'); } /* * Get a handle for the current window */ getWindowHandle(): WindowHandle { const windowHandle = this.driver.requestJSON('GET', '/window_handle'); return new WindowHandle(this.driver, windowHandle); } /* * Execute a script on the browser and return the result. * * Source should be either a function body as a string or a function. * Keep in mind that if it is a function it will not have access to * any variables from the node.js process. */ execute(script: string | Function, args: Array<any> = []): any { return this.driver.requestJSON('POST', '/execute', { script: codeToString(script), args }); } /* * Execute a script asynchronously on the browser. * * Source should be either a function body as a string or a function. * Keep in mind that if it is a function it will not have access to * any variables from the node.js process. */ asyncExecute(script: string | Function, args: Array<any> = []): void { this.driver.requestJSON('POST', '/execute_async', { script: codeToString(script), args }); } /* * Type a string of characters into the browser * * Note: Modifier keys is kept between calls, so mouse interactions can be performed * while modifier keys are depressed. */ sendKeys(str: string | Array<string>): void { this.driver.requestJSON('POST', '/keys', { value: Array.isArray(str) ? str : [str] }); } /* * Take a screenshot of the current page * * This returns the result as a buffer containing the binary image data */ takeScreenshot(): Buffer { const base64data = this.driver.requestJSON('GET', '/screenshot'); return Buffer.from ? Buffer.from(base64data, 'base64') : new Buffer(base64data, 'base64'); } /* * Get the element on the page that currently has focus */ getActiveElement(): Element { const elementHandle = this.driver.requestJSON('POST', '/element/active'); return new Element(this.driver, this.driver, '<active>', elementHandle); } /* * Get an element via a selector. * Will throw an error if the element does not exist. */ getElement(selector: string, selectorType: SelectorType = SelectorTypes.CSS): Element { const elementHandle = waitFor(() => this.driver.requestJSON('POST', '/element', { using: selectorType, value: selector })); return new Element(this.driver, this.driver, selector, elementHandle); } /* * Get an element via a selector. * Will return null if the element does not exist */ tryGetElement(selector: string, selectorType: SelectorType = SelectorTypes.CSS): Element | null { try { const elementHandle = this.driver.requestJSON('POST', '/element', { using: selectorType, value: selector }); return new Element(this.driver, this.driver, selector, elementHandle); } catch (ex) { if (ex.code === 'NoSuchElement' || ex.code === 'ElementNotVisible' || ex.code === 'ElementIsNotSelectable') { return null; } throw ex; } } /* * Get elements via a selector. */ getElements(selector: string, selectorType: SelectorType = SelectorTypes.CSS): Array<Element> { const elementHandles = this.driver.requestJSON('POST', '/elements', { using: selectorType, value: selector }); return elementHandles.map(elementHandle => { return new Element(this.driver, this.driver, selector, elementHandle); }); } /* * Get elements by its text content, optionally narrowed down using a selector. * * N.B. this is **much** slower than getting elements by ID or css selector. */ getElementsByTextContent(textContent: string, selector: string = '*', selectorType: SelectorType = SelectorTypes.CSS): Array<Element> { if (selector === 'a' && (selectorType === SelectorTypes.CSS || selectorType === SelectorTypes.TAG)) { selector = textContent; selectorType = SelectorTypes.PARTIAL_LINK_TEXT; } textContent = textContent.trim(); const elements = this.getElements(selector, selectorType); const elementsToReturn = []; for (let i = 0; i < elements.length; i++) { if (textContent === elements[i].getText().trim()) { elementsToReturn.push(elements[i]); } } return elementsToReturn; } /* * Get elements by its text content, optionally narrowed down using a selector. * * N.B. this is **much** slower than getting elements by ID or css selector. */ getElementByTextContent(textContent: string, selector: string = '*', selectorType: SelectorType = SelectorTypes.CSS): Element { const element = waitFor(() => this.tryGetElementByTextContent(textContent, selector, selectorType)); if (element) { return element; } const err = new Error('Could not find an element with the text content: ' + textContent); err.name = 'NoSuchElement'; (err: any).code = 'NoSuchElement'; throw err; } /* * Get elements by its text content, optionally narrowed down using a selector. * * N.B. this is **much** slower than getting elements by ID or css selector. */ tryGetElementByTextContent(textContent: string, selector: string = '*', selectorType: SelectorType = SelectorTypes.CSS): Element | null { if (selector === 'a' && (selectorType === SelectorTypes.CSS || selectorType === SelectorTypes.TAG)) { selector = textContent; selectorType = SelectorTypes.PARTIAL_LINK_TEXT; } textContent = textContent.trim().toLowerCase(); const elements = this.getElements(selector, selectorType); for (let i = 0; i < elements.length; i++) { if (textContent === elements[i].getText().trim().toLowerCase()) { return elements[i]; } } return null; } /* * Does a specific element exist? */ hasElement(selector: string, selectorType: SelectorType = SelectorTypes.CSS): boolean { const elements = this.getElements(selector, selectorType); return elements.length > 0; } /* * Close the current window */ close(): void { this.driver.requestJSON('DELETE', '/window'); } /* * Get the current page title */ getTitle(): string { return this.driver.requestJSON('GET', '/title'); } /* * Get the current page source */ getSource(): string { return this.driver.requestJSON('GET', '/source'); } /* * Navigate forwards in the browser history, if possible. */ goForward(): void { this.driver.requestJSON('POST', '/forward'); } /* * Navigate backwards in the browser history, if possible. */ goBackward(): void { this.driver.requestJSON('POST', '/back'); } /* * Refreshes the browser */ refresh(): void { this.driver.requestJSON('POST', '/refresh'); } /* * Get the current url that the browser is displaying */ getUrl(): string { return this.driver.requestJSON('GET', '/url'); } /* * Navigates the browser to the specified path * * - if `path` begins with a "/" it is relative to `options.base` * - if `path` begins with "http" it is absolute * - otherwise it is relative to the current path */ navigateTo(path: string): void { if (path[0] === '/') { const base = this._options.base; if (!base) { throw new Error('You must provide a "base" option to use urls starting with "/"'); } path = base.replace(/\/$/, '') + path; } else if (path.indexOf('http') !== 0) { const base = this.getUrl(); this.navigateTo(resolve(base, path)); return; } this.driver.requestJSON('POST', '/url', { url: path }); } } /* * Convert code to string before execution */ function codeToString(code: string | Function): string { if (typeof code === 'function') { // $FlowFixMe: intentionally concatenating string onto end of code return 'return (' + code + ').apply(null, arguments);'; } else { return code; } } addDebugging(ActiveWindow); export default ActiveWindow;