// Type definitions for leadfoot // Project: https://github.com/theintern/leadfoot // Definitions by: theintern // Definitions: https://github.com/borisyankov/DefinitelyTyped /// /// declare module leadfoot { /** * An error from the remote WebDriver server. */ interface WebDriverError extends Error { /** * The human-readable error type returned by the WebDriver server. See {@link module:leadfoot/lib/statusCodes} for a * list of error types. */ name: string; /** * A human-readable message describing the error. */ message: string; /** * The raw error status code returned by the WebDriver server. */ status: number; /** * The raw detail of the error returned by the WebDriver server. */ detail: any; /** * The parameters for the request. */ request: { url: string; method: string; requestData: {}; }; /** * The response object for the request. */ // response: request.IResponse; response: any; /** * The stack trace for the request. */ stack: string; } /** * An object that describes an HTTP cookie. */ interface WebDriverCookie { /** * The name of the cookie. */ name: string; /** * The value of the cookie. */ value: string; /** * The registered path for the cookie. */ path: string; /** * The registered domain for the cookie. */ domain: string; /** * True if the cookie should only be transmitted over HTTPS. */ secure: boolean; /** * True if the cookie should be inaccessible to client-side scripting. */ httpOnly: boolean; /** * The expiration date of the cookie. */ expiry: Date; } /** * An object that describes a geographical location. */ interface Geolocation { /** * Latitude in WGS84 decimal coordinate system. */ latitude: number; /** * Longitude in WGS84 decimal coordinate system. */ longitude: number; /** * Altitude in meters above the WGS84 ellipsoid. */ altitude: number; } /** * A remote log entry. */ interface LogEntry { /** * The timestamp of the entry in seconds since unix epoch. */ timestamp: number; /** * The severity level of the entry. This level is not currently normalised. */ level: string; /** * The log entry message. */ message: string; } /** * A list of possible capabilities for a remote WebDriver environment. */ interface Capabilities { /** * Environments with this capability expose the state of the browser’s offline application cache via the WebDriver API. */ applicationCacheEnabled?: boolean; /** * Environments with this capability are incapable of clearing or deleting cookies. This issue cannot be worked around. */ brokenCookies?: boolean; /** * Environments with this capability do not correctly retrieve the size of a CSS transformed element. This issue is * automatically corrected. */ brokenCssTransformedSize?: boolean; /** * Environments with this capability do not correctly delete cookies. This issue is automatically corrected for cookies * that are accessible via JavaScript. */ brokenDeleteCookie?: boolean; /** * Environments with this capability do not follow the correct event order when double-clicking. This issue is * automatically corrected. */ brokenDoubleClick?: boolean; /** * Environments with this capability return invalid element handles from execute functions. This issue cannot be worked * around. */ brokenExecuteElementReturn?: boolean; /** * Environments with this capability claim fully transparent elements are non-hidden. This issue is automatically * corrected. */ brokenElementDisplayedOpacity?: boolean; /** * Environments with this capability claim elements positioned offscreen to the top/left of the page are non-hidden. * This issue is automatically corrected. */ brokenElementDisplayedOffscreen?: boolean; /** * Environments with this capability do not correctly retrieve the position of a CSS transformed element. This issue is * automatically corrected. */ brokenElementPosition?: boolean; /** * Environments with this capability do not operate correctly when the `flickFinger` method is called. This issue cannot * be corrected. */ brokenFlickFinger?: boolean; /** * Environments with this capability return HTML tag names with the incorrect case. This issue is automatically * corrected. */ brokenHtmlTagName?: boolean; /** * Environments with this capability fail to perform long tap gestures. This issue is not currently corrected. */ brokenLongTap?: boolean; /** * Environments with this capability have broken mouse event APIs. This issue is automatically corrected as much as * possible through JavaScript-based event emulation. */ brokenMouseEvents?: boolean; /** * Environments with this capability do not support dragging fingers across the page. This issue is not currently * corrected. */ brokenMoveFinger?: boolean; /** * Environments with this capability do not support browser navigation functions (back, forward, refresh). This issue * cannot be corrected. */ brokenNavigation?: boolean; /** * Environments with this capability incorrectly return an empty string instead of `null` for attributes that do not * exist when using the `getSpecAttribute` retrieval method. This issue is automatically corrected. */ brokenNullGetSpecAttribute?: boolean; /** * Environments with this capability fail to complete calls to refresh a page through the standard WebDriver API. This * issue is automatically corrected. */ brokenRefresh?: boolean; /** * Environments with this capability have broken keyboard event APIs. This issue is automatically corrected as much as * possible through JavaScript-based event emulation. */ brokenSendKeys?: boolean; /** * Environments with this capability incorrectly omit the key/value of the button being submitted. This issue is * automatically corrected. */ brokenSubmitElement?: boolean; /** * Environments with this capability do not operate correctly when the `touchScroll` method is called. This issue is * automatically corrected. */ brokenTouchScroll?: boolean; /** * Environments with this capability cannot switch between windows. This issue cannot be corrected. */ brokenWindowSwitch?: boolean; /** * Environments with this capability break when `setWindowPosition` is called. This issue cannot be corrected. */ brokenWindowPosition?: boolean; /** * The name of the current environment. */ browserName: string; /** * Environments with this capability can use CSS selectors to find elements. */ cssSelectorsEnabled?: boolean; /** * Environments with this capability have viewports that can be resized. */ dynamicViewport?: boolean; /** * Environments with this capability break when the `getLogTypes` method is called. The list of log types provided here * are used in lieu of the values provided by the server when calling `getLogTypes`. */ fixedLogTypes?: boolean | string[]; /** * Environments with this capability have JavaScript enabled. Leadfoot does not operate in environments without * JavaScript. */ javascriptEnabled?: boolean; /** * Environments with this capability allow the geographic location of the browser to be set and retrieved using the * WebDriver API. */ locationContextEnabled?: boolean; /** * Environments with this capability support interaction via mouse commands. */ mouseEnabled?: boolean; /** * Environments with this capability use platform native events instead of emulated events. */ nativeEvents?: boolean; /** * The name of the platform on which the current environment is running. */ platform: string; /** * Environments with this capability allow files to be uploaded from a remote client. */ remoteFiles?: boolean; /** * Environments with this capability allow the rotation of the device to be set and retrieved using the WebDriver API. */ rotatable?: boolean; /** * The special key that is used by default on the given platform to perform keyboard shortcuts. */ shortcutKey?: string; /** * Environments with this capability support CSS transforms. */ supportsCssTransforms?: boolean; /** * Environments with this capability support asynchronous JavaScript execution. */ supportsExecuteAsync?: boolean; /** * Environments with this capability support navigation to `data:` URIs. */ supportsNavigationDataUris?: boolean; /** {boolean} takesScreenshot * Environments with this capability allow screenshots of the current screen to be taken. */ takesScreenshot?: boolean; /** * Environments with this capability support interaction via touch commands. */ touchEnabled?: boolean; /** * The version number of the current environment. */ version: string; /** * Environments with this capability allow local storage and session storage to be set and retrieved using the * WebDriver API. */ webStorageEnabled?: boolean; } } declare module 'leadfoot/helpers/pollUntil' { import Promise = require('dojo/promise/Promise'); namespace pollUntil { } /** * A {@link module:leadfoot/Command} helper that polls for a value within the client environment until the value exists * or a timeout is reached. * * @param poller * The poller function to execute on an interval. The function should return `null` or `undefined` if there is not a * result. If the poller function throws, polling will halt. * * @param args * An array of arguments to pass to the poller function when it is invoked. Only values that can be serialised to JSON, * plus {@link module:leadfoot/Element} objects, can be specified as arguments. * * @param timeout * The maximum amount of time to wait for a successful result, in milliseconds. If not specified, the current * `executeAsync` maximum timeout for the session will be used. * * @param pollInterval * The amount of time to wait between calls to the poller function, in milliseconds. If not specified, defaults to 67ms. * * @returns * A {@link module:leadfoot/Command#then} callback function that, when called, returns a promise that resolves to the * value returned by the poller function on success and rejects on failure. * * @example * var Command = require('leadfoot/Command'); * var pollUntil = require('leadfoot/helpers/pollUntil'); * * new Command(session) * .get('http://example.com') * .then(pollUntil('return document.getElementById("a");', 1000)) * .then(function (elementA) { * // element was found * }, function (error) { * // element was not found * }); * * @example * var Command = require('leadfoot/Command'); * var pollUntil = require('leadfoot/helpers/pollUntil'); * * new Command(session) * .get('http://example.com') * .then(pollUntil(function (value) { * var element = document.getElementById('a'); * return element && element.value === value ? true : null; * }, [ 'foo' ], 1000)) * .then(function () { * // value was set to 'foo' * }, function (error) { * // value was never set * }); */ function pollUntil(poller: Function | string, args?: any[], timeout?: number, pollInterval?: number): (value: any) => Promise; function pollUntil(poller: Function | string, timeout?: number, pollInterval?: number): (value: any) => Promise; export = pollUntil; } declare module 'leadfoot/Command' { import Element = require('leadfoot/Element'); import Promise = require('dojo/promise/Promise'); import Thenable = require('dojo/promise/Thenable'); import Session = require('leadfoot/Session'); /** * The Command class is a chainable, subclassable object type that can be used to execute commands serially against a * remote WebDriver environment. The standard Command class includes methods from the {@link module:leadfoot/Session} * and {@link module:leadfoot/Element} classes, so you can perform all standard session and element operations that * come with Leadfoot without being forced to author long promise chains. * * In order to use the Command class, you first need to pass it a {@link module:leadfoot/Session} instance for it to * use: * * ```js * var command = new Command(session); * ``` * * Once you have created the Command, you can then start chaining methods, and they will execute in order one after * another: * * ```js * command.get('http://example.com') * .findByTagName('h1') * .getVisibleText() * .then(function (text) { * assert.strictEqual(text, 'Example Domain'); * }); * ``` * * Because these operations are asynchronous, you need to use a `then` callback in order to retrieve the value from the * last method. Command objects are Thenables, which means that they can be used with any Promises/A+ or ES6-confirmant * Promises implementation, though there are some specific differences in the arguments and context that are provided * to callbacks; see {@link module:leadfoot/Command#then} for more details. * * --- * * Each call on a Command generates a new Command object, which means that certain operations can be parallelised: * * ```js * command = command.get('http://example.com'); * Promise.all([ * command.getPageTitle(), * command.findByTagName('h1').getVisibleText() * ]).then(function (results) { * assert.strictEqual(results[0], results[1]); * }); * ``` * * In this example, the commands on line 3 and 4 both depend upon the `get` call completing successfully but are * otherwise independent of each other and so execute here in parallel. This is different from commands in Intern 1 * which were always chained onto the last called method within a given test. * * --- * * Command objects actually encapsulate two different types of interaction: *session* interactions, which operate * against the entire browser session, and *element* interactions, which operate against specific elements taken from * the currently loaded page. Things like navigating the browser, moving the mouse cursor, and executing scripts are * session interactions; things like getting text displayed on the page, typing into form fields, and getting element * attributes are element interactions. * * Session interactions can be performed at any time, from any Command. On the other hand, to perform element * interactions, you first need to retrieve one or more elements to interact with. This can be done using any of the * `find` or `findAll` methods, by the `getActiveElement` method, or by returning elements from `execute` or * `executeAsync` calls. The retrieved elements are stored internally as the *element context* of all chained * Commands. When an element method is called on a chained Command with a single element context, the result will be * returned as-is: * * ```js * command = command.get('http://example.com') * // finds one element -> single element context * .findByTagName('h1') * .getVisibleText() * .then(function (text) { * // `text` is the text from the element context * assert.strictEqual(text, 'Example Domain'); * }); * ``` * * When an element method is called on a chained Command with a multiple element context, the result will be returned * as an array: * * ```js * command = command.get('http://example.com') * // finds multiple elements -> multiple element context * .findAllByTagName('p') * .getVisibleText() * .then(function (texts) { * // `texts` is an array of text from each of the `p` elements * assert.deepEqual(texts, [ * 'This domain is established to be used for […]', * 'More information...' * ]); * }); * ``` * * The `find` and `findAll` methods are special and change their behaviour based on the current element filtering state * of a given command. If a command has been filtered by element, the `find` and `findAll` commands will only find * elements *within* the currently filtered set of elements. Otherwise, they will find elements throughout the page. * * Some method names, like `click`, are identical for both Session and Element APIs; in this case, the element APIs * are suffixed with the word `Element` in order to identify them uniquely. * * --- * * Commands can be subclassed in order to add additional functionality without making direct modifications to the * default Command prototype that might break other parts of the system: * * ```js * function CustomCommand() { * Command.apply(this, arguments); * } * CustomCommand.prototype = Object.create(Command.prototype); * CustomCommand.prototype.constructor = CustomCommand; * CustomCommand.prototype.login = function (username, password) { * return new this.constructor(this, function () { * return this.parent * .findById('username') * .click() * .type(username) * .end() * .findById('password') * .click() * .type(password) * .end() * .findById('login') * .click() * .end(); * }); * }; * ``` * * Note that returning `this`, or a command chain starting from `this`, from a callback or command initialiser will * deadlock the Command, as it waits for itself to settle before settling. */ class Command implements Thenable { /** * @constructor module:leadfoot/Command * @param {module:leadfoot/Command|module:leadfoot/Session} parent * The parent command that this command is chained to, or a {@link module:leadfoot/Session} object if this is the * first command in a command chain. * * @param {function(setContext:Function, value:any): (any|Promise)} initialiser * A function that will be executed when all parent commands have completed execution. This function can create a * new context for this command by calling the passed `setContext` function any time prior to resolving the Promise * that it returns. If no context is explicitly provided, the context from the parent command will be used. * * @param {(function(setContext:Function, error:Error): (any|Promise))=} errback * A function that will be executed if any parent commands failed to complete successfully. This function can create * a new context for the current command by calling the passed `setContext` function any time prior to resolving the * Promise that it returns. If no context is explicitly provided, the context from the parent command will be used. */ constructor( parent: Command | Session, initialiser?: (setContext: Command.ContextSetter, value: any) => Thenable | T, errback?: (setContext: Command.ContextSetter, error: Error) => Thenable | T ); /** * The parent Command of the Command, if one exists. * * @readonly */ parent: Command; /** * The parent Session of the Command. * * @readonly */ session: Session; /** * The filtered elements that will be used if an element-specific method is invoked. Note that this property is not * valid until the parent Command has been settled. The context array also has two additional properties: * * - isSingle (boolean): If true, the context will always contain a single element. This is used to differentiate * between methods that should still return scalar values (`find`) and methods that should return arrays of * values even if there is only one element in the context (`findAll`). * - depth (number): The depth of the context within the command chain. This is used to prevent traversal into * higher filtering levels by {@link module:leadfoot/Command#end}. * * @readonly */ context: Command.Context; /** * The underlying Promise for the Command. * * @readonly */ promise: Promise; /** * Pauses execution of the next command in the chain for `ms` milliseconds. * * @param {number} ms Time to delay, in milliseconds. * @returns {module:leadfoot/Command.} */ sleep(ms: number): Command; /** * Ends the most recent filtering operation in the current Command chain and returns the set of matched elements * to the previous state. This is equivalent to the `jQuery#end` method. * * @example * command * .findById('parent') // sets filter to #parent * .findByClassName('child') // sets filter to all .child inside #parent * .getVisibleText() * .then(function (visibleTexts) { * // all the visible texts from the children * }) * .end() // resets filter to #parent * .end(); // resets filter to nothing (the whole document) * * @param numCommandsToPop The number of element contexts to pop. Defaults to 1. */ end(numCommandsToPop?: number): Command; /** * Adds a callback to be invoked once the previously chained operation has completed. * * This method is compatible with the `Promise#then` API, with two important differences: * * 1. The context (`this`) of the callback is set to the Command object, rather than being `undefined`. This allows * promise helpers to be created that can retrieve the appropriate session and element contexts for execution. * 2. A second non-standard `setContext` argument is passed to the callback. This `setContext` function can be * called at any time before the callback fulfills its return value and expects either a single * {@link module:leadfoot/Element} or an array of Elements to be provided as its only argument. The provided * element(s) will be used as the context for subsequent element method invocations (`click`, etc.). If * the `setContext` method is not called, the element context from the parent will be passed through unmodified. * * @param {Function=} callback * @param {Function=} errback * @returns {module:leadfoot/Command.} */ then( callback: (value: T, setContext?: Command.ContextSetter) => Thenable | U, errback?: (error: Error, setContext?: Command.ContextSetter) => Thenable | U ): Command; /** * Adds a callback to be invoked when any of the previously chained operations have failed. */ catch(errback: (error: Error, setContext?: Command.ContextSetter) => Thenable | U): Command; /** * Adds a callback to be invoked once the previously chained operations have resolved. */ finally(callback: (valueOrError: T | Error, setContext?: Command.ContextSetter) => Thenable | U): Command; /** * Cancels all outstanding chained operations of the Command. Calling this method will cause this command and all * subsequent chained commands to fail with a CancelError. */ cancel(): Command; /** * Gets the current value of a timeout for the session. * * @param type The type of timeout to retrieve. One of 'script', 'implicit', or 'page load'. * @returns The timeout, in milliseconds. */ getTimeout(type: string): Command; /** * Sets the value of a timeout for the session. * * @param type * The type of timeout to set. One of 'script', 'implicit', or 'page load'. * * @param ms * The length of time to use for the timeout, in milliseconds. A value of 0 will cause operations to time out * immediately. */ setTimeout(type: string, ms: number): Command; /** * Gets the identifier for the window that is currently focused. * * @returns A window handle identifier that can be used with other window handling functions. */ getCurrentWindowHandle(): Command; /** * Gets a list of identifiers for all currently open windows. */ getAllWindowHandles(): Command; /** * Gets the URL that is loaded in the focused window/frame. */ getCurrentUrl(): Command; /** * Navigates the focused window/frame to a new URL. */ get(url: string): Command; /** * Navigates the focused window/frame forward one page using the browser’s navigation history. */ goForward(): Command; /** * Navigates the focused window/frame back one page using the browser’s navigation history. */ goBack(): Command; /** * Reloads the current browser window/frame. */ refresh(): Command; /** * Executes JavaScript code within the focused window/frame. The code should return a value synchronously. * * @see {@link module:leadfoot/Session#executeAsync} to execute code that returns values asynchronously. * * @param script * The code to execute. If a string value is passed, it will be converted to a function on the remote end. * * @param args * An array of arguments that will be passed to the executed code. Only values that can be serialised to JSON, plus * {@link module:leadfoot/Element} objects, can be specified as arguments. * * @returns * The value returned by the remote code. Only values that can be serialised to JSON, plus DOM elements, can be * returned. */ execute(script: Function | string, args: any[]): Command; /** * Executes JavaScript code within the focused window/frame. The code must invoke the provided callback in * order to signal that it has completed execution. * * @see {@link module:leadfoot/Session#execute} to execute code that returns values synchronously. * @see {@link module:leadfoot/Session#setExecuteAsyncTimeout} to set the time until an asynchronous script is * considered timed out. * * @param script * The code to execute. If a string value is passed, it will be converted to a function on the remote end. * * @param args * An array of arguments that will be passed to the executed code. Only values that can be serialised to JSON, plus * {@link module:leadfoot/Element} objects, can be specified as arguments. In addition to these arguments, a * callback function will always be passed as the final argument to the script. This callback function must be * invoked in order to signal that execution has completed. The return value of the script, if any, should be passed * to this callback function. * * @returns * The value returned by the remote code. Only values that can be serialised to JSON, plus DOM elements, can be * returned. */ executeAsync(script: Function | string, args: any[]): Command; /** * Gets a screenshot of the focused window and returns it in PNG format. * * @returns A buffer containing a PNG image. */ takeScreenshot(): Command; /** * Gets a list of input method editor engines available to the remote environment. * As of April 2014, no known remote environments support IME functions. */ getAvailableImeEngines(): Command; /** * Gets the currently active input method editor for the remote environment. * As of April 2014, no known remote environments support IME functions. */ getActiveImeEngine(): Command; /** * Returns whether or not an input method editor is currently active in the remote environment. * As of April 2014, no known remote environments support IME functions. */ isImeActivated(): Command; /** * Deactivates any active input method editor in the remote environment. * As of April 2014, no known remote environments support IME functions. */ deactivateIme(): Command; /** * Activates an input method editor in the remote environment. * As of April 2014, no known remote environments support IME functions. * * @param engine The type of IME to activate. */ activateIme(engine: string): Command; /** * Switches the currently focused frame to a new frame. * * @param id * The frame to switch to. In most environments, a number or string value corresponds to a key in the * `window.frames` object of the currently active frame. If `null`, the topmost (default) frame will be used. * If an Element is provided, it must correspond to a `` or `