UNPKG

nightwatch

Version:

Easy to use Node.js based end-to-end testing solution for web applications using the W3C WebDriver API.

141 lines (113 loc) 4.44 kB
const chai = require('chai-nightwatch'); const path = require('path'); const fs = require('fs'); const Utils = require('../../utils'); const BaseCommandLoader = require('./_command-loader.js'); const ExpectAssertionLoader = require('./expect-assertion.js'); class ExpectLoader extends BaseCommandLoader { static get interfaceMethods() { return { command: 'function' }; } static createInstance(nightwatchInstance, CommandModule, opts) { const commandInstance = new CommandModule({ nightwatchInstance, commandName: opts.commandName, commandArgs: opts.args }); Object.keys(ExpectLoader.interfaceMethods).forEach(method => { const type = ExpectLoader.interfaceMethods[method]; if (!BaseCommandLoader.isTypeImplemented(commandInstance, method, type)) { throw new Error(`Command class must implement method .${method}()`); } }); return commandInstance; } createWrapper(abortOnFailure) { if (this.module) { this.abortOnFailure = abortOnFailure; const commandName = this.commandName; this.commandFn = function commandFn({args, stackTrace}) { this.stackTrace = stackTrace; const flagsOk = this.checkFlags(); if (!flagsOk) { this.emit('error', new Error(`Incomplete expect assertion for "expect.${commandName}()". Please consult the docs at https://nightwatchjs.org/api/expect/`)); return this; } if ((args[0] instanceof Promise) && args[0]['@nightwatch_element']) { const elementArgs = args[0]['@nightwatch_args']; let selector = ''; if (elementArgs[0] && elementArgs[0].value) { selector = elementArgs[0].value; } args[0].then(result => { args[0] = result; if (!result) { const err = new Error(`Unable to find element <${selector}>.`); err.isExpect = true; this.emit('error', err); return this; } this.run(...args); }); } else { this.run(...args); } this.promise.catch(err => { if (!(this.instance instanceof chai.Assertion)) { this.emit('error', new Error(this.promiseRejectedMsg || `An error occurred while running .expect.${commandName}`)); } }); return this; }; } return this; } define(parent = null) { const {commandName, nightwatchInstance, commandFn, commandQueue} = this; const namespace = (parent || nightwatchInstance.api).expect; nightwatchInstance.setApiMethod(commandName, namespace, function queuedCommandFn(...args) { const stackTrace = Utils.getOriginalStackTrace(queuedCommandFn); const expectCommand = ExpectLoader.createInstance(nightwatchInstance, this.module, { args, commandName }); const isAsyncCommand = this.isES6Async; const isES6Async = Utils.isUndefined(this.isES6Async) ? (nightwatchInstance.isES6AsyncTestcase || nightwatchInstance.settings.always_async_commands) : isAsyncCommand; const {deferred} = expectCommand; this.loadAssertions(expectCommand); const node = commandQueue.add({ commandName, namespace: 'expect', commandFn, deferred, context: expectCommand, isAsyncCommand, isES6Async, args, stackTrace }); return expectCommand.instance; }.bind(this)); } loadAssertions(expectCommand) { const {nightwatchInstance, commandName} = this; // expect commands like .element() and .elements() have individual assertions (e.g. visible, present... / count); // however expect commands like .url(), .title(), and .cookie only have an implicit assertion which is based on their value if (expectCommand.hasAssertions) { const assertionsPath = path.join(__dirname, '../expect/assertions', expectCommand.assertionsPath || commandName); let modules = fs.readdirSync(assertionsPath); modules = modules.filter(moduleName => { return !moduleName.startsWith('_'); }); modules.forEach(assertionFileName => { const loader = new ExpectAssertionLoader(nightwatchInstance); loader .loadModule(assertionsPath, assertionFileName) .loadAssertion(commandName); }); } } } module.exports = ExpectLoader;