| // Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| // use this file except in compliance with the License. You may obtain a copy of |
| // the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| // License for the specific language governing permissions and limitations under |
| // the License. |
| |
| module.exports = function (grunt) { |
| var _ = grunt.util._, |
| fs = require('fs'), |
| os = require('os'); |
| |
| grunt.registerMultiTask('get_deps', 'Fetch external dependencies', function () { |
| |
| grunt.log.writeln('Fetching external dependencies'); |
| const data = this.data, |
| target = data.target || 'app/addons/', |
| settingsFile = fs.existsSync(data.src) ? data.src : 'settings.json.default.json', |
| settings = grunt.file.readJSON(settingsFile); |
| |
| const fetch = deps => { |
| var fs = require('fs-extra'); |
| deps.forEach(dep => { |
| const path = target + dep.name; |
| const location = dep.url || dep.path; |
| grunt.log.writeln('Fetching: ' + dep.name + ' (' + location + ')'); |
| try { |
| fs.copySync(dep.path, path); |
| } catch (e) { |
| grunt.log.writeln('ERROR: ' + e.message); |
| } |
| }); |
| }; |
| |
| const localDeps = settings.deps.filter(dep => !!dep.path); |
| grunt.log.writeln(localDeps.length + ' local dependencies'); |
| fetch(localDeps); |
| }); |
| |
| grunt.registerMultiTask('gen_load_addons', 'Generate the load_addons.js file', function () { |
| var data = this.data, |
| _ = grunt.util._, |
| settingsFile = fs.existsSync(data.src) ? data.src : 'settings.json.default.json', |
| settings = grunt.file.readJSON(settingsFile), |
| template = 'app/load_addons.js.underscore', |
| dest = 'app/load_addons.js', |
| deps = _.map(settings.deps, function (dep) { |
| return './addons/' + dep.name + '/base'; |
| }); |
| |
| var tmpl = _.template(grunt.file.read(template)); |
| grunt.file.write(dest, tmpl({deps: deps})); |
| }); |
| |
| grunt.registerMultiTask('gen_initialize', 'Generate the app.js file', function () { |
| var _ = grunt.util._, |
| settings = this.data, |
| template = 'app/initialize.js.underscore', |
| dest = 'app/initialize.js', |
| tmpl = _.template(grunt.file.read(template)), |
| app = {}; |
| |
| _.defaults(app, settings.app, { |
| root: '/', |
| host: '../..', |
| version: "0.0" |
| }); |
| |
| grunt.file.write(dest, tmpl(app)); |
| }); |
| |
| // run every time nightwatch is executed from the command line |
| grunt.registerMultiTask('initNightwatch', 'Sets up Nightwatch', function () { |
| // perform a little validation on the settings |
| _validateNightwatchSettings(this.data.settings); |
| |
| // figure out what tests we need to run by examining the settings.json file content. This method returns |
| // the list of addon folders to test, plus a list of files to exclude |
| var result = _getNightwatchTests(this.data.settings); |
| var addonsWithTests = result.addonFolders; |
| var excludeTests = result.excludeTests; |
| var skipTags = result.skipTags; |
| console.info('addons and excluded', addonsWithTests, excludeTests); |
| console.info('skipTags', skipTags); |
| |
| // if the user passed a --file="X" on the command line, filter out |
| var singleTestToRun = grunt.option('file'); |
| if (singleTestToRun) { |
| addonsWithTests = _findSpecificNightwatchTest(addonsWithTests, singleTestToRun); |
| } |
| |
| // now generate the new nightwatch.json file |
| var nightwatchTemplate = _.template(grunt.file.read(this.data.template)); |
| grunt.file.write(this.data.dest, nightwatchTemplate({ |
| src_folders: JSON.stringify(addonsWithTests), |
| exclude_tests: JSON.stringify(excludeTests, null, '\t'), |
| custom_commands_path: JSON.stringify(this.data.settings.nightwatch.custom_commands_path), |
| globals_path: this.data.settings.nightwatch.globals_path, |
| fauxton_username: this.data.settings.nightwatch.fauxton_username, |
| password: this.data.settings.nightwatch.password, |
| launch_url: this.data.settings.nightwatch.launch_url, |
| fauxton_host: _getHost(this.data.settings.nightwatch.fauxton_ip), |
| fauxton_port: this.data.settings.nightwatch.fauxton_port, |
| db_protocol: this.data.settings.nightwatch.db_protocol, |
| db_host: this.data.settings.nightwatch.db_host, |
| db_port: this.data.settings.nightwatch.db_port, |
| selenium_port: this.data.settings.nightwatch.selenium_port, |
| skiptags: skipTags |
| })); |
| }); |
| |
| // HELPERS |
| |
| //if FAUXTON_HOST not set use ip address |
| function _getHost (fauxton_ip) { |
| if (fauxton_ip) { |
| return fauxton_ip; |
| } |
| //making some assumptions here |
| const interfaces = os.networkInterfaces(); |
| const eth0 = interfaces[Object.keys(interfaces)[2]]; |
| return eth0.find(function (item) { |
| return item.family === 'IPv4'; |
| }).address; |
| } |
| |
| function _validateNightwatchSettings (data) { |
| var error = ''; |
| |
| // if the settings file didn't contain any addons, it points to bigger problems! |
| if (!data.deps.length) { |
| error = 'No addons listed in settings.json - no tests to run!'; |
| |
| // check the requires nightwatch settings. These should always exist in the settings.json file |
| } else if (!_.has(data, 'nightwatch') || |
| !_.has(data.nightwatch, 'fauxton_username') || |
| !_.has(data.nightwatch, 'password')) { |
| error = 'Your settings.json file doesn\'t contain valid nightwatch settings. Please check the user doc.'; |
| } |
| |
| if (error) { |
| grunt.fail.fatal(error); |
| } |
| } |
| |
| function _findSpecificNightwatchTest (addonsWithTests, file) { |
| var filename = file + '.js'; |
| |
| var paths = addonsWithTests.reduce(function (acc, dir) { |
| if (fs.existsSync(dir + '/' + filename)) { |
| acc.push(dir + '/' + filename); |
| } |
| return acc; |
| }, []); |
| |
| if (paths.length > 1) { |
| grunt.fail.fatal('Found multiple nightwatch tests with that filename.'); |
| } else if (!paths.length) { |
| grunt.fail.fatal('Found no testfile named ' + filename); |
| } |
| |
| return paths[0]; |
| } |
| |
| function _getNightwatchTests (settings) { |
| var testBlacklist = (_.has(settings.nightwatch, 'testBlacklist')) ? settings.nightwatch.testBlacklist : {}; |
| var addonFolders = [], |
| excludeTests = []; |
| |
| _.each(settings.deps, function (addon) { |
| var addonTestsFolder = 'app/addons/' + addon.name + '/tests/nightwatch'; |
| if (_.has(addon, 'path')) { |
| addonTestsFolder = addon.path + '/tests/nightwatch'; |
| } |
| |
| // if this addon doesn't have any tests, just move along. Nothing to see here. |
| if (!fs.existsSync(addonTestsFolder)) { |
| return; |
| } |
| |
| // next up: see if this addon has anything blacklisted |
| if (_.has(testBlacklist, addon.name) && _.isArray(testBlacklist[addon.name]) && testBlacklist[addon.name].length > 0) { |
| |
| // a '*' means the user wants to blacklist all tests in the addon |
| if (_.includes(testBlacklist[addon.name], '*')) { |
| return; |
| } |
| |
| // add the folder to test. Any specific files will be blacklisted separately |
| addonFolders.push(addonTestsFolder); |
| |
| _.each(fs.readdirSync(addonTestsFolder), function (file) { |
| if (_.includes(testBlacklist[addon.name], file)) { |
| // the relative path is added to work around an oddity with nightwatch. It evaluates all exclude paths |
| // relative to the current src_folder being examined, so we need to return to the root first |
| excludeTests.push('../../../../../' + addonTestsFolder + '/' + file); |
| } |
| }); |
| |
| } else { |
| |
| // add the whole folder |
| addonFolders.push(addonTestsFolder); |
| } |
| }); |
| |
| var skipTags = process.env.NIGHTWATCH_SKIPTAGS || 'nonpartitioned'; |
| var skipTagsJSON = JSON.stringify(skipTags.split(',').map(s => s.trim())); |
| |
| return { |
| addonFolders: addonFolders, |
| excludeTests: excludeTests, |
| skipTags: skipTagsJSON |
| }; |
| } |
| |
| }; |