UNPKG

nightwatch

Version:

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

138 lines (112 loc) 4.2 kB
const BaseCommandLoader = require('./_command-loader.js'); const Utils = require('../../utils'); const AssertionInstance = require('../assertions/_assertionInstance.js'); const Scheduler = require('./assertion-scheduler.js'); class AssertionLoader extends BaseCommandLoader { static get interfaceMethods() { return { expected: '*', 'pass|evaluate': 'function', command: 'function' }; } static validateAssertClass(instance) { Object.keys(AssertionLoader.interfaceMethods).forEach(method => { let type = AssertionLoader.interfaceMethods[method]; if (!BaseCommandLoader.isTypeImplemented(instance, method, type)) { const methodTypes = method.split('|').map(name => `"${name}"`); throw new Error(`Assertion class must implement method/property ${methodTypes.join(' or ')}`); } }); } constructor(nightwatchInstance) { super(nightwatchInstance); this.type = 'assertion'; this.abortOnFailure = this.globals.abortOnAssertionFailure; } get timeout() { return this.globals.retryAssertionTimeout; } get rescheduleInterval() { return this.globals.waitForConditionPollInterval; } get globals() { return this.api.globals; } validateModuleDefinition() { if (!(Utils.isObject(this.module) && this.module.assertion)) { throw new Error('The assertion module needs to contain an .assertion() method'); } } createQueuedCommandFn(parent) { const commandFn = this.commandFn.bind(this); const {commandQueue, commandName, namespace, api, nightwatchInstance} = this; return function queuedCommandFn({negate, args}) { const stackTrace = Utils.getOriginalStackTrace(queuedCommandFn); // we only should return a Promise if not a nightwatch element, otherwise we risk breaking changes const element = args[0]; const shouldReturnPromise = element && (element.sessionId && element.elementId || element.driver_ && element.id_); const deferred = Utils.createPromise(); const isES6Async = shouldReturnPromise || nightwatchInstance.settings.always_async_commands || (Utils.isUndefined(this.isES6Async) ? nightwatchInstance.isES6AsyncTestcase : this.isES6Async); const node = commandQueue.add({ commandName, commandFn, context: this, args, options: { negate }, stackTrace, namespace, deferred, isES6Async }); if (isES6Async) { commandQueue.tree.once('asynctree:finished', (err) => { node.deferred.resolve(node.resolveValue); }); if (parent && parent.__pageObjectItem__) { Object.assign(node.deferred.promise, parent.__pageObjectItem__); } else { Object.assign(node.deferred.promise, api); } return node.deferred.promise; } return api; }.bind(this); } createWrapper(abortOnFailure) { if (this.module) { this.validateModuleDefinition(); this.abortOnFailure = abortOnFailure; this.commandFn = function commandFn({args, stackTrace, options}) { return this.resolveElementSelector(args) .then(elementResult => { if (elementResult) { args[0] = elementResult; } const {nightwatchInstance, reporter, abortOnFailure, module, fileName} = this; const instance = AssertionInstance.create({ nightwatchInstance, assertionModule: module, fileName, args, options }); AssertionLoader.validateAssertClass(instance); this.__instance = instance; return Scheduler.create(instance, { stackTrace, rescheduleInterval: Utils.isNumber(instance.rescheduleInterval) ? instance.rescheduleInterval : this.rescheduleInterval, timeout: Utils.isNumber(instance.retryAssertionTimeout) ? instance.retryAssertionTimeout : this.timeout, abortOnFailure, reporter }); }); }; } return this; } } module.exports = AssertionLoader;