UNPKG

nightwatch

Version:

Easy to use Node.js based End-to-End testing solution for browser based apps and websites, using the W3C WebDriver API.

262 lines (196 loc) 5.5 kB
const path = require('path'); const fs = require('fs'); const EventEmitter = require('events'); const Utils = require('../../utils'); const Element = require('../../element'); const VALID_FILENAME_EXT = '.js'; class BaseLoader extends EventEmitter { constructor(nightwatchInstance) { super(); this.type = 'command'; this.__namespace = null; this.__module = null; this.__commandName = null; this.__commandFn = null; this.__instance = null; this.__isUserDefined = false; this.ignoreUnderscoreLeadingNames = true; this.nightwatchInstance = nightwatchInstance; } static isTypeImplemented(instance, method, type) { const methodTypes = method.split('|'); if (type === '*') { return instance[method] !== undefined; } return methodTypes.some(method => (typeof instance[method] == type)); } static getOriginalStackTrace(commandFn) { let originalStackTrace; if (commandFn.stackTrace) { originalStackTrace = commandFn.stackTrace; } else { let err = new Error; Error.captureStackTrace(err, commandFn); originalStackTrace = err.stack; } return originalStackTrace; } static unflattenNamespace(target, namespace, value) { const key = namespace.shift(); if (key) { target[key] = target[key] || {}; value = target[key]; return BaseLoader.unflattenNamespace(target[key], namespace, value); } return value; } get loadSubDirectories() { return false; } get reporter() { return this.nightwatchInstance.reporter; } get api() { return this.nightwatchInstance.api; } get elementLocator() { return this.nightwatchInstance.elementLocator; } get transport() { return this.nightwatchInstance.transport; } get sessionId() { return this.nightwatchInstance.session.sessionId; } get module() { return this.__module; } set module(val) { this.__module = val; } get commandName() { return this.__commandName; } get namespace() { return this.__namespace; } get commandFn() { return this.__commandFn; } get commandQueue() { return this.nightwatchInstance.session.commandQueue; } set commandFn(val) { this.__commandFn = val; } set commandName(val) { this.__commandName = val; } set stackTrace(val) { this.__stackTrace = val; } get stackTrace() { return this.__stackTrace; } get instance() { return this.__instance; } get isUserDefined() { return this.__isUserDefined; } set isUserDefined(val) { this.__isUserDefined = val; } set ignoreUnderscoreLeadingNames(val) { this.__ignoreUnderscoreNames = val; } get ignoreUnderscoreLeadingNames() { return this.__ignoreUnderscoreNames && !this.isUserDefined; } setNamespace(val) { this.__namespace = val; return this; } loadModule(dirPath, fileName) { const fullPath = path.join(dirPath, fileName); if (!this.loadSubDirectories && fs.lstatSync(fullPath).isDirectory()) { return this; } this.requireModule(fullPath, fileName); return this; } requireModule(fullPath, fileName) { if (!Utils.isFileNameValid(fileName) || fileName.startsWith('_') && this.ignoreUnderscoreLeadingNames) { return this; } this.commandName = path.basename(fileName, VALID_FILENAME_EXT); this.fileName = fullPath; try { this.module = require(fullPath); } catch (err) { throw new Error(`There was an error while trying to load the file ${fileName}: ${err.message}`); } } validateMethod(parent) { let namespace = this.getTargetNamespace(parent); if (this.nightwatchInstance.isApiMethodDefined(this.commandName, namespace)) { throw new Error(`The ${this.type} ${this.namespace || ''}.${this.commandName}() is already defined.`); } return this; } resolveElementSelector(args) { if ((args[0] instanceof Element) && this.isUserDefined) { const element = args[0]; if (element.usingRecursion) { return this.elementLocator.resolveElementRecursively({element}); } return Promise.resolve(element); } return Promise.resolve(); } getTargetNamespace(parent) { let namespace = this.namespace; if (!parent) { return namespace; } if (!namespace) { return parent; } parent[namespace] = parent[namespace] || {}; return parent[namespace]; } getQueuedCommandFn() { const commandFn = this.commandFn.bind(this); const {commandQueue, commandName, namespace} = this; return function queuedCommandFn(...args) { const stackTrace = BaseLoader.getOriginalStackTrace(queuedCommandFn); commandQueue.add({ commandName, commandFn, context: this, args, stackTrace, namespace }); return this.api; }.bind(this); } define(parent = null) { if (!this.commandFn) { return this; } this.validateMethod(parent); const {commandName, nightwatchInstance} = this; const args = [this.getQueuedCommandFn()]; const namespace = this.getTargetNamespace(parent); if (namespace) { args.unshift(namespace); } nightwatchInstance.setApiMethod(commandName, ...args); if (this.module && this.module.AliasName) { nightwatchInstance.setApiMethod(this.module.AliasName, ...args); } return this; } } module.exports = BaseLoader;