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.

239 lines (186 loc) 5.7 kB
const path = require('path'); const minimatch = require('minimatch'); const Utils = require('../utils'); const FilenameMatcher = require('./matchers/filename.js'); const TagsMatcher = require('./matchers/tags.js'); class Results { constructor() { this.dataArray = []; } getData() { return this.dataArray; } register(sourcePath) { if (!Array.isArray(sourcePath)) { sourcePath = [sourcePath]; } sourcePath.filter(item => { return Walker.FILE_EXT_PATTERN.test(item); }).forEach(item => { if (this.dataArray.indexOf(item) === -1) { this.dataArray.push(item); } }); } } class Walker { static get FILE_EXT_PATTERN () { return /\.js$/; } constructor(testSource = [], settings, argv = {}) { if (Utils.isString(testSource)) { testSource = [testSource]; } this.testSource = testSource; this.settings = settings; this.argv = argv; this.registerMatchers(); this.results = new Results(); this.validateSource(); } get promise() { return this.__promise; } validateSource() { // TODO: refactor this into TestSource if (this.testSource.length === 0) { let err = new Error('No test source specified, please check configuration'); if (Array.isArray(this.settings.src_folders) && this.settings.src_folders.length > 0) { let srcFolders = this.settings.src_folders.map(item => `"${item}"`).join(', '); err.message += `; src_folders: ${srcFolders}`; } if (this.argv.group) { let groups = this.argv.group.map(item => `"${item}"`).join(', '); err.message += `; group(s): ${groups}`; } err.message += '.'; throw err; } } registerMatchers() { this.tags = new TagsMatcher(this.settings); if (this.settings.exclude) { FilenameMatcher.addMatcher(FilenameMatcher.TYPE_EXCLUDE, this.settings); } if (this.settings.filter) { FilenameMatcher.addMatcher(FilenameMatcher.TYPE_FILTER, this.settings); } } /** * Apply filters on resolved file names * * @param {Array} list */ applyFilters(list) { return list.sort().filter(filePath => { let matched = true; if (this.settings.filter && !FilenameMatcher.register.filter.match(filePath)) { matched = false; } if (this.settings.exclude && FilenameMatcher.register.exclude.match(filePath)) { matched = false; } let filename = filePath.split(path.sep).slice(-1)[0]; if (this.settings.filename_filter) { matched = minimatch(filename, this.settings.filename_filter); } if (this.tags.anyTagsDefined()) { matched = this.tags.match(filePath); } return matched; }); } promiseFn(resolve, reject) { let sourcePath = this.modulePathsCopy.shift(); let fullPath = path.resolve(sourcePath); Utils.checkPath(fullPath) .catch(err => { if (err.code === 'ENOENT') { fullPath = path.join(Utils.getConfigFolder(this.argv), sourcePath); return Utils.checkPath(fullPath, err); } throw err; }) .then(stat => { if (stat.isFile()) { return fullPath; } if (!stat.isDirectory()) { return null; } return this.readFolderDeep(fullPath); }) .then(fullPath => { if (Array.isArray(fullPath)) { fullPath = this.applyFilters(fullPath); } if (fullPath) { this.results.register(fullPath); } if (this.modulePathsCopy.length === 0) { resolve(this.results.getData()); } else { this.promiseFn(resolve, reject); } }) .catch(function(err) { reject(err); }); } createPromise() { this.__promise = new Promise(this.promiseFn.bind(this)); return this; } readTestSource() { this.modulePathsCopy = this.testSource.slice(0); this.createPromise(); return this.promise; } readFolderDeep(folderPath) { return Utils.readDir(folderPath) .then(list => { if (list.length === 0) { return null; } const statPromises = list.map(resource => { resource = path.join(folderPath, resource); return Utils.checkPath(resource); }); return Promise.all(statPromises) .then(statResults => { return statResults.reduce((prev, value, index) => { prev.push([list[index], value]); return prev; }, []); }); }) .then(promiseResults => { if (!promiseResults) { return null; } return Promise.all(promiseResults.map(item => { const resource = item[0]; const stat = item[1]; if (stat.isDirectory()) { const dirName = path.basename(resource); const isExcluded = FilenameMatcher.isFolderExcluded(resource, this.settings); // prevent loading of files from an excluded folder const isSkipped = this.settings.skipgroup && this.settings.skipgroup.indexOf(dirName) > -1; if (isExcluded || isSkipped) { return null; } return this.readFolderDeep(path.join(folderPath, resource)); } if (stat.isFile() && Utils.isFileNameValid(resource)) { return path.join(folderPath, resource); } return null; })); }).then(results => { if (!results) { return null; } return Utils.flattenArrayDeep(results, 3) }); } } module.exports = Walker;