diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 585359e4..00000000 --- a/.babelrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "presets": [ - ["env", { - "targets": { - "node": 7.0 - } - }] - ], - "plugins": [ - "transform-object-rest-spread" - ] -} diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 09f4d4d3..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,44 +0,0 @@ -module.exports = { - "extends": "airbnb/legacy", - "parserOptions": { - "ecmaVersion": 2018, - "sourceType": "module" - }, - "rules": { - "no-plusplus": 0, - "no-trailing-spaces": ["error", { - "skipBlankLines": true - }], - "max-len": [2, 120, 4, {"ignoreUrls": true}], - "class-methods-use-this": ["error", {"exceptMethods": ["isSatisfiedBy", "handleFill", "handleCheck", "match", "buildRegex", "getPriority", "filter"]}], - "space-before-function-paren": "off", - "func-names": "off", - "no-console": "off", - "prefer-promise-reject-errors": "off", - "object-curly-newline": ["error", { - "ImportDeclaration": "never", - }], - "no-unused-expressions": "off", - "consistent-return": "off", - "guard-for-in": "off", - "no-restricted-syntax" : "off", - "radix": "off", - "no-prototype-builtins": "off", - "comma-dangle": "off", - "no-await-in-loop": "off", - "no-buffer-constructor": "off", - "no-throw-literal": "off", - "no-nested-ternary": "off", - "operator-linebreak": "off" - }, - "globals": { - "Promise": true, - "expect": true - }, - "env": { - "browser": true, - "node": true, - "protractor": true, - "mocha": true - } -}; diff --git a/.gitignore b/.gitignore index 4ea0501d..b0a498ca 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +#build files +dist + # dependencies node_modules @@ -26,3 +29,6 @@ functional-tests/package-lock.json website/yarn.lock website/node_modules website/i18n/* + +local.log +browserstack.err \ No newline at end of file diff --git a/.npmignore b/.npmignore new file mode 100644 index 00000000..491994c1 --- /dev/null +++ b/.npmignore @@ -0,0 +1,3 @@ +website +functional-tests +docs \ No newline at end of file diff --git a/.prettierrc b/.prettierrc index b7377236..4473ca4c 100644 --- a/.prettierrc +++ b/.prettierrc @@ -4,5 +4,5 @@ "tabWidth": 2, "singleQuote": true, "trailingComma": "es5", - "bracketSpacing": true, -} \ No newline at end of file + "bracketSpacing": true +} diff --git a/build.sh b/build.sh index eba784c8..08f4ec64 100755 --- a/build.sh +++ b/build.sh @@ -1,2 +1,2 @@ #!/bin/sh -git subtree push --prefix website/build/Kakunin origin gh-pages \ No newline at end of file +git subtree push --prefix website/build/Kakunin origin gh-pages diff --git a/dist/cli.js b/dist/cli.js deleted file mode 100755 index 985ce35d..00000000 --- a/dist/cli.js +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -var _initializer = require('./core/cli/initializer'); - -var _initializer2 = _interopRequireDefault(_initializer); - -var _cli = require('./core/cli/cli.helper'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } - -const commandArgs = require('minimist')(process.argv.slice(2)); -const path = require('path'); -const childProcess = require('child_process'); -const envfile = require('node-env-file'); -const os = require('os'); - -envfile(process.cwd() + '/.env', { raise: false, overwrite: false }); - -if ((0, _cli.isInitCommand)(process.argv)) { - _asyncToGenerator(function* () { - yield _initializer2.default.initConfig(commandArgs); - yield _initializer2.default.generateProjectStructure(); - })(); -} else { - const optionsToFilter = ['config', 'projectPath', 'disableChecks', 'tags']; - - const argv = ['./node_modules/kakunin/dist/protractor.conf.js', `--config=${(0, _cli.getConfigPath)('kakunin.conf.js', commandArgs.config, process.cwd())}`, `--projectPath=${process.cwd()}`, '--disableChecks', ...(0, _cli.createTagsCLIArgument)(commandArgs), ...(0, _cli.filterCLIArguments)(optionsToFilter)(commandArgs)]; - - const protractorExecutable = os.platform() === 'win32' ? 'protractor.cmd' : 'protractor'; - - childProcess.spawn(path.join('node_modules', '.bin', protractorExecutable), argv, { - stdio: 'inherit', - cwd: process.cwd() - }).once('exit', code => { - console.log('Protractor has finished'); - process.exit(code); - }); -} \ No newline at end of file diff --git a/dist/comparators/comparator/date.comparator.js b/dist/comparators/comparator/date.comparator.js deleted file mode 100644 index 5108820e..00000000 --- a/dist/comparators/comparator/date.comparator.js +++ /dev/null @@ -1,59 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.DateComparator = exports.supportedFormats = undefined; - -var _moment = require('moment'); - -var _moment2 = _interopRequireDefault(_moment); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const supportedFormats = exports.supportedFormats = ['DD-MM-YYYY', 'DD-MM-YY', 'DD/MM/YYYY', 'DD/MM/YY']; - -const isValidDate = date => { - for (let index = 0; index < supportedFormats.length; index++) { - if ((0, _moment2.default)(date, supportedFormats[index]).isValid()) { - return true; - } - } - - return false; -}; - -const DateComparator = exports.DateComparator = { - isSatisfiedBy: values => { - for (let i = 0; i < values.length; i++) { - const date = values[i]; - const found = isValidDate(date); - - if (!found) { - return false; - } - } - return true; - }, - - compare: (values, order) => { - for (let i = 1; i < values.length; i++) { - const datePrevious = values[i - 1]; - const date = values[i]; - const foundPrevious = (0, _moment2.default)(datePrevious, supportedFormats.find(format => (0, _moment2.default)(datePrevious, format).isValid())); - const found = (0, _moment2.default)(date, supportedFormats.find(format => (0, _moment2.default)(date, format).isValid())); - - const previousTimestamp = foundPrevious.unix(); - const currentTimestamp = found.unix(); - - if (order === 'ascending') { - if (currentTimestamp < previousTimestamp) { - return Promise.reject(`Date ${foundPrevious[1]} should be before ${found[1]}.`); - } - } else if (currentTimestamp > previousTimestamp) { - return Promise.reject(`Date ${found[1]} should be after ${foundPrevious[1]}.`); - } - } - return Promise.resolve(); - } -}; \ No newline at end of file diff --git a/dist/comparators/comparator/index.js b/dist/comparators/comparator/index.js deleted file mode 100644 index fe2c0553..00000000 --- a/dist/comparators/comparator/index.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _date = require('./date.comparator'); - -Object.keys(_date).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _date[key]; - } - }); -}); - -var _number = require('./number.comparator'); - -Object.keys(_number).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _number[key]; - } - }); -}); \ No newline at end of file diff --git a/dist/comparators/comparator/number.comparator.js b/dist/comparators/comparator/number.comparator.js deleted file mode 100644 index 16f58fca..00000000 --- a/dist/comparators/comparator/number.comparator.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -const NumberComparator = exports.NumberComparator = { - isSatisfiedBy: values => { - for (let i = 0; i < values.length; i++) { - const value = Number(values[i]); - if (Number.isNaN(value)) { - return false; - } - } - return true; - }, - - compare: (values, order) => { - for (let i = 1; i < values.length; i++) { - const previousValue = Number(values[i - 1]); - const currentValue = Number(values[i]); - - if (Number.isNaN(previousValue) || Number.isNaN(currentValue)) { - return Promise.reject(`${values[i - 1]} and ${values[i]} cannot be NaN after conversion to Number`); - } - - if (order === 'ascending') { - if (previousValue > currentValue) { - return Promise.reject(`${previousValue} should be lower than ${currentValue}`); - } - } else if (previousValue < currentValue) { - return Promise.reject(`${previousValue} should be higher than ${currentValue}`); - } - } - return Promise.resolve(); - } -}; \ No newline at end of file diff --git a/dist/comparators/comparators.js b/dist/comparators/comparators.js deleted file mode 100644 index 5f0164e8..00000000 --- a/dist/comparators/comparators.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.create = undefined; - -var _comparator = require('./comparator'); - -var comparators = _interopRequireWildcard(_comparator); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -class Comparators { - constructor() { - this.availableComparators = [comparators.DateComparator, comparators.NumberComparator]; - } - - compare(values, order) { - const comparator = this.findComparator(values); - - if (comparator === undefined) { - throw new Error(`Could not find comparator for ${values}.`); - } - - return comparator.compare(values, order); - } - - findComparator(values) { - return this.availableComparators.find(comparator => comparator.isSatisfiedBy(values)); - } - - addComparator(comparator) { - this.availableComparators.push(comparator); - } -} - -const create = exports.create = () => new Comparators(); \ No newline at end of file diff --git a/dist/comparators/index.js b/dist/comparators/index.js deleted file mode 100644 index 2d4c4677..00000000 --- a/dist/comparators/index.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.comparators = undefined; - -var _comparators = require('./comparators'); - -const comparators = exports.comparators = (0, _comparators.create)(); \ No newline at end of file diff --git a/dist/comparators/interfaces/comparator.interface.js b/dist/comparators/interfaces/comparator.interface.js deleted file mode 100644 index e69de29b..00000000 diff --git a/dist/core/cli/cli.helper.js b/dist/core/cli/cli.helper.js deleted file mode 100644 index 50d06b2c..00000000 --- a/dist/core/cli/cli.helper.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.filterCLIArguments = exports.createTagsCLIArgument = exports.getConfigPath = exports.isInitCommand = undefined; - -var _path = require('path'); - -var path = _interopRequireWildcard(_path); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -const isInitCommand = exports.isInitCommand = args => { - if (Array.isArray(args)) { - return args.length > 2 && args[2] === 'init'; - } - - return false; -}; - -const getConfigPath = exports.getConfigPath = (configFile, argsConfig, basePath) => { - return argsConfig ? path.join(basePath, argsConfig) : path.join(basePath, configFile); -}; - -const createTagsCLIArgument = exports.createTagsCLIArgument = commandArgs => { - const tags = []; - - if (commandArgs.performance) { - if (commandArgs.tags !== undefined && commandArgs.tags.indexOf('@performance') < 0) { - tags.push('--cucumberOpts.tags'); - tags.push(`${commandArgs.tags} and @performance`); - } else if (commandArgs.tags === undefined) { - tags.push('--cucumberOpts.tags'); - tags.push('@performance'); - } else { - tags.push('--cucumberOpts.tags'); - tags.push(commandArgs.tags); - } - } else if (commandArgs.tags !== undefined) { - tags.push('--cucumberOpts.tags'); - tags.push(commandArgs.tags); - } - - return tags; -}; - -const filterCLIArguments = exports.filterCLIArguments = blackList => commandArgs => { - const commandLineArgs = []; - - for (const prop in commandArgs) { - if (prop !== '_' && !blackList.includes(prop)) { - if (commandArgs[prop] === true || commandArgs[prop] === false) { - commandLineArgs.push(`--${prop}`); - } else { - commandLineArgs.push(`--${prop}=${commandArgs[prop]}`); - } - } - } - - return commandLineArgs; -}; \ No newline at end of file diff --git a/dist/core/cli/initializer.js b/dist/core/cli/initializer.js deleted file mode 100644 index 0edd819d..00000000 --- a/dist/core/cli/initializer.js +++ /dev/null @@ -1,265 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -var _inquirer = require('inquirer'); - -var _inquirer2 = _interopRequireDefault(_inquirer); - -var _mkdirp = require('mkdirp'); - -var _mkdirp2 = _interopRequireDefault(_mkdirp); - -var _fs = require('fs'); - -var _fs2 = _interopRequireDefault(_fs); - -var _path = require('path'); - -var _path2 = _interopRequireDefault(_path); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } - -class Initializer { - // eslint-disable-next-line class-methods-use-this - createProjectDirectory(dirPath) { - const projectPath = process.cwd() + dirPath; - - (0, _mkdirp2.default)(projectPath); - - console.log(`Created directory at path ${projectPath}`); - } - - // eslint-disable-next-line class-methods-use-this - createTemplateFile(templatePath, content) { - const filePath = process.cwd() + templatePath; - - _fs2.default.writeFileSync(filePath, content); - - console.log(`Created file at path ${filePath}`); - } - - createTemplateFileWithContentFrom(contentPath, file) { - const content = _fs2.default.readFileSync(_path2.default.join(__dirname, `../../../templates/${file}`)); - - this.createTemplateFile(contentPath, content); - } - - // eslint-disable-next-line class-methods-use-this - promptFolders(message, defaultValue, type = 'input') { - return _asyncToGenerator(function* () { - let fullMessage = message; - - if (defaultValue !== '') { - fullMessage += ` [${defaultValue}]`; - } - - return _inquirer2.default.prompt([{ - type: type, - name: 'input', - message: fullMessage - }]).then(function (answer) { - return answer.input === '' ? defaultValue : answer.input; - }); - })(); - } - - initConfig(commandArgs) { - var _this = this; - - return _asyncToGenerator(function* () { - const conf = { - type: 'otherWeb', - browserWidth: 1600, - browserHeight: 900, - timeout: 60, - intervalEmail: 5, - maxEmailRepeats: 5, - elementsVisibilityTimeout: 5, - waitForPageTimeout: 5, - downloadTimeout: 30, - emails: ['/emails'], - reports: '/reports', - downloads: '/downloads', - data: '/data', - features: ['/features'], - pages: ['/pages'], - matchers: ['/matchers'], - generators: ['/generators'], - form_handlers: ['/form_handlers'], - step_definitions: ['/step_definitions'], - comparators: ['/comparators'], - dictionaries: ['/dictionaries'], - transformers: ['/transformers'], - regexes: ['/regexes'], - hooks: ['/hooks'], - clearEmailInboxBeforeTests: false, - clearCookiesAfterScenario: true, - clearLocalStorageAfterScenario: true, - email: null, - headless: false, - noGpu: false - }; - - if (typeof commandArgs.baseUrl === 'undefined') { - conf.baseUrl = yield _this.promptFolders('What is base url?', 'http://localhost:3000'); - } else { - conf.baseUrl = commandArgs.baseUrl; - } - - if (typeof commandArgs.emailType === 'undefined') { - yield _inquirer2.default.prompt([{ - type: 'rawlist', - name: 'type', - message: 'What kind of email service would you like to use?', - choices: [{ name: 'None', value: 'none' }, { name: 'Custom (you will have to fill configuration on your own)', value: 'custom' }, { name: 'MailTrap', value: 'mailtrap' }] - }]).then(function (answer) { - if (answer.type !== 'none') { - conf.email = { - type: answer.type - }; - } - }); - } else { - conf.email = { - type: commandArgs.emailType - }; - } - - if (conf.email && conf.email.type === 'mailtrap') { - conf.email = _extends({}, conf.email, { - config: { - url: 'https://mailtrap.io', - apiKey: '', - inboxId: '' - } - }); - - if (typeof commandArgs.emailApiKey === 'undefined') { - conf.email.config.apiKey = yield _this.promptFolders('Type in your mailtrap apikey:', conf.email.config.apiKey); - } else { - conf.email.config.apiKey = commandArgs.emailApiKey; - } - - if (typeof commandArgs.emailInboxId === 'undefined') { - conf.email.config.inboxId = yield _this.promptFolders('Type in your mailtrap inboxId:', conf.email.config.inboxId); - } else { - conf.email.config.inboxId = commandArgs.emailInboxId; - } - } - - if (commandArgs.advanced) { - yield _this.initEnv(); - conf.browserWidth = parseInt((yield _this.promptFolders('What is desired browser width?', conf.browserWidth))); - conf.browserHeight = parseInt((yield _this.promptFolders('What is desired browser height?', conf.browserHeight))); - - conf.timeout = parseInt((yield _this.promptFolders('What is desired step timeout in seconds?', conf.timeout))); - conf.intervalEmail = parseInt((yield _this.promptFolders('What is desired step email interval in seconds?', conf.intervalEmail))); - conf.maxEmailRepeats = parseInt((yield _this.promptFolders('How many times emails should be checked - maximum repeats?', conf.maxEmailRepeats))); - conf.elementsVisibilityTimeout = parseInt((yield _this.promptFolders('What is desired elements visibility timeout in seconds?', conf.elementsVisibilityTimeout))); - conf.waitForPageTimeout = parseInt((yield _this.promptFolders('How long should I wait for page to load in seconds?', conf.waitForPageTimeout))); - conf.downloadTimeout = parseInt((yield _this.promptFolders('How long should I wait for files to download in seconds?', conf.downloadTimeout))); - - conf.reports = yield _this.promptFolders('Where are your reports stored?', conf.reports); - conf.downloads = yield _this.promptFolders('Where are your downloads stored?', conf.downloads); - conf.data = yield _this.promptFolders('Where is your data stored?', conf.data); - - conf.features = [yield _this.promptFolders('Where are your features stored?', conf.features[0])]; - conf.pages = [yield _this.promptFolders('Where are your pages stored?', conf.pages[0])]; - conf.matchers = [yield _this.promptFolders('Where are your matchers stored?', conf.matchers[0])]; - conf.generators = [yield _this.promptFolders('Where are your generators stored?', conf.generators[0])]; - conf.form_handlers = [yield _this.promptFolders('Where are your form handlers stored?', conf.form_handlers[0])]; - conf.step_definitions = [yield _this.promptFolders('Where are your step definitions stored?', conf.step_definitions[0])]; - conf.comparators = [yield _this.promptFolders('Where are your comparators stored?', conf.comparators[0])]; - conf.dictionaries = [yield _this.promptFolders('Where are your dictionaries stored?', conf.dictionaries[0])]; - conf.regexes = [yield _this.promptFolders('Where are your regexes stored?', conf.regexes[0])]; - conf.hooks = [yield _this.promptFolders('Where are your hooks stored?', conf.hooks[0])]; - conf.transformers = [yield _this.promptFolders('Where are your transformers stored?', conf.transformers[0])]; - - conf.clearEmailInboxBeforeTests = yield _this.promptFolders('Should email inbox be cleared before tests?', conf.clearEmailInboxBeforeTests, 'confirm'); - conf.clearCookiesAfterScenario = yield _this.promptFolders('Should cookies be cleared after scenario?', conf.clearCookiesAfterScenario, 'confirm'); - conf.clearLocalStorageAfterScenario = yield _this.promptFolders('Should local storage be cleared after scenario?', conf.clearLocalStorageAfterScenario, 'confirm'); - conf.browserMob = { - serverPort: parseInt((yield _this.promptFolders('Define port where browsermob-proxy is running!', 8887))), - port: parseInt((yield _this.promptFolders('Define port where browsermob-proxy should be listening!', 8888))), - host: yield _this.promptFolders('Define host where browsermob-proxy is running!', 'localhost') - }; - } - - conf.accounts = { - someAccount: { - accounts: [{ - email: '', - password: '' - }] - } - }; - - _this.createTemplateFile('/kakunin.conf.js', 'module.exports = ' + JSON.stringify(conf, null, 4)); - })(); - } - - initEnv() { - var _this2 = this; - - return _asyncToGenerator(function* () { - const envs = []; - - envs.push('FIXTURES_RELOAD_HOST=' + (yield _this2.promptFolders('Define FIXTURES_RELOAD_HOST', ''))); - - _this2.createTemplateFile('/.env', envs.join('\n')); - })(); - } - - generateProjectStructure() { - var _this3 = this; - - return _asyncToGenerator(function* () { - /* eslint-disable */ - const config = require(process.cwd() + '/kakunin.conf.js'); - /* eslint-enable */ - - _this3.createProjectDirectory(config.reports); - _this3.createProjectDirectory(_path2.default.join(config.reports, 'report')); - _this3.createProjectDirectory(_path2.default.join(config.reports, 'json-output-folder')); - _this3.createProjectDirectory(_path2.default.join(config.reports, 'report', 'features')); - _this3.createProjectDirectory(_path2.default.join(config.reports, 'performance')); - _this3.createProjectDirectory(config.downloads); - _this3.createProjectDirectory(config.data); - - _this3.createProjectDirectory(config.features[0]); - _this3.createProjectDirectory(config.pages[0]); - _this3.createProjectDirectory(config.matchers[0]); - _this3.createProjectDirectory(config.generators[0]); - _this3.createProjectDirectory(config.form_handlers[0]); - _this3.createProjectDirectory(config.step_definitions[0]); - _this3.createProjectDirectory(config.comparators[0]); - _this3.createProjectDirectory(config.dictionaries[0]); - _this3.createProjectDirectory(config.regexes[0]); - _this3.createProjectDirectory(config.hooks[0]); - _this3.createProjectDirectory(config.transformers[0]); - _this3.createProjectDirectory(config.emails[0]); - - _this3.createTemplateFile(_path2.default.join(config.downloads, '.gitkeep'), ''); - _this3.createTemplateFile(_path2.default.join(config.reports, 'json-output-folder', '.gitkeep'), ''); - _this3.createTemplateFile(_path2.default.join(config.reports, 'report', '.gitkeep'), ''); - _this3.createTemplateFile(_path2.default.join(config.reports, 'report', 'features', '.gitkeep'), ''); - _this3.createTemplateFile(_path2.default.join(config.reports, 'performance', '.gitkeep'), ''); - _this3.createTemplateFileWithContentFrom(config.features[0] + '/example.feature', 'example.feature'); - _this3.createTemplateFileWithContentFrom(config.pages[0] + '/page.js', 'page.js'); - _this3.createTemplateFileWithContentFrom(config.matchers[0] + '/matcher.js', 'matcher.js'); - _this3.createTemplateFileWithContentFrom(config.generators[0] + '/generator.js', 'generator.js'); - _this3.createTemplateFileWithContentFrom(config.step_definitions[0] + '/steps.js', 'steps.js'); - _this3.createTemplateFileWithContentFrom(config.regexes[0] + '/regex.js', 'regex.js'); - _this3.createTemplateFileWithContentFrom(config.hooks[0] + '/hook.js', 'hook.js'); - })(); - } -} - -exports.default = new Initializer(); \ No newline at end of file diff --git a/dist/core/config.helper.js b/dist/core/config.helper.js deleted file mode 100644 index 077ae5e3..00000000 --- a/dist/core/config.helper.js +++ /dev/null @@ -1,28 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -const commandArgs = require('minimist')(process.argv.slice(2)); -let config; - -if (process.env.NODE_ENV === 'test') { - config = { - projectPath: process.cwd(), - email: { - config: {} - } - }; -} else { - const configFile = process.argv.find(name => name.indexOf('--config') >= 0); - const configFilePath = configFile.substr(configFile.indexOf('=') + 1); - - const project = process.argv.find(name => name.indexOf('--projectPath') >= 0); - const projectPath = project.substr(project.indexOf('=') + 1); - - config = require(configFilePath); // eslint-disable-line global-require - config.projectPath = projectPath; - config.performance = commandArgs.performance || false; -} - -exports.default = config; \ No newline at end of file diff --git a/dist/core/fs/delete-files.helper.js b/dist/core/fs/delete-files.helper.js deleted file mode 100644 index d6406a1e..00000000 --- a/dist/core/fs/delete-files.helper.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.deleteReports = undefined; - -var _fs = require('fs'); - -var _fs2 = _interopRequireDefault(_fs); - -var _path = require('path'); - -var _path2 = _interopRequireDefault(_path); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const deleteReports = exports.deleteReports = directory => { - return _fs2.default.readdirSync(directory).filter(file => _fs2.default.statSync(_path2.default.join(directory, file)).isFile() && file !== '.gitkeep').forEach(file => _fs2.default.unlinkSync(_path2.default.join(directory, file))); -}; \ No newline at end of file diff --git a/dist/core/fs/prepare-catalogs.helper.js b/dist/core/fs/prepare-catalogs.helper.js deleted file mode 100644 index 46179e88..00000000 --- a/dist/core/fs/prepare-catalogs.helper.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.prepareCatalogs = undefined; - -var _fs = require('fs'); - -var _fs2 = _interopRequireDefault(_fs); - -var _mkdirp = require('mkdirp'); - -var _mkdirp2 = _interopRequireDefault(_mkdirp); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } - -const prepareCatalogs = exports.prepareCatalogs = (() => { - var _ref = _asyncToGenerator(function* (directory) { - if (_fs2.default.existsSync(directory)) { - return Promise.resolve(); - } - - yield (0, _mkdirp2.default)(directory); - yield console.log(`${directory} has been added!`); - yield _fs2.default.writeFileSync(`${directory}/.gitkeep`, ''); - }); - - return function prepareCatalogs(_x) { - return _ref.apply(this, arguments); - }; -})(); \ No newline at end of file diff --git a/dist/core/modules-loader.helper.js b/dist/core/modules-loader.helper.js deleted file mode 100644 index 4238c451..00000000 --- a/dist/core/modules-loader.helper.js +++ /dev/null @@ -1,76 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.create = undefined; - -var _fs = require('fs'); - -var _fs2 = _interopRequireDefault(_fs); - -var _path = require('path'); - -var _path2 = _interopRequireDefault(_path); - -var _config = require('./config.helper'); - -var _config2 = _interopRequireDefault(_config); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class ModulesLoader { - constructor(configuration) { - this.paths = { - comparators: [], - dictionaries: [], - form_handlers: [], - generators: [], - matchers: [], - regexes: [], - transformers: [], - emails: [] - }; - - Object.keys(this.paths).forEach(group => { - if (typeof _config2.default[group] !== 'undefined') { - configuration[group].forEach(groupPath => { - this.paths[group].push(_path2.default.join(configuration.projectPath + groupPath)); - }); - } - }); - } - - getModules(group) { - return this.getFilePaths(this.paths[group]).map(file => require(file[1]) // eslint-disable-line global-require - ); - } - - getModulesAsObject(projectFolders) { - const modules = {}; - const filePaths = this.getFilePaths(projectFolders); - - filePaths.forEach(file => { - modules[file[0]] = require(file[1]); // eslint-disable-line global-require - }); - - return modules; - } - - // eslint-disable-next-line class-methods-use-this - getFilePaths(folders) { - let files = []; - - folders.forEach(folder => { - if (_fs2.default.existsSync(folder)) { - files = files.concat(_fs2.default.readdirSync(folder).filter(file => file !== '.gitkeep' && file.indexOf('.spec.js') < 0).map(file => [file.substr(0, file.indexOf('.')), `${folder}/${file}`])); - } else { - console.log(`Directory ${folder} does not exist.`); - } - }); - - return files; - } -} - -const create = exports.create = (configuration = _config2.default) => new ModulesLoader(configuration); \ No newline at end of file diff --git a/dist/core/prototypes.js b/dist/core/prototypes.js deleted file mode 100644 index e1089500..00000000 --- a/dist/core/prototypes.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; - -// eslint-disable-next-line no-extend-native -String.prototype.toCamelCase = function () { - return this.charAt(0).toUpperCase() + this.slice(1); -}; - -RegExp.escape = function (text) { - return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); -}; \ No newline at end of file diff --git a/dist/dictionaries/base.js b/dist/dictionaries/base.js deleted file mode 100644 index dcedb6ff..00000000 --- a/dist/dictionaries/base.js +++ /dev/null @@ -1,21 +0,0 @@ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -class Dictionary { - constructor(dictionaryName, valuesObject) { - this.values = valuesObject; - this.name = dictionaryName; - } - - isSatisfiedBy(name) { - return this.name === name; - } - - getMappedValue(key) { - return this.values[key]; - } -} - -exports.default = Dictionary; \ No newline at end of file diff --git a/dist/dictionaries/dictionaries.js b/dist/dictionaries/dictionaries.js deleted file mode 100644 index b116b3b6..00000000 --- a/dist/dictionaries/dictionaries.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -class Dictionaries { - constructor() { - this.availableDictionaries = []; - } - - getMappedValue(dictionaryName, key) { - const dic = this.findDictionary(dictionaryName); - - if (dic === undefined) { - throw new Error(`Could not find dictionary for ${dictionaryName}.`); - } - - return dic.getMappedValue(key); - } - - findDictionary(name) { - return this.availableDictionaries.find(dic => dic.isSatisfiedBy(name)); - } - - findMappedValueByPhrase(phrase) { - const parameters = phrase.split(':'); - if (parameters[0] === 'd') { - const dictionary = this.findDictionary(parameters[1]); - - if (dictionary) { - return this.getMappedValue(parameters[1], parameters[2]); - } - } - - return phrase; - } - - addDictionary(dictionary) { - this.availableDictionaries.push(dictionary); - } -} - -const create = exports.create = () => new Dictionaries(); \ No newline at end of file diff --git a/dist/dictionaries/index.js b/dist/dictionaries/index.js deleted file mode 100644 index ded2acf8..00000000 --- a/dist/dictionaries/index.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Base = exports.dictionaries = undefined; - -var _dictionaries = require('./dictionaries'); - -var _base = require('./base'); - -var _base2 = _interopRequireDefault(_base); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const dictionaries = exports.dictionaries = (0, _dictionaries.create)(); -const Base = exports.Base = _base2.default; \ No newline at end of file diff --git a/dist/emails/adapter/mailtrap.client.js b/dist/emails/adapter/mailtrap.client.js deleted file mode 100644 index 494e0585..00000000 --- a/dist/emails/adapter/mailtrap.client.js +++ /dev/null @@ -1,127 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.create = undefined; - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -var _nodeFetch = require('node-fetch'); - -var _nodeFetch2 = _interopRequireDefault(_nodeFetch); - -var _config = require('../../core/config.helper'); - -var _config2 = _interopRequireDefault(_config); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } - -class MailTrapClient { - constructor(requestClient, config) { - this.requestClient = requestClient; - this.config = config; - } - - isSatisfiedBy(emailConfiguration) { - return emailConfiguration.type === 'mailtrap' && emailConfiguration.config.hasOwnProperty('apiKey') && emailConfiguration.config.hasOwnProperty('inboxId') && emailConfiguration.config.hasOwnProperty('url'); - } - - getMailtrapConfig() { - return { - apiKey: this.config.config.apiKey, - inboxId: this.config.config.inboxId, - endpoint: this.config.config.url - }; - } - - clearInbox() { - const config = this.getMailtrapConfig(); - const url = `${config.endpoint}/api/v1/inboxes/${config.inboxId}/clean?api_token=${config.apiKey}`; - - return this.requestClient(url, { - method: 'PATCH' - }).then(res => { - if (res.status !== 200) { - throw new Error(res); - } - - return res.json(); - }); - } - - getEmails() { - var _this = this; - - return _asyncToGenerator(function* () { - const config = _this.getMailtrapConfig(); - const url = `${config.endpoint}/api/v1/inboxes/${config.inboxId}/messages?api_token=${config.apiKey}`; - - const messages = yield _this.requestClient(url).then(function (res) { - if (res.status !== 200) { - throw new Error(res); - } - - return res.json(); - }); - - const messagesWithBody = []; - - for (const message of messages) { - const rawBody = yield _this.requestClient(`${config.endpoint}${message.raw_path}?api_token=${config.apiKey}`).then(function (res) { - return res.text(); - }); - - messagesWithBody.push(_extends({}, message, { - html_body: rawBody - })); - } - - return messagesWithBody.filter(function (message) { - return !message.is_read; - }); - })(); - } - - getAttachments(email) { - const config = this.getMailtrapConfig(); - const url = `${config.endpoint}/api/v1/inboxes/${config.inboxId}/messages/${email.id}/attachments?api_token=${config.apiKey}`; - - return this.requestClient(url).then(res => { - if (res.status !== 200) { - throw new Error(res); - } - - return res.json(); - }); - } - - markAsRead(email) { - const config = this.getMailtrapConfig(); - const url = `${config.endpoint}/api/v1/inboxes/${config.inboxId}/messages/${email.id}?api_token=${config.apiKey}`; - - return this.requestClient(url, { - method: 'PATCH', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - message: { - is_read: true - } - }) - }).then(res => { - if (res.status !== 200) { - throw new Error(res); - } - - return res.json(); - }); - } -} - -const create = exports.create = (requestClient = _nodeFetch2.default, config = _config2.default.email) => { - return new MailTrapClient(requestClient, config); -}; \ No newline at end of file diff --git a/dist/emails/email.service.js b/dist/emails/email.service.js deleted file mode 100644 index d15c9caa..00000000 --- a/dist/emails/email.service.js +++ /dev/null @@ -1,66 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.create = undefined; - -var _config = require('../core/config.helper'); - -var _config2 = _interopRequireDefault(_config); - -var _mailtrapClient = require('./adapter/mailtrap.client.js'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class EmailService { - constructor(config, defaultAdapters) { - this.config = config; - - this.availableAdapters = defaultAdapters; - } - - clearInbox() { - const adapter = this.getAdapter(); - - return adapter.clearInbox(); - } - - getEmails() { - const adapter = this.getAdapter(); - - return adapter.getEmails(); - } - - getAttachments(email) { - const adapter = this.getAdapter(); - - return adapter.getAttachments(email); - } - - markAsRead(email) { - const adapter = this.getAdapter(); - - return adapter.markAsRead(email); - } - - addAdapter(adapter) { - this.availableAdapters.push(adapter); - } - - getAdapter() { - const emailAdapter = this.availableAdapters.find(adapter => adapter.isSatisfiedBy(this.config.email)); - - if (emailAdapter === undefined) { - throw new Error('Could not find email adapter for given configuration.'); - } - - return emailAdapter; - } -} - -const mailtrapAdapter = (0, _mailtrapClient.create)(); - -const create = exports.create = (defaultAdapters = [mailtrapAdapter], config = _config2.default) => { - return new EmailService(config, defaultAdapters); -}; \ No newline at end of file diff --git a/dist/emails/filter/current-user.filter.js b/dist/emails/filter/current-user.filter.js deleted file mode 100644 index 2b52cd0f..00000000 --- a/dist/emails/filter/current-user.filter.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -// TODO: stop injecting world here and use some kind of a user provider - -class CurrentUserFilter { - isSatisfiedBy(type) { - return type === 'currentUser'; - } - - filter(emails, type, value, world) { - return emails.filter(email => email.to_email === world.currentUser.account.email); - } -} - -const currentUserFilter = exports.currentUserFilter = new CurrentUserFilter(); \ No newline at end of file diff --git a/dist/emails/filter/index.js b/dist/emails/filter/index.js deleted file mode 100644 index 34bdf824..00000000 --- a/dist/emails/filter/index.js +++ /dev/null @@ -1,41 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _currentUser = require('./current-user.filter'); - -Object.keys(_currentUser).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _currentUser[key]; - } - }); -}); - -var _minimalEmailSize = require('./minimal-email-size.filter'); - -Object.keys(_minimalEmailSize).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _minimalEmailSize[key]; - } - }); -}); - -var _textFields = require('./text-fields.filter'); - -Object.keys(_textFields).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _textFields[key]; - } - }); -}); \ No newline at end of file diff --git a/dist/emails/filter/minimal-email-size.filter.js b/dist/emails/filter/minimal-email-size.filter.js deleted file mode 100644 index a4b1b59f..00000000 --- a/dist/emails/filter/minimal-email-size.filter.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -class MinimalEmailSizeFilter { - isSatisfiedBy(type) { - return type === 'minimalEmailSize'; - } - - // eslint-disable-next-line no-unused-vars - filter(emails, type, value, world) { - return emails.filter(email => email.email_size >= parseInt(value)); - } -} - -const minimalEmailSizeFilter = exports.minimalEmailSizeFilter = new MinimalEmailSizeFilter(); \ No newline at end of file diff --git a/dist/emails/filter/text-fields.filter.js b/dist/emails/filter/text-fields.filter.js deleted file mode 100644 index 173eb6c5..00000000 --- a/dist/emails/filter/text-fields.filter.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.textFieldFilter = undefined; - -var _matchers = require('../../matchers'); - -var _variableStore = require('../../web/variable-store.helper'); - -var _variableStore2 = _interopRequireDefault(_variableStore); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class TextFieldFilter { - isSatisfiedBy(type) { - return ['subject', 'from_email', 'from_name', 'to_email', 'to_name', 'html_body', 'text_body'].indexOf(type) !== -1; - } - - // eslint-disable-next-line no-unused-vars - filter(emails, type, value, world) { - return emails.filter(email => { - if (value.startsWith('r:')) { - return _matchers.regexBuilder.buildRegex(value).test(email[type]); - } - - if (value.startsWith('t:')) { - return new RegExp(RegExp.escape(_variableStore2.default.replaceTextVariables(value.substr(2)))).test(email[type]); - } - - throw 'Comparison type not specified. Please use r: for regex and t: for text'; - }); - } -} - -const textFieldFilter = exports.textFieldFilter = new TextFieldFilter(); \ No newline at end of file diff --git a/dist/emails/filters.js b/dist/emails/filters.js deleted file mode 100644 index c790be2a..00000000 --- a/dist/emails/filters.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.filters = undefined; - -var _filter = require('./filter'); - -var defaultFilters = _interopRequireWildcard(_filter); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -class Filters { - constructor() { - this.availableFilters = [defaultFilters.currentUserFilter, defaultFilters.minimalEmailSizeFilter, defaultFilters.textFieldFilter]; - } - - filter(emails, type, value, world) { - const filter = this.findFilter(type); - - if (typeof filter === 'undefined') { - throw new Error(`Could not find filter for ${type}.`); - } - - return filter.filter(emails, type, value, world); - } - - findFilter(type) { - return this.availableFilters.find(filter => filter.isSatisfiedBy(type)); - } -} - -const filters = exports.filters = new Filters(); \ No newline at end of file diff --git a/dist/emails/index.js b/dist/emails/index.js deleted file mode 100644 index 73211a09..00000000 --- a/dist/emails/index.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.emailService = undefined; - -var _email = require('./email.service'); - -const emailService = exports.emailService = (0, _email.create)(); \ No newline at end of file diff --git a/dist/form-handlers/handler/checkbox.handler.js b/dist/form-handlers/handler/checkbox.handler.js deleted file mode 100644 index 6bbbed9f..00000000 --- a/dist/form-handlers/handler/checkbox.handler.js +++ /dev/null @@ -1,60 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -class CheckboxHandler { - isSatisfiedBy(element) { - return element.getTagName().then(tagName => { - if (tagName === 'input') { - return element.getAttribute('type').then(inputType => inputType === 'checkbox'); - } - - if (tagName instanceof Array) { - return element.first().getAttribute('type').then(inputType => inputType === 'checkbox'); - } - - return false; - }); - } - - handleFill(page, elementName, desiredValue) { - return page[elementName].filter(elem => { - return elem.element(by.xpath('..')).getText().then(text => { - return text.trim() === desiredValue; - }); - }).first().click(); - } - - handleCheck(page, elementName, desiredValue) { - const filteredElements = page[elementName].filter(element => element.isSelected()); - - return filteredElements.count().then(count => { - if (desiredValue === '') { - if (count === 0) { - return Promise.resolve(); - } - - return Promise.reject(`Expected count to be 0 got ${count}`); - } - - return page[elementName].filter(element => { - return element.element(by.xpath('..')).getText().then(text => { - return text.trim() === desiredValue; - }); - }).first().isSelected().then(selected => { - if (selected) { - return Promise.resolve(); - } - - return Promise.reject(`Expected element ${elementName} to be selected`); - }); - }); - } - - getPriority() { - return 998; - } -} - -const checkboxHandler = exports.checkboxHandler = new CheckboxHandler(); \ No newline at end of file diff --git a/dist/form-handlers/handler/ckeditor.handler.js b/dist/form-handlers/handler/ckeditor.handler.js deleted file mode 100644 index 45017263..00000000 --- a/dist/form-handlers/handler/ckeditor.handler.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -class CKEditorHandler { - isSatisfiedBy(element, elementName) { - return Promise.resolve(elementName.endsWith('CKEditor')); - } - - handleFill(page, elementName, desiredValue) { - browser.switchTo().frame(page[elementName].getWebElement()); - - browser.driver.findElement(by.tagName('body')).sendKeys(desiredValue); - - browser.switchTo().defaultContent(); - - return browser.waitForAngular(); - } - - // eslint-disable-next-line no-unused-vars - handleCheck(page, elementName, desiredValue) { - return Promise.reject('Checking CKEditor is not supported'); - } - - getPriority() { - return 998; - } -} - -const ckEditorHandler = exports.ckEditorHandler = new CKEditorHandler(); \ No newline at end of file diff --git a/dist/form-handlers/handler/custom-angular-select.handler.js b/dist/form-handlers/handler/custom-angular-select.handler.js deleted file mode 100644 index 56984944..00000000 --- a/dist/form-handlers/handler/custom-angular-select.handler.js +++ /dev/null @@ -1,51 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -class CustomAngularSelectHandler { - constructor() { - this.optionsSelector = by.css('ul.ui-select-choices li a.ui-select-choices-row-inner'); - this.selectedOptionSelector = by.css('div.ui-select-match .ui-select-match-text'); - } - - isSatisfiedBy(element, elementName) { - return Promise.resolve(elementName.endsWith('CustomAngularSelect')); - } - - handleFill(page, elementName, desiredValue) { - return browser.executeScript('arguments[0].scrollIntoView(false);', page[elementName].getWebElement()).then(() => { - return page[elementName].click().then(() => { - const filtered = page[elementName].all(this.optionsSelector).filter(function (elem) { - return elem.getText().then(function (text) { - return text === desiredValue; - }); - }); - - return filtered.count().then(count => { - if (count === 0) { - return page[elementName].all(this.optionsSelector).first().click(); - } - - return filtered.first().click(); - }); - }); - }); - } - - handleCheck(page, elementName, desiredValue) { - return page[elementName].element(this.selectedOptionSelector).getText().then(function (text) { - if (text === desiredValue) { - return Promise.resolve(); - } - - return Promise.reject(`Expected ${desiredValue} got ${text} for select element ${elementName}`); - }); - } - - getPriority() { - return 998; - } -} - -const customAngularSelectHandler = exports.customAngularSelectHandler = new CustomAngularSelectHandler(); \ No newline at end of file diff --git a/dist/form-handlers/handler/default.handler.js b/dist/form-handlers/handler/default.handler.js deleted file mode 100644 index 5594b99d..00000000 --- a/dist/form-handlers/handler/default.handler.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -class DefaultHandler { - isSatisfiedBy() { - return Promise.resolve(true); - } - - handleFill(page, elementName, desiredValue) { - return page[elementName].isDisplayed().then(function () { - return page[elementName].clear().then(function () { - return page[elementName].sendKeys(desiredValue); - }); - }); - } - - handleCheck(page, elementName, desiredValue) { - return page[elementName].isDisplayed().then(function () { - return page[elementName].getAttribute('value').then(function (value) { - if (value === desiredValue) { - return Promise.resolve(); - } - - return Promise.reject(`Expected ${desiredValue} got ${value} for text input element ${elementName}`); - }); - }); - } - - getPriority() { - return 999; - } -} - -const defaultHandler = exports.defaultHandler = new DefaultHandler(); \ No newline at end of file diff --git a/dist/form-handlers/handler/file.handler.js b/dist/form-handlers/handler/file.handler.js deleted file mode 100644 index be316289..00000000 --- a/dist/form-handlers/handler/file.handler.js +++ /dev/null @@ -1,54 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.fileHandler = undefined; - -var _path = require('path'); - -var _path2 = _interopRequireDefault(_path); - -var _config = require('../../core/config.helper'); - -var _config2 = _interopRequireDefault(_config); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class FileHandler { - isSatisfiedBy(element) { - return element.getTagName().then(function (tagName) { - if (tagName === 'input') { - return element.getAttribute('type').then(inputType => inputType === 'file'); - } - - if (tagName instanceof Array) { - return element.first().getAttribute('type').then(inputType => inputType === 'file'); - } - - return false; - }); - } - - handleFill(page, elementName, desiredValue) { - const fileToUpload = _path2.default.resolve(_path2.default.join(_config2.default.projectPath, _config2.default.data, desiredValue)); - - return page[elementName].sendKeys(fileToUpload); - } - - handleCheck(page, elementName, desiredValue) { - return page[elementName].getText().then(function (text) { - if (text === desiredValue) { - return Promise.resolve(); - } - - return Promise.reject(`Expected ${desiredValue} got ${text} for file element ${elementName}`); - }); - } - - getPriority() { - return 998; - } -} - -const fileHandler = exports.fileHandler = new FileHandler(); \ No newline at end of file diff --git a/dist/form-handlers/handler/index.js b/dist/form-handlers/handler/index.js deleted file mode 100644 index f7c20d95..00000000 --- a/dist/form-handlers/handler/index.js +++ /dev/null @@ -1,101 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _checkbox = require('./checkbox.handler'); - -Object.keys(_checkbox).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _checkbox[key]; - } - }); -}); - -var _ckeditor = require('./ckeditor.handler'); - -Object.keys(_ckeditor).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _ckeditor[key]; - } - }); -}); - -var _customAngularSelect = require('./custom-angular-select.handler'); - -Object.keys(_customAngularSelect).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _customAngularSelect[key]; - } - }); -}); - -var _default = require('./default.handler'); - -Object.keys(_default).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _default[key]; - } - }); -}); - -var _file = require('./file.handler'); - -Object.keys(_file).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _file[key]; - } - }); -}); - -var _uploadedFile = require('./uploaded-file.handler'); - -Object.keys(_uploadedFile).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _uploadedFile[key]; - } - }); -}); - -var _radio = require('./radio.handler'); - -Object.keys(_radio).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _radio[key]; - } - }); -}); - -var _select = require('./select.handler'); - -Object.keys(_select).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _select[key]; - } - }); -}); \ No newline at end of file diff --git a/dist/form-handlers/handler/radio.handler.js b/dist/form-handlers/handler/radio.handler.js deleted file mode 100644 index 6721be42..00000000 --- a/dist/form-handlers/handler/radio.handler.js +++ /dev/null @@ -1,66 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -class RadioHandler { - isSatisfiedBy(element) { - return element.getTagName().then(function (tagName) { - if (tagName === 'input') { - return element.getAttribute('type').then(inputType => inputType === 'radio'); - } - - if (tagName instanceof Array) { - return element.first().getAttribute('type').then(inputType => inputType === 'radio'); - } - - return false; - }); - } - - handleFill(page, elementName, desiredValue) { - const firstRadio = page[elementName].filter(function (elem) { - return elem.getAttribute('value').then(function (elemValue) { - return elemValue === desiredValue; - }); - }).first(); - - return firstRadio.isDisplayed().then(function (isDisplayed) { - if (isDisplayed) { - return firstRadio.click(); - } - - return firstRadio.element(by.xpath('..')).click(); - }); - } - - handleCheck(page, elementName, desiredValue) { - const filteredElements = page[elementName].filter(function (element) { - return element.isSelected(); - }); - - return filteredElements.count().then(function (count) { - if (desiredValue === '') { - if (count === 0) { - return Promise.resolve(); - } - - return Promise.reject(`Expected count to be 0 got ${count}`); - } - - return filteredElements.first().getAttribute('value').then(function (value) { - if (value === desiredValue) { - return Promise.resolve(); - } - - return Promise.reject(`Expected ${desiredValue} got ${value} for radio element ${elementName}`); - }); - }); - } - - getPriority() { - return 998; - } -} - -const radioHandler = exports.radioHandler = new RadioHandler(); \ No newline at end of file diff --git a/dist/form-handlers/handler/select.handler.js b/dist/form-handlers/handler/select.handler.js deleted file mode 100644 index 57c26e87..00000000 --- a/dist/form-handlers/handler/select.handler.js +++ /dev/null @@ -1,66 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -class SelectHandler { - constructor() { - this.optionsSelector = by.css('option'); - } - - isSatisfiedBy(element) { - return element.getTagName().then(function (tagName) { - return tagName === 'select'; - }); - } - - handleFill(page, elementName, desiredValue) { - const self = this; - - const filteredByText = page[elementName].all(this.optionsSelector).filter(function (elem) { - return elem.getText().then(function (text) { - return text.trim() === desiredValue; - }); - }); - - return filteredByText.count().then(filteredByTextCount => { - if (filteredByTextCount === 0) { - const filteredByValue = page[elementName].all(by.css('option')).filter(function (elem) { - return elem.getAttribute('value').then(function (elemValue) { - return elemValue === desiredValue; - }); - }); - - return filteredByValue.count().then(function (filteredByValueCount) { - if (filteredByValueCount === 0) { - return page[elementName].all(self.optionsSelector).first().click(); - } - - return filteredByValue.first().click(); - }); - } - - return filteredByText.first().click(); - }); - } - - handleCheck(page, elementName, desiredValue) { - return page[elementName].all(this.optionsSelector).filter(function (element) { - return element.getAttribute('value').then(function (elemValue) { - return elemValue === desiredValue; - }); - }).count().then(function (count) { - if (count === 1) { - return Promise.resolve(); - } - - return Promise.reject('Option not found for select element.'); - }); - } - - getPriority() { - return 998; - } -} - -const selectHandler = exports.selectHandler = new SelectHandler(); \ No newline at end of file diff --git a/dist/form-handlers/handler/uploaded-file.handler.js b/dist/form-handlers/handler/uploaded-file.handler.js deleted file mode 100644 index 42e76f6c..00000000 --- a/dist/form-handlers/handler/uploaded-file.handler.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -class UploadedFileHandler { - isSatisfiedBy(element, elementName) { - return Promise.resolve(elementName.endsWith('Uploaded')); - } - - // eslint-disable-next-line no-unused-vars - handleFill(page, elementName, desiredValue) { - throw new Error('Not supported for this field type'); - } - - handleCheck(page, elementName, desiredValue) { - return page[elementName].getText().then(function (text) { - if (text.indexOf(desiredValue) >= 0) { - return Promise.resolve(); - } - - return Promise.reject(`Expected ${desiredValue} got ${text} for file element ${elementName}`); - }); - } - - getPriority() { - return 998; - } -} - -const uploadedFileHandler = exports.uploadedFileHandler = new UploadedFileHandler(); \ No newline at end of file diff --git a/dist/form-handlers/handlers.js b/dist/form-handlers/handlers.js deleted file mode 100644 index 89f71129..00000000 --- a/dist/form-handlers/handlers.js +++ /dev/null @@ -1,67 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _handler = require('./handler'); - -var formHandler = _interopRequireWildcard(_handler); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } - -const availableHandlers = [formHandler.checkboxHandler, formHandler.ckEditorHandler, formHandler.customAngularSelectHandler, formHandler.defaultHandler, formHandler.fileHandler, formHandler.radioHandler, formHandler.selectHandler, formHandler.uploadedFileHandler]; - -const FormHandler = { - addHandler: function (handler) { - availableHandlers.push(handler); - }, - - handleFill: (() => { - var _ref = _asyncToGenerator(function* (page, elementName, desiredValue) { - const handlers = this.getHandlers(); - - for (let handler of handlers) { - const isSatisfied = yield handler.isSatisfiedBy(page[elementName], elementName); - - if (isSatisfied) { - return handler.handleFill(page, elementName, desiredValue); - } - } - - return Promise.reject('Could not find matching handler.'); - }); - - return function handleFill(_x, _x2, _x3) { - return _ref.apply(this, arguments); - }; - })(), - - handleCheck: (() => { - var _ref2 = _asyncToGenerator(function* (page, elementName, desiredValue) { - const handlers = this.getHandlers(); - - for (let handler of handlers) { - const isSatisfied = yield handler.isSatisfiedBy(page[elementName], elementName); - - if (isSatisfied) { - return handler.handleCheck(page, elementName, desiredValue); - } - } - - return Promise.reject('Could not find matching handler.'); - }); - - return function handleCheck(_x4, _x5, _x6) { - return _ref2.apply(this, arguments); - }; - })(), - - getHandlers: function () { - return availableHandlers.sort((handler, otherHandler) => handler.getPriority() - otherHandler.getPriority()); - } -}; - -exports.default = FormHandler; \ No newline at end of file diff --git a/dist/form-handlers/index.js b/dist/form-handlers/index.js deleted file mode 100644 index dd8ae3d9..00000000 --- a/dist/form-handlers/index.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _handlers = require('./handlers'); - -Object.defineProperty(exports, 'fromHandlers', { - enumerable: true, - get: function () { - return _interopRequireDefault(_handlers).default; - } -}); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/dist/form-handlers/interfaces/form-handler.interface.js b/dist/form-handlers/interfaces/form-handler.interface.js deleted file mode 100644 index e69de29b..00000000 diff --git a/dist/generators/generator/index.js b/dist/generators/generator/index.js deleted file mode 100644 index e79277d4..00000000 --- a/dist/generators/generator/index.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _stringWithLength = require('./string-with-length.generator'); - -Object.keys(_stringWithLength).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _stringWithLength[key]; - } - }); -}); - -var _personalData = require('./personalData.generator'); - -Object.keys(_personalData).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _personalData[key]; - } - }); -}); \ No newline at end of file diff --git a/dist/generators/generator/personalData.generator.js b/dist/generators/generator/personalData.generator.js deleted file mode 100644 index 8f39c319..00000000 --- a/dist/generators/generator/personalData.generator.js +++ /dev/null @@ -1,33 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.personalDataGenerator = undefined; - -var _faker = require('faker'); - -var _faker2 = _interopRequireDefault(_faker); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const personalDataGenerator = exports.personalDataGenerator = { - isSatisfiedBy: function (name) { - return name === 'personalData'; - }, - - generate: function (options) { - switch (options[0]) { - case 'firstName': - return Promise.resolve(_faker2.default.name.firstName()); - case 'lastName': - return Promise.resolve(_faker2.default.name.lastName()); - case 'jobTitle': - return Promise.resolve(_faker2.default.name.jobTitle()); - case 'email': - return Promise.resolve(_faker2.default.internet.email(null, null, options[1])); - default: - return Promise.reject('Option not available in "personalData" generator!'); - } - } -}; \ No newline at end of file diff --git a/dist/generators/generator/string-with-length.generator.js b/dist/generators/generator/string-with-length.generator.js deleted file mode 100644 index 5eeb2ae2..00000000 --- a/dist/generators/generator/string-with-length.generator.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -const stringWithLengthGenerator = exports.stringWithLengthGenerator = { - isSatisfiedBy: function (name) { - return name === 'stringWithLength'; - }, - - generate: function (generatorParam) { - const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - const length = parseInt(generatorParam); - - let result = ''; - for (let i = length; i > 0; i--) result += chars[Math.floor(Math.random() * chars.length)]; - - return Promise.resolve(result); - } -}; \ No newline at end of file diff --git a/dist/generators/generators.js b/dist/generators/generators.js deleted file mode 100644 index 83614d63..00000000 --- a/dist/generators/generators.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.create = undefined; - -var _generator = require('./generator'); - -var generators = _interopRequireWildcard(_generator); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -class Generators { - constructor() { - this.availableGenerators = [generators.personalDataGenerator, generators.stringWithLengthGenerator]; - } - - generate(generatorName, ...params) { - const gen = this.findGenerator(generatorName); - - if (gen === undefined) { - throw new Error(`Could not find generator for ${generatorName}.`); - } - - return gen.generate(...params); - } - - addGenerator(generator) { - this.availableGenerators.push(generator); - } - - findGenerator(name) { - return this.availableGenerators.find(gen => gen.isSatisfiedBy(name)); - } -} - -const create = exports.create = () => new Generators(); \ No newline at end of file diff --git a/dist/generators/index.js b/dist/generators/index.js deleted file mode 100644 index 7f4faaee..00000000 --- a/dist/generators/index.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.generators = undefined; - -var _generators = require('./generators'); - -const generators = exports.generators = (0, _generators.create)(); \ No newline at end of file diff --git a/dist/generators/interfaces/generator.interface.js b/dist/generators/interfaces/generator.interface.js deleted file mode 100644 index e69de29b..00000000 diff --git a/dist/index.js b/dist/index.js deleted file mode 100644 index 50e7e473..00000000 --- a/dist/index.js +++ /dev/null @@ -1,127 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.BaseDictionary = exports.BasePage = exports.waitForCondition = exports.waitForInvisibilityOf = exports.waitForVisibilityOf = exports.emailService = exports.comparators = exports.handlers = exports.variableStore = exports.generators = exports.transformers = exports.dictionaries = exports.defineSupportCode = exports.regexBuilder = exports.matchers = undefined; - -var _matchers = require('./matchers'); - -Object.defineProperty(exports, 'matchers', { - enumerable: true, - get: function () { - return _matchers.matchers; - } -}); -Object.defineProperty(exports, 'regexBuilder', { - enumerable: true, - get: function () { - return _matchers.regexBuilder; - } -}); - -var _cucumber = require('cucumber'); - -Object.defineProperty(exports, 'defineSupportCode', { - enumerable: true, - get: function () { - return _cucumber.defineSupportCode; - } -}); - -var _dictionaries = require('./dictionaries'); - -Object.defineProperty(exports, 'dictionaries', { - enumerable: true, - get: function () { - return _dictionaries.dictionaries; - } -}); - -var _transformers = require('./transformers'); - -Object.defineProperty(exports, 'transformers', { - enumerable: true, - get: function () { - return _transformers.transformers; - } -}); - -var _generators = require('./generators'); - -Object.defineProperty(exports, 'generators', { - enumerable: true, - get: function () { - return _generators.generators; - } -}); - -var _variableStore = require('./web/variable-store.helper'); - -Object.defineProperty(exports, 'variableStore', { - enumerable: true, - get: function () { - return _interopRequireDefault(_variableStore).default; - } -}); - -var _handlers = require('./form-handlers/handlers'); - -Object.defineProperty(exports, 'handlers', { - enumerable: true, - get: function () { - return _interopRequireDefault(_handlers).default; - } -}); - -var _comparators = require('./comparators'); - -Object.defineProperty(exports, 'comparators', { - enumerable: true, - get: function () { - return _comparators.comparators; - } -}); - -var _emails = require('./emails'); - -Object.defineProperty(exports, 'emailService', { - enumerable: true, - get: function () { - return _emails.emailService; - } -}); - -var _waitForCondition = require('./web/cucumber/wait-for-condition.helper'); - -Object.defineProperty(exports, 'waitForVisibilityOf', { - enumerable: true, - get: function () { - return _waitForCondition.waitForVisibilityOf; - } -}); -Object.defineProperty(exports, 'waitForInvisibilityOf', { - enumerable: true, - get: function () { - return _waitForCondition.waitForInvisibilityOf; - } -}); -Object.defineProperty(exports, 'waitForCondition', { - enumerable: true, - get: function () { - return _waitForCondition.waitForCondition; - } -}); - -var _pages = require('./pages'); - -var pages = _interopRequireWildcard(_pages); - -var dictionaries = _interopRequireWildcard(_dictionaries); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const BasePage = exports.BasePage = pages.Form; -const BaseDictionary = exports.BaseDictionary = dictionaries.Base; \ No newline at end of file diff --git a/dist/matchers/index.js b/dist/matchers/index.js deleted file mode 100644 index ddadb94e..00000000 --- a/dist/matchers/index.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.regexBuilder = exports.matchers = undefined; - -var _matchers = require('./matchers'); - -var _regexBuilder = require('./matcher/regex-matcher/regex-builder'); - -const matchers = exports.matchers = (0, _matchers.create)(); -const regexBuilder = exports.regexBuilder = _regexBuilder.regexBuilder; \ No newline at end of file diff --git a/dist/matchers/interfaces/matcher.interface.js b/dist/matchers/interfaces/matcher.interface.js deleted file mode 100644 index e69de29b..00000000 diff --git a/dist/matchers/matcher/attribute.matcher.js b/dist/matchers/matcher/attribute.matcher.js deleted file mode 100644 index 5ed9399d..00000000 --- a/dist/matchers/matcher/attribute.matcher.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.attributeMatcher = undefined; - -var _regexBuilder = require('./regex-matcher/regex-builder'); - -class AttributeMatcher { - isSatisfiedBy(prefix) { - return prefix === 'attribute'; - } - - match(element, attributeName, regexName) { - return element.getAttribute(attributeName).then(value => { - if (_regexBuilder.regexBuilder.buildRegex(`r:${regexName}`).test(value)) { - return true; - } - - /* eslint-disable max-len */ - return Promise.reject(` - Matcher "AttributeMatcher" could not match regex on element "${element.locator()}" on attribute "${attributeName}". - Expected to match: "${_regexBuilder.regexBuilder.buildRegex(`r:${regexName}`).toString()}", Given: "${value}" - `); - /* eslint-enable max-len */ - }); - } -} - -const attributeMatcher = exports.attributeMatcher = new AttributeMatcher(); \ No newline at end of file diff --git a/dist/matchers/matcher/clickable.matcher.js b/dist/matchers/matcher/clickable.matcher.js deleted file mode 100644 index 7d2e7f5d..00000000 --- a/dist/matchers/matcher/clickable.matcher.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -class ClickableMatcher { - isSatisfiedBy(prefix, name) { - return prefix === 'f' && name === 'isClickable'; - } - - match(element) { - return element.getAttribute('disabled').then(function (disabled) { - return ['disabled', true, 'true'].indexOf(disabled) === -1; - }).then(result => { - if (result) { - return true; - } - - return Promise.reject(` - Matcher "ClickableMatcher" could find attribute disabled on element "${element.locator()}". - `); - }); - } -} - -const clickableMatcher = exports.clickableMatcher = new ClickableMatcher(); \ No newline at end of file diff --git a/dist/matchers/matcher/currentDate.matcher.js b/dist/matchers/matcher/currentDate.matcher.js deleted file mode 100644 index 9e6c480f..00000000 --- a/dist/matchers/matcher/currentDate.matcher.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.currentDateMatcher = undefined; - -var _moment = require('moment'); - -var _moment2 = _interopRequireDefault(_moment); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class CurrentDateMatcher { - isSatisfiedBy(prefix, name) { - return prefix === 'f' && name === 'currentDate'; - } - - // eslint-disable-next-line no-unused-vars - match(element, name = null, params = 'DD-MM-YYYY') { - const currentDate = (0, _moment2.default)(new Date()).format(params); - return element.getText().then(text => { - const compareDate = (0, _moment2.default)(new Date(text)).format(params); - - if (compareDate === currentDate) { - return true; - } - - /* eslint-disable max-len */ - return Promise.reject(` - Matcher "CurrentDate" could not match date for element "${element.locator()}". Expected: "${compareDate}", given: "${currentDate}". - `); - /* eslint-enable max-len */ - }); - } -} - -const currentDateMatcher = exports.currentDateMatcher = new CurrentDateMatcher(); \ No newline at end of file diff --git a/dist/matchers/matcher/index.js b/dist/matchers/matcher/index.js deleted file mode 100644 index 693e7b2a..00000000 --- a/dist/matchers/matcher/index.js +++ /dev/null @@ -1,86 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _clickable = require('./clickable.matcher'); - -Object.defineProperty(exports, 'clickableMatcher', { - enumerable: true, - get: function () { - return _clickable.clickableMatcher; - } -}); - -var _invisible = require('./invisible.matcher'); - -Object.defineProperty(exports, 'invisibleMatcher', { - enumerable: true, - get: function () { - return _invisible.invisibleMatcher; - } -}); - -var _notClickable = require('./not-clickable.matcher'); - -Object.defineProperty(exports, 'notClickableMatcher', { - enumerable: true, - get: function () { - return _notClickable.notClickableMatcher; - } -}); - -var _present = require('./present.matcher'); - -Object.defineProperty(exports, 'presentMatcher', { - enumerable: true, - get: function () { - return _present.presentMatcher; - } -}); - -var _text = require('./text.matcher'); - -Object.defineProperty(exports, 'textMatcher', { - enumerable: true, - get: function () { - return _text.textMatcher; - } -}); - -var _visible = require('./visible.matcher'); - -Object.defineProperty(exports, 'visibleMatcher', { - enumerable: true, - get: function () { - return _visible.visibleMatcher; - } -}); - -var _regexMatcher = require('./regex-matcher'); - -Object.defineProperty(exports, 'regexMatcher', { - enumerable: true, - get: function () { - return _regexMatcher.regexMatcher; - } -}); - -var _attribute = require('./attribute.matcher'); - -Object.defineProperty(exports, 'attributeMatcher', { - enumerable: true, - get: function () { - return _attribute.attributeMatcher; - } -}); - -var _currentDate = require('./currentDate.matcher'); - -Object.defineProperty(exports, 'currentDateMatcher', { - enumerable: true, - get: function () { - return _currentDate.currentDateMatcher; - } -}); \ No newline at end of file diff --git a/dist/matchers/matcher/invisible.matcher.js b/dist/matchers/matcher/invisible.matcher.js deleted file mode 100644 index 03b14693..00000000 --- a/dist/matchers/matcher/invisible.matcher.js +++ /dev/null @@ -1,28 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } - -class InvisibleMatcher { - isSatisfiedBy(prefix, name) { - return prefix === 'f' && name === 'isNotVisible'; - } - - match(element) { - return _asyncToGenerator(function* () { - try { - yield element.isDisplayed(); - return Promise.reject(` - Matcher "InvisibleMatcher" could find element "${element.locator()}". Expected element to be invisible. - `); - } catch (err) { - return true; - } - })(); - } -} - -const invisibleMatcher = exports.invisibleMatcher = new InvisibleMatcher(); \ No newline at end of file diff --git a/dist/matchers/matcher/not-clickable.matcher.js b/dist/matchers/matcher/not-clickable.matcher.js deleted file mode 100644 index b725f24d..00000000 --- a/dist/matchers/matcher/not-clickable.matcher.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -class NotClickableMatcher { - isSatisfiedBy(prefix, name) { - return prefix === 'f' && name === 'isNotClickable'; - } - - match(element) { - return element.getAttribute('disabled').then(function (disabled) { - return ['disabled', true, 'true'].indexOf(disabled) !== -1; - }).then(result => { - if (result) { - return true; - } - - return Promise.reject(` - Matcher "NotClickable" could not find attribute disabled on element "${element.locator()}". - `); - }); - } -} - -const notClickableMatcher = exports.notClickableMatcher = new NotClickableMatcher(); \ No newline at end of file diff --git a/dist/matchers/matcher/present.matcher.js b/dist/matchers/matcher/present.matcher.js deleted file mode 100644 index 073940f3..00000000 --- a/dist/matchers/matcher/present.matcher.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -class PresentMatcher { - isSatisfiedBy(prefix, name) { - return prefix === 'f' && name === 'isPresent'; - } - - match(element) { - return element.isPresent().then(() => true).catch(() => Promise.reject(`Matcher "PresentMatcher" could not find element "${element.locator()}".`)); - } -} - -const presentMatcher = exports.presentMatcher = new PresentMatcher(); \ No newline at end of file diff --git a/dist/matchers/matcher/regex-matcher/index.js b/dist/matchers/matcher/regex-matcher/index.js deleted file mode 100644 index d35a72d5..00000000 --- a/dist/matchers/matcher/regex-matcher/index.js +++ /dev/null @@ -1,57 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.regexMatcher = undefined; - -var _regexBuilder = require('./regex-builder'); - -var _regex = require('./regex'); - -var _regex2 = _interopRequireDefault(_regex); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class RegexMatcher { - isSatisfiedBy(prefix, name) { - return prefix === 'r' && typeof _regex2.default[name] !== 'undefined'; - } - - match(element, regexName) { - return element.getText().then(text => { - return element.getAttribute('value').then(value => { - const regularExpression = _regexBuilder.regexBuilder.buildRegex(`r:${regexName}`); - - if (text === '') { - if (value === null) { - return Promise.reject(` - Matcher "RegexMatcher" could not match value for element "${element.locator()}". - Both text and attribute value are empty. - `); - } - - if (regularExpression.test(value)) { - return true; - } - - return Promise.reject(` - Matcher "RegexMatcher" could not match regex on element "${element.locator()}" on value "${value}". - Expected to match: "${regularExpression.toString()}", Given: "${value}" - `); - } - - if (regularExpression.test(text)) { - return true; - } - - return Promise.reject(` - Matcher "RegexMatcher" could not match regex on element "${element.locator()}" on text "${text}". - Expected to match: "${regularExpression.toString()}", Given: "${text}" - `); - }); - }); - } -} - -const regexMatcher = exports.regexMatcher = new RegexMatcher(); \ No newline at end of file diff --git a/dist/matchers/matcher/regex-matcher/regex-builder.js b/dist/matchers/matcher/regex-matcher/regex-builder.js deleted file mode 100644 index 12a4d8e0..00000000 --- a/dist/matchers/matcher/regex-matcher/regex-builder.js +++ /dev/null @@ -1,28 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.regexBuilder = undefined; - -var _regex = require('./regex'); - -var _regex2 = _interopRequireDefault(_regex); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class RegexBuilder { - buildRegex(regexTemplate) { - for (let property in _regex2.default) { - if (_regex2.default.hasOwnProperty(property)) { - if (regexTemplate === 'r:' + property) { - return new RegExp(_regex2.default[property]); - } - } - } - - throw 'Regex with template ' + regexTemplate + ' was not found'; - } -} - -const regexBuilder = exports.regexBuilder = new RegexBuilder(); \ No newline at end of file diff --git a/dist/matchers/matcher/regex-matcher/regex.js b/dist/matchers/matcher/regex-matcher/regex.js deleted file mode 100644 index 1ecc0db4..00000000 --- a/dist/matchers/matcher/regex-matcher/regex.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -var _modulesLoader = require('../../../core/modules-loader.helper'); - -var _default = require('./regexes/default'); - -const modulesLoader = (0, _modulesLoader.create)(); -const availableRegexes = modulesLoader.getModules('regexes'); - -const regularExpressions = availableRegexes.reduce((regexes, newRegexes) => _extends({}, regexes, newRegexes), _extends({}, _default.regex)); - -exports.default = regularExpressions; \ No newline at end of file diff --git a/dist/matchers/matcher/regex-matcher/regexes/default.js b/dist/matchers/matcher/regex-matcher/regexes/default.js deleted file mode 100644 index 0e4902e2..00000000 --- a/dist/matchers/matcher/regex-matcher/regexes/default.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -/* eslint-disable max-len */ -const regex = exports.regex = { - arabianCharacters: '\u0621-\u064A', - arabianNumbers: '\u0660-\u0669', - standardCharacters: 'a-zA-Z', - standardNumbers: '0-9', - notEmpty: '.+', - number: '[0-9]+', - pdfFile: '[\\w]+.pdf', - pdfFileType: 'application/pdf', - email: "[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", - // todo: following regex should be moved to tests/regexes - someRandomLinkRegex: '(http(s)?://some-random-link.com)' -}; -/* eslint-enable max-len */ \ No newline at end of file diff --git a/dist/matchers/matcher/text.matcher.js b/dist/matchers/matcher/text.matcher.js deleted file mode 100644 index 670f5c1e..00000000 --- a/dist/matchers/matcher/text.matcher.js +++ /dev/null @@ -1,46 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.textMatcher = undefined; - -var _matchers = require('../matchers'); - -class TextMatcher { - isSatisfiedBy(prefix) { - return prefix === 't'; - } - - match(element, ...params) { - const expectedValue = params.join(_matchers.separator); - - return element.getTagName().then(tag => { - if (tag === 'input' || tag === 'textarea') { - return element.getAttribute('value').then(value => { - if (new RegExp(RegExp.escape(expectedValue)).test(value)) { - return true; - } - - return Promise.reject(` - Matcher "TextMatcher" could not match value on element "${element.locator()}". - Expected: "${expectedValue}", Given: "${value}" - `); - }); - } - - return element.getText().then(text => { - if (new RegExp(RegExp.escape(expectedValue)).test(text)) { - return true; - } - - return Promise.reject(` - Matcher "TextMatcher" could not match value on element "${element.locator()}". - Expected: "${expectedValue}", Given: "${text}" - `); - }); - }); - } -} - -const textMatcher = exports.textMatcher = new TextMatcher(); \ No newline at end of file diff --git a/dist/matchers/matcher/visible.matcher.js b/dist/matchers/matcher/visible.matcher.js deleted file mode 100644 index 351badd6..00000000 --- a/dist/matchers/matcher/visible.matcher.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -class VisibleMatcher { - isSatisfiedBy(prefix, name) { - return prefix === 'f' && name === 'isVisible'; - } - - match(element) { - return element.isDisplayed().then(() => true).catch(() => { - return Promise.reject(`Matcher "VisibleMatcher" could not find element "${element.locator()}".`); - }); - } -} - -const visibleMatcher = exports.visibleMatcher = new VisibleMatcher(); \ No newline at end of file diff --git a/dist/matchers/matchers.js b/dist/matchers/matchers.js deleted file mode 100644 index 3ec66e3a..00000000 --- a/dist/matchers/matchers.js +++ /dev/null @@ -1,41 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.create = exports.separator = undefined; - -var _matcher = require('./matcher'); - -var matchers = _interopRequireWildcard(_matcher); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -const separator = exports.separator = ':'; - -class Matchers { - constructor() { - this.availableMatchers = [matchers.regexMatcher, matchers.clickableMatcher, matchers.invisibleMatcher, matchers.notClickableMatcher, matchers.presentMatcher, matchers.textMatcher, matchers.visibleMatcher, matchers.attributeMatcher, matchers.currentDateMatcher]; - } - - addMatcher(matcher) { - this.availableMatchers.push(matcher); - } - - match(element, matcherName) { - const splittedValue = matcherName.split(separator); - const matcher = this.findMatcher(splittedValue[0], splittedValue.slice(1)); - - if (matcher === undefined) { - throw new Error(`Could not find matcher for ${matcherName}.`); - } - - return matcher.match(element, ...splittedValue.slice(1)); - } - - findMatcher(prefix, params) { - return this.availableMatchers.find(matcher => matcher.isSatisfiedBy(prefix, ...params)); - } -} - -const create = exports.create = () => new Matchers(); \ No newline at end of file diff --git a/dist/pages/base.js b/dist/pages/base.js deleted file mode 100644 index 023917ce..00000000 --- a/dist/pages/base.js +++ /dev/null @@ -1,109 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _config = require('../core/config.helper'); - -var _config2 = _interopRequireDefault(_config); - -var _waitForCondition = require('../web/cucumber/wait-for-condition.helper'); - -var _urlParser = require('../web/url-parser.helper'); - -var _querystring = require('querystring'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } - -class Page { - visit() { - if (_config2.default.type === 'otherWeb' || !(0, _urlParser.isRelativePage)(this.url)) { - protractor.browser.ignoreSynchronization = true; - - return protractor.browser.get(this.url); - } - - return protractor.browser.get(this.url).then(() => protractor.browser.waitForAngular()); - } - - visitWithParameters(data) { - const additionalParams = {}; - - const url = data.raw().reduce((prev, item) => { - if (prev.indexOf(`:${item[0]}`) === -1) { - additionalParams[item[0]] = item[1]; - return prev; - } - return prev.replace(`:${item[0]}`, item[1]); - }, this.url) + (Object.entries(additionalParams).length > 0 ? '?' + (0, _querystring.stringify)(additionalParams) : ''); - - if (_config2.default.type === 'otherWeb' || !(0, _urlParser.isRelativePage)(url)) { - protractor.browser.ignoreSynchronization = true; - - return protractor.browser.get(url); - } - - return protractor.browser.get(url).then(() => protractor.browser.waitForAngular()); - } - - isOn() { - var _this = this; - - return _asyncToGenerator(function* () { - if ((0, _urlParser.isRelativePage)(_this.url) && _config2.default.type !== 'otherWeb') { - protractor.browser.ignoreSynchronization = false; - } - - return browser.wait(_asyncToGenerator(function* () { - const currentUrl = yield browser.getCurrentUrl().then(function (url) { - return url; - }); - - return (0, _urlParser.waitForUrlChangeTo)(_this.url, currentUrl)(_config2.default.baseUrl); - }), _config2.default.waitForPageTimeout * 1000); - })(); - } - - click(element) { - return this[element].click(); - } - - isDisabled(element) { - return this[element].getAttribute('disabled').then(function (disabled) { - return ['disabled', true, 'true'].indexOf(disabled) !== -1; - }); - } - - isVisible(element) { - return this[element].isDisplayed(); - } - - isPresent(element) { - return this[element].isPresent(); - } - - getNumberOfElements(elementName) { - return this[elementName].count(); - } - - scrollIntoElement(elementName, elementIndex = undefined) { - if (elementIndex !== undefined) { - return browser.executeScript('arguments[0].scrollIntoView(false);', this[elementName].get(elementIndex).getWebElement()); - } - - return browser.executeScript('arguments[0].scrollIntoView(false);', this[elementName].getWebElement()); - } - - waitForVisibilityOf(elementName) { - return (0, _waitForCondition.waitForVisibilityOf)(this[elementName]); - } - - waitForInvisibilityOf(elementName) { - return (0, _waitForCondition.waitForInvisibilityOf)(this[elementName]); - } -} - -exports.default = Page; \ No newline at end of file diff --git a/dist/pages/form.js b/dist/pages/form.js deleted file mode 100644 index 3d51bd9a..00000000 --- a/dist/pages/form.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _base = require('./base'); - -var _base2 = _interopRequireDefault(_base); - -var _formHandlers = require('../form-handlers'); - -var _transformers = require('../transformers'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } - -class FormPage extends _base2.default { - fillForm(formData) { - var _this = this; - - return _asyncToGenerator(function* () { - for (let item of formData) { - yield _this.fillField(item[0], item[1]); - } - - return Promise.resolve(); - })(); - } - - checkForm(formData) { - var _this2 = this; - - return _asyncToGenerator(function* () { - for (let item of formData) { - yield _this2.checkField(item[0], item[1]); - } - - return Promise.resolve(); - })(); - } - - fillField(name, value) { - return _formHandlers.fromHandlers.handleFill(this, name, _transformers.transformers.transform(value)); - } - - checkField(name, value) { - return _formHandlers.fromHandlers.handleCheck(this, name, _transformers.transformers.transform(value)); - } -} - -exports.default = FormPage; \ No newline at end of file diff --git a/dist/pages/index.js b/dist/pages/index.js deleted file mode 100644 index 64bca11d..00000000 --- a/dist/pages/index.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.Form = exports.Base = undefined; - -var _base = require('./base'); - -var _base2 = _interopRequireDefault(_base); - -var _form = require('./form'); - -var _form2 = _interopRequireDefault(_form); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const Base = exports.Base = _base2.default; -const Form = exports.Form = _form2.default; \ No newline at end of file diff --git a/dist/protractor.conf.js b/dist/protractor.conf.js deleted file mode 100644 index 7d761b0d..00000000 --- a/dist/protractor.conf.js +++ /dev/null @@ -1,115 +0,0 @@ -'use strict'; - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } - -require('./core/prototypes'); -const path = require('path'); -const chai = require('chai'); -const config = require('./core/config.helper').default; -const modulesLoader = require('./core/modules-loader.helper.js').create(); -const { deleteReports } = require('./core/fs/delete-files.helper'); -const { prepareCatalogs } = require('./core/fs/prepare-catalogs.helper'); -const browsersConfiguration = require('./web/browsers/browsers-config.helper'); -const chaiAsPromised = require('chai-as-promised'); -const { emailService } = require('./emails'); -const commandArgs = require('minimist')(process.argv.slice(2)); -chai.use(chaiAsPromised); - -const reportsDirectory = path.join(config.projectPath, config.reports); -const jsonOutputDirectory = path.join(reportsDirectory, 'json-output-folder'); -const generatedReportsDirectory = path.join(reportsDirectory, 'report'); -const featureReportsDirectory = path.join(generatedReportsDirectory, 'features'); -const performanceReportsDirectory = path.join(reportsDirectory, 'performance'); - -const prepareReportCatalogs = (() => { - var _ref = _asyncToGenerator(function* () { - yield prepareCatalogs(reportsDirectory); - yield prepareCatalogs(jsonOutputDirectory); - yield prepareCatalogs(generatedReportsDirectory); - yield prepareCatalogs(featureReportsDirectory); - yield prepareCatalogs(performanceReportsDirectory); - }); - - return function prepareReportCatalogs() { - return _ref.apply(this, arguments); - }; -})(); - -const deleteReportFiles = () => { - deleteReports(reportsDirectory); - deleteReports(jsonOutputDirectory); - deleteReports(generatedReportsDirectory); - deleteReports(featureReportsDirectory); - deleteReports(performanceReportsDirectory); - - console.log('All reports have been deleted!'); -}; - -exports.config = { - getMultiCapabilities: browsersConfiguration(config, commandArgs), - - useAllAngular2AppRoots: config.type === 'ng2', - - getPageTimeout: parseInt(config.timeout) * 1000, - allScriptsTimeout: parseInt(config.timeout) * 1000, - - framework: 'custom', - frameworkPath: require.resolve('protractor-cucumber-framework'), - specs: [], - - cucumberOpts: { - require: ['./web/cucumber/config.js', './web/cucumber/hooks.js', './step_definitions/**/*.js', ...config.step_definitions.map(file => path.join(config.projectPath, file, '**/*.js')), ...config.hooks.map(file => path.join(config.projectPath, file, '**/*.js'))], - format: [`json:./${config.reports}/features-report.json`], - profile: false, - 'no-source': true - }, - - plugins: [{ - package: 'protractor-multiple-cucumber-html-reporter-plugin', - options: { - removeExistingJsonReportFile: true, - removeOriginalJsonReportFile: true, - automaticallyGenerateReport: true, - saveCollectedJSON: true - } - }], - - beforeLaunch: (() => { - var _ref2 = _asyncToGenerator(function* () { - yield prepareReportCatalogs(); - yield deleteReportFiles(); - }); - - return function beforeLaunch() { - return _ref2.apply(this, arguments); - }; - })(), - - onPrepare: function () { - if (!config.headless) { - browser.driver.manage().window().setSize(parseInt(config.browserWidth), parseInt(config.browserHeight)); - } - - modulesLoader.getModules('matchers'); - modulesLoader.getModules('dictionaries'); - modulesLoader.getModules('generators'); - modulesLoader.getModules('comparators'); - modulesLoader.getModules('form_handlers'); - modulesLoader.getModules('transformers'); - modulesLoader.getModules('emails'); - - const modules = modulesLoader.getModulesAsObject(config.pages.map(page => path.join(config.projectPath, page))); - - browser.page = Object.keys(modules).reduce((pages, moduleName) => _extends({}, pages, { [moduleName]: new modules[moduleName]() }), {}); - - global.expect = chai.expect; - - if (config.clearEmailInboxBeforeTests) { - return emailService.clearInbox(); - } - }, - - baseUrl: config.baseUrl -}; \ No newline at end of file diff --git a/dist/step_definitions/debug.js b/dist/step_definitions/debug.js deleted file mode 100644 index 66933cfb..00000000 --- a/dist/step_definitions/debug.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; - -var _cucumber = require('cucumber'); - -(0, _cucumber.defineSupportCode)(function ({ Then }) { - Then(/^I wait for "([^"]*)" seconds$/, function (number) { - return browser.sleep(Number(number) * 1000); - }); -}); \ No newline at end of file diff --git a/dist/step_definitions/elements.js b/dist/step_definitions/elements.js deleted file mode 100644 index 5258c5b0..00000000 --- a/dist/step_definitions/elements.js +++ /dev/null @@ -1,446 +0,0 @@ -'use strict'; - -var _cucumber = require('cucumber'); - -var _matchers = require('../matchers'); - -var _variableStore = require('../web/variable-store.helper'); - -var _variableStore2 = _interopRequireDefault(_variableStore); - -var _comparators = require('../comparators'); - -var _config = require('../core/config.helper'); - -var _config2 = _interopRequireDefault(_config); - -var _chalk = require('chalk'); - -var _chalk2 = _interopRequireDefault(_chalk); - -var _waitForCondition = require('../web/cucumber/wait-for-condition.helper'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } - -const timeout = parseInt(_config2.default.elementsVisibilityTimeout) * 1000; - -const handlePromises = (hashedData, onSuccess, onReject) => resolvedPromises => { - for (let i = 0; i < resolvedPromises.length; i += hashedData.length) { - let allFieldsMatching = true; - - for (let j = i; j < i + hashedData.length; j++) { - if (resolvedPromises[j] === false) { - allFieldsMatching = false; - break; - } - } - - if (allFieldsMatching) { - return onSuccess(); - } - } - - return onReject(); -}; - -(0, _cucumber.defineSupportCode)(function ({ When, Then }) { - function checkNumberOfElements(numberExpression, element) { - const self = this; - const numberPattern = /\d+/g; - const numbers = numberExpression.match(numberPattern).map(item => parseInt(item)); - - const expectFunction = function (words, num) { - return expect(self.currentPage.getNumberOfElements(element)).to.eventually.be[words.pop()](...num); - }; - - return expectFunction(numberExpression.substr(0, numberExpression.indexOf(numbers[0]) - 1).split(' '), numbers); - } - - When(/^I wait for "([^"]*)" of the "([^"]*)" element$/, function (condition, elementName) { - if (this.currentPage[elementName] instanceof protractor.ElementArrayFinder) { - return (0, _waitForCondition.waitForCondition)(condition, timeout)(this.currentPage[elementName].first()); - } - - return (0, _waitForCondition.waitForCondition)(condition, timeout)(this.currentPage[elementName]); - }); - - When(/^I scroll to the "([^"]*)" element$/, function (elementName) { - return this.currentPage.scrollIntoElement(elementName); - }); - - When(/^I click the "([^"]*)" element$/, function (elementName) { - return this.currentPage.scrollIntoElement(elementName).catch(() => Promise.resolve()).then(() => this.currentPage.waitForVisibilityOf(elementName)).then(() => this.currentPage.scrollIntoElement(elementName)).then(() => this.currentPage.click(elementName)).catch(() => { - return (0, _waitForCondition.waitForCondition)('elementToBeClickable', timeout)(this.currentPage[elementName]).then(() => { - return this.currentPage.click(elementName); - }); - }).catch(() => { - console.warn('Warning! Element was not clickable. We need to scroll it down.'); - return browser.executeScript('window.scrollBy(0,50);').then(() => this.currentPage.waitForVisibilityOf(elementName)).then(() => this.currentPage.click(elementName)); - }).catch(() => { - console.warn('Warning! Element was not clickable. We need use the WebDriver method to perform the click action.'); - return browser.actions().mouseMove(this.currentPage[elementName]).mouseMove({ x: 5, y: 0 }).click().perform(); - }).catch(() => { - return Promise.reject(`Error, after scrolling the element "${elementName}" is still not clickable.`); - }); - }); - - When(/^I store the "([^"]*)" element text as "([^"]*)" variable$/, function (elementName, variable) { - var _this = this; - - return this.currentPage.waitForVisibilityOf(elementName).then(_asyncToGenerator(function* () { - const elementTag = yield _this.currentPage[elementName].getTagName(function (tag) { - return tag; - }); - - if (elementTag === 'input' || elementTag === 'textarea') { - return _this.currentPage[elementName].getAttribute('value').then(function (value) { - _variableStore2.default.storeVariable(variable, value); - }); - } - - return _this.currentPage[elementName].getText().then(function (text) { - _variableStore2.default.storeVariable(variable, text); - }); - })); - }); - - When(/^I update the "([^"]*)" element text as "([^"]*)" variable$/, function (elementName, variable) { - return this.currentPage.waitForVisibilityOf(elementName).then(() => { - this.currentPage[elementName].getText().then(text => { - _variableStore2.default.updateVariable(variable, text); - }); - }); - }); - - When(/^I store the "([^"]*)" element text matched by "([^"]*)" as "([^"]*)" variable$/, function (elementName, matcher, variable) { - const regex = _matchers.regexBuilder.buildRegex(matcher); - - return this.currentPage.waitForVisibilityOf(elementName).then(() => { - return this.currentPage[elementName].getText().then(text => { - const matchedText = text.match(regex); - - if (matchedText === null) { - return Promise.reject(`Could not match text ${text} with matcher ${matcher}`); - } - - if (matchedText.length <= 1) { - return Promise.reject(`Matcher ${matcher} does not contain capturing brackets`); - } - - _variableStore2.default.storeVariable(variable, matchedText[1]); - }); - }); - }); - - When(/^I wait for the "([^"]*)" element to disappear$/, function (element, sync) { - const self = this; - let maxRepeats = 10; - - const interval = setInterval(() => { - console.log('Waiting for element to disappear...'); - - return self.currentPage.isPresent(element).then(isPresent => { - if (!isPresent) { - clearInterval(interval); - sync(); - return; - } - - maxRepeats--; - - if (maxRepeats === 0) { - clearInterval(interval); - sync('Element is still visible'); - } - }); - }, 1500); - }); - - Then(/^the "([^"]*)" element is present$/, function (elementName) { - _chalk2.default.red('DEPRECATED: the "([^"]*)" element is present , use I wait for "([^"]*)" of the "([^"]*)" element instead.'); - return expect(this.currentPage.isPresent(elementName)).to.eventually.be.true; - }); - - Then(/^the "([^"]*)" element is not present$/, function (elementName) { - _chalk2.default.red('DEPRECATED: the "([^"]*)" element is not present , use I wait for the "([^"]*)" element to disappear instead.'); - return expect(this.currentPage.isPresent(elementName)).to.eventually.be.false; - }); - - Then(/^the "([^"]*)" element is visible$/, function (elementName) { - return this.currentPage.isVisible(elementName); - }); - - Then(/^the "([^"]*)" element is not visible$/, function (elementName) { - return this.currentPage.isVisible(elementName).then(isVisible => Promise.reject(isVisible)).catch(isVisible => { - if (isVisible === true) { - return Promise.reject(`Element '${elementName}' should not be visible.`); - } - - return Promise.resolve(); - }); - }); - - Then(/^the "([^"]*)" element is disabled$/, function (elementName) { - return expect(this.currentPage.isDisabled(elementName)).to.eventually.be.true; - }); - - When(/^I store table "([^"]*)" rows as "([^"]*)" with columns:$/, function (table, variableName, data) { - const self = this; - const columns = data.raw().map(element => element[0]); - const promises = []; - return this.currentPage.waitForVisibilityOf(table).then(() => { - return this.currentPage[table].each(function (element) { - const rowPromises = []; - - for (const columnIndex in columns) { - if (columns.hasOwnProperty(columnIndex)) { - rowPromises.push(element.element(self.currentPage[columns[columnIndex]].locator()).getText()); - } - } - - promises.push(Promise.all(rowPromises)); - }).then(function () { - return Promise.all(promises).then(function (resolvedPromises) { - _variableStore2.default.storeVariable(variableName, resolvedPromises); - }); - }); - }); - }); - - Then(/^there are following elements in table "([^"]*)":$/, function (table, data) { - const self = this; - const allElements = this.currentPage[table]; - const hashes = data.hashes(); - return this.currentPage.waitForVisibilityOf(table).then(() => { - return checkNumberOfElements.call(this, `equal ${hashes.length}`, table).then(function () { - const promises = []; - - return allElements.each(function (element, index) { - const hash = hashes[index]; - - for (const prop in hash) { - if (hash.hasOwnProperty(prop)) { - const propValue = hash[prop]; - - promises.push(_matchers.matchers.match(element.element(self.currentPage[prop].locator()), _variableStore2.default.replaceTextVariables(propValue))); - } - } - }).then(function () { - return Promise.all(promises); - }); - }); - }); - }); - - Then(/^there are "([^"]*)" following elements for element "([^"]*)":$/, function (numberExpression, elementName, data) { - const self = this; - const allElements = this.currentPage[elementName]; - const hashedData = data.raw(); - - if (hashedData.length === 0) { - return Promise.reject('Missing table under the step.'); - } - - return this.currentPage.waitForVisibilityOf(elementName).then(() => { - return checkNumberOfElements.call(this, numberExpression, elementName).then(function () { - const promises = []; - - return allElements.each(function (element) { - hashedData.forEach(function (hash) { - promises.push(_matchers.matchers.match(element.element(self.currentPage[hash[0]].locator()), _variableStore2.default.replaceTextVariables(hash[1]))); - }); - }).then(function () { - return Promise.all(promises); - }); - }); - }); - }); - - Then(/^there is element "([^"]*)" with value "([^"]*)"$/, function (elementName, value) { - const pageElement = this.currentPage[elementName]; - - return this.currentPage.waitForVisibilityOf(elementName).then(() => { - return _matchers.matchers.match(pageElement, _variableStore2.default.replaceTextVariables(value)).then(function (matcherResult) { - return expect(matcherResult).to.be.true; - }); - }); - }); - - Then(/^there is no element "([^"]*)" with value "([^"]*)"$/, function (elementName, value) { - const pageElement = this.currentPage[elementName]; - - return _matchers.matchers.match(pageElement, _variableStore2.default.replaceTextVariables(value)).catch(() => Promise.resolve(false)).then(result => result ? Promise.reject() : Promise.resolve()); - }); - - Then(/^there is element "([^"]*)" containing "([^"]*)" text$/, function (elementName, value) { - const pageElement = this.currentPage[elementName]; - - return this.currentPage.waitForVisibilityOf(elementName).then(() => { - return _matchers.matchers.match(pageElement, _variableStore2.default.replaceTextVariables(`t:${value}`)); - }); - }); - - Then(/^there is no element "([^"]*)" containing "([^"]*)" text$/, function (elementName, value) { - const pageElement = this.currentPage[elementName]; - - return _matchers.matchers.match(pageElement, _variableStore2.default.replaceTextVariables(`t:${value}`)).catch(() => Promise.resolve(false)).then(result => result ? Promise.reject() : Promise.resolve()); - }); - - Then(/^there is element "([^"]*)" matching "([^"]*)" matcher$/, function (elementName, matcher) { - const pageElement = this.currentPage[elementName]; - - return this.currentPage.waitForVisibilityOf(elementName).then(() => { - return _matchers.matchers.match(pageElement, _variableStore2.default.replaceTextVariables(`f:${matcher}`)).then(function (matcherResult) { - return expect(matcherResult).to.be.true; - }); - }); - }); - - Then(/^there is no element "([^"]*)" matching "([^"]*)" matcher$/, function (elementName, matcher) { - const pageElement = this.currentPage[elementName]; - - return this.currentPage.waitForVisibilityOf(elementName).then(() => { - return _matchers.matchers.match(pageElement, _variableStore2.default.replaceTextVariables(`f:${matcher}`)).catch(() => Promise.resolve(false)).then(result => result ? Promise.reject() : Promise.resolve()); - }); - }); - - Then(/^there is element "([^"]*)" with "([^"]*)" regex$/, function (elementName, matcher) { - const pageElement = this.currentPage[elementName]; - - return this.currentPage.waitForVisibilityOf(elementName).then(() => { - return _matchers.matchers.match(pageElement, _variableStore2.default.replaceTextVariables(`r:${matcher}`)).then(function (matcherResult) { - return expect(matcherResult).to.be.true; - }); - }); - }); - - Then(/^there is no element "([^"]*)" with "([^"]*)" regex$/, function (elementName, matcher) { - const pageElement = this.currentPage[elementName]; - - return this.currentPage.waitForVisibilityOf(elementName).then(() => { - return _matchers.matchers.match(pageElement, _variableStore2.default.replaceTextVariables(`r:${matcher}`)).catch(() => Promise.resolve(false)).then(result => result ? Promise.reject() : Promise.resolve()); - }); - }); - - Then(/^there are "([^"]*)" "([^"]*)" elements$/, checkNumberOfElements); - - Then(/^every "([^"]*)" element should have the same value for element "([^"]*)"$/, function (containerName, elementName) { - const self = this; - return this.currentPage.waitForVisibilityOf(containerName).then(() => { - return this.currentPage[containerName].first().element(self.currentPage[elementName].locator()).getText().then(function (firstElementText) { - return self.currentPage[containerName].each(function (containerElement) { - containerElement.element(self.currentPage[elementName].locator()).getText().then(function (elementText) { - expect(elementText).to.be.equal(firstElementText); - }); - }); - }); - }); - }); - - Then(/^the element "([^"]*)" should have an item with values:$/, function (elementName, data) { - const self = this; - const allElements = this.currentPage[elementName]; - const hashedData = data.raw(); - - if (hashedData.length === 0) { - return Promise.reject('Missing table under the step.'); - } - - const promises = []; - return this.currentPage.waitForVisibilityOf(elementName).then(() => { - return allElements.each(function (element) { - hashedData.forEach(function (hash) { - promises.push(_matchers.matchers.match(element.element(self.currentPage[hash[0]].locator()), _variableStore2.default.replaceTextVariables(hash[1])).catch(() => false)); - }); - }); - }).then(function () { - return Promise.all(promises).then(handlePromises(hashedData, () => Promise.resolve(), () => Promise.reject('No matching element has been found.'))); - }); - }); - - Then(/^the element "([^"]*)" should not have an item with values:$/, function (elementName, data) { - const self = this; - const allElements = this.currentPage[elementName]; - const hashedData = data.raw(); - - if (hashedData.length === 0) { - return Promise.reject('Missing table under the step.'); - } - - const promises = []; - - return allElements.each(function (element) { - hashedData.forEach(function (hash) { - promises.push(_matchers.matchers.match(element.element(self.currentPage[hash[0]].locator()), _variableStore2.default.replaceTextVariables(hash[1])).catch(() => false)); - }); - }).then(function () { - return Promise.all(promises).then(handlePromises(hashedData, () => Promise.reject('Matching element has been found'), () => Promise.resolve())); - }); - }); - - Then(/^"([^"]*)" value on the "([^"]*)" list is sorted in "([^"]*)" order$/, function (elementValue, elementList, dependency) { - const self = this; - const promise = []; - - return this.currentPage.waitForVisibilityOf(elementList).then(() => { - return self.currentPage[elementList].each(function (singleElement) { - promise.push(singleElement.element(self.currentPage[elementValue].locator()).getText()); - }).then(function () { - return Promise.all(promise); - }).then(function (elementsValues) { - return _comparators.comparators.compare(elementsValues, dependency); - }); - }); - }); - - When(/^I infinitely scroll to the "([^"]*)" element$/, function (elementName) { - const self = this; - - const scrollToLoader = () => { - return self.currentPage.isPresent(elementName).then(isPresent => { - if (isPresent) { - return self.currentPage.scrollIntoElement(elementName); - } - - return Promise.resolve(); - }).then(() => self.currentPage.isPresent(elementName)).then(isPresent => { - if (isPresent) { - return browser.sleep(1000).then(() => scrollToLoader()); - } - - return Promise.resolve(); - }); - }; - - return scrollToLoader(); - }); - - When(/^I press the "([^"]*)" key$/, function (key) { - const keyTransformed = key.toUpperCase(); - - return Promise.resolve(browser.actions().sendKeys(protractor.Key[keyTransformed]).perform()); - }); - - When(/^I drag "([^"]*)" element and drop over "([^"]*)" element$/, (() => { - var _ref2 = _asyncToGenerator(function* (elementDrag, elementDrop) { - const wait = function (timeToWait) { - return browser.sleep(timeToWait); - }; - - yield this.currentPage.waitForVisibilityOf(elementDrag); - yield browser.actions().mouseMove(this.currentPage[elementDrag]).perform(); - yield wait(200); - yield browser.actions().mouseDown().perform(); - yield wait(200); - yield browser.actions().mouseMove(this.currentPage[elementDrop]).perform(); - yield wait(200); - yield browser.actions().mouseUp().perform(); - }); - - return function (_x, _x2) { - return _ref2.apply(this, arguments); - }; - })()); -}); \ No newline at end of file diff --git a/dist/step_definitions/email.js b/dist/step_definitions/email.js deleted file mode 100644 index 88175595..00000000 --- a/dist/step_definitions/email.js +++ /dev/null @@ -1,144 +0,0 @@ -'use strict'; - -var _cucumber = require('cucumber'); - -var _sugarDate = require('sugar-date'); - -var _sugarDate2 = _interopRequireDefault(_sugarDate); - -var _filters = require('../emails/filters'); - -var _matchers = require('../matchers'); - -var _config = require('../core/config.helper'); - -var _config2 = _interopRequireDefault(_config); - -var _emails = require('../emails'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -(0, _cucumber.defineSupportCode)(function ({ Then }) { - function stopInterval(interval, callback) { - clearInterval(interval); - callback(); - } - - function checkAttachmentsInEmail(email, filesExtensions, attachments) { - let fileAttachments = attachments.filter(attachment => attachment.attachment_type === 'attachment'); - - const missingFiles = filesExtensions.reduce((previous, current) => { - const expectedFile = fileAttachments.find(attachment => { - return _matchers.regexBuilder.buildRegex(current.name).test(attachment.filename) && _matchers.regexBuilder.buildRegex(current.type).test(attachment.content_type) && attachment.attachment_size >= current.minimalSize; - }); - - if (typeof expectedFile === 'undefined') { - previous.push(current); - return previous; - } - - fileAttachments = fileAttachments.filter(attachment => attachment.id !== expectedFile.id); - - return previous; - }, []); - - if (missingFiles.length === 0) { - return _emails.emailService.markAsRead(email); - } - - return Promise.reject('Some attachments not found: ' + missingFiles.map(file => file.name).join(', ')); - } - - function filterEmails(emails, data) { - let originalEmails = emails; - const checks = data.raw().filter(elem => elem[0] !== 'file'); - - for (let i = 0; i < checks.length; i++) { - const checkType = checks[i][0]; - const checkValue = checks[i][1]; - - originalEmails = _filters.filters.filter(originalEmails, checkType, checkValue, this); - } - - return originalEmails; - } - - function getFilesExtensions(data) { - return data.raw().filter(elem => elem[0] === 'file').map(elem => { - return { name: elem[1], type: elem[2], minimalSize: elem[3] }; - }); - } - - function rejectIfMaxRepeatsReached(filteredEmails, maxRepeats) { - if (filteredEmails.length === 0 && maxRepeats === 0) { - return Promise.reject('No emails found and maximum repeats reached'); - } - - return filteredEmails; - } - - function rejectIfMoreThanOneEmailFound(filteredEmails) { - if (filteredEmails.length > 1) { - return Promise.reject('More than one email found'); - } - - return filteredEmails; - } - - function rejectIfEmailFound(filteredEmails) { - if (filteredEmails.length > 0) { - return Promise.reject('Email has been found!'); - } - - return filteredEmails; - } - - function validateEmailDate(filteredEmails) { - if (filteredEmails.length === 1) { - if (_sugarDate2.default.Date.minutesFromNow(_sugarDate2.default.Date.create(filteredEmails[0].created_at)) < -10) { - return Promise.reject('Email was sent more than 10 minutes ago. This is probably not what you are looking for.'); - } - } - - return filteredEmails; - } - - function validateEmailContentAndAttachments(filteredEmails, data, interval, sync) { - if (filteredEmails.length === 1) { - const filesExtensions = getFilesExtensions(data); - - if (filesExtensions.length > 0) { - return _emails.emailService.getAttachments(filteredEmails[0]).then(checkAttachmentsInEmail.bind(null, filteredEmails[0], filesExtensions)).then(stopInterval.bind(null, interval, sync)); - } - return _emails.emailService.markAsRead(filteredEmails[0]).then(stopInterval.bind(null, interval, sync)); - } - } - - Then(/^the email has been sent and contains:$/, function (data, sync) { - const self = this; - const timeout = parseInt(_config2.default.intervalEmail) * 1000; - let maxRepeats = parseInt(_config2.default.maxEmailRepeats); - - _config2.default.maxEmailRepeats === undefined ? maxRepeats = 5 : maxRepeats; - - const interval = setInterval(() => { - console.log('Checking mailbox for email...'); - - _emails.emailService.getEmails().then(emails => filterEmails.call(self, emails, data)).then(filteredEmails => rejectIfMaxRepeatsReached(filteredEmails, maxRepeats)).then(filteredEmails => rejectIfMoreThanOneEmailFound(filteredEmails)).then(filteredEmails => validateEmailDate(filteredEmails)).then(filteredEmails => validateEmailContentAndAttachments(filteredEmails, data, interval, sync)).then(() => maxRepeats--).catch(err => stopInterval(interval, sync.bind(null, err))); - }, timeout); - }); - - Then(/^the email with the following data has not been sent:$/, function (data, sync) { - const self = this; - const timeout = parseInt(_config2.default.intervalEmail) * 1000; - let maxRepeats = 5; - - const interval = setInterval(() => { - console.log('Checking mailbox for email...'); - - _emails.emailService.getEmails().then(emails => filterEmails.call(self, emails, data)).then(filteredEmails => rejectIfEmailFound(filteredEmails)).then(filteredEmails => rejectIfMaxRepeatsReached(filteredEmails, maxRepeats)).then(() => maxRepeats--).catch(err => { - err === 'No emails found and maximum repeats reached' ? stopInterval(interval, sync) : stopInterval(interval, sync.bind(null, err)); - }); - }, timeout); - }); -}); \ No newline at end of file diff --git a/dist/step_definitions/file.js b/dist/step_definitions/file.js deleted file mode 100644 index 787ce27e..00000000 --- a/dist/step_definitions/file.js +++ /dev/null @@ -1,82 +0,0 @@ -'use strict'; - -var _cucumber = require('cucumber'); - -var _fileManager = require('../web/fs/file-manager.helper'); - -var _fileManager2 = _interopRequireDefault(_fileManager); - -var _variableStore = require('../web/variable-store.helper'); - -var _variableStore2 = _interopRequireDefault(_variableStore); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -(0, _cucumber.defineSupportCode)(function ({ Then }) { - Then(/^the file "([^"]*)" should be downloaded$/, function (filename) { - return _fileManager2.default.wasDownloaded(_variableStore2.default.replaceTextVariables(filename)); - }); - - Then(/^the file "([^"]*)" contains table data stored under "([^"]*)" variable$/, function (filename, variableName) { - const file = _fileManager2.default.parseXLS(_variableStore2.default.replaceTextVariables(filename)); - const storedData = _variableStore2.default.getVariableValue(variableName); - const rows = file.filter((row, index) => row.length > 0 && index > 0); - - const findIndexes = () => { - const allFoundIndexesInRows = []; - - storedData.forEach(storedItems => { - const foundIndexesInRow = []; - let previousFoundIndex = null; - - storedItems.forEach(storedValue => { - for (const index in rows) { - if (storedValue.match(/^\d+$/)) { - if (previousFoundIndex !== null) { - foundIndexesInRow.push(rows[previousFoundIndex].indexOf(parseInt(storedValue))); - break; - } - - if (rows[index].includes(parseInt(storedValue))) { - previousFoundIndex = index; - foundIndexesInRow.push(rows[index].indexOf(parseInt(storedValue))); - break; - } - } - - if (previousFoundIndex !== null) { - foundIndexesInRow.push(rows[previousFoundIndex].indexOf(storedValue)); - break; - } - - if (rows[index].includes(storedValue)) { - previousFoundIndex = index; - foundIndexesInRow.push(rows[index].indexOf(storedValue)); - break; - } - } - }); - - allFoundIndexesInRows.push(foundIndexesInRow); - }); - - return Promise.resolve(allFoundIndexesInRows); - }; - - return findIndexes().then(allFoundIndexes => { - if (allFoundIndexes[0].length !== storedData[0].length) { - return Promise.reject('Values not found!'); - } - - if (allFoundIndexes.length === 1) { - return Promise.resolve(); - } - - for (let index = 1; index < allFoundIndexes.length; index++) { - if (JSON.stringify(allFoundIndexes[index]) !== JSON.stringify(allFoundIndexes[index - 1])) { - return Promise.reject('Arrays are different!'); - } - } - }); - }); -}); \ No newline at end of file diff --git a/dist/step_definitions/form.js b/dist/step_definitions/form.js deleted file mode 100644 index 42a4baf7..00000000 --- a/dist/step_definitions/form.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict'; - -var _cucumber = require('cucumber'); - -var _dictionaries = require('../dictionaries'); - -(0, _cucumber.defineSupportCode)(function ({ When, Then }) { - When(/^I fill the "([^"]*)" form with:$/, function (formName, data) { - const self = this; - - return this.currentPage.waitForVisibilityOf(formName).then(function () { - return expect(self.currentPage.isVisible(formName)).to.eventually.be.fulfilled.then(function () { - return self.currentPage.fillForm(data.raw()); - }); - }); - }); - - Then(/^the "([^"]*)" form is filled with:$/, function (formName, data) { - const self = this; - - return this.currentPage.waitForVisibilityOf(formName).then(function () { - return expect(self.currentPage.isVisible(formName)).to.eventually.be.fulfilled.then(function () { - return self.currentPage.checkForm(data.raw()); - }); - }); - }); - - Then(/^the error messages should be displayed:$/, function (data) { - const self = this; - const table = data.rows(); - - const promise = []; - - table.forEach(function (item) { - promise.push(expect(self.currentPage.isVisible(item[0])).to.eventually.be.fulfilled.then(function () { - return self.currentPage[item[0]].getText().then(function (text) { - if (text.indexOf(_dictionaries.dictionaries.findMappedValueByPhrase(item[1])) >= 0) { - return Promise.resolve(); - } - - return Promise.reject(`Error "${_dictionaries.dictionaries.findMappedValueByPhrase(item[1])}" for element "${item[0]}" was not found.`); - }); - })); - }); - - return Promise.all(promise); - }); -}); \ No newline at end of file diff --git a/dist/step_definitions/generators.js b/dist/step_definitions/generators.js deleted file mode 100644 index 883523e5..00000000 --- a/dist/step_definitions/generators.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; - -var _cucumber = require('cucumber'); - -var _variableStore = require('../web/variable-store.helper'); - -var _variableStore2 = _interopRequireDefault(_variableStore); - -var _transformers = require('../transformers'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -(0, _cucumber.defineSupportCode)(function ({ When }) { - When(/^I generate random "([^"]*)" as "([^"]*)"$/, function (generator, variableName) { - return _transformers.transformers.transform(`g:${generator}`).then(result => _variableStore2.default.storeVariable(variableName, result)); - }); -}); \ No newline at end of file diff --git a/dist/step_definitions/navigation.js b/dist/step_definitions/navigation.js deleted file mode 100644 index e6529d2a..00000000 --- a/dist/step_definitions/navigation.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict'; - -var _cucumber = require('cucumber'); - -(0, _cucumber.defineSupportCode)(function ({ Then, Given }) { - Given(/^I visit the "([^"]*)" page$/, function (pageName) { - expect(browser.page[pageName]).to.not.be.undefined; - - this.currentPage = browser.page[pageName]; - - return this.currentPage.visit(); - }); - - Given(/^I visit the "([^"]*)" page with parameters:$/, function (pageName, data) { - expect(browser.page[pageName]).to.not.be.undefined; - - this.currentPage = browser.page[pageName]; - - return this.currentPage.visitWithParameters(data); - }); - - Then(/^the "([^"]*)" page is displayed$/, function (pageName) { - const self = this; - - return browser.page[pageName].isOn().then(checkResult => { - if (typeof checkResult !== 'object') { - return Promise.reject('Check result must be an object!!!'); - } - - self.currentPage = browser.page[pageName]; - self.urlParameters = checkResult.parameters; - }); - }); -}); \ No newline at end of file diff --git a/dist/step_definitions/performance.js b/dist/step_definitions/performance.js deleted file mode 100644 index 35e30857..00000000 --- a/dist/step_definitions/performance.js +++ /dev/null @@ -1,83 +0,0 @@ -'use strict'; - -var _cucumber = require('cucumber'); - -var _chalk = require('chalk'); - -var _chalk2 = _interopRequireDefault(_chalk); - -var _config = require('../core/config.helper'); - -var _config2 = _interopRequireDefault(_config); - -var _timeToFirstByteAnalyser = require('../web/performance/time-to-first-byte-analyser.helper'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const analyser = (0, _timeToFirstByteAnalyser.create)(); -const Browsermob = require('browsermob-proxy').Proxy; -const fs = require('fs'); -let proxy; - -(0, _cucumber.defineSupportCode)(function ({ When, Then }) { - When(/^I start performance monitor mode$/, function () { - proxy = new Browsermob({ - port: _config2.default.browserMob.serverPort - }); - - let proxyReady = false; - proxy.start(_config2.default.browserMob.port, err => { - if (!err) { - proxy.startHAR(_config2.default.browserMob.port, 'test', true, true, () => { - proxyReady = true; - }); - } else { - console.error(err); - } - }); - - browser.driver.wait(() => { - return proxyReady; - }); - }); - - When(/^I save performance report file as "([^"]*)"$/, function (fileName) { - const uniqueFileName = `${fileName}-${Date.now()}.har`; - let proxyDone = false; - - proxy.getHAR(_config2.default.browserMob.port, (err, resp) => { - if (!err) { - console.log(`har saved at ${uniqueFileName}`); - fs.writeFileSync(`reports/performance/${uniqueFileName}`, resp, 'utf8'); - } else { - console.err('Error getting HAR file: ' + err); - } - proxy.stop(_config2.default.browserMob.port, () => { - proxyDone = true; - }); - }); - - return browser.driver.wait(() => { - this.performanceReportFile = uniqueFileName; - return proxyDone; - }); - }); - - Then(/^the requests should take a maximum of "([^"]*)" milliseconds$/, function (maxTiming) { - try { - const slowRequests = analyser.checkTiming(this.performanceReportFile, parseFloat(maxTiming)); - - if (slowRequests.length > 0) { - slowRequests.forEach(({ url, ttfb }) => { - console.log(_chalk2.default.white.bgRed('\r\n', 'Slow request:', '\r\n', `URL: ${url}`, '\r\n', `TTFB: ${ttfb.toFixed(2)} ms`, '\r\n')); - }); - - return Promise.reject('TTFB value is too big! Details available above.'); - } - - return Promise.resolve(); - } catch (err) { - return Promise.reject(err); - } - }); -}); \ No newline at end of file diff --git a/dist/step_definitions/tabs.js b/dist/step_definitions/tabs.js deleted file mode 100644 index dc27a72d..00000000 --- a/dist/step_definitions/tabs.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -const { defineSupportCode } = require('cucumber'); - -defineSupportCode(({ When }) => { - When(/^I switch to window number "([^"]*)" of a browser$/, function (tabNumber) { - return browser.getAllWindowHandles().then(handles => browser.switchTo().window(handles[tabNumber - 1])); - }); - - When(/^I close the current browser tab$/, function () { - return browser.close().then(() => browser.getAllWindowHandles()).then(tabs => browser.switchTo().window(tabs[0])); - }); -}); \ No newline at end of file diff --git a/dist/templates/example.feature b/dist/templates/example.feature deleted file mode 100644 index 6c400206..00000000 --- a/dist/templates/example.feature +++ /dev/null @@ -1,6 +0,0 @@ -Feature: - Scenario: - When I visit the "page" page - And I generate random "name" as "myName" - Then my matcher "e:name" matches "v:myName" - And my matcher "e:name" matches "Bob" diff --git a/dist/templates/generator.js b/dist/templates/generator.js deleted file mode 100644 index 8cd4b3e8..00000000 --- a/dist/templates/generator.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; - -const { generators } = require('kakunin'); - -class Generator { - isSatisfiedBy(name) { - return name === 'name'; - } - - generate() { - const names = ['Bob', 'John', 'Paul']; - - return Promise.resolve(names[Math.floor(Math.random() * names.length)]); - } -} - -generators.addGenerator(new Generator()); \ No newline at end of file diff --git a/dist/templates/hook.js b/dist/templates/hook.js deleted file mode 100644 index 07f26a9f..00000000 --- a/dist/templates/hook.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; - -const { defineSupportCode } = require('kakunin'); - -defineSupportCode(({ Before }) => { - Before(function () { - console.log('If you can see this in console then hook is working properly.'); - }); -}); \ No newline at end of file diff --git a/dist/templates/login.js b/dist/templates/login.js deleted file mode 100644 index 62108a50..00000000 --- a/dist/templates/login.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; - -const { defineSupportCode } = require('kakunin'); - -defineSupportCode(({ Given }) => { - Given(/^I am logged in as a "([^"]*)$/, function (user) { - this.currentUser = { - account: this.userProvider.getUser(user), - type: user - }; - - const mainPage = browser.page.main; - const loginPage = browser.page.login; - const self = this; - - return mainPage.visit().then(function () { - return mainPage.isVisible('login'); - }).then(function () { - return mainPage.click('login'); - }).then(function () { - return loginPage.login(self.currentUser.account.email, self.currentUser.account.password); - }).then(function () { - return expect(mainPage.isPresent('login')).not.to.eventually.be.ok; - }).then(function () { - self.currentPage = mainPage; - return Promise.resolve(); - }); - }); -}); \ No newline at end of file diff --git a/dist/templates/matcher.js b/dist/templates/matcher.js deleted file mode 100644 index c796dd44..00000000 --- a/dist/templates/matcher.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; - -const { regexBuilder, matchers } = require('kakunin'); - -const ExampleMatcher = { - isSatisfiedBy: function (prefix, name) { - return prefix === 'e'; - }, - - match: function (element, regexName) { - const regex = regexBuilder.buildRegex(`r:${regexName}`); - - return regex.test(element); - } -}; - -matchers.addMatcher(ExampleMatcher); \ No newline at end of file diff --git a/dist/templates/page.js b/dist/templates/page.js deleted file mode 100644 index bfb46376..00000000 --- a/dist/templates/page.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -const { BasePage } = require('kakunin'); - -class ExamplePage extends BasePage { - constructor() { - super(); - - this.url = '/'; - } -} - -module.exports = ExamplePage; \ No newline at end of file diff --git a/dist/templates/regex.js b/dist/templates/regex.js deleted file mode 100644 index 57fd15e8..00000000 --- a/dist/templates/regex.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -module.exports = { - name: '(Bob|John|Paul)' -}; \ No newline at end of file diff --git a/dist/templates/steps.js b/dist/templates/steps.js deleted file mode 100644 index 0d291c67..00000000 --- a/dist/templates/steps.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; - -const { matchers, variableStore, defineSupportCode } = require('kakunin'); - -defineSupportCode(({ Then }) => { - Then(/^my matcher "([^"]*)" matches "([^"]*)"$/, function (matcher, text) { - return expect(matchers.match(variableStore.replaceTextVariables(text), matcher)).to.be.true; - }); -}); \ No newline at end of file diff --git a/dist/transformers/index.js b/dist/transformers/index.js deleted file mode 100644 index 13df74e3..00000000 --- a/dist/transformers/index.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.transformers = undefined; - -var _transformers = require('./transformers'); - -const transformers = exports.transformers = (0, _transformers.create)(); \ No newline at end of file diff --git a/dist/transformers/interfaces/transformer.interface.js b/dist/transformers/interfaces/transformer.interface.js deleted file mode 100644 index e69de29b..00000000 diff --git a/dist/transformers/transformer/dictionary.transformer.js b/dist/transformers/transformer/dictionary.transformer.js deleted file mode 100644 index c17ab646..00000000 --- a/dist/transformers/transformer/dictionary.transformer.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.createDictionaryTransformer = undefined; - -var _dictionaries = require('../../dictionaries'); - -class DictionaryTransformer { - constructor(dictionaries) { - this.dictionaries = dictionaries; - } - - isSatisfiedBy(prefix) { - return prefix === 'd:'; - } - - transform(value) { - const splittedValue = value.split(':'); - return this.dictionaries.getMappedValue(splittedValue[0], splittedValue[1]); - } -} -const createDictionaryTransformer = exports.createDictionaryTransformer = (dictionaries = _dictionaries.dictionaries) => new DictionaryTransformer(dictionaries); \ No newline at end of file diff --git a/dist/transformers/transformer/generator.transformer.js b/dist/transformers/transformer/generator.transformer.js deleted file mode 100644 index d21358ad..00000000 --- a/dist/transformers/transformer/generator.transformer.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.createGeneratorTransformer = undefined; - -var _generators = require('../../generators'); - -class GeneratorTransformer { - constructor(generator) { - this.generator = generator; - } - - isSatisfiedBy(prefix) { - return prefix === 'g:'; - } - - transform(value) { - const splittedValues = value.split(':'); - const generatorName = splittedValues[0]; - - return this.generator.generate(generatorName, splittedValues.slice(1)); - } -} -const createGeneratorTransformer = exports.createGeneratorTransformer = (geners = _generators.generators) => new GeneratorTransformer(geners); \ No newline at end of file diff --git a/dist/transformers/transformer/variable-store.transformer.js b/dist/transformers/transformer/variable-store.transformer.js deleted file mode 100644 index c792fd78..00000000 --- a/dist/transformers/transformer/variable-store.transformer.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.createVariableStoreTransformer = undefined; - -var _variableStore = require('../../web/variable-store.helper'); - -var _variableStore2 = _interopRequireDefault(_variableStore); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class VariableStoreTransformer { - constructor(variableStore) { - this.variableStore = variableStore; - } - - isSatisfiedBy(prefix) { - return prefix === 'v:'; - } - - transform(value) { - return this.variableStore.getVariableValue(value); - } -} -const createVariableStoreTransformer = exports.createVariableStoreTransformer = (variableStore = _variableStore2.default) => new VariableStoreTransformer(variableStore); \ No newline at end of file diff --git a/dist/transformers/transformers.js b/dist/transformers/transformers.js deleted file mode 100644 index a66b4585..00000000 --- a/dist/transformers/transformers.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.create = undefined; - -var _variableStore = require('./transformer/variable-store.transformer'); - -var _dictionary = require('./transformer/dictionary.transformer'); - -var _generator = require('./transformer/generator.transformer'); - -class Transformers { - constructor(transformers) { - this.availableTransformers = transformers; - } - - transform(value) { - const transformer = this.findTransformer(value.substr(0, 2)); - - if (transformer === undefined) { - return value; - } - - return transformer.transform(value.substr(2)); - } - - findTransformer(prefix) { - return this.availableTransformers.find(transformer => transformer.isSatisfiedBy(prefix)); - } - - addTransformer(transformer) { - this.availableTransformers.push(transformer); - } -} - -const transformers = [(0, _variableStore.createVariableStoreTransformer)(), (0, _dictionary.createDictionaryTransformer)(), (0, _generator.createGeneratorTransformer)()]; - -const create = exports.create = (transf = transformers) => new Transformers(transf); \ No newline at end of file diff --git a/dist/web/browsers/browsers-config.helper.js b/dist/web/browsers/browsers-config.helper.js deleted file mode 100644 index 0f2f1225..00000000 --- a/dist/web/browsers/browsers-config.helper.js +++ /dev/null @@ -1,122 +0,0 @@ -'use strict'; - -var _glob = require('glob'); - -var _glob2 = _interopRequireDefault(_glob); - -var _path = require('path'); - -var _path2 = _interopRequireDefault(_path); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } - -const { createFirefoxProfile } = require('./create-firefox-profile.helper'); -const { safariBrowserConfigurator } = require('./safari-browser-configurator.helper'); -const { prepareBrowserInstance } = require('../parallel/prepare-browser-instance-specs.helper'); -const { chunkSpecs } = require('../parallel/chunk-specs.helper'); - -const getDefaultBrowsersConfigs = config => { - const chromeConfig = { - browserName: 'chrome', - chromeOptions: { - args: [], - prefs: { - credentials_enable_service: false, - profile: { - password_manager_enabled: false - }, - download: { - prompt_for_download: false, - default_directory: config.projectPath + config.downloads, - directory_upgrade: true - } - } - } - }; - - const firefoxConfig = { - browserName: 'firefox', - marionette: true, - 'moz:firefoxOptions': { - args: [] - } - }; - - const safariConfig = { - browserName: 'safari' - }; - - return { - chromeConfig, - firefoxConfig, - safariConfig - }; -}; - -const getExtendedBrowsersConfigs = config => { - const configs = getDefaultBrowsersConfigs(config); - - if (config.performance) { - configs.chromeConfig.proxy = { - proxyType: 'manual', - httpProxy: `${config.browserMob.host}:${config.browserMob.port}`, - sslProxy: `${config.browserMob.host}:${config.browserMob.port}` - }; - } - - if (config.noGpu) { - configs.chromeConfig.chromeOptions.args = [...configs.chromeConfig.chromeOptions.args, '--disable-gpu', '--disable-impl-side-painting', '--disable-gpu-sandbox', '--disable-accelerated-2d-canvas', '--disable-accelerated-jpeg-decoding', '--no-sandbox']; - } - - if (config.headless) { - configs.chromeConfig.chromeOptions.args = [...configs.chromeConfig.chromeOptions.args, '--headless', `--window-size=${config.browserWidth}x${config.browserHeight}`]; - - configs.firefoxConfig['moz:firefoxOptions'].args = [...configs.firefoxConfig['moz:firefoxOptions'].args, '-headless', `--window-size=${config.browserWidth}x${config.browserHeight}`]; - } - - return configs; -}; - -const browsersConfiguration = (config, commandArgs) => { - return _asyncToGenerator(function* () { - const browsersSettings = []; - const browserConfigs = getExtendedBrowsersConfigs(config, commandArgs); - const allSpecs = _glob2.default.sync(config.features.map(function (file) { - return _path2.default.join(config.projectPath, file, '**/*.feature'); - })[0]); - const isParallel = commandArgs.parallel !== undefined && Number.isInteger(commandArgs.parallel) && commandArgs.parallel !== 0; - const numberOfInstances = isParallel ? commandArgs.parallel >= allSpecs.length ? allSpecs.length : commandArgs.parallel : 1; - const expectedArrayLength = Math.ceil(allSpecs.length / numberOfInstances); - const chunkedSpecs = chunkSpecs(commandArgs, allSpecs, expectedArrayLength, numberOfInstances); - - if (allSpecs.length === 0) { - throw new Error('Could not find any files matching regex in the directory!'); - } - - const pushPreparedBrowserInstance = function (browserType) { - for (let i = 0; i < numberOfInstances; i++) { - browsersSettings.push(prepareBrowserInstance(browserConfigs[browserType], chunkedSpecs[i])); - } - }; - - if (commandArgs.firefox) { - browserConfigs.firefoxConfig.firefox_profile = yield createFirefoxProfile(config); - pushPreparedBrowserInstance('firefoxConfig'); - } - - if (commandArgs.safari) { - safariBrowserConfigurator(config); - pushPreparedBrowserInstance('safariConfig'); - } - - if (commandArgs.chrome || commandArgs.firefox === undefined && commandArgs.safari === undefined) { - pushPreparedBrowserInstance('chromeConfig'); - } - - return Promise.resolve(browsersSettings); - }); -}; - -module.exports = browsersConfiguration; \ No newline at end of file diff --git a/dist/web/browsers/create-firefox-profile.helper.js b/dist/web/browsers/create-firefox-profile.helper.js deleted file mode 100644 index 2f29f90e..00000000 --- a/dist/web/browsers/create-firefox-profile.helper.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.createFirefoxProfile = undefined; - -var _path = require('path'); - -var _path2 = _interopRequireDefault(_path); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const firefox = require('selenium-webdriver/firefox'); -const createFirefoxProfile = exports.createFirefoxProfile = config => { - const profile = new firefox.Profile(); - - profile.setPreference('browser.download.dir', _path2.default.join(config.projectPath, config.downloads)); - profile.setPreference('browser.download.folderList', 2); - profile.setPreference('browser.download.panel.shown', true); - profile.setPreference('browser.safebrowsing.downloads.enabled', false); - profile.setPreference('browser.helperApps.alwaysAsk.force', false); - profile.setPreference('browser.download.manager.showWhenStarting', false); - profile.setPreference('browser.download.manager.showAlertOnComplete', false); - /* eslint-disable max-len */ - profile.setPreference('browser.helperApps.neverAsk.saveToDisk', 'application/vnd.hzn-3d-crossword;video/3gpp;video/3gpp2;application/vnd.mseq;application/vnd.3m.post-it-notes;application/vnd.3gpp.pic-bw-large;application/vnd.3gpp.pic-bw-small;application/vnd.3gpp.pic-bw-var;application/vnd.3gp2.tcap;application/x-7z-compressed;application/x-abiword;application/x-ace-compressed;application/vnd.americandynamics.acc;application/vnd.acucobol;application/vnd.acucorp;audio/adpcm;application/x-authorware-bin;application/x-athorware-map;application/x-authorware-seg;application/vnd.adobe.air-application-installer-package+zip;application/x-shockwave-flash;application/vnd.adobe.fxp;application/pdf;application/vnd.cups-ppd;application/x-director;applicaion/vnd.adobe.xdp+xml;application/vnd.adobe.xfdf;audio/x-aac;application/vnd.ahead.space;application/vnd.airzip.filesecure.azf;application/vnd.airzip.filesecure.azs;application/vnd.amazon.ebook;application/vnd.amiga.ami;applicatin/andrew-inset;application/vnd.android.package-archive;application/vnd.anser-web-certificate-issue-initiation;application/vnd.anser-web-funds-transfer-initiation;application/vnd.antix.game-component;application/vnd.apple.installe+xml;application/applixware;application/vnd.hhe.lesson-player;application/vnd.aristanetworks.swi;text/x-asm;application/atomcat+xml;application/atomsvc+xml;application/atom+xml;application/pkix-attr-cert;audio/x-aiff;video/x-msvieo;application/vnd.audiograph;image/vnd.dxf;model/vnd.dwf;text/plain-bas;application/x-bcpio;application/octet-stream;image/bmp;application/x-bittorrent;application/vnd.rim.cod;application/vnd.blueice.multipass;application/vnd.bm;application/x-sh;image/prs.btif;application/vnd.businessobjects;application/x-bzip;application/x-bzip2;application/x-csh;text/x-c;application/vnd.chemdraw+xml;text/css;chemical/x-cdx;chemical/x-cml;chemical/x-csml;application/vn.contact.cmsg;application/vnd.claymore;application/vnd.clonk.c4group;image/vnd.dvb.subtitle;application/cdmi-capability;application/cdmi-container;application/cdmi-domain;application/cdmi-object;application/cdmi-queue;applicationvnd.cluetrust.cartomobile-config;application/vnd.cluetrust.cartomobile-config-pkg;image/x-cmu-raster;model/vnd.collada+xml;text/csv;application/mac-compactpro;application/vnd.wap.wmlc;image/cgm;x-conference/x-cooltalk;image/x-cmx;application/vnd.xara;application/vnd.cosmocaller;application/x-cpio;application/vnd.crick.clicker;application/vnd.crick.clicker.keyboard;application/vnd.crick.clicker.palette;application/vnd.crick.clicker.template;application/vn.crick.clicker.wordbank;application/vnd.criticaltools.wbs+xml;application/vnd.rig.cryptonote;chemical/x-cif;chemical/x-cmdf;application/cu-seeme;application/prs.cww;text/vnd.curl;text/vnd.curl.dcurl;text/vnd.curl.mcurl;text/vnd.crl.scurl;application/vnd.curl.car;application/vnd.curl.pcurl;application/vnd.yellowriver-custom-menu;application/dssc+der;application/dssc+xml;application/x-debian-package;audio/vnd.dece.audio;image/vnd.dece.graphic;video/vnd.dec.hd;video/vnd.dece.mobile;video/vnd.uvvu.mp4;video/vnd.dece.pd;video/vnd.dece.sd;video/vnd.dece.video;application/x-dvi;application/vnd.fdsn.seed;application/x-dtbook+xml;application/x-dtbresource+xml;application/vnd.dvb.ait;applcation/vnd.dvb.service;audio/vnd.digital-winds;image/vnd.djvu;application/xml-dtd;application/vnd.dolby.mlp;application/x-doom;application/vnd.dpgraph;audio/vnd.dra;application/vnd.dreamfactory;audio/vnd.dts;audio/vnd.dts.hd;imag/vnd.dwg;application/vnd.dynageo;application/ecmascript;application/vnd.ecowin.chart;image/vnd.fujixerox.edmics-mmr;image/vnd.fujixerox.edmics-rlc;application/exi;application/vnd.proteus.magazine;application/epub+zip;message/rfc82;application/vnd.enliven;application/vnd.is-xpr;image/vnd.xiff;application/vnd.xfdl;application/emma+xml;application/vnd.ezpix-album;application/vnd.ezpix-package;image/vnd.fst;video/vnd.fvt;image/vnd.fastbidsheet;application/vn.denovo.fcselayout-link;video/x-f4v;video/x-flv;image/vnd.fpx;image/vnd.net-fpx;text/vnd.fmi.flexstor;video/x-fli;application/vnd.fluxtime.clip;application/vnd.fdf;text/x-fortran;application/vnd.mif;application/vnd.framemaker;imae/x-freehand;application/vnd.fsc.weblaunch;application/vnd.frogans.fnc;application/vnd.frogans.ltf;application/vnd.fujixerox.ddd;application/vnd.fujixerox.docuworks;application/vnd.fujixerox.docuworks.binder;application/vnd.fujitu.oasys;application/vnd.fujitsu.oasys2;application/vnd.fujitsu.oasys3;application/vnd.fujitsu.oasysgp;application/vnd.fujitsu.oasysprs;application/x-futuresplash;application/vnd.fuzzysheet;image/g3fax;application/vnd.gmx;model/vn.gtw;application/vnd.genomatix.tuxedo;application/vnd.geogebra.file;application/vnd.geogebra.tool;model/vnd.gdl;application/vnd.geometry-explorer;application/vnd.geonext;application/vnd.geoplan;application/vnd.geospace;applicatio/x-font-ghostscript;application/x-font-bdf;application/x-gtar;application/x-texinfo;application/x-gnumeric;application/vnd.google-earth.kml+xml;application/vnd.google-earth.kmz;application/vnd.grafeq;image/gif;text/vnd.graphviz;aplication/vnd.groove-account;application/vnd.groove-help;application/vnd.groove-identity-message;application/vnd.groove-injector;application/vnd.groove-tool-message;application/vnd.groove-tool-template;application/vnd.groove-vcar;video/h261;video/h263;video/h264;application/vnd.hp-hpid;application/vnd.hp-hps;application/x-hdf;audio/vnd.rip;application/vnd.hbci;application/vnd.hp-jlyt;application/vnd.hp-pcl;application/vnd.hp-hpgl;application/vnd.yamaha.h-script;application/vnd.yamaha.hv-dic;application/vnd.yamaha.hv-voice;application/vnd.hydrostatix.sof-data;application/hyperstudio;application/vnd.hal+xml;text/html;application/vnd.ibm.rights-management;application/vnd.ibm.securecontainer;text/calendar;application/vnd.iccprofile;image/x-icon;application/vnd.igloader;image/ief;application/vnd.immervision-ivp;application/vnd.immervision-ivu;application/reginfo+xml;text/vnd.in3d.3dml;text/vnd.in3d.spot;mode/iges;application/vnd.intergeo;application/vnd.cinderella;application/vnd.intercon.formnet;application/vnd.isac.fcs;application/ipfix;application/pkix-cert;application/pkixcmp;application/pkix-crl;application/pkix-pkipath;applicaion/vnd.insors.igm;application/vnd.ipunplugged.rcprofile;application/vnd.irepository.package+xml;text/vnd.sun.j2me.app-descriptor;application/java-archive;application/java-vm;application/x-java-jnlp-file;application/java-serializd-object;text/x-java-source,java;application/javascript;application/json;application/vnd.joost.joda-archive;video/jpm;image/jpeg;video/jpeg;application/vnd.kahootz;application/vnd.chipnuts.karaoke-mmd;application/vnd.kde.karbon;aplication/vnd.kde.kchart;application/vnd.kde.kformula;application/vnd.kde.kivio;application/vnd.kde.kontour;application/vnd.kde.kpresenter;application/vnd.kde.kspread;application/vnd.kde.kword;application/vnd.kenameaapp;applicatin/vnd.kidspiration;application/vnd.kinar;application/vnd.kodak-descriptor;application/vnd.las.las+xml;application/x-latex;application/vnd.llamagraphics.life-balance.desktop;application/vnd.llamagraphics.life-balance.exchange+xml;application/vnd.jam;application/vnd.lotus-1-2-3;application/vnd.lotus-approach;application/vnd.lotus-freelance;application/vnd.lotus-notes;application/vnd.lotus-organizer;application/vnd.lotus-screencam;application/vnd.lotus-wordro;audio/vnd.lucent.voice;audio/x-mpegurl;video/x-m4v;application/mac-binhex40;application/vnd.macports.portpkg;application/vnd.osgeo.mapguide.package;application/marc;application/marcxml+xml;application/mxf;application/vnd.wolfrm.player;application/mathematica;application/mathml+xml;application/mbox;application/vnd.medcalcdata;application/mediaservercontrol+xml;application/vnd.mediastation.cdkey;application/vnd.mfer;application/vnd.mfmp;model/mesh;appliation/mads+xml;application/mets+xml;application/mods+xml;application/metalink4+xml;application/vnd.ms-powerpoint.template.macroenabled.12;application/vnd.ms-word.document.macroenabled.12;application/vnd.ms-word.template.macroenabed.12;application/vnd.mcd;application/vnd.micrografx.flo;application/vnd.micrografx.igx;application/vnd.eszigno3+xml;application/x-msaccess;video/x-ms-asf;application/x-msdownload;application/vnd.ms-artgalry;application/vnd.ms-ca-compressed;application/vnd.ms-ims;application/x-ms-application;application/x-msclip;image/vnd.ms-modi;application/vnd.ms-fontobject;application/vnd.ms-excel;application/vnd.ms-excel.addin.macroenabled.12;application/vnd.ms-excelsheet.binary.macroenabled.12;application/vnd.ms-excel.template.macroenabled.12;application/vnd.ms-excel.sheet.macroenabled.12;application/vnd.ms-htmlhelp;application/x-mscardfile;application/vnd.ms-lrm;application/x-msmediaview;aplication/x-msmoney;application/vnd.openxmlformats-officedocument.presentationml.presentation;application/vnd.openxmlformats-officedocument.presentationml.slide;application/vnd.openxmlformats-officedocument.presentationml.slideshw;application/vnd.openxmlformats-officedocument.presentationml.template;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;application/vnd.openxmlformats-officedocument.spreadsheetml.template;application/vnd.openxmformats-officedocument.wordprocessingml.document;application/vnd.openxmlformats-officedocument.wordprocessingml.template;application/x-msbinder;application/vnd.ms-officetheme;application/onenote;audio/vnd.ms-playready.media.pya;vdeo/vnd.ms-playready.media.pyv;application/vnd.ms-powerpoint;application/vnd.ms-powerpoint.addin.macroenabled.12;application/vnd.ms-powerpoint.slide.macroenabled.12;application/vnd.ms-powerpoint.presentation.macroenabled.12;appliation/vnd.ms-powerpoint.slideshow.macroenabled.12;application/vnd.ms-project;application/x-mspublisher;application/x-msschedule;application/x-silverlight-app;application/vnd.ms-pki.stl;application/vnd.ms-pki.seccat;application/vn.visio;video/x-ms-wm;audio/x-ms-wma;audio/x-ms-wax;video/x-ms-wmx;application/x-ms-wmd;application/vnd.ms-wpl;application/x-ms-wmz;video/x-ms-wmv;video/x-ms-wvx;application/x-msmetafile;application/x-msterminal;application/msword;application/x-mswrite;application/vnd.ms-works;application/x-ms-xbap;application/vnd.ms-xpsdocument;audio/midi;application/vnd.ibm.minipay;application/vnd.ibm.modcap;application/vnd.jcp.javame.midlet-rms;application/vnd.tmobile-ivetv;application/x-mobipocket-ebook;application/vnd.mobius.mbk;application/vnd.mobius.dis;application/vnd.mobius.plc;application/vnd.mobius.mqy;application/vnd.mobius.msl;application/vnd.mobius.txf;application/vnd.mobius.daf;tex/vnd.fly;application/vnd.mophun.certificate;application/vnd.mophun.application;video/mj2;audio/mpeg;video/vnd.mpegurl;video/mpeg;application/mp21;audio/mp4;video/mp4;application/mp4;application/vnd.apple.mpegurl;application/vnd.msician;application/vnd.muvee.style;application/xv+xml;application/vnd.nokia.n-gage.data;application/vnd.nokia.n-gage.symbian.install;application/x-dtbncx+xml;application/x-netcdf;application/vnd.neurolanguage.nlu;application/vnd.na;application/vnd.noblenet-directory;application/vnd.noblenet-sealer;application/vnd.noblenet-web;application/vnd.nokia.radio-preset;application/vnd.nokia.radio-presets;text/n3;application/vnd.novadigm.edm;application/vnd.novadim.edx;application/vnd.novadigm.ext;application/vnd.flographit;audio/vnd.nuera.ecelp4800;audio/vnd.nuera.ecelp7470;audio/vnd.nuera.ecelp9600;application/oda;application/ogg;audio/ogg;video/ogg;application/vnd.oma.dd2+xml;applicatin/vnd.oasis.opendocument.text-web;application/oebps-package+xml;application/vnd.intu.qbo;application/vnd.openofficeorg.extension;application/vnd.yamaha.openscoreformat;audio/webm;video/webm;application/vnd.oasis.opendocument.char;application/vnd.oasis.opendocument.chart-template;application/vnd.oasis.opendocument.database;application/vnd.oasis.opendocument.formula;application/vnd.oasis.opendocument.formula-template;application/vnd.oasis.opendocument.grapics;application/vnd.oasis.opendocument.graphics-template;application/vnd.oasis.opendocument.image;application/vnd.oasis.opendocument.image-template;application/vnd.oasis.opendocument.presentation;application/vnd.oasis.opendocumen.presentation-template;application/vnd.oasis.opendocument.spreadsheet;application/vnd.oasis.opendocument.spreadsheet-template;application/vnd.oasis.opendocument.text;application/vnd.oasis.opendocument.text-master;application/vnd.asis.opendocument.text-template;image/ktx;application/vnd.sun.xml.calc;application/vnd.sun.xml.calc.template;application/vnd.sun.xml.draw;application/vnd.sun.xml.draw.template;application/vnd.sun.xml.impress;application/vnd.sun.xl.impress.template;application/vnd.sun.xml.math;application/vnd.sun.xml.writer;application/vnd.sun.xml.writer.global;application/vnd.sun.xml.writer.template;application/x-font-otf;application/vnd.yamaha.openscoreformat.osfpvg+xml;application/vnd.osgi.dp;application/vnd.palm;text/x-pascal;application/vnd.pawaafile;application/vnd.hp-pclxl;application/vnd.picsel;image/x-pcx;image/vnd.adobe.photoshop;application/pics-rules;image/x-pict;application/x-chat;aplication/pkcs10;application/x-pkcs12;application/pkcs7-mime;application/pkcs7-signature;application/x-pkcs7-certreqresp;application/x-pkcs7-certificates;application/pkcs8;application/vnd.pocketlearn;image/x-portable-anymap;image/-portable-bitmap;application/x-font-pcf;application/font-tdpfr;application/x-chess-pgn;image/x-portable-graymap;image/png;image/x-portable-pixmap;application/pskc+xml;application/vnd.ctc-posml;application/postscript;application/xfont-type1;application/vnd.powerbuilder6;application/pgp-encrypted;application/pgp-signature;application/vnd.previewsystems.box;application/vnd.pvi.ptid1;application/pls+xml;application/vnd.pg.format;application/vnd.pg.osasli;tex/prs.lines.tag;application/x-font-linux-psf;application/vnd.publishare-delta-tree;application/vnd.pmi.widget;application/vnd.quark.quarkxpress;application/vnd.epson.esf;application/vnd.epson.msf;application/vnd.epson.ssf;applicaton/vnd.epson.quickanime;application/vnd.intu.qfx;video/quicktime;application/x-rar-compressed;audio/x-pn-realaudio;audio/x-pn-realaudio-plugin;application/rsd+xml;application/vnd.rn-realmedia;application/vnd.realvnc.bed;applicatin/vnd.recordare.musicxml;application/vnd.recordare.musicxml+xml;application/relax-ng-compact-syntax;application/vnd.data-vision.rdz;application/rdf+xml;application/vnd.cloanto.rp9;application/vnd.jisp;application/rtf;text/richtex;application/vnd.route66.link66+xml;application/rss+xml;application/shf+xml;application/vnd.sailingtracker.track;image/svg+xml;application/vnd.sus-calendar;application/sru+xml;application/set-payment-initiation;application/set-reistration-initiation;application/vnd.sema;application/vnd.semd;application/vnd.semf;application/vnd.seemail;application/x-font-snf;application/scvp-vp-request;application/scvp-vp-response;application/scvp-cv-request;application/svp-cv-response;application/sdp;text/x-setext;video/x-sgi-movie;application/vnd.shana.informed.formdata;application/vnd.shana.informed.formtemplate;application/vnd.shana.informed.interchange;application/vnd.shana.informed.package;application/thraud+xml;application/x-shar;image/x-rgb;application/vnd.epson.salt;application/vnd.accpac.simply.aso;application/vnd.accpac.simply.imp;application/vnd.simtech-mindmapper;application/vnd.commonspace;application/vnd.ymaha.smaf-audio;application/vnd.smaf;application/vnd.yamaha.smaf-phrase;application/vnd.smart.teacher;application/vnd.svd;application/sparql-query;application/sparql-results+xml;application/srgs;application/srgs+xml;application/sml+xml;application/vnd.koan;text/sgml;application/vnd.stardivision.calc;application/vnd.stardivision.draw;application/vnd.stardivision.impress;application/vnd.stardivision.math;application/vnd.stardivision.writer;application/vnd.tardivision.writer-global;application/vnd.stepmania.stepchart;application/x-stuffit;application/x-stuffitx;application/vnd.solent.sdkm+xml;application/vnd.olpc-sugar;audio/basic;application/vnd.wqd;application/vnd.symbian.install;application/smil+xml;application/vnd.syncml+xml;application/vnd.syncml.dm+wbxml;application/vnd.syncml.dm+xml;application/x-sv4cpio;application/x-sv4crc;application/sbml+xml;text/tab-separated-values;image/tiff;application/vnd.to.intent-module-archive;application/x-tar;application/x-tcl;application/x-tex;application/x-tex-tfm;application/tei+xml;text/plain;application/vnd.spotfire.dxp;application/vnd.spotfire.sfs;application/timestamped-data;applicationvnd.trid.tpt;application/vnd.triscape.mxs;text/troff;application/vnd.trueapp;application/x-font-ttf;text/turtle;application/vnd.umajin;application/vnd.uoml+xml;application/vnd.unity;application/vnd.ufdl;text/uri-list;application/nd.uiq.theme;application/x-ustar;text/x-uuencode;text/x-vcalendar;text/x-vcard;application/x-cdlink;application/vnd.vsf;model/vrml;application/vnd.vcx;model/vnd.mts;model/vnd.vtu;application/vnd.visionary;video/vnd.vivo;applicatin/ccxml+xml,;application/voicexml+xml;application/x-wais-source;application/vnd.wap.wbxml;image/vnd.wap.wbmp;audio/x-wav;application/davmount+xml;application/x-font-woff;application/wspolicy+xml;image/webp;application/vnd.webturb;application/widget;application/winhlp;text/vnd.wap.wml;text/vnd.wap.wmlscript;application/vnd.wap.wmlscriptc;application/vnd.wordperfect;application/vnd.wt.stf;application/wsdl+xml;image/x-xbitmap;image/x-xpixmap;image/x-xwindowump;application/x-x509-ca-cert;application/x-xfig;application/xhtml+xml;application/xml;application/xcap-diff+xml;application/xenc+xml;application/patch-ops-error+xml;application/resource-lists+xml;application/rls-services+xml;aplication/resource-lists-diff+xml;application/xslt+xml;application/xop+xml;application/x-xpinstall;application/xspf+xml;application/vnd.mozilla.xul+xml;chemical/x-xyz;text/yaml;application/yang;application/yin+xml;application/vnd.ul;application/zip;application/vnd.handheld-entertainment+xml;application/vnd.zzazz.deck+xml'); - /* eslint-enable max-len */ - profile.setPreference('pdfjs.disabled', true); - - return profile; -}; \ No newline at end of file diff --git a/dist/web/browsers/safari-browser-configurator.helper.js b/dist/web/browsers/safari-browser-configurator.helper.js deleted file mode 100644 index 3f0ddd63..00000000 --- a/dist/web/browsers/safari-browser-configurator.helper.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.safariBrowserConfigurator = undefined; - -var _shelljs = require('shelljs'); - -var _shelljs2 = _interopRequireDefault(_shelljs); - -var _path = require('path'); - -var _path2 = _interopRequireDefault(_path); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const safariBrowserConfigurator = exports.safariBrowserConfigurator = config => { - _shelljs2.default.exec(`defaults write -app Safari DownloadsPath ${_path2.default.join(config.projectPath, config.downloads)}`); -}; \ No newline at end of file diff --git a/dist/web/cucumber/config.js b/dist/web/cucumber/config.js deleted file mode 100644 index 0878fa6b..00000000 --- a/dist/web/cucumber/config.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -var _config = require('../../core/config.helper'); - -var _config2 = _interopRequireDefault(_config); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const { defineSupportCode } = require('cucumber'); - -defineSupportCode(function ({ setDefaultTimeout }) { - setDefaultTimeout(Number(_config2.default.timeout) * 1000); -}); \ No newline at end of file diff --git a/dist/web/cucumber/hooks.js b/dist/web/cucumber/hooks.js deleted file mode 100644 index ba8f7fe6..00000000 --- a/dist/web/cucumber/hooks.js +++ /dev/null @@ -1,148 +0,0 @@ -'use strict'; - -var _config = require('../../core/config.helper'); - -var _config2 = _interopRequireDefault(_config); - -var _fs = require('fs'); - -var _fs2 = _interopRequireDefault(_fs); - -var _path = require('path'); - -var _path2 = _interopRequireDefault(_path); - -var _userProvider = require('../user-provider.helper'); - -var _userProvider2 = _interopRequireDefault(_userProvider); - -var _fixturesLoader = require('../fixtures/fixtures-loader.helper'); - -var _fixturesLoader2 = _interopRequireDefault(_fixturesLoader); - -var _parameters = require('../parameters'); - -var _parameters2 = _interopRequireDefault(_parameters); - -var _chalk = require('chalk'); - -var _chalk2 = _interopRequireDefault(_chalk); - -var _cucumber = require('cucumber'); - -var _variableStore = require('../variable-store.helper'); - -var _variableStore2 = _interopRequireDefault(_variableStore); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const logRequestTime = timeStart => { - const timeDiff = process.hrtime(timeStart); - - console.log(_chalk2.default.black.bgYellow('Request took ' + (timeDiff[0] + timeDiff[1] / 1000000000) + ' seconds')); -}; - -const takeScreenshot = scenario => { - return browser.takeScreenshot().then(function (base64png) { - scenario.attach(new Buffer(base64png, 'base64'), 'image/png'); - return Promise.resolve(); - }, function () { - return Promise.resolve(); - }); -}; - -const clearCookiesAndLocalStorage = callback => { - let cookiesFunc = () => Promise.resolve(true); - - if (_config2.default.clearCookiesAfterScenario) { - cookiesFunc = () => protractor.browser.manage().deleteAllCookies(); - } - - let localStorageFunc = () => Promise.resolve(true); - if (_config2.default.clearLocalStorageAfterScenario) { - localStorageFunc = () => protractor.browser.executeScript('window.localStorage.clear();'); - } - - browser.wait(cookiesFunc().then(localStorageFunc).catch(() => false), _config2.default.waitForPageTimeout * 1000).then(() => { - protractor.browser.ignoreSynchronization = _config2.default.type === 'otherWeb'; - callback(); - }); -}; - -const clearDownload = callback => { - const files = _fs2.default.readdirSync(_path2.default.join(_config2.default.projectPath, _config2.default.downloads)).filter(function (file) { - return file !== '.gitkeep'; - }); - - for (let index = 0; index < files.length; index++) { - _fs2.default.unlinkSync(_path2.default.join(_config2.default.projectPath, _config2.default.downloads, files[index])); - } - - callback(); -}; - -(0, _cucumber.defineSupportCode)(({ After, Before }) => { - After(function (scenario, callback) { - if (scenario.result.status !== 'passed') { - takeScreenshot(this).then(() => { - clearCookiesAndLocalStorage(callback); - }); - } else { - clearCookiesAndLocalStorage(callback); - } - }); - - Before(function (scenario, callback) { - this.currentUser = null; - - if (typeof this.userProvider === 'undefined') { - this.userProvider = _userProvider2.default; - } - - _variableStore2.default.clearVariables(); - - callback(); - }); - - Before('@downloadClearBefore', function (scenario, callback) { - clearDownload(callback); - }); - - After('@downloadClearAfter', function (scenario, callback) { - clearDownload(callback); - }); - - Before('@reloadFixtures', function (scenario, callback) { - console.log(_chalk2.default.black.bgYellow('Reloading fixtures')); - - const timeStart = process.hrtime(); - - _fixturesLoader2.default.reloadFixtures(_parameters2.default.getReloadFixturesEndpoint()).then(function (response) { - if (response.status === 200) { - console.log(_chalk2.default.black.bgGreen('Fixtures reloaded')); - } else { - console.log(_chalk2.default.black.bgRed('There was a problem with fixtures reloading. The response is: '), response); - } - - logRequestTime(timeStart); - - callback(); - }).catch(function (error) { - console.log(_chalk2.default.black.bgRed('An error occurred during fixtures reloading: '), error); - - logRequestTime(timeStart); - - callback(); - }); - }); - - After('@reloadUsers', function (scenario, callback) { - if (this.currentUser !== null) { - this.userProvider.lockUser(this.currentUser.account, this.currentUser.type); - } - - callback(); - }); - - protractor.browser.ignoreSynchronization = _config2.default.type === 'otherWeb'; -}); \ No newline at end of file diff --git a/dist/web/cucumber/wait-for-condition.helper.js b/dist/web/cucumber/wait-for-condition.helper.js deleted file mode 100644 index ae9f67f2..00000000 --- a/dist/web/cucumber/wait-for-condition.helper.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.waitForInvisibilityOf = exports.waitForVisibilityOf = exports.waitForCondition = undefined; - -var _config = require('../../core/config.helper'); - -var _config2 = _interopRequireDefault(_config); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const globalTimeout = parseInt(_config2.default.elementsVisibilityTimeout) * 1000; - -const waitForCondition = exports.waitForCondition = (condition, timeout) => { - return element => { - if (element instanceof protractor.ElementArrayFinder) { - return browser.wait(protractor.ExpectedConditions[condition](element.first()), timeout); - } - - return browser.wait(protractor.ExpectedConditions[condition](element), timeout); - }; -}; - -const waitForVisibilityOf = exports.waitForVisibilityOf = element => { - return waitForCondition('visibilityOf', globalTimeout)(element); -}; - -const waitForInvisibilityOf = exports.waitForInvisibilityOf = element => { - return waitForCondition('invisibilityOf', globalTimeout)(element); -}; \ No newline at end of file diff --git a/dist/web/fixtures/fixtures-loader.helper.js b/dist/web/fixtures/fixtures-loader.helper.js deleted file mode 100644 index df904a5b..00000000 --- a/dist/web/fixtures/fixtures-loader.helper.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _nodeFetch = require('node-fetch'); - -var _nodeFetch2 = _interopRequireDefault(_nodeFetch); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const FixturesLoader = { - reloadFixtures: function (endpoint) { - return (0, _nodeFetch2.default)(endpoint); - } -}; - -exports.default = FixturesLoader; \ No newline at end of file diff --git a/dist/web/fs/download-checker.helper.js b/dist/web/fs/download-checker.helper.js deleted file mode 100644 index 9021864d..00000000 --- a/dist/web/fs/download-checker.helper.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _fs = require('fs'); - -var _fs2 = _interopRequireDefault(_fs); - -var _path = require('path'); - -var _path2 = _interopRequireDefault(_path); - -var _config = require('../../core/config.helper'); - -var _config2 = _interopRequireDefault(_config); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const DownloadChecker = { - wasDownloaded: function (expectedFileName) { - return browser.driver.wait(function () { - return _fs2.default.existsSync(_path2.default.join(_config2.default.projectPath, _config2.default.downloads, expectedFileName)); - }, _config2.default.downloadTimeout * 1000); - } -}; - -exports.default = DownloadChecker; \ No newline at end of file diff --git a/dist/web/fs/file-manager.helper.js b/dist/web/fs/file-manager.helper.js deleted file mode 100644 index 3d6aa295..00000000 --- a/dist/web/fs/file-manager.helper.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _fs = require('fs'); - -var _fs2 = _interopRequireDefault(_fs); - -var _path = require('path'); - -var _path2 = _interopRequireDefault(_path); - -var _nodeXlsx = require('node-xlsx'); - -var _nodeXlsx2 = _interopRequireDefault(_nodeXlsx); - -var _config = require('../../core/config.helper'); - -var _config2 = _interopRequireDefault(_config); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const FileManager = { - wasDownloaded: function (expectedFileName) { - return browser.driver.wait(function () { - return _fs2.default.existsSync(_path2.default.join(_config2.default.projectPath, _config2.default.downloads, expectedFileName)); - }, _config2.default.downloadTimeout * 1000); - }, - - parseXLS: function (expectedFileName) { - return _nodeXlsx2.default.parse(_path2.default.join(_config2.default.projectPath, _config2.default.downloads, expectedFileName))[0].data; - } -}; - -exports.default = FileManager; \ No newline at end of file diff --git a/dist/web/parallel/chunk-specs.helper.js b/dist/web/parallel/chunk-specs.helper.js deleted file mode 100644 index f4ad51df..00000000 --- a/dist/web/parallel/chunk-specs.helper.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.chunkSpecs = undefined; - -var _lodash = require('lodash'); - -var _lodash2 = _interopRequireDefault(_lodash); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const chunkSpecs = exports.chunkSpecs = (commandArgs, allSpecs, expectedArrayLength, numberOfInstances) => { - if (commandArgs.pattern !== undefined && typeof commandArgs.pattern !== 'boolean') { - const patterns = commandArgs.pattern.split(','); - const chunkedSpecs = []; - - if (patterns.length !== numberOfInstances) { - throw new Error('Number of the specified patterns is different than number of instances!'); - } - - for (const pattern of patterns) { - chunkedSpecs.push(allSpecs.filter(spec => spec.match(new RegExp(pattern)))); - } - - return chunkedSpecs; - } - - return _lodash2.default.chunk(allSpecs, expectedArrayLength); -}; \ No newline at end of file diff --git a/dist/web/parallel/prepare-browser-instance-specs.helper.js b/dist/web/parallel/prepare-browser-instance-specs.helper.js deleted file mode 100644 index 1389f44e..00000000 --- a/dist/web/parallel/prepare-browser-instance-specs.helper.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.prepareBrowserInstance = undefined; - -var _lodash = require('lodash'); - -var _lodash2 = _interopRequireDefault(_lodash); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const prepareBrowserInstance = exports.prepareBrowserInstance = (browserConfig, specs) => { - const instance = _lodash2.default.cloneDeep(browserConfig); - instance.specs = specs; - - return instance; -}; \ No newline at end of file diff --git a/dist/web/parameters.js b/dist/web/parameters.js deleted file mode 100644 index 0f8eea9a..00000000 --- a/dist/web/parameters.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -const Parameters = { - getReloadFixturesEndpoint: function () { - const config = this.getConfig(); - - return config.fixturesReloadHost; - }, - - getConfig() { - if (typeof process.env.FIXTURES_RELOAD_HOST === 'undefined') { - throw new Error('Missing fixtures reload url. Use export FIXTURES_RELOAD_HOST=valid-host for setup.'); - } - - return { - fixturesReloadHost: process.env.FIXTURES_RELOAD_HOST - }; - } -}; - -exports.default = Parameters; \ No newline at end of file diff --git a/dist/web/performance/JSON-performance-report-parser.helper.js b/dist/web/performance/JSON-performance-report-parser.helper.js deleted file mode 100644 index fdea0655..00000000 --- a/dist/web/performance/JSON-performance-report-parser.helper.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _fs = require('fs'); - -var _fs2 = _interopRequireDefault(_fs); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const getReport = (fileName, path) => { - return JSON.parse(_fs2.default.readFileSync(`${path}/${fileName}`, 'utf8')); -}; - -class JSONPerformanceReportParser { - constructor(path = 'reports/performance') { - this.path = path; - } - - parse(fileName) { - const reportFile = getReport(fileName, this.path); - const requests = reportFile.log.entries.map(item => ({ - ttfb: item.timings.wait, - url: item.request.url - })); - - if (requests.length > 0) { - return requests; - } - - throw Error(`${fileName} contains incorrect data!`); - } -} - -exports.default = JSONPerformanceReportParser; \ No newline at end of file diff --git a/dist/web/performance/time-to-first-byte-analyser.helper.js b/dist/web/performance/time-to-first-byte-analyser.helper.js deleted file mode 100644 index fc2eeb65..00000000 --- a/dist/web/performance/time-to-first-byte-analyser.helper.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.create = undefined; - -var _JSONPerformanceReportParser = require('./JSON-performance-report-parser.helper'); - -var _JSONPerformanceReportParser2 = _interopRequireDefault(_JSONPerformanceReportParser); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -class TimeToFirstByteAnalyser { - constructor(jsonPerformanceReportParser) { - this.reader = jsonPerformanceReportParser; - } - - checkTiming(fileName, maxTiming) { - const parsedReport = this.reader.parse(fileName); - - return parsedReport.filter(report => report.ttfb > maxTiming); - } -} - -const create = exports.create = (reportParser = new _JSONPerformanceReportParser2.default()) => new TimeToFirstByteAnalyser(reportParser); \ No newline at end of file diff --git a/dist/web/url-parser.helper.js b/dist/web/url-parser.helper.js deleted file mode 100644 index 9f076dc9..00000000 --- a/dist/web/url-parser.helper.js +++ /dev/null @@ -1,68 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.waitForUrlChangeTo = exports.isRelativePage = undefined; - -var _url = require('url'); - -var _url2 = _interopRequireDefault(_url); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const extractDomain = url => _url2.default.parse(url).host; -const extractUrl = url => _url2.default.parse(url).pathname; -const normalizeUrl = url => { - if (url.length === 0) { - return extractUrl('/'); - } - - if (url[url.length - 1] === '/' && url.length > 1) { - return extractUrl(url.substr(0, url.length - 1)); - } - - return extractUrl(url); -}; - -const compareUrls = (urlSplit, baseUrlSplit) => { - const resultParameters = {}; - - for (let i in urlSplit) { - const template = baseUrlSplit[i]; - const actual = urlSplit[i]; - - if (template.startsWith(':')) { - resultParameters[template.substr(1)] = actual; - } else if (template !== actual) { - return false; - } - } - - return resultParameters; -}; - -const isRelativePage = exports.isRelativePage = url => { - return url === '' || url[0] === '/'; -}; - -const waitForUrlChangeTo = exports.waitForUrlChangeTo = (newUrl, currentUrl) => { - return baseUrl => { - const pageUrl = _url2.default.resolve(baseUrl, newUrl); - const pageDomain = extractDomain(pageUrl); - const currentUrlDomain = extractDomain(currentUrl); - - if (pageDomain !== currentUrlDomain) { - return false; - } - - const urlSplit = normalizeUrl(currentUrl).split('/'); - const pageUrlSplit = normalizeUrl(pageUrl).split('/'); - - if (urlSplit.length !== pageUrlSplit.length) { - return false; - } - - return compareUrls(urlSplit, pageUrlSplit); - }; -}; \ No newline at end of file diff --git a/dist/web/user-provider.helper.js b/dist/web/user-provider.helper.js deleted file mode 100644 index a9b5ef18..00000000 --- a/dist/web/user-provider.helper.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -var _config = require('../core/config.helper'); - -var _config2 = _interopRequireDefault(_config); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -const accounts = _config2.default.accounts; - -const userProvider = { - getUser: function (userType) { - const user = accounts[userType]; - - if (user.accounts.length > 1) { - const usedAccounts = user.accounts.filter(account => account.used); - - if (usedAccounts.length === user.accounts.length) { - user.accounts.map(account => _extends({}, account, { - used: false - })); - } - - return user.accounts.find(account => !account.used); - } - - return user.accounts[0]; - }, - - lockUser: function (user, userType) { - if (accounts[userType].accounts.length > 1) { - accounts[userType].accounts.forEach((account, index) => { - if (account.email === user.email) { - accounts[userType].accounts[index].used = true; - } - }); - } - } -}; - -exports.default = userProvider; \ No newline at end of file diff --git a/dist/web/variable-store.helper.js b/dist/web/variable-store.helper.js deleted file mode 100644 index afedf7fb..00000000 --- a/dist/web/variable-store.helper.js +++ /dev/null @@ -1,68 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -class VariableStore { - constructor() { - this.variables = []; - } - - storeVariable(name, value) { - const foundVariable = this.variables.find(variable => variable.name === name); - - if (typeof foundVariable !== 'undefined') { - throw new Error(`Variable ${name} is stored already`); - } - - this.variables.push({ name: name, value: value }); - } - - updateVariable(name, value) { - const foundVariable = this.variables.find(variable => variable.name === name); - - if (typeof foundVariable === 'undefined') { - throw new Error(`Variable ${name} does not exist.`); - } - - this.variables.push({ name: name, value: value }); - } - - getVariableValue(name) { - const foundVariable = this.variables.find(variable => variable.name === name); - - if (typeof foundVariable === 'undefined') { - throw new Error(`Variable ${name} was not stored`); - } - - return foundVariable.value; - } - - isStored(name) { - const foundVariable = this.variables.find(variable => variable.name === name); - - return typeof foundVariable !== 'undefined'; - } - - clearVariables() { - this.variables = []; - } - - replaceTextVariables(text) { - let newText = text; - const variableNames = this.variables.map(variable => variable.name); - - for (let variableNameIndex in variableNames) { - const variableName = variableNames[variableNameIndex]; - - if (newText.indexOf(variableName) > -1) { - newText = text.replace(`v:${variableName}`, this.getVariableValue(variableName)); - break; - } - } - - return newText; - } -} - -exports.default = new VariableStore(); \ No newline at end of file diff --git a/docs/browserstack.md b/docs/browserstack.md new file mode 100644 index 00000000..b2f7425f --- /dev/null +++ b/docs/browserstack.md @@ -0,0 +1,100 @@ +--- +id: browserstack +title: Browserstack integration +--- + +## Browserstack project configuration + +1. Create a new account in Browserstack: https://www.browserstack.com/ +2. Login and visit the website https://www.browserstack.com/accounts/settings +3. Scroll down to the `Automation` section and copy: +- `Username` +- `Access Key` + +4. Add a new `browserstack` section to the `kakunin.conf.js` file in the repository. +This is an example of a configuration for IE8 on Windows 7. + +```javascript + browserstack: { + seleniumAddress: 'http://hub-cloud.browserstack.com/wd/hub', + defaultPort: 45691, + capabilities: { + 'browserstack.user': 'example-user', + 'browserstack.key': 'example-key', + 'browserstack.local': true, + nativeEvents: true, + 'browserstack.ie.driver': '3.14.0', + 'browserstack.selenium_version': '3.14.0', + browserName: 'IE', + browser_version: '8.0', + } + }, +``` + +5. Set `'browserstack.user'` to the `Username` value that you copied from the `Automation` section +6. Set `'browserstack.key'` to the `Access Key` value that you copied from the `Automation` section + +7. Visit the link https://www.browserstack.com/automate/capabilities if you want to find more capabilities for your project!. + +## Run tests in Browserstack + +Runs the application with the capabilities set in `kakunin.conf.js` file through the command line: +- `npm run kakunin -- --browserstack` + +Keep in mind that all capabilities that you set via CLI will be ignored! + +For example, `npm run kakunin -- --safari --browserstack` will ignore the `safari` part. +Only `--browserstack` matters in case of running tests in Browserstack. + + +## Example kakunin.conf.js configuration file + +This is an example configuration for Internet Explorer 8 on Windows 7. + +```javascript +module.exports = { + browserWidth: 1600, + browserHeight: 900, + timeout: 60, + elementsVisibilityTimeout: 5, + waitForPageTimeout: 5, + downloadTimeout: 30, + reports: '/reports', + downloads: '/downloads', + data: '/data', + features: ['/features'], + pages: ['/pages'], + matchers: ['/matchers'], + generators: ['/generators'], + form_handlers: ['/form_handlers'], + step_definitions: ['/step_definitions'], + comparators: ['/comparators'], + dictionaries: ['/dictionaries'], + transformers: ['/transformers'], + regexes: ['/regexes'], + hooks: ['/hooks'], + clearEmailInboxBeforeTests: false, + clearCookiesAfterScenario: true, + clearLocalStorageAfterScenario: true, + email: null, + headless: true, + noGpu: true, + type: 'otherWeb', + baseUrl: 'http://localhost:8080', + apiUrl: 'http://localhost:8080/', + browserstack: { + seleniumAddress: 'http://hub-cloud.browserstack.com/wd/hub', + defaultPort: 45691, + capabilities: { + 'browserstack.user': 'example-user', + 'browserstack.key': 'example-key', + 'browserstack.local': true, + nativeEvents: true, + 'browserstack.ie.driver': '3.14.0', + 'browserstack.selenium_version': '3.14.0', + browserName: 'IE', + browser_version: '8.0', + } + }, +}; +``` \ No newline at end of file diff --git a/docs/configuration.md b/docs/configuration.md index c3896606..6c123973 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -146,7 +146,7 @@ for custom email checking system only type is required: "type": "custom-type" ``` -`headless` - flag to activate chrome headless browser `default: false` +`headless` - flag to activate chrome headless browser `default: false`. Keep in mind that CLI command `-- --headless=false/true` has higher priority than the config file. `noGpu` - flag to activate cpu only mode `default: false` diff --git a/docs/cross-browser.md b/docs/cross-browser.md index a1c9571d..342f2844 100644 --- a/docs/cross-browser.md +++ b/docs/cross-browser.md @@ -9,12 +9,14 @@ There is a possibility to run Kakunin in various browsers: - Google Chrome (by default) `npm run kakunin` or `npm run kakunin -- --chrome` - Firefox `npm run kakunin -- --firefox` - Safari `npm run kakunin -- --safari` +- Internet Explorer `npm run kakunin -- --ie` (supported versions IE8, IE9, IE10, IE11) ## To run tests in different browsers at once There is a possibility to run more than one instance of WebDriver by giving an extra parameter to a command line: -- `npm run kakunin --chrome --firefox` +- `npm run kakunin --chrome --safari` +Currently, there is a problem with running more than one instance of Firefox! ## Safari ### Run tests @@ -23,6 +25,12 @@ There is a possibility to run more than one instance of WebDriver by giving an e 3. Open "Develop" tab 4. Enable "Allow Remote Automation" +## Internet Explorer +### Configure the browser +1. Open Internet options and set: +- IE browser zoom level to 100 procent +- IE Security level: keep all of the tabs either checked / unchecked (Itnernet, Local internet, Trusted sites, Restricted sites) + ### Troubleshooting Safari version 12.0: - drag & drop actions in Kakunin impossible (more details https://github.com/angular/protractor/issues/1526) diff --git a/docs/headless.md b/docs/headless.md new file mode 100644 index 00000000..d512b607 --- /dev/null +++ b/docs/headless.md @@ -0,0 +1,19 @@ +--- +id: headless +title: Headless +--- + +# Headless browser control + +Currently only Firefox and Google Chrome browser can be run headless. + +For the rest of the supported browsers this flag is ignored. + +To control headless via command line: +- `npm run kakunin -- --headless` opens browser in headless mode +- `npm run kakunin -- --headless=true` opens browser in headless mode +- `npm run kakunin -- --headless=false` opens browser in normal mode + +Also, there is a possibility to set `"headless: "true"` or `"headless: "false"` in the `kakunin.conf.js` config file. + +Keep in mind that CLI has greater prority than the cofig file (overides settings on runtime). diff --git a/docs/hooks.md b/docs/hooks.md new file mode 100644 index 00000000..8ac95a79 --- /dev/null +++ b/docs/hooks.md @@ -0,0 +1,55 @@ +--- +id: hooks +title: Hooks +--- +# Hooks for Kakunin tests + +This section explains how to add priority hooks for kakunin tests based on the built-in adapter. +Hooks allow you to perform actions before and after scenario. +For example, it lets you clear all files from the downloads folder. + + + +## How to add hook with priority: +##### initializeHook() + - this method is provided to execute hook logic. +##### getPriority() + - this method returns numeric value and then it's sorted in order. + +```text +Remember that new Hook must contain these 2 methods to fulfill interface. +``` + +After your hook is ready to use method `hookHandlers.addHook(Hook object)` + + +### Example of example.hook.js: +```typescript +const { hookHandlers, Before } = require('kakunin'); + +class ExampleHook { + initializeHook() { + Before(() => { + console.log('This hook is going to be 5th in order'); + }); + } + + getPriority() { + return 5; + } +} + +hookHandlers.addHook(new ExampleHook()); +``` + +### Build in hooks: + +#### Clear download: + - Clears download folder before or/and after scenario. To use them add `@downloadClearBefore` or `@downloadClearAfter` tag. + Its priority is set to 1. +#### Reload fixtures: + - allows you to reload fixtures before the desired scenario, via URL provided in `.env` file. + Its priority is set to 2. +#### Take a screenshot and clear variables: + - These hooks are used by kakunin mechanism to clear variable store and take screenshots after scenarios. + Their priority is set to 1. diff --git a/docs/index.md b/docs/index.md index 57d06142..d9ea58f3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -35,7 +35,7 @@ npm init Install dependencies ```bash -npm install cross-env protractor webdriver-manager kakunin --save +npm install cross-env kakunin --save ``` Inside `package.json` file; add new script in `scripts` section: @@ -161,18 +161,20 @@ ln -s ../node_modules/kakunin/dist/step_definitions/form.js kakunin-form.js ln -s ../node_modules/kakunin/dist/step_definitions/email.js kakunin-email.js ln -s ../node_modules/kakunin/dist/step_definitions/generators.js kakunin-generators.js ln -s ../node_modules/kakunin/dist/step_definitions/navigation.js kakunin-navigation.js +ln -s ../node_modules/kakunin/dist/step_definitions/performance.js kakunin-performance.js ``` For Windows 8+: (you have to do this as administrator) ```bash -mklink kakunin-elements.js ..\node_modules\kakunin\dist\step_definitions\elements.js" -mklink kakunin-debug.js ..\node_modules\kakunin\dist\step_definitions\debug.js" -mklink kakunin-file.js ..\node_modules\kakunin\dist\step_definitions\file.js" -mklink kakunin-form.js ..\node_modules\kakunin\dist\step_definitions\form.js" -mklink kakunin-email.js ..\node_modules\kakunin\dist\step_definitions\email.js" -mklink kakunin-generators.js ..\node_modules\kakunin\dist\step_definitions\generators.js" -mklink kakunin-navigation.js ..\node_modules\kakunin\dist\step_definitions\navigation.js" +mklink kakunin-elements.js ../node_modules/kakunin/dist/step_definitions/elements.js +mklink kakunin-debug.js ../node_modules/kakunin/dist/step_definitions/debug.js +mklink kakunin-file.js ../node_modules/kakunin/dist/step_definitions/file.js +mklink kakunin-form.js ../node_modules/kakunin/dist/step_definitions/form.js +mklink kakunin-email.js ../node_modules/kakunin/dist/step_definitions/email.js +mklink kakunin-generators.js ../node_modules/kakunin/dist/step_definitions/generators.js +mklink kakunin-navigation.js ../node_modules/kakunin/dist/step_definitions/navigation.js +mklink kakunin-performance.js ../node_modules/kakunin/dist/step_definitions/performance.js ``` Keep in mind that `mklink` is not available in older Windows distributions. diff --git a/docs/quickstart.md b/docs/quickstart.md index e734b2ce..1758b9b9 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -31,7 +31,7 @@ npm init Install dependencies ```bash -npm install cross-env protractor webdriver-manager kakunin --save +npm install cross-env kakunin --save ``` Inside `package.json` file add new script in `scripts` section: diff --git a/docs/steps-elements.md b/docs/steps-elements.md index ee464a41..f0df8775 100644 --- a/docs/steps-elements.md +++ b/docs/steps-elements.md @@ -195,6 +195,31 @@ You can use all kind of matchers here. --- +## `there are ":elementName" dropdown list elements with following options:` + +Allows to check if there is exact match to options provided in table for option selector. +```html + +``` +For example: + +```gherkin +there are "personOption" dropdown list elements with following options: + | Person 1 | + | Person 2 | + | Person 3 | + | Person 4 | +``` +The element must be for example: +`this.personOption = this.personForm.$$('option');`. + +--- + ## `there is element ":elementName" with value ":matcher"` Allows to check if `:elementName` has a value that matches the `:matcher`. @@ -246,6 +271,7 @@ Allows to check if `:elementName` is not matching the given type of `:matcher`. --- ## `there is no element ":elementName" with regex ":matcher"` + Allows to check if `:elementName` is not matching given type of regex. --- diff --git a/docs/steps-rest.md b/docs/steps-rest.md new file mode 100644 index 00000000..13d95eac --- /dev/null +++ b/docs/steps-rest.md @@ -0,0 +1,90 @@ +--- +id: steps-rest +title: Rest api +--- + +# Steps used for testing REST api: + +In order to configure url for api, please change `apiUrl` field in `functional-tests/kakunin.conf.js`. This will set url of application api. + +## `I send ":methodName" request on ":endpoint" endpoint` + +Sends to the given request method to given website endpoint. + +For example, in case of GET request for /posts endpoint it should look like: +```gherkin +I send "GET" request on "posts" endpoint +``` + +## `^I send ":methodName" request on ":endpoint" endpoint with JSON body:` + +Sends request method to website endpoint requiring JSON body. + +```gherkin +I send "POST" request on "posts" endpoint with JSON body: + """ + { + "title": "user", + "body": "test" + } + """ +``` + +## `^I send "methodName" request on ":endpoint" endpoint using form data:` + +Sends request method to website endpoint using form data. + +```gherkin +I send "POST" request on "posts" endpoint using form data: + | title | user | +``` + +## `the response code should be ":statusCode"` + +Verifies if the server response code has match to given one. + +## `the response should exact match to body:` + +Verifies if the server response body has exact match to given one. + +```gherkin +the response should exact match to body: + """ + { + "userId": 1, + "id": 1, + "title": "user", + "body": "test" + } + """ +``` + +## `the response should match JSON schema:` + +Verifies if the server response body has exact match to given JSON schema. + +```gherkin +the response should exact match JSON schema: + """ + { + "title": "Test schema", + "type": "object", + "properties": { + "id": { + "type": "integer" + } + }, + "required": ["id"] + } + """ +``` + +## `I set request headers:` + +Sets the request headers to given one till creating new request. + +```gherkin +I set request headers: + | Content-type | application/json | + | accept | */* | +``` diff --git a/docs/testing-rest-api.md b/docs/testing-rest-api.md new file mode 100644 index 00000000..47bccbed --- /dev/null +++ b/docs/testing-rest-api.md @@ -0,0 +1,159 @@ +--- +id: testing-rest-api +title: REST API examples +--- + +# Testing REST API of your application + +In this section examples of using steps provided for testing, REST API will be provided. +All examples can be checked on site https://reqres.in/ which is simple REST API service + +# Available methods + +At this moment Kakunin supports methods for REST API: +- GET +- POST +- DELETE +- PATCH + +Also, You can set the headers for the request. + +# Making GET request + +In order to create get request and verify if the response is ok you need to create scenario step: + +```gherkin +Given I send "GET" request on "/api/users/2" endpoint +Then the response code should be "200" +``` + +This scenario will create a get request to the application and verify if the response was 200. +The response is stored till creating another request. So if We want to test the response body of a server we can create a scenario like: + +```gherkin +Given I send "GET" request on "/api/users/2" endpoint +Then the response code should be "200" +And the response should exact match to body: + """ + { + "data": { + "id": 2, + "first_name": "Janet", + "last_name": "Weaver", + "avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg" + } + } + """ +``` + +Based on this We can also check if the response matches schema that we have provided by using step: + +```gherkin +Then the response should exact match JSON schema: +``` + +# Making POST request + +In order to create post request and attach the JSON body to it You need to create a scenario: + +```gherkin +Given I send "POST" request on "/api/users" endpoint with body: + """ + { + "name": "morpheus", + "job": "leader" + } + """ +Then the response code should be "201" +``` + +or you can create post request and attach the form data to it: + +```gherkin +Given I send "POST" request on "/api/users" endpoint using form data: + | name | morpheus | +Then the response code should be "201" +``` + +This scenario will create a post request to the application and verify if response was 201 (created). +The response is stored till creating another request. So if We want to test the response body of a server we can create scenarios +like before: + +```gherkin +Given I send "POST" request on "/api/users" endpoint with body: + """ + { + "name": "morpheus", + "job": "leader" + } + """ +Then the response code should be "201" +And the response should match JSON schema: + """ + { + "title": "Post schema", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "job": { + "type": "string" + } + }, + "required": ["name", "job"] + } + """ +``` + +Scenario like that will verify if the post request was executed and response schema matches given one. + +# Making DELETE request + +Delete request works similarly to get request. Example of delete scenario: + +```gherkin +Given I send "DELETE" request on "/api/users/2" endpoint +Then the response code should be "204" +``` + +# Making PATCH request + +Patch request works similarly to post request. Example of patch scenario: + +```gherkin +Given I send "PATCH" request on "/api/users/2" endpoint with JSON body: + """ + { + "name": "morpheus", + "job": "zion resident" + } + """ +Then the response code should be "200" +And the response should exact match to body: + """ + { + "name": "morpheus", + "job": "zion resident", + "updatedAt": "2019-02-12T18:25:06.001Z" + } + """ +``` + +# Setting headers for request + +Sometimes We want to set the headers for next request. In order to achieve this, We can create scenario like: + +```gherkin +Given I set request headers: + | User-Agent | Mozilla | +When I send "POST" request on "postTestEndpoint" endpoint with JSON body: + """ + { + "title": "adam", + "body": "test" + } + """ +Then the response code should be "403" +``` + This scenario will set "User-Agent" header of next request to "Mozilla". diff --git a/functional-tests/dictionaries/test-dictionary.js b/functional-tests/dictionaries/test-dictionary.js index c6a73913..ed8a6b08 100644 --- a/functional-tests/dictionaries/test-dictionary.js +++ b/functional-tests/dictionaries/test-dictionary.js @@ -5,7 +5,7 @@ class TestDictionary extends BaseDictionary { constructor() { super('test-dictionary', { 'test-name': 'Janek', - 'test-value': 'lux' + 'test-value': 'lux', }); } } diff --git a/functional-tests/features/content/validate_tabular_data.feature b/functional-tests/features/content/validate_tabular_data.feature index 35ff2ffe..89d40fed 100644 --- a/functional-tests/features/content/validate_tabular_data.feature +++ b/functional-tests/features/content/validate_tabular_data.feature @@ -6,14 +6,27 @@ Feature: Tabular data Given I visit the "main" page When I click the "tabularDataLink" element Then the "tabularData" page is displayed + And there are "at least 1" "rows" elements + And there are "above 3" "rows" elements + And there are "below 5" "rows" elements + And there are "within 3 5" "rows" elements And there are "equal 4" "rows" elements Scenario: Validate tabular data count and content, also check sorting Given I visit the "main" page When I click the "tabularDataLink" element Then the "tabularData" page is displayed - And the "rows" element is present And the "rows" element is visible + And there are "at least 4" following elements for element "rows": + | indexLocator | r:validNumber | + And there are "above 3" following elements for element "rows": + | indexLocator | r:validNumber | + And there are "equal 4" following elements for element "rows": + | indexLocator | r:validNumber | + And there are "below 5" following elements for element "rows": + | indexLocator | r:validNumber | + And there are "within 3-5" following elements for element "rows": + | indexLocator | r:validNumber | And there are "equal 4" following elements for element "rows": | indexLocator | r:validNumber | | idLocator | t:MY_CUSTOM_ID_ | diff --git a/functional-tests/features/content/validate_tabular_data_css.feature b/functional-tests/features/content/validate_tabular_data_css.feature new file mode 100644 index 00000000..c4b10702 --- /dev/null +++ b/functional-tests/features/content/validate_tabular_data_css.feature @@ -0,0 +1,59 @@ +Feature: Tabular data + As a kakunin user + I want validate tabular data + + Scenario: Validate tabular data count + Given I visit the "main" page + When I click the "a[href='/tabular-data']" element + Then the "tabularData" page is displayed + And there are "at least 1" "table tr" elements + And there are "above 3" "table tr" elements + And there are "below 5" "table tr" elements + And there are "within 3 5" "table tr" elements + And there are "equal 4" "table tr" elements + + Scenario: Validate tabular data count and content, also check sorting + Given I visit the "main" page + When I click the "a[href='/tabular-data']" element + Then the "tabularData" page is displayed + And the "table tr" element is visible + And there are "at least 4" following elements for element "table tr": + | .index | r:validNumber | + And there are "above 3" following elements for element "table tr": + | .index | r:validNumber | + And there are "equal 4" following elements for element "table tr": + | .index | r:validNumber | + And there are "below 5" following elements for element "table tr": + | .index | r:validNumber | + And there are "within 3-5" following elements for element "table tr": + | .index | r:validNumber | + And there are "equal 4" following elements for element "table tr": + | .index | r:validNumber | + | .id | t:MY_CUSTOM_ID_ | + | .name | r:notEmpty | + | button.view | f:isVisible | + | button.view | f:isClickable | + And every "table tr" element should have the same value for element "button.view" + And ".index" value on the "table tr" list is sorted in "ascending" order + And ".descending-sort" value on the "table tr" list is sorted in "descending" order + + Scenario: Validate exact tabular data by columns + Given I visit the "main" page + When I click the "a[href='/tabular-data']" element + Then the "tabularData" page is displayed + And there are following elements in table "table tr": + | .index | nameLocator | + | t:1 | t:Some custom name 1 | + | t:2 | t:Some custom name 2 | + | t:3 | t:Some custom name 3 | + | t:4 | t:Some custom name 4 | + And the element "table tr" should have an item with values: + | .index | t:1 | + | .index | f:isVisible | + And the element "table tr" should not have an item with values: + | .index | t:incorrect-number-value | + + Scenario: Navigate to pages by using click steps + Given I visit the "main" page + When I click the ".valueForClickStep" element + Then the "tabularData" page is displayed diff --git a/functional-tests/features/content/wait_for_element_dissapear_css.feature b/functional-tests/features/content/wait_for_element_dissapear_css.feature new file mode 100644 index 00000000..1b9ba64f --- /dev/null +++ b/functional-tests/features/content/wait_for_element_dissapear_css.feature @@ -0,0 +1,18 @@ +Feature: Element visibility + As a kakunin user + I want to wait for element to disappear + + Scenario: Check visibility - disappear step + Given I visit the "main" page + When I click the "a[href='/form/disappear']" element + Then the "buttonForm" page is displayed + When I click the "#button" element + Then I wait for the "#button" element to disappear + + Scenario: Check visibility with - wait for condition step + Given I visit the "main" page + When I click the "buttonLink" element + Then the "buttonForm" page is displayed + When I click the "#button" element + And I wait for "invisibilityOf" of the "#button" element + Then the "#button" element is not visible diff --git a/functional-tests/features/drag-and-drop/operations_on_elements_css.feature b/functional-tests/features/drag-and-drop/operations_on_elements_css.feature new file mode 100644 index 00000000..1facd45e --- /dev/null +++ b/functional-tests/features/drag-and-drop/operations_on_elements_css.feature @@ -0,0 +1,8 @@ +Feature: Drag and drop + As a kakunin user + I want to be able to make operations on elements + + Scenario: Drag element and drop on the other one + Given I visit the "dragAndDrop" page + When I drag "#draggable" element and drop over "#droppable" element + Then the ".ui-state-highlight" element is visible diff --git a/functional-tests/features/forms/fill_and_check_form_css.feature b/functional-tests/features/forms/fill_and_check_form_css.feature new file mode 100644 index 00000000..99e2c915 --- /dev/null +++ b/functional-tests/features/forms/fill_and_check_form_css.feature @@ -0,0 +1,29 @@ +Feature: Forms + As a kakunin user + I want fill and check form fields + + Scenario: Fill and check form fields + Given I visit the "main" page + When I click the "a[href='/form/simple']" element + Then the "simpleForm" page is displayed + When I generate random "stringWithLength:10" as "storedStringWithLength" + And I fill the "form" form with: + | nameInput | v:storedStringWithLength | + Then the "form" form is filled with: + | nameInput | v:storedStringWithLength | + When I fill the "form" form with: + | input[name="name"] | d:test-dictionary:test-name | + | textarea[name="description"] | some description | + | input[type="checkbox"] | Checkbox Option 2 | + | input[type="checkbox"] | Checkbox Option 3 | + | input[type="radio"] | third-radio-option | + | select[name="status"] | unknown | + And I click the "submitButton" element + Then the "simpleFormPost" page is displayed + And the "form" form is filled with: + | input[name="name"] | d:test-dictionary:test-name | + | textarea[name="description"] | some description | + | input[type="checkbox"] | Checkbox Option 2 | + | input[type="checkbox"] | Checkbox Option 3 | + | input[type="radio"] | third-radio-option | + | select[name="status"] | unknown | diff --git a/functional-tests/features/forms/fill_select.feature b/functional-tests/features/forms/fill_select.feature new file mode 100644 index 00000000..1345e244 --- /dev/null +++ b/functional-tests/features/forms/fill_select.feature @@ -0,0 +1,13 @@ +Feature: Forms + As a kakunin user + I want to check options + + Scenario: Fill and check form fields + Given I visit the "main" page + When I click the "formSelectLink" element + Then the "simpleSelectForm" page is displayed + And there are "personOption" dropdown list elements with following options: + | Person3 | + | Person2 | + | Person1 | + | Person4 | diff --git a/functional-tests/features/matchers/match_current_date.feature b/functional-tests/features/matchers/match_current_date.feature index e45be903..3b174784 100644 --- a/functional-tests/features/matchers/match_current_date.feature +++ b/functional-tests/features/matchers/match_current_date.feature @@ -6,6 +6,11 @@ Feature: Matchers Given I visit the "main" page When I click the "matchersLink" element Then the "matchers" page is displayed + And there is element "dateElement" with value "f:isVisible" + And there is element "dateMatcherText" with value "t:Date/Time:" + And there is element "dateElement" with value "f:isClickable" + And there is element "dateElement" with value "f:isPresent" + And there is element "dateElement" with value "r:notEmpty" And there is element "dateElement" with value "f:currentDate:YYYY-MM-DD" Scenario: I want to match current date without additional parameters diff --git a/functional-tests/features/matchers/match_current_date_css.feature b/functional-tests/features/matchers/match_current_date_css.feature new file mode 100644 index 00000000..4c9b2dfd --- /dev/null +++ b/functional-tests/features/matchers/match_current_date_css.feature @@ -0,0 +1,20 @@ +Feature: Matchers + As a kakunin user + I want to navigate to matcher page and match current date + + Scenario: I want to match current date with format + Given I visit the "main" page + When I click the ".matchers" element + Then the "matchers" page is displayed + And there is element "span.current_date" with value "f:isVisible" + And there is element "p.date-matcher" with value "t:Date/Time:" + And there is element "span.current_date" with value "f:isClickable" + And there is element "span.current_date" with value "f:isPresent" + And there is element "span.current_date" with value "r:notEmpty" + And there is element "span.current_date" with value "f:currentDate:YYYY-MM-DD" + + Scenario: I want to match current date without additional parameters + Given I visit the "main" page + When I click the ".matchers" element + Then the "matchers" page is displayed + And there is element "span.current_date" with value "f:currentDate" diff --git a/functional-tests/features/matchers/matchers.feature b/functional-tests/features/matchers/matchers.feature index 4080a368..72370da8 100644 --- a/functional-tests/features/matchers/matchers.feature +++ b/functional-tests/features/matchers/matchers.feature @@ -1,21 +1,21 @@ Feature: Matchers As a Kakunin user I want to fill input and then check if the value matches the expected result -@wip -Scenario: Fill the input and check value - Given I visit the "main" page - When I click the "formLink" element - Then the "simpleForm" page is displayed - And I fill the "form" form with: - | nameInput | test | - And there is element "nameInput" with value "t:test" - And there is element "nameInput" containing "test" text - And there is no element "nameInput" with value "t:hello" - And there is no element "nameInput" containing "hello" text - And there is element "nameInput" matching "isVisible" matcher - And there is no element "nameInput" matching "isNotVisible" matcher - And there is element "nameInput" with "notEmpty" regex - And there is no element "nameInput" with "number" regex + + Scenario: Fill the input and check value + Given I visit the "main" page + When I click the "formLink" element + Then the "simpleForm" page is displayed + And I fill the "form" form with: + | nameInput | test | + And there is element "nameInput" with value "t:test" + And there is element "nameInput" containing "test" text + And there is no element "nameInput" with value "t:hello" + And there is no element "nameInput" containing "hello" text + And there is element "nameInput" matching "isVisible" matcher + And there is no element "nameInput" matching "isNotVisible" matcher + And there is element "nameInput" with "notEmpty" regex + And there is no element "nameInput" with "number" regex diff --git a/functional-tests/features/matchers/matchers_css.feature b/functional-tests/features/matchers/matchers_css.feature new file mode 100644 index 00000000..af4a5c45 --- /dev/null +++ b/functional-tests/features/matchers/matchers_css.feature @@ -0,0 +1,21 @@ +Feature: Matchers + As a Kakunin user + I want to fill input and then check if the value matches the expected result + + Scenario: Fill the input and check value + Given I visit the "main" page + When I click the "a[href='/form/simple']" element + Then the "simpleForm" page is displayed + And I fill the "form" form with: + | input[name="name"] | test | + And there is element "input[name='name']" with value "t:test" + And there is element "input[name='name']" containing "test" text + And there is no element "input[name='name']" with value "t:hello" + And there is no element "input[name='name']" containing "hello" text + And there is element "input[name='name']" matching "isVisible" matcher + And there is no element "input[name='name']" matching "isNotVisible" matcher + And there is element "input[name='name']" with "notEmpty" regex + And there is no element "input[name='name']" with "number" regex + + + diff --git a/functional-tests/features/navigation/navigate_to_given_page.feature b/functional-tests/features/navigation/navigate_to_given_page.feature index a0b1b77d..0a327b41 100644 --- a/functional-tests/features/navigation/navigate_to_given_page.feature +++ b/functional-tests/features/navigation/navigate_to_given_page.feature @@ -15,13 +15,17 @@ Feature: Navigation Then there is element "pageId" with value "t:myPageId" And there is element "title" with value "t:myPageTitle" - Scenario: Navigate to parametrized url with query string + Scenario: Navigate to parametrized url with additional params Given I visit the "navigationPages" page with parameters: - | pageId | myPageId | - | title | myPageTitle | - | queryParam1 | value1 | - | queryParam2 | value2 | - Then there is element "pageId" with value "t:myPageId" - And there is element "title" with value "t:myPageTitle" - And there is element "queryParam1" with value "t:value1" - And there is element "queryParam2" with value "t:value2" + | pageId | myPageId | + | additionalParam1 | value1 | + | title | myPageTitle | + | additionalParam2 | value2 | + Then the "additionalParams" page is displayed + # check again + Then I visit the "navigationPages" page with parameters: + | pageId | myPageId | + | additionalParam1 | value1 | + | title | myPageTitle | + | additionalParam2 | value2 | + Then the "additionalParams" page is displayed diff --git a/functional-tests/features/navigation/navigate_to_given_page_css.feature b/functional-tests/features/navigation/navigate_to_given_page_css.feature new file mode 100644 index 00000000..ee233907 --- /dev/null +++ b/functional-tests/features/navigation/navigate_to_given_page_css.feature @@ -0,0 +1,17 @@ +Feature: Navigation + As a kakunin user + I want to navigate to selected page + + Scenario: Navigate by link click + Given I visit the "main" page + When I click the "a[href='/form/simple']" element + Then the "simpleForm" page is displayed + And the "form" element is visible + + Scenario: Navigate to parametrized url + Given I visit the "navigationPages" page with parameters: + | pageId | myPageId | + | title | myPageTitle | + Then there is element "p.pageId" with value "t:myPageId" + And there is element "p.title" with value "t:myPageTitle" + diff --git a/functional-tests/features/testing-api/testing_delete_request.feature b/functional-tests/features/testing-api/testing_delete_request.feature new file mode 100644 index 00000000..ae102b69 --- /dev/null +++ b/functional-tests/features/testing-api/testing_delete_request.feature @@ -0,0 +1,7 @@ +Feature: Test server delete request + As a kakunin user + I want to test restApi delete request + + Scenario: REST get example test + Given I send "delete" request on "deleteTestEndpoint" endpoint + Then the response code should be "200" diff --git a/functional-tests/features/testing-api/testing_get_response.feature b/functional-tests/features/testing-api/testing_get_response.feature new file mode 100644 index 00000000..b81f7af0 --- /dev/null +++ b/functional-tests/features/testing-api/testing_get_response.feature @@ -0,0 +1,15 @@ +Feature: Test server get response + As a kakunin user + I want to test restApi get response + + Scenario: REST get example test + Given I send "GET" request on "getTestEndpoint" endpoint + Then the response code should be "200" + And the response should exact match to body: + """ + { + "id": 1, + "title": "Kaunin", + "body": "test" + } + """ diff --git a/functional-tests/features/testing-api/testing_headers_setting.feature b/functional-tests/features/testing-api/testing_headers_setting.feature new file mode 100644 index 00000000..4f3ab926 --- /dev/null +++ b/functional-tests/features/testing-api/testing_headers_setting.feature @@ -0,0 +1,15 @@ +Feature: Test setting headers + As a kakunin user + I want to set the headers + + Scenario: Setting http headers + Given I set request headers: + | User-Agent | Mozilla | + When I send "POST" request on "postTestEndpoint" endpoint with JSON body: + """ + { + "title": "adam", + "body": "test" + } + """ + Then the response code should be "403" diff --git a/functional-tests/features/testing-api/testing_patch_request.feature b/functional-tests/features/testing-api/testing_patch_request.feature new file mode 100644 index 00000000..a44dabe5 --- /dev/null +++ b/functional-tests/features/testing-api/testing_patch_request.feature @@ -0,0 +1,13 @@ +Feature: Test patch endpoint + As a kakunin user + I want to set test the patch endpoint + + Scenario: REST patch example test + Given I send "PATCH" request on "patchTestEndpoint" endpoint with JSON body: + """ + { + "first_name": "adam" + } + """ + Then the response code should be "200" + diff --git a/functional-tests/features/testing-api/testing_post_form_data.feature b/functional-tests/features/testing-api/testing_post_form_data.feature new file mode 100644 index 00000000..006af159 --- /dev/null +++ b/functional-tests/features/testing-api/testing_post_form_data.feature @@ -0,0 +1,8 @@ +Feature: Test server post request using form data + As a kakunin user + I want to test restApi post request + + Scenario: REST get example test + Given I send "POST" request on "postFormDataEndpoint" endpoint using form data: + | name | adam1 | + Then the response code should be "201" diff --git a/functional-tests/features/testing-api/testing_post_json.feature b/functional-tests/features/testing-api/testing_post_json.feature new file mode 100644 index 00000000..90d76469 --- /dev/null +++ b/functional-tests/features/testing-api/testing_post_json.feature @@ -0,0 +1,33 @@ +Feature: Test server post response + As a kakunin user + I want to test restApi post request + + Scenario: REST post example test + Given I send "POST" request on "postTestEndpoint" endpoint with JSON body: + """ + { + "name": "adam", + "title": "test" + } + """ + + Then the response code should be "201" + Then the response should match JSON schema: + """ + { + "title": "Posts schema", + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "name": { + "type": "string" + }, + "title": { + "type": "string" + } + }, + "required": ["code", "name", "title"] + } + """ diff --git a/functional-tests/features/wait-for-elements/wait_for_form_css.feature b/functional-tests/features/wait-for-elements/wait_for_form_css.feature new file mode 100644 index 00000000..8ff49b16 --- /dev/null +++ b/functional-tests/features/wait-for-elements/wait_for_form_css.feature @@ -0,0 +1,25 @@ +Feature: Wait for forms + As a kakunin user + I want fill and check form fields + + Scenario: Fill and check form fields + Given I visit the "main" page + When I click the ".appearForm" element + Then the "appearSimpleForm" page is displayed + When I click the ".colored" element + And I fill the "form" form with: + | input[name="name"] | d:test-dictionary:test-name | + | textarea[name="description"] | some description | + | input[type="checkbox"] | Checkbox Option 2 | + | input[type="checkbox"] | Checkbox Option 3 | + | input[type="radio"] | third-radio-option | + | select[name="status"] | unknown | + Then the "form" form is filled with: + | input[name="name"] | d:test-dictionary:test-name | + | textarea[name="description"] | some description | + | input[type="checkbox"] | Checkbox Option 2 | + | input[type="checkbox"] | Checkbox Option 3 | + | input[type="radio"] | third-radio-option | + | select[name="status"] | unknown | + When I click the "input[type='submit']" element + Then the "appearSimpleFormPost" page is displayed diff --git a/functional-tests/kakunin.conf.js b/functional-tests/kakunin.conf.js index 4f1f9e88..f3b8ae38 100644 --- a/functional-tests/kakunin.conf.js +++ b/functional-tests/kakunin.conf.js @@ -1,67 +1,56 @@ module.exports = { - "browserWidth": 1600, - "browserHeight": 900, - "timeout": 60, - "elementsVisibilityTimeout": 5, - "waitForPageTimeout": 5, - "downloadTimeout": 30, - "reports": "/reports", - "downloads": "/downloads", - "data": "/data", - "features": [ - "/features" - ], - "pages": [ - "/pages" - ], - "matchers": [ - "/matchers" - ], - "generators": [ - "/generators" - ], - "form_handlers": [ - "/form_handlers" - ], - "step_definitions": [ - "/step_definitions" - ], - "comparators": [ - "/comparators" - ], - "dictionaries": [ - "/dictionaries" - ], - "transformers": [ - "/transformers" - ], - "regexes": [ - "/regexes" - ], - "hooks": [ - "/hooks" - ], - "clearEmailInboxBeforeTests": false, - "clearCookiesAfterScenario": true, - "clearLocalStorageAfterScenario": true, - "email": null, - "headless": true, - "noGpu": false, - "type": "otherWeb", - "baseUrl": "http://localhost:8080", - "browserMob": { - "serverPort": 8887, - "port": 8888, - "host": "localhost" - }, - "accounts": { - "someAccount": { - "accounts": [ - { - "email": "", - "password": "" - } - ] - } + browserWidth: 1600, + browserHeight: 900, + timeout: 60, + elementsVisibilityTimeout: 5, + waitForPageTimeout: 5, + downloadTimeout: 30, + reports: '/reports', + downloads: '/downloads', + data: '/data', + features: ['/features'], + pages: ['/pages'], + matchers: ['/matchers'], + generators: ['/generators'], + form_handlers: ['/form_handlers'], + step_definitions: ['/step_definitions'], + comparators: ['/comparators'], + dictionaries: ['/dictionaries'], + transformers: ['/transformers'], + regexes: ['/regexes'], + hooks: ['/hooks'], + clearEmailInboxBeforeTests: false, + clearCookiesAfterScenario: true, + clearLocalStorageAfterScenario: true, + email: null, + headless: true, + noGpu: true, + type: 'otherWeb', + baseUrl: 'http://localhost:8080', + apiUrl: 'http://localhost:8080/', + browserMob: { + serverPort: 8887, + port: 8888, + host: 'localhost', + }, + browserstack: { + seleniumAddress: 'http://hub-cloud.browserstack.com/wd/hub', + defaultPort: 45691, + capabilities: { + 'browserstack.user': '', + 'browserstack.key': '', + 'browserstack.local': true, + browserName: 'chrome', } -} + }, + accounts: { + someAccount: { + accounts: [ + { + email: '', + password: '', + }, + ], + }, + }, +}; diff --git a/functional-tests/package.json b/functional-tests/package.json index f131e683..fc8c791f 100644 --- a/functional-tests/package.json +++ b/functional-tests/package.json @@ -7,24 +7,23 @@ "kakunin": "cross-env NODE_ENV=prod kakunin", "start": "pm2 update && pm2 start www", "stop": "pm2 delete www", - "test-ci": "npm run start && webdriver-manager update --gecko false && npm run kakunin -- --parallel 4 && npm run stop", - "test": "npm run start && webdriver-manager update && npm run kakunin && npm run stop" + "test-ci": "npm run start && npm run kakunin -- --parallel 4 && npm run stop", + "test": "npm run start && npm run kakunin && npm run stop" }, "author": "", "dependencies": { - "cross-env": "5.2.0", - "body-parser": "1.18.3", + "body-parser": "^1.18.3", + "cross-env": "^5.2.0", "eslint": "5.10.0", "eslint-config-airbnb": "17.1.0", "eslint-plugin-import": "2.14.0", "eslint-plugin-jsx-a11y": "6.1.2", "eslint-plugin-react": "7.11.1", "express": "4.16.4", - "nunjucks": "3.1.4", - "node-fetch": "2.3.0", "kakunin": "file:../", - "protractor": "5.4.1", - "webdriver-manager": "12.1.0" + "node-fetch": "2.3.0", + "nunjucks": "3.1.4", + "protractor": "^5.4.1" }, "license": "ISC", "devDependencies": { diff --git a/functional-tests/pages/additionalParams.js b/functional-tests/pages/additionalParams.js new file mode 100644 index 00000000..da6aa98f --- /dev/null +++ b/functional-tests/pages/additionalParams.js @@ -0,0 +1,13 @@ +'use strict'; + +const { BasePage } = require('kakunin'); + +class AdditionalParamsPage extends BasePage { + constructor() { + super(); + + this.url = '/navigation/pages/:id/titles/:title?additionalParam1=:value1&additionalParam2=:value2'; + } +} + +module.exports = AdditionalParamsPage; diff --git a/functional-tests/pages/buttonForm.js b/functional-tests/pages/buttonForm.js index 3f526b82..9b0ef170 100644 --- a/functional-tests/pages/buttonForm.js +++ b/functional-tests/pages/buttonForm.js @@ -9,7 +9,6 @@ class ButtonForm extends BasePage { this.url = '/form/disappear'; this.disappearBtn = $('#button'); - } } diff --git a/functional-tests/pages/main.js b/functional-tests/pages/main.js index e8b28c25..07d506cf 100644 --- a/functional-tests/pages/main.js +++ b/functional-tests/pages/main.js @@ -10,6 +10,7 @@ class MainPage extends BasePage { this.linkDivs = $$('.available-examples-links'); this.formLink = $('a[href="/form/simple"]'); + this.formSelectLink = $('a[href="/form/select"]'); this.absolutePageLink = $('a[href="/absolute-page"]'); this.googleLink = $('a[href="https://www.google.pl"]'); this.tabularDataLink = $('a[href="/tabular-data"]'); diff --git a/functional-tests/pages/matchers.js b/functional-tests/pages/matchers.js index dd3f3453..679f236b 100644 --- a/functional-tests/pages/matchers.js +++ b/functional-tests/pages/matchers.js @@ -8,6 +8,7 @@ class MatchersPage extends BasePage { this.url = '/matchers'; + this.dateMatcherText = $('p.date-matcher '); this.dateElement = $('span.current_date '); } } diff --git a/functional-tests/pages/simpleSelectForm.js b/functional-tests/pages/simpleSelectForm.js new file mode 100644 index 00000000..e51849e8 --- /dev/null +++ b/functional-tests/pages/simpleSelectForm.js @@ -0,0 +1,18 @@ +'use strict'; + +const { BasePage } = require('kakunin'); + +class SimpleForm extends BasePage { + constructor() { + super(); + + this.url = '/form/select'; + + this.form = $('form'); + this.selectPerson = $('#personlist'); + this.personOption = this.selectPerson.$$('option'); + this.submitButton = this.form.$('input[type="submit"]'); + } +} + +module.exports = SimpleForm; diff --git a/functional-tests/step_definitions/custom_json_parser.js b/functional-tests/step_definitions/custom_json_parser.js index aab618ba..93f2d337 100644 --- a/functional-tests/step_definitions/custom_json_parser.js +++ b/functional-tests/step_definitions/custom_json_parser.js @@ -1,25 +1,23 @@ const variableStore = require('kakunin').variableStore; const fetch = require('node-fetch'); -const { defineSupportCode } = require('kakunin'); +const { When } = require('kakunin'); -defineSupportCode(function ({ When }) { - When(/^compare given JSON string with stored "([^"]*)" JSON:$/, function(storedJsonArray, json) { - const removeNewLines = (str) => str.replace(/(\r\n|\n|\r)/gm, ''); +When(/^compare given JSON string with stored "([^"]*)" JSON:$/, function(storedJsonArray, json) { + const removeNewLines = str => str.replace(/(\r\n|\n|\r)/gm, ''); - const storedJsonString = JSON.stringify(variableStore.getVariableValue(storedJsonArray)); - const expectedJsonString = JSON.stringify(JSON.parse(removeNewLines(json))); + const storedJsonString = JSON.stringify(variableStore.getVariableValue(storedJsonArray)); + const expectedJsonString = JSON.stringify(JSON.parse(removeNewLines(json))); - if (storedJsonString === expectedJsonString) { - return Promise.resolve(); - } + if (storedJsonString === expectedJsonString) { + return Promise.resolve(); + } - return Promise.reject('JSON strings are not the same!'); - }); + return Promise.reject('JSON strings are not the same!'); +}); - When(/^I store the content from "([^"]*)" endpoint as "([^"]*)" variable/, function (url, variableName) { - return fetch(url) - .then(res => res.json()) - .then(data => variableStore.storeVariable(variableName, JSON.parse(data.content))); - }) +When(/^I store the content from "([^"]*)" endpoint as "([^"]*)" variable/, function(url, variableName) { + return fetch(url) + .then(res => res.json()) + .then(data => variableStore.storeVariable(variableName, JSON.parse(data.content))); }); diff --git a/functional-tests/www/index.js b/functional-tests/www/index.js index b05ffcd3..a731ba44 100644 --- a/functional-tests/www/index.js +++ b/functional-tests/www/index.js @@ -1,6 +1,5 @@ const express = require('express'); const nunjucks = require('nunjucks'); -const bodyParser = require('body-parser'); const path = require('path'); const app = express(); const { xlsxDataRouting } = require('./jsonData/xlsxData.router'); @@ -11,43 +10,43 @@ app.use('/assets', express.static(path.join(__dirname, 'assets'))); nunjucks.configure(app.get('views'), { autoescape: true, - express: app + express: app, }); -app.use(bodyParser.json()); -app.use(bodyParser.urlencoded({ extended: true })); +app.use(express.json()); +app.use(express.urlencoded({ extended: true })); -app.get('/', function (req, res) { +app.get('/', function(req, res) { res.render('index.njs'); }); -app.get('/drag-and-drop', function (req, res) { +app.get('/drag-and-drop', function(req, res) { res.render('drag-and-drop/index.njs'); }); -app.get('/tabular-data', function (req, res) { +app.get('/tabular-data', function(req, res) { res.render('table/tabular-data.njs'); }); -app.get('/absolute-page', function (req, res) { +app.get('/absolute-page', function(req, res) { res.render('absolute/index.njs'); }); -app.get('/form/simple', function (req, res) { +app.get('/form/simple', function(req, res) { res.render('form/simple.njs'); }); -app.get('/form/disappear', function (req, res) { +app.get('/form/disappear', function(req, res) { res.render('form/disappear.njs'); }); -app.post('/form/simple/post', function (req, res) { +app.post('/form/simple/post', function(req, res) { res.render('form/simple.njs', { - form: req.body + form: req.body, }); }); -app.get('/navigation/pages/:pageId/titles/:title', function (req, res) { +app.get('/navigation/pages/:pageId/titles/:title', function(req, res) { res.render('navigation/page.njs', { pageId: req.params.pageId, title: req.params.title, @@ -56,26 +55,87 @@ app.get('/navigation/pages/:pageId/titles/:title', function (req, res) { }); }); -app.get('/wait-for-appear/table', function (req, res) { +app.get('/wait-for-appear/table', function(req, res) { res.render('wait-for-appear/table.njs'); }); -app.get('/wait-for-appear/form', function (req, res) { +app.get('/wait-for-appear/form', function(req, res) { res.render('wait-for-appear/form.njs'); }); -app.post('/wait-for-appear/form/post', function (req, res) { +app.post('/wait-for-appear/form/post', function(req, res) { res.render('wait-for-appear/form.njs', { - form: req.body + form: req.body, }); }); -app.get('/matchers', function (req, res) { +app.get('/matchers', function(req, res) { res.render('matchers/matchers.njs'); }); +app.get('/form/select', function(req, res) { + res.render('form/select.njs'); +}); +app.post('/form/select/post', function(req, res) { + res.render('form/select.njs', { + form: req.body, + }); +}); + +app.delete('/deleteTestEndpoint',function(req, res, next){ + res.status(200); + return res.end(); +}); + +app.get('/getTestEndpoint', function (req, res) { + res.setHeader('Content-Type', 'application/json'); + const header = req.header('host'); + if (header === 'localhost:8080') { + return res.send(JSON.stringify( + { id: 1, + title: 'Kaunin', + body: 'test' } + )); + } + res.status(403); + return res.end(); +}); + +app.patch('/patchTestEndpoint', function (req, res) { + if(req.body.hasOwnProperty('first_name') === true) { + res.status(200); + return res.end(); + } + res.status(400) + return res.end(); +}); + +app.post('/postTestEndpoint', function (req, res) { + const name = req.body.name; + const title = req.body.title; + const header = req.header('User-Agent'); + const object = { code: 'created', name: name, title: title }; + if (header === 'Mozilla') { + res.status(403); + return res.end(); + } + res.status(201); + return res.json(object); +}); + +app.post('/postFormDataEndpoint', function (req, res) { + const contentType = req.header('Content-Type'); + + if (contentType !== 'multipart/form-data') { + res.status(403); + return res.end(); + } + res.status(201); + return res.end(); +}); + app.use('/xlsx', xlsxDataRouting()); -app.listen(8080, function () { +app.listen(8080, function() { console.log('Example app listening on port 8080!'); }); diff --git a/functional-tests/www/jsonData/xlsxData.router.js b/functional-tests/www/jsonData/xlsxData.router.js index 862f818a..ed53032f 100644 --- a/functional-tests/www/jsonData/xlsxData.router.js +++ b/functional-tests/www/jsonData/xlsxData.router.js @@ -5,38 +5,43 @@ function xlsxDataRouting() { router.get('/data-9rows', (req, res) => { res.json({ - content: '[["Schamberger PLC","33333003158","25","Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["JANEK","9912396963","2","Security Guards, Printing & Advertising, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["شركة تكامل القابضة","9912396963","2","Contracting & Maintenance, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["شركة تكامل القابضة","9912396963","2","Contracting & Maintenance, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["Bosco, Marks and Walker","9910412435","7","Contracting & Maintenance, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["Rippin-Torp","9912038835","7","Contracting & Maintenance, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["Kling-Bogan","9910412335","25","Contracting & Maintenance, Security Guards, Printing & Advertising, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["Hane, Bartoletti and Mitchell","9911038835","7","Contracting & Maintenance, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["Zemlak, Stiedemann and Green","9912496963","7","Contracting & Maintenance, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"]]' - }) + content: + '[["Schamberger PLC","33333003158","25","Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["JANEK","9912396963","2","Security Guards, Printing & Advertising, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["شركة تكامل القابضة","9912396963","2","Contracting & Maintenance, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["شركة تكامل القابضة","9912396963","2","Contracting & Maintenance, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["Bosco, Marks and Walker","9910412435","7","Contracting & Maintenance, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["Rippin-Torp","9912038835","7","Contracting & Maintenance, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["Kling-Bogan","9910412335","25","Contracting & Maintenance, Security Guards, Printing & Advertising, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["Hane, Bartoletti and Mitchell","9911038835","7","Contracting & Maintenance, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["Zemlak, Stiedemann and Green","9912496963","7","Contracting & Maintenance, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"]]', + }); }); router.get('/data-9rows-part', (req, res) => { res.json({ - content: '[["Schamberger PLC"],["JANEK"],["شركة تكامل القابضة"],["شركة تكامل القابضة"],["Bosco, Marks and Walker"],["Rippin-Torp"],["Kling-Bogan"],["Hane, Bartoletti and Mitchell"],["Zemlak, Stiedemann and Green"]]' - }) + content: + '[["Schamberger PLC"],["JANEK"],["شركة تكامل القابضة"],["شركة تكامل القابضة"],["Bosco, Marks and Walker"],["Rippin-Torp"],["Kling-Bogan"],["Hane, Bartoletti and Mitchell"],["Zemlak, Stiedemann and Green"]]', + }); }); router.get('/data-3rows', (req, res) => { res.json({ - content: '[["Schamberger PLC","33333003158","25","Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["JANEK","9912396963","2","Security Guards, Printing & Advertising, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["شركة تكامل القابضة","9912396963","2","Contracting & Maintenance, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"]]' - }) + content: + '[["Schamberger PLC","33333003158","25","Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["JANEK","9912396963","2","Security Guards, Printing & Advertising, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"],["شركة تكامل القابضة","9912396963","2","Contracting & Maintenance, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"]]', + }); }); router.get('/data-3rows-part', (req, res) => { res.json({ - content: '[["Rippin-Torp","9912038835"],["Kling-Bogan","9910412335"],["Hane, Bartoletti and Mitchell","9911038835"]]' - }) + content: + '[["Rippin-Torp","9912038835"],["Kling-Bogan","9910412335"],["Hane, Bartoletti and Mitchell","9911038835"]]', + }); }); router.get('/data-1row', (req, res) => { res.json({ - content: '[["Bosco, Marks and Walker","9910412435","7","Contracting & Maintenance, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"]]' - }) + content: + '[["Bosco, Marks and Walker","9910412435","7","Contracting & Maintenance, Food & Consumable supply, IT, Medical Supplies and Equipment, Motors & Vehicles, Office Furniture, Office Supplies"]]', + }); }); router.get('/data-1row-part', (req, res) => { res.json({ - content: '[["Bosco, Marks and Walker","9910412435"]]' - }) + content: '[["Bosco, Marks and Walker","9910412435"]]', + }); }); return router; diff --git a/functional-tests/www/views/form/select.njs b/functional-tests/www/views/form/select.njs new file mode 100644 index 00000000..9679c303 --- /dev/null +++ b/functional-tests/www/views/form/select.njs @@ -0,0 +1,13 @@ +{% extends 'layout/default.njs' %} + +{% block content %} +
+ + +
+{% endblock %} diff --git a/functional-tests/www/views/index.njs b/functional-tests/www/views/index.njs index 31e91985..ff2ea338 100644 --- a/functional-tests/www/views/index.njs +++ b/functional-tests/www/views/index.njs @@ -12,6 +12,6 @@ Simple wait for form
Simple matchers
Matchers in a new tab
- + Simple select example
{% endblock %} diff --git a/functional-tests/www/views/matchers/matchers.njs b/functional-tests/www/views/matchers/matchers.njs index 08974ac1..852914cb 100644 --- a/functional-tests/www/views/matchers/matchers.njs +++ b/functional-tests/www/views/matchers/matchers.njs @@ -9,7 +9,7 @@ } -

Date/Time:

+

Date/Time:

diff --git a/package-lock.json b/package-lock.json index adde3aad..a461d7d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "kakunin", - "version": "2.6.1", + "version": "3.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -8,7 +8,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", - "dev": true, "requires": { "@babel/highlight": "^7.0.0" } @@ -17,7 +16,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", - "dev": true, "requires": { "chalk": "^2.0.0", "esutils": "^2.0.2", @@ -27,35 +25,26 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" } } }, "@babel/polyfill": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.4.0.tgz", - "integrity": "sha512-bVsjsrtsDflIHp5I6caaAa2V25Kzn50HKPL6g3X0P0ni1ks+58cPB8Mz6AOKVuRPgaVdq/OwEUc/1vKqX+Mo4A==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.4.4.tgz", + "integrity": "sha512-WlthFLfhQQhh+A2Gn5NSFl0Huxz36x86Jn+E9OW7ibK8edKPq+KLy4apM1yDpQ8kJOVi1OVjpP4vSDLdrI04dg==", "requires": { "core-js": "^2.6.5", "regenerator-runtime": "^0.13.2" } }, "@babel/runtime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0.tgz", - "integrity": "sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.4.tgz", + "integrity": "sha512-w0+uT71b6Yi7i5SE0co4NioIpSYS6lLiXvCzWzGSKvpK5vdQtCbICHMj+gbAKAOtxiV6HsVh/MBdaF9EQ6faSg==", "dev": true, "requires": { - "regenerator-runtime": "^0.12.0" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", - "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==", - "dev": true - } + "regenerator-runtime": "^0.13.2" } }, "@samverschueren/stream-to-observable": { @@ -67,30 +56,175 @@ "any-observable": "^0.3.0" } }, + "@types/cucumber": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/cucumber/-/cucumber-4.0.5.tgz", + "integrity": "sha512-0KRiDjnzCZz7WDhdH0N418Kpsa1utoFvA1KSk38LPi2SjLy1EaD/hJcWPXCG+6kj5O+qXMPXW3VjzxWX3T/6HA==", + "dev": true + }, + "@types/events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", + "dev": true + }, + "@types/extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/extend/-/extend-3.0.1.tgz", + "integrity": "sha512-R1g/VyKFFI2HLC1QGAeTtCBWCo6n75l41OnsVYNbmKG+kempOESaodf6BeJyUM3Q0rKa/NQcTHbB2+66lNnxLw==", + "dev": true + }, + "@types/faker": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/faker/-/faker-4.1.5.tgz", + "integrity": "sha512-YSDqoBEWYGdNk53xSkkb6REaUaVSlIjxIAGjj/nbLzlZOit7kUU+nA2zC2qQkIVO4MQ+3zl4Sz7aw+kbpHHHUQ==", + "dev": true + }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/inquirer": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-6.0.1.tgz", + "integrity": "sha512-O9rEHE9iBvYaFAGS0fAlDzqY/3CsOrRKzni4zwnAEce2JrHUEbXAce2Pwwe8ZGzmQkucwSXn1tSiKig37INgfA==", + "dev": true, + "requires": { + "@types/through": "*", + "rxjs": ">=6.4.0" + } + }, + "@types/jest": { + "version": "24.0.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.12.tgz", + "integrity": "sha512-60sjqMhat7i7XntZckcSGV8iREJyXXI6yFHZkSZvCPUeOnEJ/VP1rU/WpEWQ56mvoh8NhC+sfKAuJRTyGtCOow==", + "dev": true, + "requires": { + "@types/jest-diff": "*" + } + }, + "@types/jest-diff": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@types/jest-diff/-/jest-diff-20.0.1.tgz", + "integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==", + "dev": true + }, + "@types/lodash": { + "version": "4.14.123", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.123.tgz", + "integrity": "sha512-pQvPkc4Nltyx7G1Ww45OjVqUsJP4UsZm+GWJpigXgkikZqJgRm4c48g027o6tdgubWHwFRF15iFd+Y4Pmqv6+Q==", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=", + "dev": true + }, + "@types/mkdirp": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-0.5.2.tgz", + "integrity": "sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/moment": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@types/moment/-/moment-2.13.0.tgz", + "integrity": "sha1-YE69GJvDvDShVIaJQE5hoqSqyJY=", + "dev": true, + "requires": { + "moment": "*" + } + }, + "@types/node": { + "version": "10.14.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.6.tgz", + "integrity": "sha512-Fvm24+u85lGmV4hT5G++aht2C5I4Z4dYlWZIh62FAfFO/TfzXtPpoLI6I7AuBWkIFqZCnhFOoTT7RjjaIL5Fjg==", + "dev": true + }, + "@types/node-fetch": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.3.3.tgz", + "integrity": "sha512-MIplfRxrDTsIbOLGyFqNWTmxho5Fs710Kul35tEcaqkx9He86mGbSCDvILL0LCMfmm+oJ8tDg51crE9+pJGgiQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", + "dev": true + }, + "@types/protractor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/protractor/-/protractor-4.0.0.tgz", + "integrity": "sha1-EZFYRbONSD9wYNdOyOLu7kNXOZk=", + "dev": true, + "requires": { + "protractor": "*" + } + }, "@types/q": { "version": "0.0.32", "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=" }, "@types/selenium-webdriver": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.15.tgz", - "integrity": "sha512-5nh8/K2u9p4bk95GGCJB7KBvewaB0TUziZ9DTr+mR2I6RoO4OJVqx7rxK83hs2J1tomwtCGkhiW+Dy8EUnfB+Q==" + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.16.tgz", + "integrity": "sha512-lMC2G0ItF2xv4UCiwbJGbnJlIuUixHrioOhNGHSCsYCJ8l4t9hMCUimCytvFv7qy6AfSzRxhRHoGa+UqaqwyeA==" + }, + "@types/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-bZgjwIWu9gHCjirKJoOlLzGi5N0QgZ5t7EXEuoqyWCHTuSddURXo3FOBYDyRPNOWzZ6NbkLvZnVkn483Y/tvcQ==", + "dev": true, + "requires": { + "@types/glob": "*", + "@types/node": "*" + } + }, + "@types/through": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.29.tgz", + "integrity": "sha512-9a7C5VHh+1BKblaYiq+7Tfc+EOmjMdZaD1MYtkQjSoxgB69tBjW98ry6SKsi4zEIWztLOMRuL87A3bdT/Fc/4w==", + "dev": true, + "requires": { + "@types/node": "*" + } }, "@wdio/config": { - "version": "5.7.8", - "resolved": "https://registry.npmjs.org/@wdio/config/-/config-5.7.8.tgz", - "integrity": "sha512-XYx1OtJ/9iWk+s9svH1QmyKdWtOakK1o/0V7WBHBFQxR/iSpxRi3IyDPp2nnLTFz6T5eSipH4yS92bAJ1Q6XkQ==", + "version": "5.8.1", + "resolved": "https://registry.npmjs.org/@wdio/config/-/config-5.8.1.tgz", + "integrity": "sha512-/1DTXXnsJa04fQXRQz0uwqlkE3Vc9hY9c8P6LJ5vIQOL4tK1MuiHWHpdfywPZlc1Kr8g5oJLSygX9WrSFCZHsA==", "requires": { - "@wdio/logger": "^5.7.8", + "@wdio/logger": "^5.8.0", "deepmerge": "^2.0.1", "glob": "^7.1.2" } }, "@wdio/logger": { - "version": "5.7.8", - "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-5.7.8.tgz", - "integrity": "sha512-cbX/fHoTQ7xZvl8X4r828UjWv/ccKhpzPuNGZGukK2DRC7vSOg8sAi8bKNyjvv8nedaZkCQKaSFmsuHHlbIJ7g==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-5.8.0.tgz", + "integrity": "sha512-YQ6fybKvWEZPBVf/rrhedohj6g4U1cb9w/6IkHOOhDYbiwwvmAVk7h7QTCsdVc1pxO7Y4/5gI46bmoASgPsrnw==", "requires": { "chalk": "^2.3.0", "loglevel": "^1.6.0", @@ -99,46 +233,43 @@ } }, "@wdio/repl": { - "version": "5.7.8", - "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-5.7.8.tgz", - "integrity": "sha512-Qbm7UTtFW3QsqyhRCDvVmB4gfo83yWeUVSvHS2eeBZGEcxEU/oZZV0d7NwSwJcYjWO53U8a0ScxMe7d2YknZcA==", + "version": "5.8.1", + "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-5.8.1.tgz", + "integrity": "sha512-vbX3tCeNjav07N5wYbeJQT5wM1VUoMk0++dQNCP8H05j0Hyqs1Z8K4VpLa1JCieWxQIUFgY703y6cZ6+YhDJEg==", "requires": { - "@wdio/config": "^5.7.8" + "@wdio/config": "^5.8.1" } }, "abab": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", - "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", - "dev": true + "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==" }, "acorn": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", - "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", - "dev": true + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" }, "acorn-globals": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.0.tgz", - "integrity": "sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw==", - "dev": true, + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.2.tgz", + "integrity": "sha512-BbzvZhVtZP+Bs1J1HcwrQe8ycfO0wStkSGxuul3He3GkHOIZ6eTqOkPuw9IP1X3+IkOo4wiJmwkobzXYz4wewQ==", "requires": { "acorn": "^6.0.1", "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==" + } } }, - "acorn-jsx": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", - "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", - "dev": true - }, "acorn-walk": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", - "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", - "dev": true + "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==" }, "adler-32": { "version": "1.2.0", @@ -203,932 +334,618 @@ "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" }, "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "dev": true, - "optional": true, - "requires": { - "micromatch": "^2.1.5", - "normalize-path": "^2.0.0" - } - }, - "append-transform": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", - "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", - "dev": true, - "requires": { - "default-require-extensions": "^1.0.0" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "aria-query": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz", - "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=", - "dev": true, - "requires": { - "ast-types-flow": "0.0.7", - "commander": "^2.11.0" - } - }, - "arr-diff": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", - "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", - "dev": true - }, - "array-includes": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", - "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.7.0" - } - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" - }, - "assertion-error-formatter": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error-formatter/-/assertion-error-formatter-2.0.1.tgz", - "integrity": "sha512-cjC3jUCh9spkroKue5PDSKH5RFQ/KNuZJhk3GwHYmB/8qqETxLOmMdLH+ohi/VukNzxDlMvIe7zScvLoOdhb6Q==", - "requires": { - "diff": "^3.0.0", - "pad-right": "^0.2.2", - "repeat-string": "^1.6.1" - } - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", - "dev": true - }, - "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true - }, - "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } - }, - "async-each": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.2.tgz", - "integrity": "sha512-6xrbvN0MOBKSJDdonmSSz2OwFSgxRaVtBDes26mj9KIGtDo+g9xosFRSC+i1gQh2oAN/tQ62AI/pGZGQjVOiRg==", - "dev": true, - "optional": true - }, - "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" - }, - "axobject-query": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz", - "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==", - "dev": true, - "requires": { - "ast-types-flow": "0.0.7" - } - }, - "babel-cli": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", - "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", - "dev": true, + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "requires": { - "babel-core": "^6.26.0", - "babel-polyfill": "^6.26.0", - "babel-register": "^6.26.0", - "babel-runtime": "^6.26.0", - "chokidar": "^1.6.1", - "commander": "^2.11.0", - "convert-source-map": "^1.5.0", - "fs-readdir-recursive": "^1.0.0", - "glob": "^7.1.2", - "lodash": "^4.17.4", - "output-file-sync": "^1.1.2", - "path-is-absolute": "^1.0.1", - "slash": "^1.0.0", - "source-map": "^0.5.6", - "v8flags": "^2.1.1" - } - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" }, "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "requires": { - "ansi-regex": "^2.0.0" + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } } }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "babel-core": { - "version": "6.26.3", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", - "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-generator": "^6.26.0", - "babel-helpers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-register": "^6.26.0", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "convert-source-map": "^1.5.1", - "debug": "^2.6.9", - "json5": "^0.5.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.4", - "path-is-absolute": "^1.0.1", - "private": "^0.1.8", - "slash": "^1.0.0", - "source-map": "^0.5.7" - }, - "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "babel-generator": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", - "dev": true, - "requires": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.7", - "trim-right": "^1.0.1" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "babel-helper-builder-binary-assignment-operator-visitor": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", - "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true, - "requires": { - "babel-helper-explode-assignable-expression": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-call-delegate": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-define-map": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", - "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "babel-helper-explode-assignable-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", - "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } } }, - "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true, + "append-transform": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", + "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", "requires": { - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "default-require-extensions": "^1.0.0" } }, - "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "sprintf-js": "~1.0.2" } }, - "babel-helper-hoist-variables": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "arr-flatten": "^1.0.1" } }, - "babel-helper-optimise-call-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" }, - "babel-helper-regex": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", - "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" }, - "babel-helper-remap-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", - "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=" }, - "babel-helper-replace-supers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "requires": { - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "array-uniq": "^1.0.1" } }, - "babel-helpers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" }, - "babel-jest": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-23.6.0.tgz", - "integrity": "sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew==", - "dev": true, - "requires": { - "babel-plugin-istanbul": "^4.1.6", - "babel-preset-jest": "^23.2.0" - } + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" }, - "babel-plugin-check-es2015-constants": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", "requires": { - "babel-runtime": "^6.22.0" + "safer-buffer": "~2.1.0" } }, - "babel-plugin-istanbul": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz", - "integrity": "sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==", - "dev": true, - "requires": { - "babel-plugin-syntax-object-rest-spread": "^6.13.0", - "find-up": "^2.1.0", - "istanbul-lib-instrument": "^1.10.1", - "test-exclude": "^4.2.1" - } + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, - "babel-plugin-jest-hoist": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz", - "integrity": "sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc=", - "dev": true + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" }, - "babel-plugin-syntax-async-functions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", - "dev": true - }, - "babel-plugin-syntax-exponentiation-operator": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", - "dev": true + "assertion-error-formatter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error-formatter/-/assertion-error-formatter-2.0.1.tgz", + "integrity": "sha512-cjC3jUCh9spkroKue5PDSKH5RFQ/KNuZJhk3GwHYmB/8qqETxLOmMdLH+ohi/VukNzxDlMvIe7zScvLoOdhb6Q==", + "requires": { + "diff": "^3.0.0", + "pad-right": "^0.2.2", + "repeat-string": "^1.6.1" + } }, - "babel-plugin-syntax-object-rest-spread": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", - "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", - "dev": true + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" }, - "babel-plugin-syntax-trailing-function-commas": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", - "dev": true + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==" }, - "babel-plugin-transform-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", - "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true, + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "requires": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-functions": "^6.8.0", - "babel-runtime": "^6.22.0" + "lodash": "^4.17.11" } }, - "babel-plugin-transform-es2015-arrow-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" }, - "babel-plugin-transform-es2015-block-scoped-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "requires": { - "babel-runtime": "^6.22.0" + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } } }, - "babel-plugin-transform-es2015-block-scoping": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true, + "babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", "requires": { + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", "babel-runtime": "^6.26.0", "babel-template": "^6.26.0", "babel-traverse": "^6.26.0", "babel-types": "^6.26.0", - "lodash": "^4.17.4" + "babylon": "^6.18.0", + "convert-source-map": "^1.5.1", + "debug": "^2.6.9", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.8", + "slash": "^1.0.0", + "source-map": "^0.5.7" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } } }, - "babel-plugin-transform-es2015-classes": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", "requires": { - "babel-helper-define-map": "^6.24.1", - "babel-helper-function-name": "^6.24.1", - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-helper-replace-supers": "^6.24.1", "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } } }, - "babel-plugin-transform-es2015-computed-properties": { + "babel-helpers": { "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true, + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", "requires": { "babel-runtime": "^6.22.0", "babel-template": "^6.24.1" } }, - "babel-plugin-transform-es2015-destructuring": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-duplicate-keys": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true, + "babel-jest": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-23.6.0.tgz", + "integrity": "sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew==", "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "babel-plugin-istanbul": "^4.1.6", + "babel-preset-jest": "^23.2.0" } }, - "babel-plugin-transform-es2015-for-of": { + "babel-messages": { "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true, + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", "requires": { "babel-runtime": "^6.22.0" } }, - "babel-plugin-transform-es2015-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true, + "babel-plugin-istanbul": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz", + "integrity": "sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==", "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "babel-plugin-syntax-object-rest-spread": "^6.13.0", + "find-up": "^2.1.0", + "istanbul-lib-instrument": "^1.10.1", + "test-exclude": "^4.2.1" } }, - "babel-plugin-transform-es2015-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } + "babel-plugin-jest-hoist": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz", + "integrity": "sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc=" }, - "babel-plugin-transform-es2015-modules-amd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=" }, - "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", - "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", "dev": true, "requires": { - "babel-plugin-transform-strict-mode": "^6.24.1", "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-types": "^6.26.0" + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "dev": true + } } }, - "babel-plugin-transform-es2015-modules-systemjs": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true, + "babel-preset-jest": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz", + "integrity": "sha1-jsegOhOPABoaj7HoETZSvxpV2kY=", "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" + "babel-plugin-jest-hoist": "^23.2.0", + "babel-plugin-syntax-object-rest-spread": "^6.13.0" } }, - "babel-plugin-transform-es2015-modules-umd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", "requires": { - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-object-super": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true, - "requires": { - "babel-helper-replace-supers": "^6.24.1", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-parameters": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true, - "requires": { - "babel-helper-call-delegate": "^6.24.1", - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-spread": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-template-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-typeof-symbol": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "regexpu-core": "^2.0.0" - } - }, - "babel-plugin-transform-exponentiation-operator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true, - "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", - "babel-plugin-syntax-exponentiation-operator": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-object-rest-spread": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", - "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "dev": true, - "requires": { - "babel-plugin-syntax-object-rest-spread": "^6.8.0", - "babel-runtime": "^6.26.0" - } - }, - "babel-plugin-transform-regenerator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", - "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "dev": true, - "requires": { - "regenerator-transform": "^0.10.0" - } - }, - "babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-polyfill": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", - "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "regenerator-runtime": "^0.10.5" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", - "dev": true - } - } - }, - "babel-preset-env": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", - "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "^6.22.0", - "babel-plugin-syntax-trailing-function-commas": "^6.22.0", - "babel-plugin-transform-async-to-generator": "^6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoping": "^6.23.0", - "babel-plugin-transform-es2015-classes": "^6.23.0", - "babel-plugin-transform-es2015-computed-properties": "^6.22.0", - "babel-plugin-transform-es2015-destructuring": "^6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", - "babel-plugin-transform-es2015-for-of": "^6.23.0", - "babel-plugin-transform-es2015-function-name": "^6.22.0", - "babel-plugin-transform-es2015-literals": "^6.22.0", - "babel-plugin-transform-es2015-modules-amd": "^6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-umd": "^6.23.0", - "babel-plugin-transform-es2015-object-super": "^6.22.0", - "babel-plugin-transform-es2015-parameters": "^6.23.0", - "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", - "babel-plugin-transform-es2015-spread": "^6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", - "babel-plugin-transform-es2015-template-literals": "^6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", - "babel-plugin-transform-exponentiation-operator": "^6.22.0", - "babel-plugin-transform-regenerator": "^6.22.0", - "browserslist": "^3.2.6", - "invariant": "^2.2.2", - "semver": "^5.3.0" - } - }, - "babel-preset-jest": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz", - "integrity": "sha1-jsegOhOPABoaj7HoETZSvxpV2kY=", - "dev": true, - "requires": { - "babel-plugin-jest-hoist": "^23.2.0", - "babel-plugin-syntax-object-rest-spread": "^6.13.0" - } - }, - "babel-register": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "dev": true, - "requires": { - "babel-core": "^6.26.0", - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "home-or-tmp": "^2.0.0", - "lodash": "^4.17.4", - "mkdirp": "^0.5.1", - "source-map-support": "^0.4.15" + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" } }, "babel-runtime": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, "requires": { "core-js": "^2.4.0", "regenerator-runtime": "^0.11.0" @@ -1137,8 +954,7 @@ "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" } } }, @@ -1146,7 +962,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true, "requires": { "babel-runtime": "^6.26.0", "babel-traverse": "^6.26.0", @@ -1159,7 +974,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, "requires": { "babel-code-frame": "^6.26.0", "babel-messages": "^6.23.0", @@ -1176,7 +990,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -1184,8 +997,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -1193,7 +1005,6 @@ "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, "requires": { "babel-runtime": "^6.26.0", "esutils": "^2.0.2", @@ -1204,8 +1015,7 @@ "babylon": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" }, "balanced-match": { "version": "1.0.0", @@ -1216,7 +1026,6 @@ "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, "requires": { "cache-base": "^1.0.1", "class-utils": "^0.3.5", @@ -1231,7 +1040,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, "requires": { "is-descriptor": "^1.0.0" } @@ -1240,7 +1048,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -1249,7 +1056,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -1258,7 +1064,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -1268,14 +1073,12 @@ "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, @@ -1292,13 +1095,6 @@ "resolved": "https://registry.npmjs.org/becke-ch--regex--s0-0-v1--base--pl--lib/-/becke-ch--regex--s0-0-v1--base--pl--lib-1.4.0.tgz", "integrity": "sha1-Qpzuu/pffpNueNc/vcfacWKyDiA=" }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true, - "optional": true - }, "blocking-proxy": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz", @@ -1308,9 +1104,9 @@ } }, "bluebird": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", - "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==" + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.4.tgz", + "integrity": "sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw==" }, "brace-expansion": { "version": "1.1.11", @@ -1325,7 +1121,6 @@ "version": "1.8.5", "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, "requires": { "expand-range": "^1.8.1", "preserve": "^0.2.0", @@ -1335,14 +1130,12 @@ "browser-process-hrtime": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", - "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", - "dev": true + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==" }, "browser-resolve": { "version": "1.11.3", "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", - "dev": true, "requires": { "resolve": "1.1.7" }, @@ -1350,8 +1143,7 @@ "resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" } } }, @@ -1360,17 +1152,7 @@ "resolved": "https://registry.npmjs.org/browsermob-proxy/-/browsermob-proxy-1.0.10.tgz", "integrity": "sha512-M/mrsFBwZsHVlVFmIk4xg/l7E6rWK0Xq+BKNCfFW2ITROwubqWhy2/Eg+JvQAYxDRJ3S/v0aaHrnNjm9yehlKg==", "requires": { - "webdriverio": "^5.7.8" - } - }, - "browserslist": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", - "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000844", - "electron-to-chromium": "^1.3.47" + "webdriverio": "^5.8.3" } }, "browserstack": { @@ -1381,11 +1163,31 @@ "https-proxy-agent": "^2.2.1" } }, + "browserstack-local": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.0.tgz", + "integrity": "sha512-BUJWxIsJkJxqfTPJIvGWTsf+IYSqSFUeFNW9tnuyTG7va/0LkXLhIi/ErFGDle1urQkol48HlQUXj4QrliXFpg==", + "requires": { + "https-proxy-agent": "^2.2.1", + "is-running": "^2.0.0", + "ps-tree": "=1.1.1", + "sinon": "^1.17.6", + "temp-fs": "^0.9.9" + } + }, + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "2.x" + } + }, "bser": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/bser/-/bser-2.0.0.tgz", "integrity": "sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk=", - "dev": true, "requires": { "node-int64": "^0.4.0" } @@ -1395,11 +1197,16 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, "requires": { "collection-visit": "^1.0.0", "component-emitter": "^1.2.1", @@ -1415,8 +1222,7 @@ "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" } } }, @@ -1427,14 +1233,6 @@ "dev": true, "requires": { "callsites": "^2.0.0" - }, - "dependencies": { - "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "dev": true - } } }, "caller-path": { @@ -1447,28 +1245,19 @@ } }, "callsites": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.0.0.tgz", - "integrity": "sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw==", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=" }, "camelcase": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30000955", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000955.tgz", - "integrity": "sha512-6AwmIKgqCYfDWWadRkAuZSHMQP4Mmy96xAXEdRBlN/luQhlRYOKgwOlZ9plpCOsVbBuqbTmGqDK3JUM/nlr8CA==", - "dev": true + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" }, "capture-exit": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-1.2.0.tgz", "integrity": "sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28=", - "dev": true, "requires": { "rsvp": "^3.3.3" } @@ -1479,11 +1268,13 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "cfb": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.0.8.tgz", - "integrity": "sha1-d/ITST1pfXVP2cD1UR6rWtctAs8=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.1.0.tgz", + "integrity": "sha512-ZqfxNGWTMKhd0a/n6YKJLq8hWbd5kR3cA4kXwUj9vVEdHlwJ09werR8gN15Z7Y1FTXqdD6dE3GGCxv4uc28raA==", "requires": { - "commander": "^2.14.1", + "adler-32": "~1.2.0", + "commander": "^2.16.0", + "crc-32": "~1.2.0", "printj": "~1.1.2" } }, @@ -1500,19 +1291,6 @@ "type-detect": "^4.0.5" } }, - "chai-as-promised": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", - "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", - "requires": { - "check-error": "^1.0.2" - } - }, - "chai-string": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/chai-string/-/chai-string-1.5.0.tgz", - "integrity": "sha512-sydDC3S3pNAQMYwJrs6dQX0oBQ6KfIPuOZ78n7rocW0eJJlsHPh2t3kwW7xfwYA/1Bf6/arGtSUo16rxR2JFlw==" - }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -1538,40 +1316,20 @@ "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz", "integrity": "sha1-sffn/HPSXn/R1FWtyU4UODAYK1o=" }, - "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true, - "optional": true, - "requires": { - "anymatch": "^1.3.0", - "async-each": "^1.0.0", - "fsevents": "^1.0.0", - "glob-parent": "^2.0.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^2.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0" - } - }, "chownr": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==" }, "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==" }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, "requires": { "arr-union": "^3.1.0", "define-property": "^0.2.5", @@ -1583,7 +1341,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -1591,8 +1348,7 @@ "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" } } }, @@ -1639,12 +1395,6 @@ "number-is-nan": "^1.0.0" } }, - "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true - }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -1685,8 +1435,7 @@ "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" }, "code-point-at": { "version": "1.1.0", @@ -1694,9 +1443,9 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "codepage": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.13.1.tgz", - "integrity": "sha512-KnY6cQlgkfBjplnQkLk3M5KEfAKa7i9SMqXp+bMuy2/bgYovvU4LDAQvkMaoScwhvozA9VUtgnbS4Z8f7zVA8w==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.14.0.tgz", + "integrity": "sha1-jL4lSBMjVZ19MHVxsP/5HnodL5k=", "requires": { "commander": "~2.14.1", "exit-on-epipe": "~1.0.1" @@ -1713,7 +1462,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, "requires": { "map-visit": "^1.0.0", "object-visit": "^1.0.0" @@ -1746,32 +1494,24 @@ } }, "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==" + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==" }, "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, "convert-source-map": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", - "dev": true, "requires": { "safe-buffer": "~5.1.1" } @@ -1779,8 +1519,7 @@ "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" }, "core-js": { "version": "2.6.5", @@ -1804,16 +1543,6 @@ "parse-json": "^4.0.0" }, "dependencies": { - "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", - "dev": true, - "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - } - }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -1823,12 +1552,6 @@ "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" } - }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true } } }, @@ -1845,7 +1568,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.2.0.tgz", "integrity": "sha512-jtdNFfFW1hB7sMhr/H6rW1Z45LFqyI431m3qU6bFXcQ3Eh7LtBuG3h74o7ohHZ3crrRkkqHlo4jYHFPcjroANg==", - "dev": true, "requires": { "cross-spawn": "^6.0.5", "is-windows": "^1.0.0" @@ -1871,14 +1593,12 @@ "cssom": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.6.tgz", - "integrity": "sha512-DtUeseGk9/GBW0hl0vVPpU22iHL6YB5BUX7ml1hB+GMpo0NX5G4voX3kdWiMSEguFtcW3Vh3djqNF4aIe6ne0A==", - "dev": true + "integrity": "sha512-DtUeseGk9/GBW0hl0vVPpU22iHL6YB5BUX7ml1hB+GMpo0NX5G4voX3kdWiMSEguFtcW3Vh3djqNF4aIe6ne0A==" }, "cssstyle": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.2.2.tgz", "integrity": "sha512-43wY3kl1CVQSvL7wUY1qXkxVGkStjpkDmVjiIKX8R97uhajy8Bybay78uOtqvh7Q5GK75dNPfW0geWjE6qQQow==", - "dev": true, "requires": { "cssom": "0.3.x" } @@ -1940,12 +1660,6 @@ "es5-ext": "^0.10.9" } }, - "damerau-levenshtein": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz", - "integrity": "sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ=", - "dev": true - }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -1958,7 +1672,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", - "dev": true, "requires": { "abab": "^2.0.0", "whatwg-mimetype": "^2.2.0", @@ -1969,7 +1682,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", - "dev": true, "requires": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", @@ -2000,8 +1712,7 @@ "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, "dedent": { "version": "0.7.0", @@ -2020,8 +1731,7 @@ "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" }, "deepmerge": { "version": "2.2.1", @@ -2032,27 +1742,14 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", - "dev": true, "requires": { "strip-bom": "^2.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - } } }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, "requires": { "object-keys": "^1.0.12" } @@ -2061,7 +1758,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, "requires": { "is-descriptor": "^1.0.2", "isobject": "^3.0.1" @@ -2071,7 +1767,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -2080,7 +1775,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -2089,7 +1783,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -2099,14 +1792,12 @@ "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, @@ -2133,7 +1824,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, "requires": { "repeating": "^2.0.0" } @@ -2141,32 +1831,26 @@ "detect-newline": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", - "dev": true + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=" }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, "domexception": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", - "dev": true, "requires": { "webidl-conversions": "^4.0.2" } }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" + }, "duration": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/duration/-/duration-0.2.2.tgz", @@ -2185,24 +1869,12 @@ "safer-buffer": "^2.1.0" } }, - "electron-to-chromium": { - "version": "1.3.122", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.122.tgz", - "integrity": "sha512-3RKoIyCN4DhP2dsmleuFvpJAIDOseWH88wFYBzb22CSwoFDSWRc4UAMfrtc9h8nBdJjTNIN3rogChgOy6eFInw==", - "dev": true - }, "elegant-spinner": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", "dev": true }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", @@ -2215,7 +1887,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, "requires": { "is-arrayish": "^0.2.1" } @@ -2232,7 +1903,6 @@ "version": "1.13.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", - "dev": true, "requires": { "es-to-primitive": "^1.2.0", "function-bind": "^1.1.1", @@ -2246,7 +1916,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", - "dev": true, "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -2254,9 +1923,9 @@ } }, "es5-ext": { - "version": "0.10.49", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.49.tgz", - "integrity": "sha512-3NMEhi57E31qdzmYp2jwRArIUsj1HI/RxbQ4bgnSB+AIKIxsAmTiK83bYMifIcpWvEc3P1X30DhUKOqEtF/kvg==", + "version": "0.10.50", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.50.tgz", + "integrity": "sha512-KMzZTPBkeQV/JcSQhI5/z6d9VWJ3EnQ194USTUwIYZ2ZbpN8+SGXQKt1h68EX44+qt+Fzr8DO17vnxrw7c3agw==", "requires": { "es6-iterator": "~2.0.3", "es6-symbol": "~3.1.1", @@ -2304,7 +1973,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", - "dev": true, "requires": { "esprima": "^3.1.3", "estraverse": "^4.2.0", @@ -2316,338 +1984,77 @@ "esprima": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "optional": true } } }, - "eslint": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", - "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.9.1", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "eslint-scope": "^4.0.3", - "eslint-utils": "^1.3.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^5.0.1", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.7.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "inquirer": "^6.2.2", - "js-yaml": "^3.13.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.11", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^5.5.1", - "strip-ansi": "^4.0.0", - "strip-json-comments": "^2.0.1", - "table": "^5.2.3", - "text-table": "^0.2.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "globals": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", - "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", - "dev": true - } - } - }, - "eslint-config-airbnb": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-17.1.0.tgz", - "integrity": "sha512-R9jw28hFfEQnpPau01NO5K/JWMGLi6aymiF6RsnMURjTk+MqZKllCqGK/0tOvHkPi/NWSSOU2Ced/GX++YxLnw==", - "dev": true, - "requires": { - "eslint-config-airbnb-base": "^13.1.0", - "object.assign": "^4.1.0", - "object.entries": "^1.0.4" - } - }, - "eslint-config-airbnb-base": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-13.1.0.tgz", - "integrity": "sha512-XWwQtf3U3zIoKO1BbHh6aUhJZQweOwSt4c2JrPDg9FP3Ltv3+YfEv7jIDB8275tVnO/qOHbfuYg3kzw6Je7uWw==", - "dev": true, - "requires": { - "eslint-restricted-globals": "^0.1.1", - "object.assign": "^4.1.0", - "object.entries": "^1.0.4" - } - }, - "eslint-import-resolver-node": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", - "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "resolve": "^1.5.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "eslint-module-utils": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.3.0.tgz", - "integrity": "sha512-lmDJgeOOjk8hObTysjqH7wyMi+nsHwwvfBykwfhjR1LNdd7C2uFJBvx4OpWYpXOw4df1yE1cDEVd1yLHitk34w==", - "dev": true, - "requires": { - "debug": "^2.6.8", - "pkg-dir": "^2.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "eslint-plugin-import": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.16.0.tgz", - "integrity": "sha512-z6oqWlf1x5GkHIFgrSvtmudnqM6Q60KM4KvpWi5ubonMjycLjndvd5+8VAZIsTlHC03djdgJuyKG6XO577px6A==", - "dev": true, - "requires": { - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.2", - "eslint-module-utils": "^2.3.0", - "has": "^1.0.3", - "lodash": "^4.17.11", - "minimatch": "^3.0.4", - "read-pkg-up": "^2.0.0", - "resolve": "^1.9.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "eslint-plugin-jsx-a11y": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.2.1.tgz", - "integrity": "sha512-cjN2ObWrRz0TTw7vEcGQrx+YltMvZoOEx4hWU8eEERDnBIU00OTq7Vr+jA7DFKxiwLNv4tTh5Pq2GUNEa8b6+w==", - "dev": true, - "requires": { - "aria-query": "^3.0.0", - "array-includes": "^3.0.3", - "ast-types-flow": "^0.0.7", - "axobject-query": "^2.0.2", - "damerau-levenshtein": "^1.0.4", - "emoji-regex": "^7.0.2", - "has": "^1.0.3", - "jsx-ast-utils": "^2.0.1" - } - }, - "eslint-plugin-react": { - "version": "7.12.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.12.4.tgz", - "integrity": "sha512-1puHJkXJY+oS1t467MjbqjvX53uQ05HXwjqDgdbGBqf5j9eeydI54G3KwiJmWciQ0HTBacIKw2jgwSBSH3yfgQ==", - "dev": true, - "requires": { - "array-includes": "^3.0.3", - "doctrine": "^2.1.0", - "has": "^1.0.3", - "jsx-ast-utils": "^2.0.1", - "object.fromentries": "^2.0.0", - "prop-types": "^15.6.2", - "resolve": "^1.9.0" - }, - "dependencies": { - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - } - } - }, - "eslint-restricted-globals": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz", - "integrity": "sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc=", - "dev": true - }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", - "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", - "dev": true - }, - "eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", - "dev": true - }, - "espree": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", - "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", - "dev": true, - "requires": { - "acorn": "^6.0.7", - "acorn-jsx": "^5.0.0", - "eslint-visitor-keys": "^1.0.0" - } - }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", - "dev": true, - "requires": { - "estraverse": "^4.0.0" - } - }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, - "requires": { - "estraverse": "^4.1.0" - } + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "estraverse": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" }, "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "requires": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } }, "exec-sh": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.2.tgz", "integrity": "sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==", - "dev": true, "requires": { "merge": "^1.2.0" } }, "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", "signal-exit": "^3.0.0", "strip-eof": "^1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + } } }, "exit": { @@ -2664,7 +2071,6 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, "requires": { "is-posix-bracket": "^0.1.0" } @@ -2673,7 +2079,6 @@ "version": "1.8.2", "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, "requires": { "fill-range": "^2.1.0" } @@ -2682,7 +2087,6 @@ "version": "23.6.0", "resolved": "https://registry.npmjs.org/expect/-/expect-23.6.0.tgz", "integrity": "sha512-dgSoOHgmtn/aDGRVFWclQyPDKl2CQRq0hmIEoUAuQs/2rn2NcvCWcSCovm6BLeuB/7EZuLGu2QfnR+qRt5OM4w==", - "dev": true, "requires": { "ansi-styles": "^3.2.0", "jest-diff": "^23.6.0", @@ -2701,7 +2105,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, "requires": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" @@ -2711,7 +2114,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, "requires": { "is-plain-object": "^2.0.4" } @@ -2732,7 +2134,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, "requires": { "is-extglob": "^1.0.0" } @@ -2760,22 +2161,20 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "fb-watchman": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", - "dev": true, "requires": { "bser": "^2.0.0" } }, "fetch-mock": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-7.3.1.tgz", - "integrity": "sha512-euKqWnxeApj0toZ5MSavZJ7IIxbMaHpgteV2GNuz6/slAY0JUbRe95U/ueaz2spT/4nR75H4wpEmy2MMEsCoRg==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-7.3.3.tgz", + "integrity": "sha512-MHKcwZ4n9TmnfnVfelUBrrfxtC9tztafIR+F8l/Yu9N+y48fU1BAwj3iSxhYFYELVw73rCZh2DPWtWCekY/t+w==", "dev": true, "requires": { "babel-polyfill": "^6.26.0", @@ -2792,26 +2191,15 @@ "escape-string-regexp": "^1.0.5" } }, - "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "dev": true, - "requires": { - "flat-cache": "^2.0.1" - } - }, "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" }, "fileset": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", - "dev": true, "requires": { "glob": "^7.0.3", "minimatch": "^3.0.3" @@ -2821,7 +2209,6 @@ "version": "2.2.4", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", - "dev": true, "requires": { "is-number": "^2.1.0", "isobject": "^2.0.0", @@ -2848,28 +2235,10 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, "requires": { "locate-path": "^2.0.0" } }, - "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", - "dev": true, - "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - } - }, - "flatted": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", - "dev": true - }, "fn-name": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fn-name/-/fn-name-2.0.1.tgz", @@ -2879,14 +2248,12 @@ "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" }, "for-own": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, "requires": { "for-in": "^1.0.1" } @@ -2906,6 +2273,14 @@ "mime-types": "^2.1.12" } }, + "formatio": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", + "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", + "requires": { + "samsam": "~1.1" + } + }, "frac": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", @@ -2915,11 +2290,15 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, "requires": { "map-cache": "^0.2.2" } }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" + }, "fs-extra": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", @@ -2938,49 +2317,42 @@ "minipass": "^2.2.1" } }, - "fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", - "dev": true - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", - "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", - "dev": true, + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", "optional": true, "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" }, "dependencies": { "abbrev": { "version": "1.1.1", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "optional": true }, "ansi-regex": { "version": "2.1.1", - "bundled": true, - "dev": true + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "aproba": { "version": "1.2.0", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "optional": true, "requires": { "delegates": "^1.0.0", @@ -2989,13 +2361,13 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true, - "dev": true + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "brace-expansion": { "version": "1.1.11", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3003,62 +2375,62 @@ }, "chownr": { "version": "1.1.1", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", + "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", "optional": true }, "code-point-at": { "version": "1.1.0", - "bundled": true, - "dev": true + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "concat-map": { "version": "0.0.1", - "bundled": true, - "dev": true + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "console-control-strings": { "version": "1.1.0", - "bundled": true, - "dev": true + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "core-util-is": { "version": "1.0.2", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "optional": true }, "debug": { - "version": "2.6.9", - "bundled": true, - "dev": true, + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "optional": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "deep-extend": { "version": "0.6.0", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "optional": true }, "delegates": { "version": "1.0.0", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "optional": true }, "detect-libc": { "version": "1.0.3", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "optional": true }, "fs-minipass": { "version": "1.2.5", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", + "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "optional": true, "requires": { "minipass": "^2.2.1" @@ -3066,14 +2438,14 @@ }, "fs.realpath": { "version": "1.0.0", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "optional": true }, "gauge": { "version": "2.7.4", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "optional": true, "requires": { "aproba": "^1.0.3", @@ -3088,8 +2460,8 @@ }, "glob": { "version": "7.1.3", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "optional": true, "requires": { "fs.realpath": "^1.0.0", @@ -3102,14 +2474,14 @@ }, "has-unicode": { "version": "2.0.1", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "optional": true }, "iconv-lite": { "version": "0.4.24", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "optional": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" @@ -3117,8 +2489,8 @@ }, "ignore-walk": { "version": "3.0.1", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", + "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "optional": true, "requires": { "minimatch": "^3.0.4" @@ -3126,8 +2498,8 @@ }, "inflight": { "version": "1.0.6", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "optional": true, "requires": { "once": "^1.3.0", @@ -3136,46 +2508,46 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, - "dev": true + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { "version": "1.3.5", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "requires": { "number-is-nan": "^1.0.0" } }, "isarray": { "version": "1.0.0", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "optional": true }, "minimatch": { "version": "3.0.4", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true, - "dev": true + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "minipass": { "version": "2.3.5", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", + "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -3183,8 +2555,8 @@ }, "minizlib": { "version": "1.2.1", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", + "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", "optional": true, "requires": { "minipass": "^2.2.1" @@ -3192,33 +2564,33 @@ }, "mkdirp": { "version": "0.5.1", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "requires": { "minimist": "0.0.8" } }, "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "optional": true }, "needle": { - "version": "2.2.4", - "bundled": true, - "dev": true, + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.3.0.tgz", + "integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==", "optional": true, "requires": { - "debug": "^2.1.2", + "debug": "^4.1.0", "iconv-lite": "^0.4.4", "sax": "^1.2.4" } }, "node-pre-gyp": { - "version": "0.10.3", - "bundled": true, - "dev": true, + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz", + "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==", "optional": true, "requires": { "detect-libc": "^1.0.2", @@ -3235,8 +2607,8 @@ }, "nopt": { "version": "4.0.1", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "optional": true, "requires": { "abbrev": "1", @@ -3244,15 +2616,15 @@ } }, "npm-bundled": { - "version": "1.0.5", - "bundled": true, - "dev": true, + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz", + "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", "optional": true }, "npm-packlist": { - "version": "1.2.0", - "bundled": true, - "dev": true, + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.1.tgz", + "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", "optional": true, "requires": { "ignore-walk": "^3.0.1", @@ -3261,8 +2633,8 @@ }, "npmlog": { "version": "4.1.2", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "optional": true, "requires": { "are-we-there-yet": "~1.1.2", @@ -3273,39 +2645,39 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, - "dev": true + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "object-assign": { "version": "4.1.1", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "optional": true }, "once": { "version": "1.4.0", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "requires": { "wrappy": "1" } }, "os-homedir": { "version": "1.0.2", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "optional": true }, "os-tmpdir": { "version": "1.0.2", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "optional": true }, "osenv": { "version": "0.1.5", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "optional": true, "requires": { "os-homedir": "^1.0.0", @@ -3314,20 +2686,20 @@ }, "path-is-absolute": { "version": "1.0.1", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "optional": true }, "process-nextick-args": { "version": "2.0.0", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "optional": true }, "rc": { "version": "1.2.8", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "optional": true, "requires": { "deep-extend": "^0.6.0", @@ -3338,16 +2710,16 @@ "dependencies": { "minimist": { "version": "1.2.0", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "optional": true } } }, "readable-stream": { "version": "2.3.6", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "optional": true, "requires": { "core-util-is": "~1.0.0", @@ -3361,8 +2733,8 @@ }, "rimraf": { "version": "2.6.3", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "optional": true, "requires": { "glob": "^7.1.3" @@ -3370,43 +2742,43 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true, - "dev": true + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "safer-buffer": { "version": "2.1.2", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "optional": true }, "sax": { "version": "1.2.4", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "optional": true }, "semver": { - "version": "5.6.0", - "bundled": true, - "dev": true, + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "optional": true }, "set-blocking": { "version": "2.0.0", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "optional": true }, "signal-exit": { "version": "3.0.2", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "optional": true }, "string-width": { "version": "1.0.2", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3415,8 +2787,8 @@ }, "string_decoder": { "version": "1.1.1", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "optional": true, "requires": { "safe-buffer": "~5.1.0" @@ -3424,22 +2796,22 @@ }, "strip-ansi": { "version": "3.0.1", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { "ansi-regex": "^2.0.0" } }, "strip-json-comments": { "version": "2.0.1", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "optional": true }, "tar": { "version": "4.4.8", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz", + "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", "optional": true, "requires": { "chownr": "^1.1.1", @@ -3453,14 +2825,14 @@ }, "util-deprecate": { "version": "1.0.2", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "optional": true }, "wide-align": { "version": "1.1.3", - "bundled": true, - "dev": true, + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "optional": true, "requires": { "string-width": "^1.0.2 || 2" @@ -3468,27 +2840,20 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, - "dev": true + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "yallist": { "version": "3.0.3", - "bundled": true, - "dev": true + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" } } }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "g-status": { "version": "2.0.2", @@ -3518,24 +2883,20 @@ "dev": true }, "get-stdin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", + "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", "dev": true }, "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "requires": { - "pump": "^3.0.0" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" }, "getpass": { "version": "0.1.7", @@ -3567,7 +2928,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, "requires": { "glob-parent": "^2.0.0", "is-glob": "^2.0.0" @@ -3577,22 +2937,20 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, "requires": { "is-glob": "^2.0.0" } }, "glob-to-regexp": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.0.tgz", - "integrity": "sha512-fyPCII4vn9Gvjq2U/oDAfP433aiE64cyP/CJjRJcpVGjqqNdioUYn9+r0cSzT1XPwmGAHuTT7iv+rQT8u/YHKQ==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" }, "globby": { "version": "5.0.0", @@ -3620,14 +2978,12 @@ "growly": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", - "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", - "dev": true + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=" }, "handlebars": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.1.tgz", - "integrity": "sha512-3Zhi6C0euYZL5sM0Zcy7lInLXKQ+YLcF/olbN010mzGQ4XVm50JeyBnMqofHh696GrciGruC7kCcApPDJvVgwA==", - "dev": true, + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", + "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", "requires": { "neo-async": "^2.6.0", "optimist": "^0.6.1", @@ -3638,8 +2994,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" } } }, @@ -3661,7 +3016,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -3689,14 +3043,12 @@ "has-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, "requires": { "get-value": "^2.0.6", "has-values": "^1.0.0", @@ -3706,8 +3058,7 @@ "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" } } }, @@ -3715,7 +3066,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, "requires": { "is-number": "^3.0.0", "kind-of": "^4.0.0" @@ -3725,7 +3075,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -3734,7 +3083,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -3745,7 +3093,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -3756,7 +3103,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, "requires": { "os-homedir": "^1.0.0", "os-tmpdir": "^1.0.1" @@ -3765,14 +3111,12 @@ "hosted-git-info": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", - "dev": true + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" }, "html-encoding-sniffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", - "dev": true, "requires": { "whatwg-encoding": "^1.0.1" } @@ -3797,23 +3141,44 @@ } }, "husky": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/husky/-/husky-1.3.1.tgz", - "integrity": "sha512-86U6sVVVf4b5NYSZ0yvv88dRgBSSXXmHaiq5pP4KDj5JVzdwKgBjEtUPOm8hcoytezFwbU+7gotXNhpHdystlg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/husky/-/husky-2.2.0.tgz", + "integrity": "sha512-lG33E7zq6v//H/DQIojPEi1ZL9ebPFt3MxUMD8MR0lrS2ljEPiuUUxlziKIs/o9EafF0chL7bAtLQkcPvXmdnA==", "dev": true, "requires": { - "cosmiconfig": "^5.0.7", + "cosmiconfig": "^5.2.0", "execa": "^1.0.0", "find-up": "^3.0.0", - "get-stdin": "^6.0.0", + "get-stdin": "^7.0.0", "is-ci": "^2.0.0", - "pkg-dir": "^3.0.0", + "pkg-dir": "^4.1.0", "please-upgrade-node": "^3.1.1", - "read-pkg": "^4.0.1", + "read-pkg": "^5.0.0", "run-node": "^1.0.0", "slash": "^2.0.0" }, "dependencies": { + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", @@ -3823,6 +3188,24 @@ "locate-path": "^3.0.0" } }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -3852,9 +3235,9 @@ } }, "p-try": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", - "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, "parse-json": { @@ -3867,30 +3250,25 @@ "json-parse-better-errors": "^1.0.1" } }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.1.0.tgz", + "integrity": "sha512-55k9QN4saZ8q518lE6EFgYiu95u3BWkSajCifhdQjvLvmr8IpnRbhI+UGpWJQfa0KzDguHeeWT1ccO1PmkOi3A==", "dev": true, "requires": { "find-up": "^3.0.0" } }, "read-pkg": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", - "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.1.1.tgz", + "integrity": "sha512-dFcTLQi6BZ+aFUaICg7er+/usEoqFdQxiEBsEMNGoipenihtxxtdrQuBXvyANCEI8VuUIVYFgeHGx9sLLvim4w==", "dev": true, "requires": { - "normalize-package-data": "^2.3.2", + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", "parse-json": "^4.0.0", - "pify": "^3.0.0" + "type-fest": "^0.4.1" } }, "slash": { @@ -3909,32 +3287,31 @@ "safer-buffer": ">= 2.1.2 < 3" } }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, "immediate": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" }, + "immutable": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", + "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=", + "dev": true + }, "import-fresh": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz", - "integrity": "sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", "dev": true, "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" } }, "import-local": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", - "dev": true, "requires": { "pkg-dir": "^2.0.0", "resolve-cwd": "^2.0.0" @@ -3943,8 +3320,7 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "indent-string": { "version": "3.2.0", @@ -3971,9 +3347,9 @@ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, "inquirer": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.2.tgz", - "integrity": "sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.3.1.tgz", + "integrity": "sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA==", "requires": { "ansi-escapes": "^3.2.0", "chalk": "^2.4.2", @@ -3986,7 +3362,7 @@ "run-async": "^2.2.0", "rxjs": "^6.4.0", "string-width": "^2.1.0", - "strip-ansi": "^5.0.0", + "strip-ansi": "^5.1.0", "through": "^2.3.6" }, "dependencies": { @@ -4014,7 +3390,6 @@ "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, "requires": { "loose-envify": "^1.0.0" } @@ -4022,60 +3397,48 @@ "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, "requires": { "kind-of": "^3.0.2" } }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==" + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "optional": true, - "requires": { - "binary-extensions": "^1.0.0" - } + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-callable": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", - "dev": true + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" }, "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", "requires": { - "ci-info": "^2.0.0" + "ci-info": "^1.5.0" } }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, "requires": { "kind-of": "^3.0.2" } @@ -4083,14 +3446,12 @@ "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" }, "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, "requires": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", @@ -4100,8 +3461,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" } } }, @@ -4114,14 +3474,12 @@ "is-dotfile": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" }, "is-equal-shallow": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, "requires": { "is-primitive": "^2.0.0" } @@ -4129,20 +3487,17 @@ "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" }, "is-extglob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" }, "is-finite": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4160,14 +3515,17 @@ "is-generator-fn": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-1.0.0.tgz", - "integrity": "sha1-lp1J4bszKfa7fwkIm+JleLLd1Go=", - "dev": true + "integrity": "sha1-lp1J4bszKfa7fwkIm+JleLLd1Go=" + }, + "is-generator-function": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", + "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==" }, "is-glob": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, "requires": { "is-extglob": "^1.0.0" } @@ -4176,7 +3534,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, "requires": { "kind-of": "^3.0.2" } @@ -4221,7 +3578,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, "requires": { "isobject": "^3.0.1" }, @@ -4229,22 +3585,19 @@ "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" } } }, "is-posix-bracket": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" }, "is-primitive": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" }, "is-promise": { "version": "2.1.0", @@ -4255,7 +3608,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, "requires": { "has": "^1.0.1" } @@ -4266,6 +3618,11 @@ "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", "dev": true }, + "is-running": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-running/-/is-running-2.1.0.tgz", + "integrity": "sha1-MKc/9cw4VOT8JUkICen1q/jeCeA=" + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -4275,7 +3632,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", - "dev": true, "requires": { "has-symbols": "^1.0.0" } @@ -4288,14 +3644,12 @@ "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" }, "is-wsl": { "version": "1.1.0", @@ -4316,7 +3670,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, "requires": { "isarray": "1.0.0" } @@ -4330,7 +3683,6 @@ "version": "1.3.7", "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.7.tgz", "integrity": "sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==", - "dev": true, "requires": { "async": "^2.1.4", "fileset": "^2.0.2", @@ -4348,14 +3700,12 @@ "istanbul-lib-coverage": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", - "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", - "dev": true + "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==" }, "istanbul-lib-hook": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz", "integrity": "sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==", - "dev": true, "requires": { "append-transform": "^0.4.0" } @@ -4364,7 +3714,6 @@ "version": "1.10.2", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", - "dev": true, "requires": { "babel-generator": "^6.18.0", "babel-template": "^6.16.0", @@ -4379,7 +3728,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz", "integrity": "sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==", - "dev": true, "requires": { "istanbul-lib-coverage": "^1.2.1", "mkdirp": "^0.5.1", @@ -4390,14 +3738,12 @@ "has-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" }, "supports-color": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, "requires": { "has-flag": "^1.0.0" } @@ -4408,37 +3754,45 @@ "version": "1.2.6", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", - "dev": true, "requires": { "debug": "^3.1.0", "istanbul-lib-coverage": "^1.2.1", "mkdirp": "^0.5.1", "rimraf": "^2.6.1", "source-map": "^0.5.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "requires": { + "glob": "^7.1.3" + } + } } }, "istanbul-reports": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.1.tgz", "integrity": "sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==", - "dev": true, "requires": { "handlebars": "^4.0.3" } }, "jasmine": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.3.1.tgz", - "integrity": "sha512-/vU3/H7U56XsxIXHwgEuWpCgQ0bRi2iiZeUpx7Nqo8n1TpoDHfZhkPIc7CO8I4pnMzYsi3XaSZEiy8cnTfujng==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.4.0.tgz", + "integrity": "sha512-sR9b4n+fnBFDEd7VS2el2DeHgKcPiMVn44rtKFumq9q7P/t8WrxsVIZPob4UDdgcDNCwyDqwxCt4k9TDRmjPoQ==", "requires": { - "glob": "^7.0.6", - "jasmine-core": "~3.3.0" + "glob": "^7.1.3", + "jasmine-core": "~3.4.0" } }, "jasmine-core": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.3.0.tgz", - "integrity": "sha512-3/xSmG/d35hf80BEN66Y6g9Ca5l/Isdeg/j6zvbTYlTzeKinzmaTM4p9am5kYqOmE05D7s1t8FGjzdSnbUbceA==" + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.4.0.tgz", + "integrity": "sha512-HU/YxV4i6GcmiH4duATwAbJQMlE0MsDIR5XmSVxURxKHn3aGAdbY1/ZJFmVRbKtnLwIxxMJD7gYaPsypcbYimg==" }, "jasmine-reporters": { "version": "2.3.2", @@ -4473,32 +3827,15 @@ "version": "23.6.0", "resolved": "https://registry.npmjs.org/jest/-/jest-23.6.0.tgz", "integrity": "sha512-lWzcd+HSiqeuxyhG+EnZds6iO3Y3ZEnMrfZq/OTGvF/C+Z4fPMCdhWTGSAiO2Oym9rbEXfwddHhh6jqrTF3+Lw==", - "dev": true, "requires": { "import-local": "^1.0.0", "jest-cli": "^23.6.0" }, "dependencies": { - "ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", - "dev": true - }, - "is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", - "dev": true, - "requires": { - "ci-info": "^1.5.0" - } - }, "jest-cli": { "version": "23.6.0", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-23.6.0.tgz", "integrity": "sha512-hgeD1zRUp1E1zsiyOXjEn4LzRLWdJBV//ukAHGlx6s5mfCNJTbhbHjgxnDUXA8fsKWN/HqFFF6X5XcCwC/IvYQ==", - "dev": true, "requires": { "ansi-escapes": "^3.0.0", "chalk": "^2.0.1", @@ -4544,7 +3881,6 @@ "version": "23.4.2", "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-23.4.2.tgz", "integrity": "sha512-EyNhTAUWEfwnK0Is/09LxoqNDOn7mU7S3EHskG52djOFS/z+IT0jT3h3Ql61+dklcG7bJJitIWEMB4Sp1piHmA==", - "dev": true, "requires": { "throat": "^4.0.0" } @@ -4553,7 +3889,6 @@ "version": "23.6.0", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-23.6.0.tgz", "integrity": "sha512-i8V7z9BeDXab1+VNo78WM0AtWpBRXJLnkT+lyT+Slx/cbP5sZJ0+NDuLcmBE5hXAoK0aUp7vI+MOxR+R4d8SRQ==", - "dev": true, "requires": { "babel-core": "^6.0.0", "babel-jest": "^23.6.0", @@ -4575,7 +3910,6 @@ "version": "23.6.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-23.6.0.tgz", "integrity": "sha512-Gz9l5Ov+X3aL5L37IT+8hoCUsof1CVYBb2QEkOupK64XyRR3h+uRpYIm97K7sY8diFxowR8pIGEdyfMKTixo3g==", - "dev": true, "requires": { "chalk": "^2.0.1", "diff": "^3.2.0", @@ -4587,7 +3921,6 @@ "version": "23.2.0", "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-23.2.0.tgz", "integrity": "sha1-8IXh8YVI2Z/dabICB+b9VdkTg6c=", - "dev": true, "requires": { "detect-newline": "^2.1.0" } @@ -4596,7 +3929,6 @@ "version": "23.6.0", "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-23.6.0.tgz", "integrity": "sha512-x7V6M/WGJo6/kLoissORuvLIeAoyo2YqLOoCDkohgJ4XOXSqOtyvr8FbInlAWS77ojBsZrafbozWoKVRdtxFCg==", - "dev": true, "requires": { "chalk": "^2.0.1", "pretty-format": "^23.6.0" @@ -4606,7 +3938,6 @@ "version": "23.4.0", "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz", "integrity": "sha1-BWp5UrP+pROsYqFAosNox52eYCM=", - "dev": true, "requires": { "jest-mock": "^23.2.0", "jest-util": "^23.4.0", @@ -4617,7 +3948,6 @@ "version": "23.4.0", "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-23.4.0.tgz", "integrity": "sha1-V+gO0IQd6jAxZ8zozXlSHeuv3hA=", - "dev": true, "requires": { "jest-mock": "^23.2.0", "jest-util": "^23.4.0" @@ -4626,14 +3956,12 @@ "jest-get-type": { "version": "22.4.3", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz", - "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==", - "dev": true + "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==" }, "jest-haste-map": { "version": "23.6.0", "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-23.6.0.tgz", "integrity": "sha512-uyNhMyl6dr6HaXGHp8VF7cK6KpC6G9z9LiMNsst+rJIZ8l7wY0tk8qwjPmEghczojZ2/ZhtEdIabZ0OQRJSGGg==", - "dev": true, "requires": { "fb-watchman": "^2.0.0", "graceful-fs": "^4.1.11", @@ -4649,7 +3977,6 @@ "version": "23.6.0", "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz", "integrity": "sha512-pe2Ytgs1nyCs8IvsEJRiRTPC0eVYd8L/dXJGU08GFuBwZ4sYH/lmFDdOL3ZmvJR8QKqV9MFuwlsAi/EWkFUbsQ==", - "dev": true, "requires": { "babel-traverse": "^6.0.0", "chalk": "^2.0.1", @@ -4669,7 +3996,6 @@ "version": "23.6.0", "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-23.6.0.tgz", "integrity": "sha512-f/8zA04rsl1Nzj10HIyEsXvYlMpMPcy0QkQilVZDFOaPbv2ur71X5u2+C4ZQJGyV/xvVXtCCZ3wQ99IgQxftCg==", - "dev": true, "requires": { "pretty-format": "^23.6.0" } @@ -4678,7 +4004,6 @@ "version": "23.6.0", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz", "integrity": "sha512-rosyCHQfBcol4NsckTn01cdelzWLU9Cq7aaigDf8VwwpIRvWE/9zLgX2bON+FkEW69/0UuYslUe22SOdEf2nog==", - "dev": true, "requires": { "chalk": "^2.0.1", "jest-get-type": "^22.1.0", @@ -4689,7 +4014,6 @@ "version": "23.4.0", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-23.4.0.tgz", "integrity": "sha1-F2EMUJQjSVCNAaPR4L2iwHkIap8=", - "dev": true, "requires": { "@babel/code-frame": "^7.0.0-beta.35", "chalk": "^2.0.1", @@ -4701,20 +4025,17 @@ "jest-mock": { "version": "23.2.0", "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-23.2.0.tgz", - "integrity": "sha1-rRxg8p6HGdR8JuETgJi20YsmETQ=", - "dev": true + "integrity": "sha1-rRxg8p6HGdR8JuETgJi20YsmETQ=" }, "jest-regex-util": { "version": "23.3.0", "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-23.3.0.tgz", - "integrity": "sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U=", - "dev": true + "integrity": "sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U=" }, "jest-resolve": { "version": "23.6.0", "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-23.6.0.tgz", "integrity": "sha512-XyoRxNtO7YGpQDmtQCmZjum1MljDqUCob7XlZ6jy9gsMugHdN2hY4+Acz9Qvjz2mSsOnPSH7skBmDYCHXVZqkA==", - "dev": true, "requires": { "browser-resolve": "^1.11.3", "chalk": "^2.0.1", @@ -4725,7 +4046,6 @@ "version": "23.6.0", "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz", "integrity": "sha512-EkQWkFWjGKwRtRyIwRwI6rtPAEyPWlUC2MpzHissYnzJeHcyCn1Hc8j7Nn1xUVrS5C6W5+ZL37XTem4D4pLZdA==", - "dev": true, "requires": { "jest-regex-util": "^23.3.0", "jest-snapshot": "^23.6.0" @@ -4735,7 +4055,6 @@ "version": "23.6.0", "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-23.6.0.tgz", "integrity": "sha512-kw0+uj710dzSJKU6ygri851CObtCD9cN8aNkg8jWJf4ewFyEa6kwmiH/r/M1Ec5IL/6VFa0wnAk6w+gzUtjJzA==", - "dev": true, "requires": { "exit": "^0.1.2", "graceful-fs": "^4.1.11", @@ -4755,14 +4074,12 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-support": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.11.tgz", - "integrity": "sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ==", - "dev": true, + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -4774,7 +4091,6 @@ "version": "23.6.0", "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-23.6.0.tgz", "integrity": "sha512-ycnLTNPT2Gv+TRhnAYAQ0B3SryEXhhRj1kA6hBPSeZaNQkJ7GbZsxOLUkwg6YmvWGdX3BB3PYKFLDQCAE1zNOw==", - "dev": true, "requires": { "babel-core": "^6.0.0", "babel-plugin-istanbul": "^4.1.6", @@ -4797,19 +4113,24 @@ "strip-bom": "3.0.0", "write-file-atomic": "^2.1.0", "yargs": "^11.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + } } }, "jest-serializer": { "version": "23.0.1", "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-23.0.1.tgz", - "integrity": "sha1-o3dq6zEekP6D+rnlM+hRAr0WQWU=", - "dev": true + "integrity": "sha1-o3dq6zEekP6D+rnlM+hRAr0WQWU=" }, "jest-snapshot": { "version": "23.6.0", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-23.6.0.tgz", "integrity": "sha512-tM7/Bprftun6Cvj2Awh/ikS7zV3pVwjRYU2qNYS51VZHgaAMBs5l4o/69AiDHhQrj5+LA2Lq4VIvK7zYk/bswg==", - "dev": true, "requires": { "babel-types": "^6.0.0", "chalk": "^2.0.1", @@ -4827,7 +4148,6 @@ "version": "23.4.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-23.4.0.tgz", "integrity": "sha1-TQY8uSe68KI4Mf9hvsLLv0l5NWE=", - "dev": true, "requires": { "callsites": "^2.0.0", "chalk": "^2.0.1", @@ -4839,32 +4159,10 @@ "source-map": "^0.6.0" }, "dependencies": { - "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "dev": true - }, - "ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", - "dev": true - }, - "is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", - "dev": true, - "requires": { - "ci-info": "^1.5.0" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" } } }, @@ -4872,7 +4170,6 @@ "version": "23.6.0", "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-23.6.0.tgz", "integrity": "sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==", - "dev": true, "requires": { "chalk": "^2.0.1", "jest-get-type": "^22.1.0", @@ -4884,7 +4181,6 @@ "version": "23.4.0", "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-23.4.0.tgz", "integrity": "sha1-0uKM50+NrWxq/JIrksq+9u0FyRw=", - "dev": true, "requires": { "ansi-escapes": "^3.0.0", "chalk": "^2.0.1", @@ -4895,7 +4191,6 @@ "version": "23.2.0", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-23.2.0.tgz", "integrity": "sha1-+vcGqNo2+uYOsmlXJX+ntdjqArk=", - "dev": true, "requires": { "merge-stream": "^1.0.1" } @@ -4908,14 +4203,12 @@ "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" }, "js-yaml": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.0.tgz", - "integrity": "sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ==", - "dev": true, + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -4930,7 +4223,6 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", - "dev": true, "requires": { "abab": "^2.0.0", "acorn": "^5.5.3", @@ -4958,21 +4250,12 @@ "whatwg-url": "^6.4.1", "ws": "^5.2.0", "xml-name-validator": "^3.0.0" - }, - "dependencies": { - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true - } } }, "jsesc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" }, "json-parse-better-errors": { "version": "1.0.2", @@ -4990,12 +4273,6 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -5004,8 +4281,7 @@ "json5": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" }, "jsonfile": { "version": "3.0.1", @@ -5026,15 +4302,6 @@ "verror": "1.10.0" } }, - "jsx-ast-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz", - "integrity": "sha1-6AGxs5mF4g//yHtA43SAgOLcrH8=", - "dev": true, - "requires": { - "array-includes": "^3.0.3" - } - }, "jszip": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.2.1.tgz", @@ -5050,7 +4317,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -5058,8 +4324,7 @@ "kleur": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/kleur/-/kleur-2.0.2.tgz", - "integrity": "sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==", - "dev": true + "integrity": "sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==" }, "knuth-shuffle-seeded": { "version": "1.0.6", @@ -5073,7 +4338,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, "requires": { "invert-kv": "^1.0.0" } @@ -5081,20 +4345,17 @@ "left-pad": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", - "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", - "dev": true + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==" }, "leven": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", - "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", - "dev": true + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, "requires": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -5109,9 +4370,9 @@ } }, "lint-staged": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-8.1.5.tgz", - "integrity": "sha512-e5ZavfnSLcBJE1BTzRTqw6ly8OkqVyO3GL2M6teSmTBYQ/2BuueD5GIt2RPsP31u/vjKdexUyDCxSyK75q4BDA==", + "version": "8.1.6", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-8.1.6.tgz", + "integrity": "sha512-QT13AniHN6swAtTjsrzxOfE4TVCiQ39xESwLmjGVNCMMZ/PK5aopwvbxLrzw+Zf9OxM3cQG6WCx9lceLzETOnQ==", "dev": true, "requires": { "chalk": "^2.3.1", @@ -5138,7 +4399,7 @@ "staged-git-files": "1.1.2", "string-argv": "^0.0.2", "stringify-object": "^3.2.2", - "yup": "^0.26.10" + "yup": "^0.27.0" }, "dependencies": { "arr-diff": { @@ -5196,6 +4457,21 @@ "rimraf": "^2.2.8" } }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -5356,6 +4632,15 @@ } } }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, "globby": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", @@ -5512,9 +4797,9 @@ }, "dependencies": { "p-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.0.0.tgz", - "integrity": "sha512-GO107XdrSUmtHxVoi60qc9tUl/KkNKm+X2CF4P9amalpGxv5YqVPJNfSb0wcA+syCopkZvYYIzW8OVTQW59x/w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", "dev": true } } @@ -5615,22 +4900,21 @@ } }, "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "requires": { "graceful-fs": "^4.1.2", "parse-json": "^2.2.0", "pify": "^2.0.0", - "strip-bom": "^3.0.0" + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" } }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, "requires": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -5659,8 +4943,7 @@ "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", - "dev": true + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" }, "lodash.zip": { "version": "4.2.0", @@ -5709,11 +4992,15 @@ "resolved": "https://registry.npmjs.org/loglevel-plugin-prefix/-/loglevel-plugin-prefix-0.5.3.tgz", "integrity": "sha512-zRAJw3WYCQAJ6xfEIi04/oqlmR6jkwg3hmBcMW82Zic3iPWyju1gwntcgic0m5NgqYNJ62alCmb0g/div26WjQ==" }, + "lolex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", + "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=" + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, "requires": { "js-tokens": "^3.0.0 || ^4.0.0" } @@ -5727,17 +5014,21 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, "requires": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" } }, + "make-error": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "dev": true + }, "makeerror": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", - "dev": true, "requires": { "tmpl": "1.0.x" } @@ -5753,14 +5044,17 @@ "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=" }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, "requires": { "object-visit": "^1.0.0" } @@ -5777,14 +5071,12 @@ "math-random": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", - "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", - "dev": true + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==" }, "mem": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true, "requires": { "mimic-fn": "^1.0.0" } @@ -5792,14 +5084,12 @@ "merge": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", - "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==", - "dev": true + "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==" }, "merge-stream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, "requires": { "readable-stream": "^2.0.1" } @@ -5808,7 +5098,6 @@ "version": "2.3.11", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, "requires": { "arr-diff": "^2.0.0", "array-unique": "^0.2.1", @@ -5826,16 +5115,16 @@ } }, "mime-db": { - "version": "1.38.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", - "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==" + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" }, "mime-types": { - "version": "2.1.22", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", - "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", "requires": { - "mime-db": "~1.38.0" + "mime-db": "1.40.0" } }, "mimic-fn": { @@ -5884,7 +5173,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", - "dev": true, "requires": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" @@ -5894,7 +5182,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, "requires": { "is-plain-object": "^2.0.4" } @@ -6016,14 +5303,12 @@ "version": "2.13.2", "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", - "dev": true, "optional": true }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, "requires": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -6041,34 +5326,29 @@ "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, "neo-async": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", - "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", - "dev": true + "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==" }, "next-tick": { "version": "1.0.0", @@ -6094,21 +5374,19 @@ "integrity": "sha1-/Mt7BQ9zW1oz2p65N89vGrRX+2k=" }, "node-fetch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.3.0.tgz", - "integrity": "sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA==" + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.5.0.tgz", + "integrity": "sha512-YuZKluhWGJwCcUu4RlZstdAxr8bFfOVHakc1mplwHkk8J+tqM1Y5yraYvIUpeX8aY7+crCwiELJq7Vl0o0LWXw==" }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", - "dev": true + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" }, "node-notifier": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.0.tgz", "integrity": "sha512-SUDEb+o71XR5lXSTyivXd9J7fCloE3SyP4lSgt3lU2oSANiox+SxlNRGPjDKrwU1YN3ix2KN/VGGCg0t01rttQ==", - "dev": true, "requires": { "growly": "^1.3.0", "is-wsl": "^1.1.0", @@ -6118,19 +5396,18 @@ } }, "node-xlsx": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/node-xlsx/-/node-xlsx-0.12.1.tgz", - "integrity": "sha512-PMIv0Gs05zb+7ZUQIMA5Fw8eFHxT8fVieKUKMUXI5EBuCsZ56bYKeaMaBf7pBAH3cw8Xa+dGK/xaLWZaEuyfiw==", + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/node-xlsx/-/node-xlsx-0.14.1.tgz", + "integrity": "sha512-eNtlGQdjsN2jGveaVPyVJ3MFx+V3YOu/xCAdnHndiMKWOiaA4XsSCLm8mzym0z4AF5+CBjkv/V4ssl4QJFlZFQ==", "requires": { "buffer-from": "^1.1.0", - "xlsx": "^0.12.4" + "xlsx": "^0.14.1" } }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, "requires": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -6142,7 +5419,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, "requires": { "remove-trailing-separator": "^1.0.1" } @@ -6181,85 +5457,9 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "nwsapi": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.2.tgz", - "integrity": "sha512-TQOQNxqEdxVjwgwNZyvKDF0vALmzQKZJEZwE3fZWDb7Ns5Hw6l9PxJTGKOHZGsmf7R6grsOe8lWxI43Clz79zg==", - "dev": true, - "requires": { - "jsdom": "^14.0.0" - }, - "dependencies": { - "jsdom": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-14.0.0.tgz", - "integrity": "sha512-/VkyPmdtbwqpJSkwDx3YyJ3U1oawYNB/h5z8vTUZGAzjtu2OHTeFRfnJqyMHsJ5Cyes23trOmvUpM1GfHH1leA==", - "dev": true, - "requires": { - "abab": "^2.0.0", - "acorn": "^6.0.4", - "acorn-globals": "^4.3.0", - "array-equal": "^1.0.0", - "cssom": "^0.3.4", - "cssstyle": "^1.1.1", - "data-urls": "^1.1.0", - "domexception": "^1.0.1", - "escodegen": "^1.11.0", - "html-encoding-sniffer": "^1.0.2", - "nwsapi": "^2.0.9", - "parse5": "5.1.0", - "pn": "^1.1.0", - "request": "^2.88.0", - "request-promise-native": "^1.0.5", - "saxes": "^3.1.5", - "symbol-tree": "^3.2.2", - "tough-cookie": "^2.5.0", - "w3c-hr-time": "^1.0.1", - "w3c-xmlserializer": "^1.0.1", - "webidl-conversions": "^4.0.2", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^7.0.0", - "ws": "^6.1.2", - "xml-name-validator": "^3.0.0" - } - }, - "parse5": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", - "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", - "dev": true - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "whatwg-url": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", - "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", - "dev": true, - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - }, - "ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } - } - } + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.4.tgz", + "integrity": "sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw==" }, "oauth-sign": { "version": "0.9.0", @@ -6275,7 +5475,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, "requires": { "copy-descriptor": "^0.1.0", "define-property": "^0.2.5", @@ -6286,7 +5485,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -6294,16 +5492,14 @@ } }, "object-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", - "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, "requires": { "isobject": "^3.0.0" }, @@ -6311,28 +5507,14 @@ "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" } } }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, "object.entries": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", - "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.12.0", @@ -6340,23 +5522,10 @@ "has": "^1.0.3" } }, - "object.fromentries": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.0.tgz", - "integrity": "sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.11.0", - "function-bind": "^1.1.1", - "has": "^1.0.1" - } - }, "object.getownpropertydescriptors": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "dev": true, "requires": { "define-properties": "^1.1.2", "es-abstract": "^1.5.1" @@ -6366,7 +5535,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, "requires": { "for-own": "^0.1.4", "is-extendable": "^0.1.1" @@ -6376,7 +5544,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, "requires": { "isobject": "^3.0.1" }, @@ -6384,8 +5551,7 @@ "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" } } }, @@ -6433,7 +5599,6 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, "requires": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.4", @@ -6446,60 +5611,23 @@ "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" } } }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" }, "os-locale": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, "requires": { "execa": "^0.7.0", "lcid": "^1.0.0", "mem": "^1.1.0" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - } } }, "os-tmpdir": { @@ -6507,17 +5635,6 @@ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, - "output-file-sync": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", - "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.4", - "mkdirp": "^0.5.1", - "object-assign": "^4.1.0" - } - }, "p-defer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", @@ -6529,15 +5646,14 @@ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, "p-is-promise": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.0.0.tgz", - "integrity": "sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==" }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, "requires": { "p-try": "^1.0.0" } @@ -6546,7 +5662,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, "requires": { "p-limit": "^1.1.0" } @@ -6560,8 +5675,7 @@ "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" }, "pad-right": { "version": "0.2.2", @@ -6576,20 +5690,10 @@ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==" }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, "requires": { "glob-base": "^0.3.0", "is-dotfile": "^1.0.0", @@ -6601,7 +5705,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, "requires": { "error-ex": "^1.2.0" } @@ -6609,14 +5712,12 @@ "parse5": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", - "dev": true + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==" }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" }, "path": { "version": "0.12.7", @@ -6625,6 +5726,16 @@ "requires": { "process": "^0.11.1", "util": "^0.10.3" + }, + "dependencies": { + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "requires": { + "inherits": "2.0.3" + } + } } }, "path-exists": { @@ -6659,12 +5770,13 @@ "dev": true }, "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "requires": { - "pify": "^2.0.0" + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, "pathval": { @@ -6672,6 +5784,14 @@ "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "requires": { + "through": "~2.3" + } + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -6699,7 +5819,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, "requires": { "find-up": "^2.1.0" } @@ -6716,38 +5835,33 @@ "pn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", - "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", - "dev": true + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==" }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" }, "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" }, "prettier": { - "version": "1.16.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.4.tgz", - "integrity": "sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.17.0.tgz", + "integrity": "sha512-sXe5lSt2WQlCbydGETgfm1YBShgOX4HxQkFPvbxkcwgDvGDeqVau8h+12+lmSVlP3rHPz0oavfddSZg/q+Szjw==", "dev": true }, "pretty-format": { "version": "23.6.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", "integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==", - "dev": true, "requires": { "ansi-regex": "^3.0.0", "ansi-styles": "^3.2.0" @@ -6761,8 +5875,7 @@ "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" }, "process": { "version": "0.11.10", @@ -6783,23 +5896,11 @@ "version": "0.1.14", "resolved": "https://registry.npmjs.org/prompts/-/prompts-0.1.14.tgz", "integrity": "sha512-rxkyiE9YH6zAz/rZpywySLKkpaj0NMVyNw1qhsubdbjjSgcayjTShDreZGlFMcGSu5sab3bAKPfFk78PB90+8w==", - "dev": true, "requires": { "kleur": "^2.0.1", "sisteransi": "^0.1.1" } }, - "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "dev": true, - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.8.1" - } - }, "property-expr": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-1.5.1.tgz", @@ -6879,9 +5980,9 @@ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" }, "webdriver-manager": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.1.tgz", - "integrity": "sha512-L9TEQmZs6JbMMRQI1w60mfps265/NCr0toYJl7p/R2OAk6oXAfwI6jqYP7EWae+d7Ad2S2Aj4+rzxoSjqk3ZuA==", + "version": "12.1.4", + "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.4.tgz", + "integrity": "sha512-aNUzdimlHSl3EotUTdE2QwP9sBUjZgWPCy8C+m1wMmF9jBDKuO/24nnpr2O25Db8dYtsjvj9drPTpSIGqRrNnQ==", "requires": { "adm-zip": "^0.4.9", "chalk": "^1.1.1", @@ -6925,441 +6026,126 @@ "multiple-cucumber-html-reporter": "^1.11.0" } }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "psl": { - "version": "1.1.31", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", - "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "ps-tree": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.1.tgz", + "integrity": "sha512-kef7fYYSKVqQffmzTMsVcUD1ObNJMp8sNSmHGlGKsZQyL/ht9MZKk86u0Rd1NhpTOAuhqwKCLLpktwkqz+MF8A==", "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "q": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", - "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=" - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" - }, - "randomatic": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", - "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", - "dev": true, - "requires": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "react-is": { - "version": "16.8.6", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", - "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "optional": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true, - "optional": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "optional": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "optional": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "optional": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "optional": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "optional": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "optional": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "optional": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, + "event-stream": "=3.3.4" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "psl": { + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true, - "optional": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "optional": true, + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true, - "optional": true + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "^2.0.0" + } } } }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, "realpath-native": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", - "dev": true, "requires": { "util.promisify": "^1.0.0" } @@ -7372,33 +6158,15 @@ "resolve": "^1.1.6" } }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", - "dev": true - }, "regenerator-runtime": { "version": "0.13.2", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz", "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==" }, - "regenerator-transform": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true, - "requires": { - "babel-runtime": "^6.18.0", - "babel-types": "^6.19.0", - "private": "^0.1.6" - } - }, "regex-cache": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "dev": true, "requires": { "is-equal-shallow": "^0.1.3" } @@ -7407,63 +6175,20 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, "requires": { "extend-shallow": "^3.0.2", "safe-regex": "^1.1.0" } }, - "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", - "dev": true - }, - "regexpu-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true, - "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" - } - }, - "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", - "dev": true - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } - } - }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" }, "repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" }, "repeat-string": { "version": "1.6.1", @@ -7474,7 +6199,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, "requires": { "is-finite": "^1.0.0" } @@ -7510,7 +6234,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", - "dev": true, "requires": { "lodash": "^4.17.11" } @@ -7519,7 +6242,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", - "dev": true, "requires": { "request-promise-core": "1.1.2", "stealthy-require": "^1.1.1", @@ -7537,9 +6259,9 @@ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" }, "resolve": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", - "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.1.tgz", + "integrity": "sha512-KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA==", "requires": { "path-parse": "^1.0.6" } @@ -7548,30 +6270,27 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "dev": true, "requires": { "resolve-from": "^3.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - } } }, "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "resq": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resq/-/resq-1.4.0.tgz", + "integrity": "sha512-Am0l5BD6mkzFsavqXMsIg19BpjCtq/GKTIly15JhWkwUaeM78cpFoYkdPGiKpAkbGEw8W9h/aBklgpItZgc0ZQ==", + "requires": { + "fast-deep-equal": "^2.0.1" + } }, "restore-cursor": { "version": "2.0.0", @@ -7585,8 +6304,7 @@ "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" }, "rgb2hex": { "version": "0.1.9", @@ -7594,18 +6312,17 @@ "integrity": "sha512-32iuQzhOjyT+cv9aAFRBJ19JgHwzQwbjUhH3Fj2sWW2EEGAW8fpFrDFP5ndoKDxJaLO06x1hE3kyuIFrUQtybQ==" }, "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", + "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", "requires": { - "glob": "^7.1.3" + "glob": "^7.0.5" } }, "rsvp": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz", - "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==", - "dev": true + "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==" }, "run-async": { "version": "2.3.0", @@ -7622,9 +6339,9 @@ "dev": true }, "rxjs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", - "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.1.tgz", + "integrity": "sha512-y0j31WJc83wPu31vS1VlAFW5JGrnGC+j+TtGAa1fRQphy48+fDYiDmX8tjGloToEsMkxnouOg/1IzXGKkJnZMg==", "requires": { "tslib": "^1.9.0" } @@ -7638,7 +6355,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, "requires": { "ret": "~0.1.10" } @@ -7648,11 +6364,15 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "samsam": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", + "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=" + }, "sane": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/sane/-/sane-2.5.2.tgz", "integrity": "sha1-tNwYYcIbQn6SlQej51HiosuKs/o=", - "dev": true, "requires": { "anymatch": "^2.0.0", "capture-exit": "^1.2.0", @@ -7665,33 +6385,20 @@ "watch": "~0.18.0" }, "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" }, "braces": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, "requires": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", @@ -7709,7 +6416,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -7720,7 +6426,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -7729,7 +6434,6 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, "requires": { "debug": "^2.3.3", "define-property": "^0.2.5", @@ -7744,7 +6448,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -7753,7 +6456,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -7762,7 +6464,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -7771,7 +6472,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -7782,7 +6482,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -7791,7 +6490,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -7802,7 +6500,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, "requires": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", @@ -7812,8 +6509,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" } } }, @@ -7821,7 +6517,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, "requires": { "array-unique": "^0.3.2", "define-property": "^1.0.0", @@ -7837,7 +6532,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, "requires": { "is-descriptor": "^1.0.0" } @@ -7846,7 +6540,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -7857,7 +6550,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, "requires": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", @@ -7869,7 +6561,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -7880,7 +6571,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -7889,7 +6579,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -7898,7 +6587,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -7909,7 +6597,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -7918,7 +6605,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -7928,20 +6614,17 @@ "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, "requires": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -7961,8 +6644,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -7979,15 +6661,6 @@ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, - "saxes": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.9.tgz", - "integrity": "sha512-FZeKhJglhJHk7eWG5YM0z46VHmI3KJpMBAQm3xa9meDvd+wevB5GuBB0wc0exPInZiBBHqi00DbS8AcvCGCFMw==", - "dev": true, - "requires": { - "xmlchars": "^1.3.1" - } - }, "seed-random": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/seed-random/-/seed-random-2.2.0.tgz", @@ -8044,7 +6717,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", - "dev": true, "requires": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", @@ -8056,7 +6728,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -8089,8 +6760,7 @@ "shellwords": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", - "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", - "dev": true + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==" }, "signal-exit": { "version": "3.0.2", @@ -8098,9 +6768,9 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "simple-git": { - "version": "1.110.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.110.0.tgz", - "integrity": "sha512-UYY0rQkknk0P5eb+KW+03F4TevZ9ou0H+LoGaj7iiVgpnZH4wdj/HTViy/1tNNkmIPcmtxuBqXWiYt2YwlRKOQ==", + "version": "1.112.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.112.0.tgz", + "integrity": "sha512-3vY0SW+RkO+ElWH07n/PQuKmuNLZSz3VAkxKMr3UMm/QnaSnYFjg3nqT8V6a0QCcUFpkyAWVsruQt4oSIIzPXw==", "dev": true, "requires": { "debug": "^4.0.1" @@ -8117,34 +6787,37 @@ } } }, + "sinon": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", + "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", + "requires": { + "formatio": "1.1.1", + "lolex": "1.3.2", + "samsam": "1.1.2", + "util": ">=0.10.3 <1" + } + }, "sisteransi": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-0.1.1.tgz", - "integrity": "sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g==", - "dev": true + "integrity": "sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g==" }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" }, - "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - } + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, "requires": { "base": "^0.11.1", "debug": "^2.2.0", @@ -8160,7 +6833,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -8169,7 +6841,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -8178,7 +6849,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -8186,8 +6856,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -8195,7 +6864,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, "requires": { "define-property": "^1.0.0", "isobject": "^3.0.0", @@ -8206,7 +6874,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, "requires": { "is-descriptor": "^1.0.0" } @@ -8215,7 +6882,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -8224,7 +6890,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -8233,7 +6898,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -8243,14 +6907,12 @@ "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, @@ -8258,7 +6920,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, "requires": { "kind-of": "^3.2.0" } @@ -8272,7 +6933,6 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true, "requires": { "atob": "^2.1.1", "decode-uri-component": "^0.2.0", @@ -8292,14 +6952,12 @@ "source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" }, "spdx-correct": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -8308,30 +6966,34 @@ "spdx-exceptions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" }, "spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "spdx-license-ids": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz", - "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==", - "dev": true + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", + "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==" + }, + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "requires": { + "through": "2" + } }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, "requires": { "extend-shallow": "^3.0.0" } @@ -8339,8 +7001,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "ssf": { "version": "0.10.2", @@ -8382,8 +7043,7 @@ "stack-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", - "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==", - "dev": true + "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==" }, "stackframe": { "version": "1.0.4", @@ -8419,7 +7079,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, "requires": { "define-property": "^0.2.5", "object-copy": "^0.1.0" @@ -8429,7 +7088,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -8439,8 +7097,15 @@ "stealthy-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", - "dev": true + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "requires": { + "duplexer": "~0.1.1" + } }, "string-argv": { "version": "0.1.1", @@ -8451,7 +7116,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", - "dev": true, "requires": { "astral-regex": "^1.0.0", "strip-ansi": "^4.0.0" @@ -8494,22 +7158,18 @@ } }, "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "^0.2.0" + } }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, "sugar-core": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/sugar-core/-/sugar-core-2.0.6.tgz", @@ -8540,8 +7200,7 @@ "symbol-tree": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", - "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=", - "dev": true + "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=" }, "synchronous-promise": { "version": "2.0.7", @@ -8549,46 +7208,6 @@ "integrity": "sha512-16GbgwTmFMYFyQMLvtQjvNWh30dsFe1cAW5Fg1wm5+dg84L9Pe36mftsIRU95/W2YsISxsz/xq4VB23sqpgb/A==", "dev": true }, - "table": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz", - "integrity": "sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==", - "dev": true, - "requires": { - "ajv": "^6.9.1", - "lodash": "^4.17.11", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, "tar": { "version": "4.4.8", "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz", @@ -8610,100 +7229,26 @@ } } }, + "temp-fs": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/temp-fs/-/temp-fs-0.9.9.tgz", + "integrity": "sha1-gHFzBDeHByDpQxUy/igUNk+IA9c=", + "requires": { + "rimraf": "~2.5.2" + } + }, "test-exclude": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.2.3.tgz", "integrity": "sha512-SYbXgY64PT+4GAL2ocI3HwPa4Q4TBKm0cwAVeKOt/Aoc0gSpNRjJX8w0pA1LMKZ3LBmd8pYBqApFNQLII9kavA==", - "dev": true, "requires": { "arrify": "^1.0.1", "micromatch": "^2.3.11", "object-assign": "^4.1.0", "read-pkg-up": "^1.0.1", "require-main-filename": "^1.0.1" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - } } }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, "thenify": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", @@ -8723,8 +7268,7 @@ "throat": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", - "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", - "dev": true + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=" }, "through": { "version": "2.3.8", @@ -8751,20 +7295,17 @@ "tmpl": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", - "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", - "dev": true + "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=" }, "to-fast-properties": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, "requires": { "kind-of": "^3.0.2" } @@ -8773,7 +7314,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, "requires": { "define-property": "^2.0.2", "extend-shallow": "^3.0.2", @@ -8785,7 +7325,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, "requires": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" @@ -8795,7 +7334,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, "requires": { "kind-of": "^3.0.2" } @@ -8828,7 +7366,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", - "dev": true, "requires": { "punycode": "^2.1.0" } @@ -8841,14 +7378,95 @@ "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" + }, + "ts-jest": { + "version": "24.0.2", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-24.0.2.tgz", + "integrity": "sha512-h6ZCZiA1EQgjczxq+uGLXQlNgeg02WWJBbeT8j6nyIBRQdglqbvzDoHahTEIiS6Eor6x8mK6PfZ7brQ9Q6tzHw==", + "dev": true, + "requires": { + "bs-logger": "0.x", + "buffer-from": "1.x", + "fast-json-stable-stringify": "2.x", + "json5": "2.x", + "make-error": "1.x", + "mkdirp": "0.x", + "resolve": "1.x", + "semver": "^5.5", + "yargs-parser": "10.x" + }, + "dependencies": { + "json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } }, "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" }, + "tslint": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.16.0.tgz", + "integrity": "sha512-UxG2yNxJ5pgGwmMzPMYh/CCnCnh0HfPgtlVRDs1ykZklufFBL1ZoTlWFRz2NQjcoEiDoRp+JyT0lhBbbH/obyA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.13.0", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + } + }, + "tslint-config-prettier": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz", + "integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==", + "dev": true + }, + "tslint-sonarts": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslint-sonarts/-/tslint-sonarts-1.9.0.tgz", + "integrity": "sha512-CJWt+IiYI8qggb2O/JPkS6CkC5DY1IcqRsm9EHJ+AxoWK70lvtP7jguochyNDMP2vIz/giGdWCfEM39x/I/Vnw==", + "dev": true, + "requires": { + "immutable": "^3.8.2" + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -8866,7 +7484,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, "requires": { "prelude-ls": "~1.1.2" } @@ -8876,14 +7493,25 @@ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" }, + "type-fest": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.4.1.tgz", + "integrity": "sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==", + "dev": true + }, + "typescript": { + "version": "3.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.5.tgz", + "integrity": "sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==", + "dev": true + }, "uglify-js": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.2.tgz", - "integrity": "sha512-imog1WIsi9Yb56yRt5TfYVxGmnWs3WSGU73ieSOlMVFwhJCA9W8fqFFMMj4kgDqiS/80LGdsYnWL7O9UcjEBlg==", - "dev": true, + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.11.tgz", + "integrity": "sha512-izPJg8RsSyqxbdnqX36ExpbH3K7tDBsAU/VfNv89VkMFy3z39zFjunQGsSHOlGlyIfGLGprGeosgQno3bo2/Kg==", "optional": true, "requires": { - "commander": "~2.19.0", + "commander": "~2.20.0", "source-map": "~0.6.1" }, "dependencies": { @@ -8891,7 +7519,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "optional": true } } @@ -8900,7 +7527,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "dev": true, "requires": { "arr-union": "^3.1.0", "get-value": "^2.0.6", @@ -8912,7 +7538,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -8921,7 +7546,6 @@ "version": "0.4.3", "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, "requires": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", @@ -8940,7 +7564,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, "requires": { "has-value": "^0.3.1", "isobject": "^3.0.0" @@ -8950,7 +7573,6 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, "requires": { "get-value": "^2.0.3", "has-values": "^0.1.4", @@ -8961,7 +7583,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, "requires": { "isarray": "1.0.0" } @@ -8971,14 +7592,12 @@ "has-values": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" }, "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" } } }, @@ -8998,27 +7617,23 @@ "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" }, "util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.0.tgz", + "integrity": "sha512-pPSOFl7VLhZ7LO/SFABPraZEEurkJUWSMn3MuA/r3WQZc+Z1fqou2JqLSOZbCLl73EUIxuUVX8X4jkX2vfJeAA==", "requires": { - "inherits": "2.0.3" + "inherits": "2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "object.entries": "^1.1.0", + "safe-buffer": "^5.1.2" } }, "util-arity": { @@ -9035,7 +7650,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", - "dev": true, "requires": { "define-properties": "^1.1.2", "object.getownpropertydescriptors": "^2.0.3" @@ -9046,20 +7660,10 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" }, - "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true, - "requires": { - "user-home": "^1.1.1" - } - }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, "requires": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -9079,27 +7683,14 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", - "dev": true, "requires": { "browser-process-hrtime": "^0.1.2" } }, - "w3c-xmlserializer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz", - "integrity": "sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==", - "dev": true, - "requires": { - "domexception": "^1.0.1", - "webidl-conversions": "^4.0.2", - "xml-name-validator": "^3.0.0" - } - }, "walker": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", - "dev": true, "requires": { "makeerror": "1.0.x" } @@ -9108,19 +7699,18 @@ "version": "0.18.0", "resolved": "https://registry.npmjs.org/watch/-/watch-0.18.0.tgz", "integrity": "sha1-KAlUdsbffJDJYxOJkMClQj60uYY=", - "dev": true, "requires": { "exec-sh": "^0.2.0", "minimist": "^1.2.0" } }, "webdriver": { - "version": "5.7.8", - "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-5.7.8.tgz", - "integrity": "sha512-gadTw6i0vBmAlGTSdF9wrrgnoDbwhfZYZRmi5JCEzKKknAZLi2fJGceoyxF6EyC/1wgsQKTvnxIt2l42Vdp3GQ==", + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-5.8.3.tgz", + "integrity": "sha512-8qrQehwPm1R8kOFS+7hXDUyOE/sVJwFNs1wT1b7CFw+KvMHo9p9C37ppzDXq3pS2FbZ7kFttUiEwyXQCIg34uQ==", "requires": { - "@wdio/config": "^5.7.8", - "@wdio/logger": "^5.7.8", + "@wdio/config": "^5.8.1", + "@wdio/logger": "^5.8.0", "deepmerge": "^2.0.1", "lodash.merge": "^4.6.1", "request": "^2.83.0" @@ -9150,9 +7740,23 @@ }, "dependencies": { "camelcase": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.0.tgz", - "integrity": "sha512-Y05ICatFYPAfykDIB7VdwSJ0LUl1yq/BwO2OpyGGLjiRe1fgzTwVypPiWnzkGFOVFHXrCXUNBl86bpjBhZWSJg==" + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } }, "find-up": { "version": "3.0.0", @@ -9162,6 +7766,14 @@ "locate-path": "^3.0.0" } }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, "invert-kv": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", @@ -9261,35 +7873,34 @@ } }, "webdriverio": { - "version": "5.7.8", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-5.7.8.tgz", - "integrity": "sha512-XGtbzlCsJALDXrU2XLxrVVgzh2BmW0ZyvsraftfHZvWczidtH2cCVrS8Y3ljAS/cIoR1t50lkNdN7wbPoBILXw==", + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-5.8.3.tgz", + "integrity": "sha512-3xkpLae8D5FuQov9m20vrR95JQVhHKCHzclc3rhUe0EnqS4MrvtTuny7dMg1pLDoIYdROnFnjOVwuUE63znmFg==", "requires": { - "@wdio/config": "^5.7.8", - "@wdio/logger": "^5.7.8", - "@wdio/repl": "^5.7.8", + "@wdio/config": "^5.8.1", + "@wdio/logger": "^5.8.0", + "@wdio/repl": "^5.8.1", "css-value": "^0.0.1", "grapheme-splitter": "^1.0.2", "lodash.isobject": "^3.0.2", "lodash.isplainobject": "^4.0.6", "lodash.merge": "^4.6.1", "lodash.zip": "^4.2.0", + "resq": "^1.4.0-rc.1", "rgb2hex": "^0.1.0", "serialize-error": "^3.0.0", - "webdriver": "^5.7.8" + "webdriver": "^5.8.3" } }, "webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", - "dev": true + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" }, "whatwg-encoding": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, "requires": { "iconv-lite": "0.4.24" } @@ -9297,14 +7908,12 @@ "whatwg-mimetype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" }, "whatwg-url": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", - "dev": true, "requires": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", @@ -9376,20 +7985,10 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, - "write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - }, "write-file-atomic": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.2.tgz", "integrity": "sha512-s0b6vB3xIVRLWywa6X9TOMA7k9zio0TMOsl9ZnDkliA/cfJlpHXAscj0gbHVJiTdIuAYpIyqS5GW91fqm6gG5g==", - "dev": true, "requires": { "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", @@ -9400,37 +7999,35 @@ "version": "5.2.2", "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", - "dev": true, "requires": { "async-limiter": "~1.0.0" } }, "xlsx": { - "version": "0.12.13", - "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.12.13.tgz", - "integrity": "sha512-9/2H4PLphmG8sDvI3mfWb6JIFqbvK8IRGhgS55Pw5F+fmKPuzdv4OW9RFjrH5PiTKeqB/883Z8o+jW3JrDahmw==", + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.14.3.tgz", + "integrity": "sha512-wgt9zGKeFp4WIQdPx+j2sNNbDYRbJ+M+uuFcS16pf2yLo/aKcG3RaD4xmS/LHT5rznc6V27NRwIXNWmxLj6eZw==", "requires": { "adler-32": "~1.2.0", - "cfb": "~1.0.7", - "codepage": "~1.13.0", - "commander": "~2.15.1", + "cfb": "^1.1.0", + "codepage": "~1.14.0", + "commander": "~2.17.1", "crc-32": "~1.2.0", "exit-on-epipe": "~1.0.1", "ssf": "~0.10.2" }, "dependencies": { "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==" } } }, "xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" }, "xml2js": { "version": "0.4.19", @@ -9446,12 +8043,6 @@ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" }, - "xmlchars": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-1.3.1.tgz", - "integrity": "sha512-tGkGJkN8XqCod7OT+EvGYK5Z4SfDQGD30zAa58OcnAa0RRWgzUEK72tkXhsX1FZd+rgnhRxFtmO+ihkp8LHSkw==", - "dev": true - }, "xmldom": { "version": "0.1.27", "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", @@ -9465,14 +8056,12 @@ "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, "yargs": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", - "dev": true, "requires": { "cliui": "^4.0.0", "decamelize": "^1.1.1", @@ -9492,22 +8081,21 @@ "version": "9.0.2", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", - "dev": true, "requires": { "camelcase": "^4.1.0" } }, "yup": { - "version": "0.26.10", - "resolved": "https://registry.npmjs.org/yup/-/yup-0.26.10.tgz", - "integrity": "sha512-keuNEbNSnsOTOuGCt3UJW69jDE3O4P+UHAakO7vSeFMnjaitcmlbij/a3oNb9g1Y1KvSKH/7O1R2PQ4m4TRylw==", + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.27.0.tgz", + "integrity": "sha512-v1yFnE4+u9za42gG/b/081E7uNW9mUj3qtkmelLbW5YPROZzSH/KUUyJu9Wt8vxFJcT9otL/eZopS0YK1L5yPQ==", "dev": true, "requires": { - "@babel/runtime": "7.0.0", + "@babel/runtime": "^7.0.0", "fn-name": "~2.0.1", - "lodash": "^4.17.10", + "lodash": "^4.17.11", "property-expr": "^1.5.0", - "synchronous-promise": "^2.0.5", + "synchronous-promise": "^2.0.6", "toposort": "^2.0.2" } } diff --git a/package.json b/package.json index 73e491d2..8a4abb82 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "kakunin", - "version": "2.6.1", + "version": "3.0.0", "description": "End-to-end testing framework", "homepage": "https://thesoftwarehouse.github.io/Kakunin/", "license": "MIT", @@ -30,6 +30,12 @@ }, { "name": "Wojciech Wójcik" + }, + { + "name": "Józef Szymala" + }, + { + "name": "Adam Nowrot" } ], "bin": { @@ -37,43 +43,54 @@ }, "main": "./dist/index", "scripts": { - "postinstall": "webdriver-manager update", - "units": "cross-env jest --setupFiles ./src/tests/init.js", - "functional": "cd functional-tests && npm i && npm run test", + "units": "cross-env jest --setupFiles ./src/tests/init.ts --no-cache", + "functional": "npm run build && cd functional-tests && rm -rf package-lock.json && rm -rf node_modules && npm i && npm run test", "test": "npm run units && npm run functional", - "test-ci": "npm run units && cd functional-tests && npm i && npm run test-ci", - "lint": "eslint \"src/**/*.js\" --ignore-pattern=\"*.spec.js\"", - "prettier": "prettier --write", - "build": "babel src --out-dir dist --ignore 'tests','*.spec.js' && babel templates --out-dir dist/templates --copy-files" + "test-ci": "npm run units && npm run build && cd functional-tests && npm i && npm run test-ci", + "lint": "tslint -c tslint.json 'src/**/*.ts'", + "lint-fix": "tslint -c tslint.json 'src/**/*.ts' --fix", + "prettier": "prettier --write 'src/**/*.ts'", + "type-check": "tsc --noEmit", + "build": "tsc", + "prepublishOnly": "npm run build && npm run test" }, "engines": { "node": ">=7.7.3", "npm": ">=4.1.2" }, "devDependencies": { - "babel-cli": "^6.26.0", - "babel-plugin-transform-object-rest-spread": "^6.26.0", - "babel-preset-env": "^1.7.0", - "babel-register": "^6.26.0", - "cross-env": "^5.2.0", - "eslint": "^5.10.0", - "eslint-config-airbnb": "^17.1.0", - "eslint-plugin-import": "^2.14.0", - "eslint-plugin-jsx-a11y": "^6.1.2", - "eslint-plugin-react": "^7.11.1", + "@types/cucumber": "^4.0.4", + "@types/extend": "^3.0.0", + "@types/faker": "^4.1.5", + "@types/glob": "^7.1.1", + "@types/inquirer": "^6.0.1", + "@types/jest": "^24.0.11", + "@types/lodash": "^4.14.120", + "@types/minimist": "^1.2.0", + "@types/mkdirp": "^0.5.2", + "@types/moment": "^2.13.0", + "@types/node": "^10.12.18", + "@types/node-fetch": "^2.1.4", + "@types/protractor": "^4.0.0", + "@types/shelljs": "^0.8.1", "fetch-mock": "^7.2.5", - "husky": "^1.2.0", - "jest": "^23.6.0", + "husky": "^2.1.0", "lint-staged": "^8.1.0", - "prettier": "^1.15.3" + "prettier": "^1.15.3", + "ts-jest": "^24.0.2", + "tslint": "^5.9.1", + "tslint-config-prettier": "^1.10.0", + "tslint-sonarts": "^1.6.0", + "typescript": "^3.2.4" }, "dependencies": { + "ajv": "^6.7.0", "browsermob-proxy": "^1.0.9", + "browserstack-local": "^1.3.7", "chai": "^4.2.0", - "chai-as-promised": "^7.1.1", - "chai-string": "^1.5.0", "chalk": "^2.4.1", "child_process": "^1.0.2", + "cross-env": "^5.2.0", "cucumber": "^5.0.3", "extend": "^3.0.2", "faker": "^4.1.0", @@ -82,23 +99,48 @@ "jasmine": "^3.3.1", "jasmine-reporters": "^2.3.2", "jasmine-spec-reporter": "^4.2.1", + "jest": "^23.6.0", "lodash": "^4.17.11", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "moment": "^2.23.0", "node-env-file": "^0.1.8", "node-fetch": "^2.3.0", - "node-xlsx": "^0.12.1", + "node-xlsx": "^0.14.1", "path": "^0.12.7", - "protractor": "^5.4.1", + "protractor": "5.4.2", "protractor-cucumber-framework": "^6.1.1", "protractor-multiple-cucumber-html-reporter-plugin": "^1.8.0", "shelljs": "^0.8.3", "sugar-date": "^2.0.6", - "webdriver-manager": "^13.0.0" + "webdriver-manager": "13.0.0" + }, + "jest": { + "collectCoverageFrom": [ + "src/**/*.ts", + "!src/**/index.ts", + "!src/**/*.d.ts" + ], + "transform": { + "^.+\\.(t|j)sx?$": "ts-jest" + }, + "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", + "moduleFileExtensions": [ + "ts", + "tsx", + "js", + "jsx", + "json", + "node" + ], + "globals": { + "ts-jest": { + "tsConfigFile": "tsconfig.test.json" + } + } }, "lint-staged": { - "src/**/*.js": [ + "src/**/*.ts": [ "prettier --write", "npm run lint", "git add" diff --git a/readme.md b/readme.md index ad125c54..b485d6fe 100644 --- a/readme.md +++ b/readme.md @@ -1,11 +1,11 @@ -

+

kakunin.png -

+

- travis.png + travis.png Current travis build: - build status + build statusnpm.png Current npm version: @@ -25,41 +25,51 @@ pageObjectFeature.gif

-
+

+

### **Automated testing framework** Kakunin is a Protractor extension created by The Software House sp. z o.o. and Takamol Holding. It allows you to write e2e test scenarios with a help of Gherkin language and JavaScript for all kind of applications - Angular, React and others. ------ +--- ### **Key Features:** + 1. E2E testing -2. Performance testing +2. Performance testing 3. Parallel testing -4. Cross browser testing +4. Cross browser testing 5. Reports ------ +--- ### **Documentation:** + You can find documentation on the **[official page](https://kakunin.io)**. ------ +--- + ### **Contributing:** + Feel free to contribute to this project! Just fork the code, make any updated and let us know! ------ +--- + ### **Issues:** + If you notice any issues while using, let as know on **[github](https://github.com/TheSoftwareHouse/Kakunin/issues)**. Security issues, please sent on email ------ +--- + ### **You may also like our other projects:** -* **[Babelsheet-js](https://github.com/TheSoftwareHouse/babelsheet-js)** -* **[Fogger](https://github.com/TheSoftwareHouse/fogger)** ------ +- **[Babelsheet-js](https://github.com/TheSoftwareHouse/babelsheet-js)** +- **[Fogger](https://github.com/TheSoftwareHouse/fogger)** + +--- + ### **About us:**

diff --git a/src/cli.js b/src/cli.ts similarity index 62% rename from src/cli.js rename to src/cli.ts index 0d0be076..b6b48a8b 100644 --- a/src/cli.js +++ b/src/cli.ts @@ -1,12 +1,12 @@ #!/usr/bin/env node +import * as path from 'path'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as childProcess from 'child_process'; +import * as envfile from 'node-env-file'; +import { createTagsCLIArgument, filterCLIArguments, getConfigPath, isInitCommand } from './core/cli/cli.helper'; import initializer from './core/cli/initializer'; -import { isInitCommand, getConfigPath, createTagsCLIArgument, filterCLIArguments } from './core/cli/cli.helper'; - const commandArgs = require('minimist')(process.argv.slice(2)); -const path = require('path'); -const childProcess = require('child_process'); -const envfile = require('node-env-file'); -const os = require('os'); envfile(process.cwd() + '/.env', { raise: false, overwrite: false }); @@ -29,6 +29,24 @@ if (isInitCommand(process.argv)) { const protractorExecutable = os.platform() === 'win32' ? 'protractor.cmd' : 'protractor'; + if ( + !fs.existsSync( + path.join( + process.cwd(), + 'node_modules', + 'protractor', + 'node_modules', + 'webdriver-manager', + 'selenium', + 'update-config.json' + ) + ) + ) { + childProcess.execSync( + path.join(process.cwd(), 'node_modules', '.bin', 'webdriver-manager update --ie --versions.standalone=3.14.0') + ); + } + childProcess .spawn(path.join('node_modules', '.bin', protractorExecutable), argv, { stdio: 'inherit', diff --git a/src/comparators/comparator.interface.ts b/src/comparators/comparator.interface.ts new file mode 100644 index 00000000..30966c7a --- /dev/null +++ b/src/comparators/comparator.interface.ts @@ -0,0 +1,4 @@ +export interface Comparator { + isSatisfiedBy(value: any[]): boolean; + compare(values: any[], order: string): Promise; +} diff --git a/src/comparators/comparator/date.comparator.spec.js b/src/comparators/comparator/date.comparator.spec.ts similarity index 100% rename from src/comparators/comparator/date.comparator.spec.js rename to src/comparators/comparator/date.comparator.spec.ts diff --git a/src/comparators/comparator/date.comparator.js b/src/comparators/comparator/date.comparator.ts similarity index 82% rename from src/comparators/comparator/date.comparator.js rename to src/comparators/comparator/date.comparator.ts index 56efd3bd..4efbd6ab 100644 --- a/src/comparators/comparator/date.comparator.js +++ b/src/comparators/comparator/date.comparator.ts @@ -1,10 +1,11 @@ -import moment from 'moment'; +import * as moment from 'moment'; +import { Comparator } from '../comparator.interface'; export const supportedFormats = ['DD-MM-YYYY', 'DD-MM-YY', 'DD/MM/YYYY', 'DD/MM/YY']; const isValidDate = date => { - for (let index = 0; index < supportedFormats.length; index++) { - if (moment(date, supportedFormats[index]).isValid()) { + for (const format of supportedFormats) { + if (moment(date, format).isValid()) { return true; } } @@ -12,10 +13,9 @@ const isValidDate = date => { return false; }; -export const DateComparator = { +export const DateComparator: Comparator = { isSatisfiedBy: values => { - for (let i = 0; i < values.length; i++) { - const date = values[i]; + for (const date of values) { const found = isValidDate(date); if (!found) { diff --git a/src/comparators/comparator/index.js b/src/comparators/comparator/index.ts similarity index 100% rename from src/comparators/comparator/index.js rename to src/comparators/comparator/index.ts diff --git a/src/comparators/comparator/number.comparator.spec.js b/src/comparators/comparator/number.comparator.spec.ts similarity index 100% rename from src/comparators/comparator/number.comparator.spec.js rename to src/comparators/comparator/number.comparator.spec.ts diff --git a/src/comparators/comparator/number.comparator.js b/src/comparators/comparator/number.comparator.ts similarity index 79% rename from src/comparators/comparator/number.comparator.js rename to src/comparators/comparator/number.comparator.ts index 6149f39c..8f1c8c22 100644 --- a/src/comparators/comparator/number.comparator.js +++ b/src/comparators/comparator/number.comparator.ts @@ -1,8 +1,10 @@ -export const NumberComparator = { +import { Comparator } from '../comparator.interface'; + +export const NumberComparator: Comparator = { isSatisfiedBy: values => { - for (let i = 0; i < values.length; i++) { - const value = Number(values[i]); - if (Number.isNaN(value)) { + for (const value of values) { + const numberValue = Number(value); + if (Number.isNaN(numberValue)) { return false; } } diff --git a/src/comparators/comparators.spec.js b/src/comparators/comparators.spec.ts similarity index 100% rename from src/comparators/comparators.spec.js rename to src/comparators/comparators.spec.ts diff --git a/src/comparators/comparators.js b/src/comparators/comparators.ts similarity index 56% rename from src/comparators/comparators.js rename to src/comparators/comparators.ts index 03b8de8d..d917fa13 100644 --- a/src/comparators/comparators.js +++ b/src/comparators/comparators.ts @@ -1,11 +1,12 @@ import * as comparators from './comparator'; +import { Comparator } from './comparator.interface'; class Comparators { - constructor() { - this.availableComparators = [comparators.DateComparator, comparators.NumberComparator]; - } + constructor( + private availableComparators: Comparator[] = [comparators.DateComparator, comparators.NumberComparator] + ) {} - compare(values, order) { + public compare(values: any[], order: string): Promise { const comparator = this.findComparator(values); if (comparator === undefined) { @@ -15,11 +16,11 @@ class Comparators { return comparator.compare(values, order); } - findComparator(values) { + public findComparator(values: any[]): Comparator { return this.availableComparators.find(comparator => comparator.isSatisfiedBy(values)); } - addComparator(comparator) { + public addComparator(comparator: Comparator): void { this.availableComparators.push(comparator); } } diff --git a/src/comparators/index.js b/src/comparators/index.ts similarity index 100% rename from src/comparators/index.js rename to src/comparators/index.ts diff --git a/src/core/cli/cli.helper.spec.js b/src/core/cli/cli.helper.spec.ts similarity index 96% rename from src/core/cli/cli.helper.spec.js rename to src/core/cli/cli.helper.spec.ts index 3e7dfff1..b8d34f14 100644 --- a/src/core/cli/cli.helper.spec.js +++ b/src/core/cli/cli.helper.spec.ts @@ -26,7 +26,7 @@ describe('Cli helpers', () => { }); it('returns config path by config file', () => { - expect(getConfigPath('some-file.config.js', 'other-config.js', '/my/path')).toEqual('/my/path/other-config.js'); + expect(getConfigPath('some-file.config.js', 'other-config.ts', '/my/path')).toEqual('/my/path/other-config.ts'); }); it('creates empty tags cli argument if neither performance nor tags param is defined', () => { diff --git a/src/core/cli/cli.helper.js b/src/core/cli/cli.helper.ts similarity index 95% rename from src/core/cli/cli.helper.js rename to src/core/cli/cli.helper.ts index fdc48a67..4b14ee9f 100644 --- a/src/core/cli/cli.helper.js +++ b/src/core/cli/cli.helper.ts @@ -1,6 +1,6 @@ import * as path from 'path'; -export const isInitCommand = args => { +export const isInitCommand = (args?: any[] | string) => { if (Array.isArray(args)) { return args.length > 2 && args[2] === 'init'; } diff --git a/src/core/cli/initializer.js b/src/core/cli/initializer.ts similarity index 92% rename from src/core/cli/initializer.js rename to src/core/cli/initializer.ts index 675d4f50..2ce4e1c0 100644 --- a/src/core/cli/initializer.js +++ b/src/core/cli/initializer.ts @@ -1,20 +1,18 @@ -import inquirer from 'inquirer'; -import mkdirp from 'mkdirp'; -import fs from 'fs'; -import path from 'path'; +import * as fs from 'fs'; +import * as inquirer from 'inquirer'; +import * as mkdirp from 'mkdirp'; +import * as path from 'path'; class Initializer { - // eslint-disable-next-line class-methods-use-this - createProjectDirectory(dirPath) { + public createProjectDirectory(dirPath) { const projectPath = process.cwd() + dirPath; - mkdirp(projectPath); + mkdirp(projectPath, null); console.log(`Created directory at path ${projectPath}`); } - // eslint-disable-next-line class-methods-use-this - createTemplateFile(templatePath, content) { + public createTemplateFile(templatePath, content) { const filePath = process.cwd() + templatePath; fs.writeFileSync(filePath, content); @@ -22,14 +20,13 @@ class Initializer { console.log(`Created file at path ${filePath}`); } - createTemplateFileWithContentFrom(contentPath, file) { + public createTemplateFileWithContentFrom(contentPath, file) { const content = fs.readFileSync(path.join(__dirname, `../../../templates/${file}`)); this.createTemplateFile(contentPath, content); } - // eslint-disable-next-line class-methods-use-this - async promptFolders(message, defaultValue, type = 'input') { + public async promptFolders(message, defaultValue, type = 'input') { let fullMessage = message; if (defaultValue !== '') { @@ -39,18 +36,17 @@ class Initializer { return inquirer .prompt([ { - type: type, + type, name: 'input', message: fullMessage, }, ]) - .then(function(answer) { - return answer.input === '' ? defaultValue : answer.input; - }); + .then((answer: any): any => (answer.input === '' ? defaultValue : answer.input)); } - async initConfig(commandArgs) { + public async initConfig(commandArgs) { const conf = { + baseUrl: '', type: 'otherWeb', browserWidth: 1600, browserHeight: 900, @@ -81,6 +77,8 @@ class Initializer { email: null, headless: false, noGpu: false, + browserMob: null, + accounts: null, }; if (typeof commandArgs.baseUrl === 'undefined') { @@ -103,7 +101,7 @@ class Initializer { ], }, ]) - .then(function(answer) { + .then((answer: any) => { if (answer.type !== 'none') { conf.email = { type: answer.type, @@ -221,7 +219,7 @@ class Initializer { this.createTemplateFile('/kakunin.conf.js', 'module.exports = ' + JSON.stringify(conf, null, 4)); } - async initEnv() { + public async initEnv() { const envs = []; envs.push('FIXTURES_RELOAD_HOST=' + (await this.promptFolders('Define FIXTURES_RELOAD_HOST', ''))); @@ -229,10 +227,8 @@ class Initializer { this.createTemplateFile('/.env', envs.join('\n')); } - async generateProjectStructure() { - /* eslint-disable */ + public async generateProjectStructure() { const config = require(process.cwd() + '/kakunin.conf.js'); - /* eslint-enable */ this.createProjectDirectory(config.reports); this.createProjectDirectory(path.join(config.reports, 'report')); diff --git a/src/core/config.helper.js b/src/core/config.helper.ts similarity index 89% rename from src/core/config.helper.js rename to src/core/config.helper.ts index c5d70701..0bd0aec4 100644 --- a/src/core/config.helper.js +++ b/src/core/config.helper.ts @@ -15,7 +15,7 @@ if (process.env.NODE_ENV === 'test') { const project = process.argv.find(name => name.indexOf('--projectPath') >= 0); const projectPath = project.substr(project.indexOf('=') + 1); - config = require(configFilePath); // eslint-disable-line global-require + config = require(configFilePath); config.projectPath = projectPath; config.performance = commandArgs.performance || false; } diff --git a/src/core/fs/delete-files.helper.js b/src/core/fs/delete-files.helper.ts similarity index 81% rename from src/core/fs/delete-files.helper.js rename to src/core/fs/delete-files.helper.ts index e21bdede..61f38ee1 100644 --- a/src/core/fs/delete-files.helper.js +++ b/src/core/fs/delete-files.helper.ts @@ -1,5 +1,5 @@ -import fs from 'fs'; -import path from 'path'; +import * as fs from 'fs'; +import * as path from 'path'; export const deleteReports = directory => { return fs diff --git a/src/core/fs/prepare-catalogs.helper.js b/src/core/fs/prepare-catalogs.helper.js deleted file mode 100644 index 09a93b80..00000000 --- a/src/core/fs/prepare-catalogs.helper.js +++ /dev/null @@ -1,12 +0,0 @@ -import fs from 'fs'; -import mkdirp from 'mkdirp'; - -export const prepareCatalogs = async directory => { - if (fs.existsSync(directory)) { - return Promise.resolve(); - } - - await mkdirp(directory); - await console.log(`${directory} has been added!`); - await fs.writeFileSync(`${directory}/.gitkeep`, ''); -}; diff --git a/src/core/fs/prepare-catalogs.helper.ts b/src/core/fs/prepare-catalogs.helper.ts new file mode 100644 index 00000000..959032da --- /dev/null +++ b/src/core/fs/prepare-catalogs.helper.ts @@ -0,0 +1,12 @@ +import * as fs from 'fs'; +import * as mkdirp from 'mkdirp'; + +export const prepareCatalogs = directory => { + if (fs.existsSync(directory)) { + return Promise.resolve(); + } + + mkdirp(directory, null); + console.log(`${directory} has been added!`); + fs.writeFileSync(`${directory}/.gitkeep`, ''); +}; diff --git a/src/core/modules-loader.helper.js b/src/core/modules-loader.helper.ts similarity index 75% rename from src/core/modules-loader.helper.js rename to src/core/modules-loader.helper.ts index 33edc011..d0781528 100644 --- a/src/core/modules-loader.helper.js +++ b/src/core/modules-loader.helper.ts @@ -1,8 +1,10 @@ -import fs from 'fs'; -import path from 'path'; +import * as fs from 'fs'; +import * as path from 'path'; import config from './config.helper'; class ModulesLoader { + private paths: any; + constructor(configuration) { this.paths = { comparators: [], @@ -13,6 +15,7 @@ class ModulesLoader { regexes: [], transformers: [], emails: [], + hooks: [], }; Object.keys(this.paths).forEach(group => { @@ -24,25 +27,22 @@ class ModulesLoader { }); } - getModules(group) { - return this.getFilePaths(this.paths[group]).map( - file => require(file[1]) // eslint-disable-line global-require - ); + public getModules(group) { + return this.getFilePaths(this.paths[group]).map(file => require(file[1])); } - getModulesAsObject(projectFolders) { + public getModulesAsObject(projectFolders) { const modules = {}; const filePaths = this.getFilePaths(projectFolders); filePaths.forEach(file => { - modules[file[0]] = require(file[1]); // eslint-disable-line global-require + modules[file[0]] = require(file[1]); }); return modules; } - // eslint-disable-next-line class-methods-use-this - getFilePaths(folders) { + public getFilePaths(folders) { let files = []; folders.forEach(folder => { diff --git a/src/core/prototypes.js b/src/core/prototypes.js deleted file mode 100644 index f79ee30d..00000000 --- a/src/core/prototypes.js +++ /dev/null @@ -1,8 +0,0 @@ -// eslint-disable-next-line no-extend-native -String.prototype.toCamelCase = function() { - return this.charAt(0).toUpperCase() + this.slice(1); -}; - -RegExp.escape = function(text) { - return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); -}; diff --git a/src/core/prototypes.ts b/src/core/prototypes.ts new file mode 100644 index 00000000..6dbd1a90 --- /dev/null +++ b/src/core/prototypes.ts @@ -0,0 +1,3 @@ +RegExp.escape = (text): string => { + return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); +}; diff --git a/src/dictionaries/base.js b/src/dictionaries/base.js deleted file mode 100644 index 8b48f7bf..00000000 --- a/src/dictionaries/base.js +++ /dev/null @@ -1,16 +0,0 @@ -class Dictionary { - constructor(dictionaryName, valuesObject) { - this.values = valuesObject; - this.name = dictionaryName; - } - - isSatisfiedBy(name) { - return this.name === name; - } - - getMappedValue(key) { - return this.values[key]; - } -} - -export default Dictionary; diff --git a/src/dictionaries/base.ts b/src/dictionaries/base.ts new file mode 100644 index 00000000..47658778 --- /dev/null +++ b/src/dictionaries/base.ts @@ -0,0 +1,19 @@ +class BaseDictionary { + public readonly name: string; + public readonly values: object; + + constructor(name, values) { + this.name = name; + this.values = values; + } + + public isSatisfiedBy(name: string): boolean { + return this.name === name; + } + + public getMappedValue(key: string): string { + return this.values[key]; + } +} + +export default BaseDictionary; diff --git a/src/dictionaries/dictionaries.spec.js b/src/dictionaries/dictionaries.spec.ts similarity index 77% rename from src/dictionaries/dictionaries.spec.js rename to src/dictionaries/dictionaries.spec.ts index bc9c4c9b..948efeeb 100644 --- a/src/dictionaries/dictionaries.spec.js +++ b/src/dictionaries/dictionaries.spec.ts @@ -1,5 +1,5 @@ -import { create } from './dictionaries'; -import fakeDictionary from '../tests/dictionaries/fake-dictionary'; +import { createDictionary as create, Base as BaseDictionary } from './'; +import fakeDictionary = require('../tests/dictionaries/fake-dictionary'); const dictionaries = create(); @@ -21,10 +21,7 @@ describe('Dictionaries', () => { }); it('adds a dictionary', () => { - const customDictionary = { - isSatisfiedBy: name => name === 'my-dictionary', - getMappedValue: key => `mapped-${key}`, - }; + const customDictionary = new BaseDictionary('my-dictionary', { 'some-key': 'mapped-some-key' }); dictionaries.addDictionary(customDictionary); diff --git a/src/dictionaries/dictionaries.js b/src/dictionaries/dictionaries.ts similarity index 64% rename from src/dictionaries/dictionaries.js rename to src/dictionaries/dictionaries.ts index df183b09..decffa4a 100644 --- a/src/dictionaries/dictionaries.js +++ b/src/dictionaries/dictionaries.ts @@ -1,9 +1,9 @@ -class Dictionaries { - constructor() { - this.availableDictionaries = []; - } +import Dictionary from './base'; + +export class Dictionaries { + constructor(private availableDictionaries: Dictionary[] = []) {} - getMappedValue(dictionaryName, key) { + public getMappedValue(dictionaryName: string, key: string): string { const dic = this.findDictionary(dictionaryName); if (dic === undefined) { @@ -13,11 +13,11 @@ class Dictionaries { return dic.getMappedValue(key); } - findDictionary(name) { + public findDictionary(name: string): Dictionary { return this.availableDictionaries.find(dic => dic.isSatisfiedBy(name)); } - findMappedValueByPhrase(phrase) { + public findMappedValueByPhrase(phrase: string): string { const parameters = phrase.split(':'); if (parameters[0] === 'd') { const dictionary = this.findDictionary(parameters[1]); @@ -30,7 +30,7 @@ class Dictionaries { return phrase; } - addDictionary(dictionary) { + public addDictionary(dictionary: Dictionary): void { this.availableDictionaries.push(dictionary); } } diff --git a/src/dictionaries/index.js b/src/dictionaries/index.ts similarity index 63% rename from src/dictionaries/index.js rename to src/dictionaries/index.ts index be7fa181..18556e74 100644 --- a/src/dictionaries/index.js +++ b/src/dictionaries/index.ts @@ -1,5 +1,7 @@ -import { create } from './dictionaries'; import BaseDictionary from './base'; +import { create } from './dictionaries'; +export { Dictionaries } from './dictionaries'; +export const createDictionary = create; export const dictionaries = create(); export const Base = BaseDictionary; diff --git a/src/emails/adapter/mailtrap.client.spec.js b/src/emails/adapter/mailtrap.client.spec.ts similarity index 98% rename from src/emails/adapter/mailtrap.client.spec.js rename to src/emails/adapter/mailtrap.client.spec.ts index e2c202fc..45c1de64 100644 --- a/src/emails/adapter/mailtrap.client.spec.js +++ b/src/emails/adapter/mailtrap.client.spec.ts @@ -1,5 +1,5 @@ import { create } from './mailtrap.client'; -import fetchMock from 'fetch-mock'; +import * as fetchMock from 'fetch-mock'; describe('Mailtrap client', () => { it('it returns mailtrap config', () => { diff --git a/src/emails/adapter/mailtrap.client.js b/src/emails/adapter/mailtrap.client.ts similarity index 90% rename from src/emails/adapter/mailtrap.client.js rename to src/emails/adapter/mailtrap.client.ts index d680bd5f..20b48e25 100644 --- a/src/emails/adapter/mailtrap.client.js +++ b/src/emails/adapter/mailtrap.client.ts @@ -1,13 +1,16 @@ -import fetch from 'node-fetch'; +import * as fetch from 'node-fetch'; import configuration from '../../core/config.helper'; class MailTrapClient { + private requestClient: any; + private config: any; + constructor(requestClient, config) { this.requestClient = requestClient; this.config = config; } - isSatisfiedBy(emailConfiguration) { + public isSatisfiedBy(emailConfiguration) { return ( emailConfiguration.type === 'mailtrap' && emailConfiguration.config.hasOwnProperty('apiKey') && @@ -16,7 +19,7 @@ class MailTrapClient { ); } - getMailtrapConfig() { + public getMailtrapConfig() { return { apiKey: this.config.config.apiKey, inboxId: this.config.config.inboxId, @@ -24,7 +27,7 @@ class MailTrapClient { }; } - clearInbox() { + public clearInbox() { const config = this.getMailtrapConfig(); const url = `${config.endpoint}/api/v1/inboxes/${config.inboxId}/clean?api_token=${config.apiKey}`; @@ -39,7 +42,7 @@ class MailTrapClient { }); } - async getEmails() { + public async getEmails() { const config = this.getMailtrapConfig(); const url = `${config.endpoint}/api/v1/inboxes/${config.inboxId}/messages?api_token=${config.apiKey}`; @@ -67,7 +70,7 @@ class MailTrapClient { return messagesWithBody.filter(message => !message.is_read); } - getAttachments(email) { + public getAttachments(email) { const config = this.getMailtrapConfig(); const url = `${config.endpoint}/api/v1/inboxes/${config.inboxId}/messages/${email.id}/attachments?api_token=${ config.apiKey @@ -82,7 +85,7 @@ class MailTrapClient { }); } - markAsRead(email) { + public markAsRead(email) { const config = this.getMailtrapConfig(); const url = `${config.endpoint}/api/v1/inboxes/${config.inboxId}/messages/${email.id}?api_token=${config.apiKey}`; diff --git a/src/emails/email.service.spec.js b/src/emails/email.service.spec.ts similarity index 98% rename from src/emails/email.service.spec.js rename to src/emails/email.service.spec.ts index 2fd81dd9..1f8fedf6 100644 --- a/src/emails/email.service.spec.js +++ b/src/emails/email.service.spec.ts @@ -3,7 +3,7 @@ import { create } from './email.service'; describe('Email service', () => { it('it returns adapter if found', () => { const fakeAdapter = { - isSatisfiedBy: config => true, + isSatisfiedBy: (config: any) => true, }; const fakeConfig = { diff --git a/src/emails/email.service.js b/src/emails/email.service.ts similarity index 75% rename from src/emails/email.service.js rename to src/emails/email.service.ts index 3b265824..65a7ff1d 100644 --- a/src/emails/email.service.js +++ b/src/emails/email.service.ts @@ -1,42 +1,45 @@ import configuration from '../core/config.helper'; -import { create as createMailtrapAdapter } from './adapter/mailtrap.client.js'; +import { create as createMailtrapAdapter } from './adapter/mailtrap.client'; class EmailService { + private config: any; + private availableAdapters: any; + constructor(config, defaultAdapters) { this.config = config; this.availableAdapters = defaultAdapters; } - clearInbox() { + public clearInbox() { const adapter = this.getAdapter(); return adapter.clearInbox(); } - getEmails() { + public getEmails() { const adapter = this.getAdapter(); return adapter.getEmails(); } - getAttachments(email) { + public getAttachments(email) { const adapter = this.getAdapter(); return adapter.getAttachments(email); } - markAsRead(email) { + public markAsRead(email) { const adapter = this.getAdapter(); return adapter.markAsRead(email); } - addAdapter(adapter) { + public addAdapter(adapter) { this.availableAdapters.push(adapter); } - getAdapter() { + public getAdapter() { const emailAdapter = this.availableAdapters.find(adapter => adapter.isSatisfiedBy(this.config.email)); if (emailAdapter === undefined) { @@ -49,6 +52,6 @@ class EmailService { const mailtrapAdapter = createMailtrapAdapter(); -export const create = (defaultAdapters = [mailtrapAdapter], config = configuration) => { +export const create = (defaultAdapters: any = [mailtrapAdapter], config = configuration) => { return new EmailService(config, defaultAdapters); }; diff --git a/src/emails/filter/current-user.filter.js b/src/emails/filter/current-user.filter.ts similarity index 79% rename from src/emails/filter/current-user.filter.js rename to src/emails/filter/current-user.filter.ts index 749b7ff2..39ddafa3 100644 --- a/src/emails/filter/current-user.filter.js +++ b/src/emails/filter/current-user.filter.ts @@ -1,11 +1,11 @@ // TODO: stop injecting world here and use some kind of a user provider class CurrentUserFilter { - isSatisfiedBy(type) { + public isSatisfiedBy(type) { return type === 'currentUser'; } - filter(emails, type, value, world) { + public filter(emails, type, value, world) { return emails.filter(email => email.to_email === world.currentUser.account.email); } } diff --git a/src/emails/filter/current-user.spec.js b/src/emails/filter/current-user.spec.ts similarity index 93% rename from src/emails/filter/current-user.spec.js rename to src/emails/filter/current-user.spec.ts index e429a65b..c27bce79 100644 --- a/src/emails/filter/current-user.spec.js +++ b/src/emails/filter/current-user.spec.ts @@ -1,4 +1,4 @@ -import { currentUserFilter } from './current-user.filter'; +const { currentUserFilter } = require('./current-user.filter'); const fakeWorld = { currentUser: { diff --git a/src/emails/filter/index.js b/src/emails/filter/index.ts similarity index 100% rename from src/emails/filter/index.js rename to src/emails/filter/index.ts diff --git a/src/emails/filter/minimal-email-size.filter.spec.js b/src/emails/filter/minimal-email-size.filter.spec.ts similarity index 90% rename from src/emails/filter/minimal-email-size.filter.spec.js rename to src/emails/filter/minimal-email-size.filter.spec.ts index 3eec4284..ea360d6a 100644 --- a/src/emails/filter/minimal-email-size.filter.spec.js +++ b/src/emails/filter/minimal-email-size.filter.spec.ts @@ -1,4 +1,4 @@ -import { minimalEmailSizeFilter } from './minimal-email-size.filter.js'; +const { minimalEmailSizeFilter } = require('./minimal-email-size.filter.ts'); describe('Minimal email size filter', () => { it('returns true when can be use', () => { diff --git a/src/emails/filter/minimal-email-size.filter.js b/src/emails/filter/minimal-email-size.filter.ts similarity index 67% rename from src/emails/filter/minimal-email-size.filter.js rename to src/emails/filter/minimal-email-size.filter.ts index b33cd702..d78ad721 100644 --- a/src/emails/filter/minimal-email-size.filter.js +++ b/src/emails/filter/minimal-email-size.filter.ts @@ -1,10 +1,9 @@ class MinimalEmailSizeFilter { - isSatisfiedBy(type) { + public isSatisfiedBy(type) { return type === 'minimalEmailSize'; } - // eslint-disable-next-line no-unused-vars - filter(emails, type, value, world) { + public filter(emails, type, value) { return emails.filter(email => email.email_size >= parseInt(value)); } } diff --git a/src/emails/filter/text-fields.filter.spec.js b/src/emails/filter/text-fields.filter.spec.ts similarity index 100% rename from src/emails/filter/text-fields.filter.spec.js rename to src/emails/filter/text-fields.filter.spec.ts diff --git a/src/emails/filter/text-fields.filter.js b/src/emails/filter/text-fields.filter.ts similarity index 76% rename from src/emails/filter/text-fields.filter.js rename to src/emails/filter/text-fields.filter.ts index de5cbaf5..07a25046 100644 --- a/src/emails/filter/text-fields.filter.js +++ b/src/emails/filter/text-fields.filter.ts @@ -2,12 +2,11 @@ import { regexBuilder } from '../../matchers'; import variableStore from '../../web/variable-store.helper'; class TextFieldFilter { - isSatisfiedBy(type) { + public isSatisfiedBy(type) { return ['subject', 'from_email', 'from_name', 'to_email', 'to_name', 'html_body', 'text_body'].indexOf(type) !== -1; } - // eslint-disable-next-line no-unused-vars - filter(emails, type, value, world) { + public filter(emails, type, value) { return emails.filter(email => { if (value.startsWith('r:')) { return regexBuilder.buildRegex(value).test(email[type]); @@ -17,7 +16,7 @@ class TextFieldFilter { return new RegExp(RegExp.escape(variableStore.replaceTextVariables(value.substr(2)))).test(email[type]); } - throw 'Comparison type not specified. Please use r: for regex and t: for text'; + throw new Error('Comparison type not specified. Please use r: for regex and t: for text'); }); } } diff --git a/src/emails/filters.spec.js b/src/emails/filters.spec.ts similarity index 100% rename from src/emails/filters.spec.js rename to src/emails/filters.spec.ts diff --git a/src/emails/filters.js b/src/emails/filters.ts similarity index 84% rename from src/emails/filters.js rename to src/emails/filters.ts index 922709e6..2ca937b9 100644 --- a/src/emails/filters.js +++ b/src/emails/filters.ts @@ -1,6 +1,8 @@ import * as defaultFilters from './filter'; class Filters { + private availableFilters: any; + constructor() { this.availableFilters = [ defaultFilters.currentUserFilter, @@ -9,7 +11,7 @@ class Filters { ]; } - filter(emails, type, value, world) { + public filter(emails, type, value, world) { const filter = this.findFilter(type); if (typeof filter === 'undefined') { @@ -19,7 +21,7 @@ class Filters { return filter.filter(emails, type, value, world); } - findFilter(type) { + public findFilter(type) { return this.availableFilters.find(filter => filter.isSatisfiedBy(type)); } } diff --git a/src/emails/index.js b/src/emails/index.ts similarity index 100% rename from src/emails/index.js rename to src/emails/index.ts diff --git a/src/form-handlers/form-handler.interface.ts b/src/form-handlers/form-handler.interface.ts new file mode 100644 index 00000000..6d74a6d1 --- /dev/null +++ b/src/form-handlers/form-handler.interface.ts @@ -0,0 +1,6 @@ +export interface FormHandler { + isSatisfiedBy(element?: object, elementName?: string): Promise; + handleFill(page: object, elementName: string, desiredValue: string): Promise; + handleCheck(page: object, elementName: string, desiredValue: string): Promise; + getPriority(): number; +} diff --git a/src/form-handlers/handler/checkbox.handler.js b/src/form-handlers/handler/checkbox.handler.ts similarity index 74% rename from src/form-handlers/handler/checkbox.handler.js rename to src/form-handlers/handler/checkbox.handler.ts index 9c38c43b..116080b0 100644 --- a/src/form-handlers/handler/checkbox.handler.js +++ b/src/form-handlers/handler/checkbox.handler.ts @@ -1,5 +1,7 @@ -class CheckboxHandler { - isSatisfiedBy(element) { +import { FormHandler } from '../form-handler.interface'; + +class CheckboxHandler implements FormHandler { + public isSatisfiedBy(element) { return element.getTagName().then(tagName => { if (tagName === 'input') { return element.getAttribute('type').then(inputType => inputType === 'checkbox'); @@ -16,8 +18,9 @@ class CheckboxHandler { }); } - handleFill(page, elementName, desiredValue) { - return page[elementName] + public handleFill(page, elementName, desiredValue) { + return page + .getElements(elementName) .filter(elem => { return elem .element(by.xpath('..')) @@ -30,8 +33,8 @@ class CheckboxHandler { .click(); } - handleCheck(page, elementName, desiredValue) { - const filteredElements = page[elementName].filter(element => element.isSelected()); + public handleCheck(page, elementName, desiredValue) { + const filteredElements = page.getElements(elementName).filter(element => element.isSelected()); return filteredElements.count().then(count => { if (desiredValue === '') { @@ -42,7 +45,8 @@ class CheckboxHandler { return Promise.reject(`Expected count to be 0 got ${count}`); } - return page[elementName] + return page + .getElements(elementName) .filter(element => { return element .element(by.xpath('..')) @@ -63,7 +67,7 @@ class CheckboxHandler { }); } - getPriority() { + public getPriority() { return 998; } } diff --git a/src/form-handlers/handler/ckeditor.handler.js b/src/form-handlers/handler/ckeditor.handler.ts similarity index 60% rename from src/form-handlers/handler/ckeditor.handler.js rename to src/form-handlers/handler/ckeditor.handler.ts index fe7b8582..88951d84 100644 --- a/src/form-handlers/handler/ckeditor.handler.js +++ b/src/form-handlers/handler/ckeditor.handler.ts @@ -1,9 +1,11 @@ -class CKEditorHandler { - isSatisfiedBy(element, elementName) { +import { FormHandler } from '../form-handler.interface'; + +class CKEditorHandler implements FormHandler { + public isSatisfiedBy(element, elementName) { return Promise.resolve(elementName.endsWith('CKEditor')); } - handleFill(page, elementName, desiredValue) { + public handleFill(page, elementName, desiredValue) { browser.switchTo().frame(page[elementName].getWebElement()); browser.driver.findElement(by.tagName('body')).sendKeys(desiredValue); @@ -13,12 +15,11 @@ class CKEditorHandler { return browser.waitForAngular(); } - // eslint-disable-next-line no-unused-vars - handleCheck(page, elementName, desiredValue) { + public handleCheck(page, elementName, desiredValue) { return Promise.reject('Checking CKEditor is not supported'); } - getPriority() { + public getPriority() { return 998; } } diff --git a/src/form-handlers/handler/custom-angular-select.handler.js b/src/form-handlers/handler/custom-angular-select.handler.ts similarity index 56% rename from src/form-handlers/handler/custom-angular-select.handler.js rename to src/form-handlers/handler/custom-angular-select.handler.ts index d3d65878..a3dd5ab4 100644 --- a/src/form-handlers/handler/custom-angular-select.handler.js +++ b/src/form-handlers/handler/custom-angular-select.handler.ts @@ -1,21 +1,26 @@ -class CustomAngularSelectHandler { +import { FormHandler } from '../form-handler.interface'; + +class CustomAngularSelectHandler implements FormHandler { + private selectedOptionSelector: object; + private optionsSelector: object; + constructor() { this.optionsSelector = by.css('ul.ui-select-choices li a.ui-select-choices-row-inner'); this.selectedOptionSelector = by.css('div.ui-select-match .ui-select-match-text'); } - isSatisfiedBy(element, elementName) { + public isSatisfiedBy(element, elementName) { return Promise.resolve(elementName.endsWith('CustomAngularSelect')); } - handleFill(page, elementName, desiredValue) { - return browser.executeScript('arguments[0].scrollIntoView(false);', page[elementName].getWebElement()).then(() => { - return page[elementName].click().then(() => { - const filtered = page[elementName].all(this.optionsSelector).filter(function(elem) { - return elem.getText().then(function(text) { - return text === desiredValue; - }); - }); + public handleFill(page, elementName, desiredValue) { + return browser + .executeScript('arguments[0].scrollIntoView(false);', page[elementName].getWebElement()) + .then(() => page[elementName].click()) + .then(() => { + const filtered = page[elementName] + .all(this.optionsSelector) + .filter(elem => elem.getText().then(text => text === desiredValue)); return filtered.count().then(count => { if (count === 0) { @@ -28,14 +33,13 @@ class CustomAngularSelectHandler { return filtered.first().click(); }); }); - }); } - handleCheck(page, elementName, desiredValue) { + public handleCheck(page, elementName, desiredValue) { return page[elementName] .element(this.selectedOptionSelector) .getText() - .then(function(text) { + .then(text => { if (text === desiredValue) { return Promise.resolve(); } @@ -44,7 +48,7 @@ class CustomAngularSelectHandler { }); } - getPriority() { + public getPriority() { return 998; } } diff --git a/src/form-handlers/handler/default.handler.js b/src/form-handlers/handler/default.handler.js deleted file mode 100644 index fb3ea755..00000000 --- a/src/form-handlers/handler/default.handler.js +++ /dev/null @@ -1,31 +0,0 @@ -class DefaultHandler { - isSatisfiedBy() { - return Promise.resolve(true); - } - - handleFill(page, elementName, desiredValue) { - return page[elementName].isDisplayed().then(function() { - return page[elementName].clear().then(function() { - return page[elementName].sendKeys(desiredValue); - }); - }); - } - - handleCheck(page, elementName, desiredValue) { - return page[elementName].isDisplayed().then(function() { - return page[elementName].getAttribute('value').then(function(value) { - if (value === desiredValue) { - return Promise.resolve(); - } - - return Promise.reject(`Expected ${desiredValue} got ${value} for text input element ${elementName}`); - }); - }); - } - - getPriority() { - return 999; - } -} - -export const defaultHandler = new DefaultHandler(); diff --git a/src/form-handlers/handler/default.handler.ts b/src/form-handlers/handler/default.handler.ts new file mode 100644 index 00000000..034bb262 --- /dev/null +++ b/src/form-handlers/handler/default.handler.ts @@ -0,0 +1,39 @@ +import { FormHandler } from '../form-handler.interface'; + +class DefaultHandler implements FormHandler { + public isSatisfiedBy() { + return Promise.resolve(true); + } + + public handleFill(page, elementName, desiredValue) { + return page + .getElement(elementName) + .isDisplayed() + .then(() => page.getElement(elementName).clear()) + .then(() => page.getElement(elementName).sendKeys(desiredValue)); + } + + public handleCheck(page, elementName, desiredValue) { + return page + .getElement(elementName) + .isDisplayed() + .then(() => { + return page + .getElement(elementName) + .getAttribute('value') + .then(value => { + if (value === desiredValue) { + return Promise.resolve(); + } + + return Promise.reject(`Expected ${desiredValue} got ${value} for text input element ${elementName}`); + }); + }); + } + + public getPriority() { + return 999; + } +} + +export const defaultHandler = new DefaultHandler(); diff --git a/src/form-handlers/handler/file.handler.js b/src/form-handlers/handler/file.handler.js deleted file mode 100644 index 9c24936e..00000000 --- a/src/form-handlers/handler/file.handler.js +++ /dev/null @@ -1,43 +0,0 @@ -import path from 'path'; -import config from '../../core/config.helper'; - -class FileHandler { - isSatisfiedBy(element) { - return element.getTagName().then(function(tagName) { - if (tagName === 'input') { - return element.getAttribute('type').then(inputType => inputType === 'file'); - } - - if (tagName instanceof Array) { - return element - .first() - .getAttribute('type') - .then(inputType => inputType === 'file'); - } - - return false; - }); - } - - handleFill(page, elementName, desiredValue) { - const fileToUpload = path.resolve(path.join(config.projectPath, config.data, desiredValue)); - - return page[elementName].sendKeys(fileToUpload); - } - - handleCheck(page, elementName, desiredValue) { - return page[elementName].getText().then(function(text) { - if (text === desiredValue) { - return Promise.resolve(); - } - - return Promise.reject(`Expected ${desiredValue} got ${text} for file element ${elementName}`); - }); - } - - getPriority() { - return 998; - } -} - -export const fileHandler = new FileHandler(); diff --git a/src/form-handlers/handler/file.handler.ts b/src/form-handlers/handler/file.handler.ts new file mode 100644 index 00000000..5203dcd7 --- /dev/null +++ b/src/form-handlers/handler/file.handler.ts @@ -0,0 +1,47 @@ +import * as path from 'path'; +import config from '../../core/config.helper'; +import { FormHandler } from '../form-handler.interface'; + +class FileHandler implements FormHandler { + public isSatisfiedBy(element) { + return element.getTagName().then(tagName => { + if (tagName === 'input') { + return element.getAttribute('type').then(inputType => inputType === 'file'); + } + + if (tagName instanceof Array) { + return element + .first() + .getAttribute('type') + .then(inputType => inputType === 'file'); + } + + return false; + }); + } + + public handleFill(page, elementName, desiredValue) { + const fileToUpload = path.resolve(path.join(config.projectPath, config.data, desiredValue)); + + return page.getElements(elementName).sendKeys(fileToUpload); + } + + public handleCheck(page, elementName, desiredValue) { + return page + .getElements(elementName) + .getText() + .then(text => { + if (text === desiredValue) { + return Promise.resolve(); + } + + return Promise.reject(`Expected ${desiredValue} got ${text} for file element ${elementName}`); + }); + } + + public getPriority() { + return 998; + } +} + +export const fileHandler = new FileHandler(); diff --git a/src/form-handlers/handler/index.js b/src/form-handlers/handler/index.ts similarity index 100% rename from src/form-handlers/handler/index.js rename to src/form-handlers/handler/index.ts diff --git a/src/form-handlers/handler/radio.handler.js b/src/form-handlers/handler/radio.handler.ts similarity index 59% rename from src/form-handlers/handler/radio.handler.js rename to src/form-handlers/handler/radio.handler.ts index 1dc9c903..dbde6efa 100644 --- a/src/form-handlers/handler/radio.handler.js +++ b/src/form-handlers/handler/radio.handler.ts @@ -1,6 +1,8 @@ -class RadioHandler { - isSatisfiedBy(element) { - return element.getTagName().then(function(tagName) { +import { FormHandler } from '../form-handler.interface'; + +class RadioHandler implements FormHandler { + public isSatisfiedBy(element) { + return element.getTagName().then(tagName => { if (tagName === 'input') { return element.getAttribute('type').then(inputType => inputType === 'radio'); } @@ -16,16 +18,13 @@ class RadioHandler { }); } - handleFill(page, elementName, desiredValue) { - const firstRadio = page[elementName] - .filter(function(elem) { - return elem.getAttribute('value').then(function(elemValue) { - return elemValue === desiredValue; - }); - }) + public handleFill(page, elementName, desiredValue) { + const firstRadio = page + .getElements(elementName) + .filter(elem => elem.getAttribute('value').then(elemValue => elemValue === desiredValue)) .first(); - return firstRadio.isDisplayed().then(function(isDisplayed) { + return firstRadio.isDisplayed().then(isDisplayed => { if (isDisplayed) { return firstRadio.click(); } @@ -34,12 +33,10 @@ class RadioHandler { }); } - handleCheck(page, elementName, desiredValue) { - const filteredElements = page[elementName].filter(function(element) { - return element.isSelected(); - }); + public handleCheck(page, elementName, desiredValue) { + const filteredElements = page.getElements(elementName).filter(element => element.isSelected()); - return filteredElements.count().then(function(count) { + return filteredElements.count().then(count => { if (desiredValue === '') { if (count === 0) { return Promise.resolve(); @@ -51,7 +48,7 @@ class RadioHandler { return filteredElements .first() .getAttribute('value') - .then(function(value) { + .then(value => { if (value === desiredValue) { return Promise.resolve(); } @@ -61,7 +58,7 @@ class RadioHandler { }); } - getPriority() { + public getPriority() { return 998; } } diff --git a/src/form-handlers/handler/select.handler.js b/src/form-handlers/handler/select.handler.js deleted file mode 100644 index a3dc1b5c..00000000 --- a/src/form-handlers/handler/select.handler.js +++ /dev/null @@ -1,68 +0,0 @@ -class SelectHandler { - constructor() { - this.optionsSelector = by.css('option'); - } - - isSatisfiedBy(element) { - return element.getTagName().then(function(tagName) { - return tagName === 'select'; - }); - } - - handleFill(page, elementName, desiredValue) { - const self = this; - - const filteredByText = page[elementName].all(this.optionsSelector).filter(function(elem) { - return elem.getText().then(function(text) { - return text.trim() === desiredValue; - }); - }); - - return filteredByText.count().then(filteredByTextCount => { - if (filteredByTextCount === 0) { - const filteredByValue = page[elementName].all(by.css('option')).filter(function(elem) { - return elem.getAttribute('value').then(function(elemValue) { - return elemValue === desiredValue; - }); - }); - - return filteredByValue.count().then(function(filteredByValueCount) { - if (filteredByValueCount === 0) { - return page[elementName] - .all(self.optionsSelector) - .first() - .click(); - } - - return filteredByValue.first().click(); - }); - } - - return filteredByText.first().click(); - }); - } - - handleCheck(page, elementName, desiredValue) { - return page[elementName] - .all(this.optionsSelector) - .filter(function(element) { - return element.getAttribute('value').then(function(elemValue) { - return elemValue === desiredValue; - }); - }) - .count() - .then(function(count) { - if (count === 1) { - return Promise.resolve(); - } - - return Promise.reject('Option not found for select element.'); - }); - } - - getPriority() { - return 998; - } -} - -export const selectHandler = new SelectHandler(); diff --git a/src/form-handlers/handler/select.handler.ts b/src/form-handlers/handler/select.handler.ts new file mode 100644 index 00000000..482f0ea5 --- /dev/null +++ b/src/form-handlers/handler/select.handler.ts @@ -0,0 +1,65 @@ +import { FormHandler } from '../form-handler.interface'; + +class SelectHandler implements FormHandler { + private optionsSelector: object; + + constructor() { + this.optionsSelector = by.css('option'); + } + + public isSatisfiedBy(element) { + return element.getTagName().then(tagName => tagName === 'select'); + } + + public handleFill(page, elementName, desiredValue) { + const self = this; + + const filteredByText = page + .getElements(elementName) + .all(this.optionsSelector) + .filter(elem => elem.getText().then(text => text.trim() === desiredValue)); + + return filteredByText.count().then(filteredByTextCount => { + if (filteredByTextCount === 0) { + const filteredByValue = page + .getElements(elementName) + .all(by.css('option')) + .filter(elem => elem.getAttribute('value').then(elemValue => elemValue === desiredValue)); + + return filteredByValue.count().then(filteredByValueCount => { + if (filteredByValueCount === 0) { + return page[elementName] + .all(self.optionsSelector) + .first() + .click(); + } + + return filteredByValue.first().click(); + }); + } + + return filteredByText.first().click(); + }); + } + + public handleCheck(page, elementName, desiredValue) { + return page + .getElement(elementName) + .all(this.optionsSelector) + .filter(element => element.getAttribute('value').then(elemValue => elemValue === desiredValue)) + .count() + .then(count => { + if (count === 1) { + return Promise.resolve(); + } + + return Promise.reject('Option not found for select element.'); + }); + } + + public getPriority() { + return 998; + } +} + +export const selectHandler = new SelectHandler(); diff --git a/src/form-handlers/handler/uploaded-file.handler.js b/src/form-handlers/handler/uploaded-file.handler.js deleted file mode 100644 index 3a8801b6..00000000 --- a/src/form-handlers/handler/uploaded-file.handler.js +++ /dev/null @@ -1,26 +0,0 @@ -class UploadedFileHandler { - isSatisfiedBy(element, elementName) { - return Promise.resolve(elementName.endsWith('Uploaded')); - } - - // eslint-disable-next-line no-unused-vars - handleFill(page, elementName, desiredValue) { - throw new Error('Not supported for this field type'); - } - - handleCheck(page, elementName, desiredValue) { - return page[elementName].getText().then(function(text) { - if (text.indexOf(desiredValue) >= 0) { - return Promise.resolve(); - } - - return Promise.reject(`Expected ${desiredValue} got ${text} for file element ${elementName}`); - }); - } - - getPriority() { - return 998; - } -} - -export const uploadedFileHandler = new UploadedFileHandler(); diff --git a/src/form-handlers/handler/uploaded-file.handler.ts b/src/form-handlers/handler/uploaded-file.handler.ts new file mode 100644 index 00000000..ad98048a --- /dev/null +++ b/src/form-handlers/handler/uploaded-file.handler.ts @@ -0,0 +1,27 @@ +import { FormHandler } from '../form-handler.interface'; + +class UploadedFileHandler implements FormHandler { + public isSatisfiedBy(element, elementName) { + return Promise.resolve(elementName.endsWith('Uploaded')); + } + + public handleFill(page, elementName, desiredValue) { + return Promise.reject('Not supported for this field type'); + } + + public handleCheck(page, elementName, desiredValue) { + return page[elementName].getText().then(text => { + if (text.indexOf(desiredValue) >= 0) { + return Promise.resolve(); + } + + return Promise.reject(`Expected ${desiredValue} got ${text} for file element ${elementName}`); + }); + } + + public getPriority() { + return 998; + } +} + +export const uploadedFileHandler = new UploadedFileHandler(); diff --git a/src/form-handlers/handlers.js b/src/form-handlers/handlers.js deleted file mode 100644 index 044a52a1..00000000 --- a/src/form-handlers/handlers.js +++ /dev/null @@ -1,52 +0,0 @@ -import * as formHandler from './handler'; - -const availableHandlers = [ - formHandler.checkboxHandler, - formHandler.ckEditorHandler, - formHandler.customAngularSelectHandler, - formHandler.defaultHandler, - formHandler.fileHandler, - formHandler.radioHandler, - formHandler.selectHandler, - formHandler.uploadedFileHandler, -]; - -const FormHandler = { - addHandler: function(handler) { - availableHandlers.push(handler); - }, - - handleFill: async function(page, elementName, desiredValue) { - const handlers = this.getHandlers(); - - for (let handler of handlers) { - const isSatisfied = await handler.isSatisfiedBy(page[elementName], elementName); - - if (isSatisfied) { - return handler.handleFill(page, elementName, desiredValue); - } - } - - return Promise.reject('Could not find matching handler.'); - }, - - handleCheck: async function(page, elementName, desiredValue) { - const handlers = this.getHandlers(); - - for (let handler of handlers) { - const isSatisfied = await handler.isSatisfiedBy(page[elementName], elementName); - - if (isSatisfied) { - return handler.handleCheck(page, elementName, desiredValue); - } - } - - return Promise.reject('Could not find matching handler.'); - }, - - getHandlers: function() { - return availableHandlers.sort((handler, otherHandler) => handler.getPriority() - otherHandler.getPriority()); - }, -}; - -export default FormHandler; diff --git a/src/form-handlers/handlers.ts b/src/form-handlers/handlers.ts new file mode 100644 index 00000000..d5133e49 --- /dev/null +++ b/src/form-handlers/handlers.ts @@ -0,0 +1,56 @@ +import * as formHandler from './handler'; +import { FormHandler } from './form-handler.interface'; +import Base from '../pages/base'; + +class FormHandlers { + constructor( + private availableHandlers: FormHandler[] = [ + formHandler.checkboxHandler, + formHandler.ckEditorHandler, + formHandler.customAngularSelectHandler, + formHandler.defaultHandler, + formHandler.fileHandler, + formHandler.radioHandler, + formHandler.selectHandler, + formHandler.uploadedFileHandler, + ] + ) {} + + public addHandler(handler: FormHandler): void { + this.availableHandlers.push(handler); + } + + public async handleFill(page: Base, elementName: string, desiredValue: string): Promise { + const handlers = this.getHandlers(); + + for (const handler of handlers) { + const isSatisfied = await handler.isSatisfiedBy(page.getElement(elementName), elementName); + + if (isSatisfied) { + return handler.handleFill(page, elementName, desiredValue); + } + } + + return Promise.reject('Could not find matching handler.'); + } + + public async handleCheck(page: Base, elementName: string, desiredValue: string): Promise { + const handlers = this.getHandlers(); + + for (const handler of handlers) { + const isSatisfied = await handler.isSatisfiedBy(page.getElement(elementName), elementName); + + if (isSatisfied) { + return handler.handleCheck(page, elementName, desiredValue); + } + } + + return Promise.reject('Could not find matching handler.'); + } + + public getHandlers(): FormHandler[] { + return this.availableHandlers.sort((handler, otherHandler) => handler.getPriority() - otherHandler.getPriority()); + } +} + +export default new FormHandlers(); diff --git a/src/form-handlers/index.js b/src/form-handlers/index.ts similarity index 100% rename from src/form-handlers/index.js rename to src/form-handlers/index.ts diff --git a/src/generators/generator.interface.ts b/src/generators/generator.interface.ts new file mode 100644 index 00000000..1c71cac7 --- /dev/null +++ b/src/generators/generator.interface.ts @@ -0,0 +1,4 @@ +export interface Generator { + isSatisfiedBy(name: string): boolean; + generate(...params: any): Promise; +} diff --git a/src/generators/generator/index.js b/src/generators/generator/index.ts similarity index 100% rename from src/generators/generator/index.js rename to src/generators/generator/index.ts diff --git a/src/generators/generator/personalData.generator.spec.js b/src/generators/generator/personalData.generator.spec.ts similarity index 100% rename from src/generators/generator/personalData.generator.spec.js rename to src/generators/generator/personalData.generator.spec.ts diff --git a/src/generators/generator/personalData.generator.js b/src/generators/generator/personalData.generator.ts similarity index 74% rename from src/generators/generator/personalData.generator.js rename to src/generators/generator/personalData.generator.ts index ec198850..787b8e6b 100644 --- a/src/generators/generator/personalData.generator.js +++ b/src/generators/generator/personalData.generator.ts @@ -1,11 +1,12 @@ -import faker from 'faker'; +import * as faker from 'faker'; +import { Generator } from '../generator.interface'; -export const personalDataGenerator = { - isSatisfiedBy: function(name) { +export const personalDataGenerator: Generator = { + isSatisfiedBy(name) { return name === 'personalData'; }, - generate: function(options) { + generate(options) { switch (options[0]) { case 'firstName': return Promise.resolve(faker.name.firstName()); diff --git a/src/generators/generator/string-with-length.generator.js b/src/generators/generator/string-with-length.generator.js deleted file mode 100644 index 3a44e895..00000000 --- a/src/generators/generator/string-with-length.generator.js +++ /dev/null @@ -1,15 +0,0 @@ -export const stringWithLengthGenerator = { - isSatisfiedBy: function(name) { - return name === 'stringWithLength'; - }, - - generate: function(generatorParam) { - const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - const length = parseInt(generatorParam); - - let result = ''; - for (let i = length; i > 0; i--) result += chars[Math.floor(Math.random() * chars.length)]; - - return Promise.resolve(result); - }, -}; diff --git a/src/generators/generator/string-with-length.generator.spec.js b/src/generators/generator/string-with-length.generator.spec.ts similarity index 100% rename from src/generators/generator/string-with-length.generator.spec.js rename to src/generators/generator/string-with-length.generator.spec.ts diff --git a/src/generators/generator/string-with-length.generator.ts b/src/generators/generator/string-with-length.generator.ts new file mode 100644 index 00000000..8cb83d99 --- /dev/null +++ b/src/generators/generator/string-with-length.generator.ts @@ -0,0 +1,19 @@ +import { Generator } from '../generator.interface'; + +export const stringWithLengthGenerator: Generator = { + isSatisfiedBy(name) { + return name === 'stringWithLength'; + }, + + generate(generatorParam) { + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + const length = parseInt(generatorParam); + + let result = ''; + for (let i = length; i > 0; i--) { + result += chars[Math.floor(Math.random() * chars.length)]; + } + + return Promise.resolve(result); + }, +}; diff --git a/src/generators/generators.js b/src/generators/generators.js deleted file mode 100644 index 828b2061..00000000 --- a/src/generators/generators.js +++ /dev/null @@ -1,27 +0,0 @@ -import * as generators from './generator'; - -class Generators { - constructor() { - this.availableGenerators = [generators.personalDataGenerator, generators.stringWithLengthGenerator]; - } - - generate(generatorName, ...params) { - const gen = this.findGenerator(generatorName); - - if (gen === undefined) { - throw new Error(`Could not find generator for ${generatorName}.`); - } - - return gen.generate(...params); - } - - addGenerator(generator) { - this.availableGenerators.push(generator); - } - - findGenerator(name) { - return this.availableGenerators.find(gen => gen.isSatisfiedBy(name)); - } -} - -export const create = () => new Generators(); diff --git a/src/generators/generators.spec.js b/src/generators/generators.spec.ts similarity index 100% rename from src/generators/generators.spec.js rename to src/generators/generators.spec.ts diff --git a/src/generators/generators.ts b/src/generators/generators.ts new file mode 100644 index 00000000..b747fc31 --- /dev/null +++ b/src/generators/generators.ts @@ -0,0 +1,28 @@ +import * as generators from './generator'; +import { Generator } from './generator.interface'; + +export class Generators { + constructor( + private availableGenerators: Generator[] = [generators.personalDataGenerator, generators.stringWithLengthGenerator] + ) {} + + public generate(generatorName: string, ...params: any): Promise { + const gen: Generator = this.findGenerator(generatorName); + + if (gen === undefined) { + throw new Error(`Could not find generator for ${generatorName}.`); + } + + return gen.generate(...params); + } + + public addGenerator(generator: Generator): void { + this.availableGenerators.push(generator); + } + + public findGenerator(name: string): Generator { + return this.availableGenerators.find(gen => gen.isSatisfiedBy(name)); + } +} + +export const create = () => new Generators(); diff --git a/src/generators/index.js b/src/generators/index.ts similarity index 63% rename from src/generators/index.js rename to src/generators/index.ts index 10b7f3b5..07656ec1 100644 --- a/src/generators/index.js +++ b/src/generators/index.ts @@ -1,3 +1,4 @@ import { create } from './generators'; +export { Generators } from './generators'; export const generators = create(); diff --git a/src/index.js b/src/index.ts similarity index 81% rename from src/index.js rename to src/index.ts index 7d92d183..a7443acb 100644 --- a/src/index.js +++ b/src/index.ts @@ -1,9 +1,9 @@ // entry file -import * as pages from './pages'; import * as dictionaries from './dictionaries'; +import * as pages from './pages'; export { matchers, regexBuilder } from './matchers'; -export { defineSupportCode } from 'cucumber'; +export { defineSupportCode, Given, When, Then, After, Before, AfterAll, BeforeAll } from 'cucumber'; export { dictionaries } from './dictionaries'; export { transformers } from './transformers'; export { generators } from './generators'; @@ -12,6 +12,7 @@ export { default as handlers } from './form-handlers/handlers'; export { comparators } from './comparators'; export { emailService } from './emails'; export { waitForVisibilityOf, waitForInvisibilityOf, waitForCondition } from './web/cucumber/wait-for-condition.helper'; +export { hookHandlers } from './web/cucumber/hooks/hooks'; export const BasePage = pages.Form; export const BaseDictionary = dictionaries.Base; diff --git a/src/kakunin.d.ts b/src/kakunin.d.ts new file mode 100644 index 00000000..0c8adeac --- /dev/null +++ b/src/kakunin.d.ts @@ -0,0 +1,18 @@ +declare let browser: any; +declare let by: any; +declare let protractor: any; + +declare module NodeJS { + interface Global { + by: any; + expect(value: any): any; + } +} + +interface Console { + err: any; +} + +declare interface RegExpConstructor { + escape(text: string): any; +} diff --git a/src/matchers/index.js b/src/matchers/index.ts similarity index 100% rename from src/matchers/index.js rename to src/matchers/index.ts index cfe7c606..398694f7 100644 --- a/src/matchers/index.js +++ b/src/matchers/index.ts @@ -1,5 +1,5 @@ -import { create as createMatchers } from './matchers'; import { regexBuilder as builder } from './matcher/regex-matcher/regex-builder'; +import { create as createMatchers } from './matchers'; export const matchers = createMatchers(); export const regexBuilder = builder; diff --git a/src/matchers/matcher.interface.ts b/src/matchers/matcher.interface.ts new file mode 100644 index 00000000..d3f423b6 --- /dev/null +++ b/src/matchers/matcher.interface.ts @@ -0,0 +1,4 @@ +export interface Matcher { + isSatisfiedBy(prefix: string, name?: string): boolean; + match(element: object, param1?: string, param2?: string): Promise; +} diff --git a/src/matchers/matcher/attribute.matcher.spec.js b/src/matchers/matcher/attribute.matcher.spec.ts similarity index 69% rename from src/matchers/matcher/attribute.matcher.spec.js rename to src/matchers/matcher/attribute.matcher.spec.ts index f9d9b762..911d7063 100644 --- a/src/matchers/matcher/attribute.matcher.spec.js +++ b/src/matchers/matcher/attribute.matcher.spec.ts @@ -1,17 +1,18 @@ import { attributeMatcher } from './attribute.matcher'; -import { regexBuilder } from './regex-matcher/regex-builder'; describe('Attribute matcher', () => { it('is satisfied when the prefix and name are correct', () => { - expect(attributeMatcher.isSatisfiedBy('attribute', 'class:some-url-regex')).toEqual(true); + expect(attributeMatcher.isSatisfiedBy('attribute')).toEqual(true); }); it('is not satisfied when the prefix and name are incorrect', () => { - const incorrectParameters = [{ prefix: 'f' }, { prefix: 'incorrect' }, { prefix: 'g' }]; + const incorrectParameters = [ + { prefix: 'f', name: 'incorrect' }, + { prefix: 'incorrect', name: 'incorrect' }, + { prefix: 'g', name: 'isVisible' }, + ]; - incorrectParameters.forEach(parameters => - expect(attributeMatcher.isSatisfiedBy(parameters.prefix, parameters.name)).toEqual(false) - ); + incorrectParameters.forEach(parameters => expect(attributeMatcher.isSatisfiedBy(parameters.prefix)).toEqual(false)); }); it('returns true when the attribute is matched', done => { diff --git a/src/matchers/matcher/attribute.matcher.js b/src/matchers/matcher/attribute.matcher.ts similarity index 59% rename from src/matchers/matcher/attribute.matcher.js rename to src/matchers/matcher/attribute.matcher.ts index 6a672b54..4f5e99e6 100644 --- a/src/matchers/matcher/attribute.matcher.js +++ b/src/matchers/matcher/attribute.matcher.ts @@ -1,22 +1,22 @@ import { regexBuilder } from './regex-matcher/regex-builder'; +import { Matcher } from '../matcher.interface'; -class AttributeMatcher { - isSatisfiedBy(prefix) { +class AttributeMatcher implements Matcher { + public isSatisfiedBy(prefix) { return prefix === 'attribute'; } - match(element, attributeName, regexName) { + public match(element, attributeName, regexName) { return element.getAttribute(attributeName).then(value => { if (regexBuilder.buildRegex(`r:${regexName}`).test(value)) { return true; } - /* eslint-disable max-len */ + const transformedRegexName = `r:${regexName}`; return Promise.reject(` Matcher "AttributeMatcher" could not match regex on element "${element.locator()}" on attribute "${attributeName}". - Expected to match: "${regexBuilder.buildRegex(`r:${regexName}`).toString()}", Given: "${value}" + Expected to match: "${regexBuilder.buildRegex(transformedRegexName).toString()}", Given: "${value}" `); - /* eslint-enable max-len */ }); } } diff --git a/src/matchers/matcher/clickable.matcher.spec.js b/src/matchers/matcher/clickable.matcher.spec.ts similarity index 100% rename from src/matchers/matcher/clickable.matcher.spec.js rename to src/matchers/matcher/clickable.matcher.spec.ts diff --git a/src/matchers/matcher/clickable.matcher.js b/src/matchers/matcher/clickable.matcher.ts similarity index 63% rename from src/matchers/matcher/clickable.matcher.js rename to src/matchers/matcher/clickable.matcher.ts index 964f5a71..1affab2e 100644 --- a/src/matchers/matcher/clickable.matcher.js +++ b/src/matchers/matcher/clickable.matcher.ts @@ -1,14 +1,14 @@ -class ClickableMatcher { - isSatisfiedBy(prefix, name) { +import { Matcher } from '../matcher.interface'; + +class ClickableMatcher implements Matcher { + public isSatisfiedBy(prefix, name) { return prefix === 'f' && name === 'isClickable'; } - match(element) { + public match(element) { return element .getAttribute('disabled') - .then(function(disabled) { - return ['disabled', true, 'true'].indexOf(disabled) === -1; - }) + .then(disabled => ['disabled', true, 'true'].indexOf(disabled) === -1) .then(result => { if (result) { return true; diff --git a/src/matchers/matcher/currentDate.matcher.spec.js b/src/matchers/matcher/currentDate.matcher.spec.ts similarity index 98% rename from src/matchers/matcher/currentDate.matcher.spec.js rename to src/matchers/matcher/currentDate.matcher.spec.ts index b22b36ce..1bf78546 100644 --- a/src/matchers/matcher/currentDate.matcher.spec.js +++ b/src/matchers/matcher/currentDate.matcher.spec.ts @@ -1,5 +1,5 @@ import { currentDateMatcher } from './currentDate.matcher'; -import moment from 'moment'; +import * as moment from 'moment'; describe('Current Date matcher', () => { it('is satisfied when the prefix and the name are correct', () => { diff --git a/src/matchers/matcher/currentDate.matcher.js b/src/matchers/matcher/currentDate.matcher.ts similarity index 68% rename from src/matchers/matcher/currentDate.matcher.js rename to src/matchers/matcher/currentDate.matcher.ts index cd40abf6..6286b95c 100644 --- a/src/matchers/matcher/currentDate.matcher.js +++ b/src/matchers/matcher/currentDate.matcher.ts @@ -1,12 +1,12 @@ -import moment from 'moment'; +import * as moment from 'moment'; +import { Matcher } from '../matcher.interface'; -class CurrentDateMatcher { - isSatisfiedBy(prefix, name) { +class CurrentDateMatcher implements Matcher { + public isSatisfiedBy(prefix, name) { return prefix === 'f' && name === 'currentDate'; } - // eslint-disable-next-line no-unused-vars - match(element, name = null, params = 'DD-MM-YYYY') { + public match(element, name = null, params = 'DD-MM-YYYY') { const currentDate = moment(new Date()).format(params); return element.getText().then(text => { const compareDate = moment(new Date(text)).format(params); @@ -15,11 +15,9 @@ class CurrentDateMatcher { return true; } - /* eslint-disable max-len */ return Promise.reject(` Matcher "CurrentDate" could not match date for element "${element.locator()}". Expected: "${compareDate}", given: "${currentDate}". `); - /* eslint-enable max-len */ }); } } diff --git a/src/matchers/matcher/index.js b/src/matchers/matcher/index.ts similarity index 100% rename from src/matchers/matcher/index.js rename to src/matchers/matcher/index.ts diff --git a/src/matchers/matcher/invisible.matcher.spec.js b/src/matchers/matcher/invisible.matcher.spec.ts similarity index 100% rename from src/matchers/matcher/invisible.matcher.spec.js rename to src/matchers/matcher/invisible.matcher.spec.ts diff --git a/src/matchers/matcher/invisible.matcher.js b/src/matchers/matcher/invisible.matcher.ts similarity index 68% rename from src/matchers/matcher/invisible.matcher.js rename to src/matchers/matcher/invisible.matcher.ts index fc5e541b..531fdbe1 100644 --- a/src/matchers/matcher/invisible.matcher.js +++ b/src/matchers/matcher/invisible.matcher.ts @@ -1,9 +1,11 @@ -class InvisibleMatcher { - isSatisfiedBy(prefix, name) { +import { Matcher } from '../matcher.interface'; + +class InvisibleMatcher implements Matcher { + public isSatisfiedBy(prefix, name) { return prefix === 'f' && name === 'isNotVisible'; } - async match(element) { + public async match(element) { try { await element.isDisplayed(); return Promise.reject(` diff --git a/src/matchers/matcher/not-clickable.matcher.spec.js b/src/matchers/matcher/not-clickable.matcher.spec.ts similarity index 100% rename from src/matchers/matcher/not-clickable.matcher.spec.js rename to src/matchers/matcher/not-clickable.matcher.spec.ts diff --git a/src/matchers/matcher/not-clickable.matcher.js b/src/matchers/matcher/not-clickable.matcher.ts similarity index 63% rename from src/matchers/matcher/not-clickable.matcher.js rename to src/matchers/matcher/not-clickable.matcher.ts index 2fb1c238..9ae771f0 100644 --- a/src/matchers/matcher/not-clickable.matcher.js +++ b/src/matchers/matcher/not-clickable.matcher.ts @@ -1,14 +1,14 @@ -class NotClickableMatcher { - isSatisfiedBy(prefix, name) { +import { Matcher } from '../matcher.interface'; + +class NotClickableMatcher implements Matcher { + public isSatisfiedBy(prefix, name) { return prefix === 'f' && name === 'isNotClickable'; } - match(element) { + public match(element) { return element .getAttribute('disabled') - .then(function(disabled) { - return ['disabled', true, 'true'].indexOf(disabled) !== -1; - }) + .then(disabled => ['disabled', true, 'true'].indexOf(disabled) !== -1) .then(result => { if (result) { return true; diff --git a/src/matchers/matcher/present.matcher.spec.js b/src/matchers/matcher/present.matcher.spec.ts similarity index 100% rename from src/matchers/matcher/present.matcher.spec.js rename to src/matchers/matcher/present.matcher.spec.ts diff --git a/src/matchers/matcher/present.matcher.js b/src/matchers/matcher/present.matcher.ts similarity index 64% rename from src/matchers/matcher/present.matcher.js rename to src/matchers/matcher/present.matcher.ts index 0e38a95d..08cb556f 100644 --- a/src/matchers/matcher/present.matcher.js +++ b/src/matchers/matcher/present.matcher.ts @@ -1,9 +1,11 @@ -class PresentMatcher { - isSatisfiedBy(prefix, name) { +import { Matcher } from '../matcher.interface'; + +class PresentMatcher implements Matcher { + public isSatisfiedBy(prefix, name) { return prefix === 'f' && name === 'isPresent'; } - match(element) { + public match(element) { return element .isPresent() .then(() => true) diff --git a/src/matchers/matcher/regex-matcher/index.spec.js b/src/matchers/matcher/regex-matcher/index.spec.ts similarity index 98% rename from src/matchers/matcher/regex-matcher/index.spec.js rename to src/matchers/matcher/regex-matcher/index.spec.ts index 0c2d01e2..a1f26288 100644 --- a/src/matchers/matcher/regex-matcher/index.spec.js +++ b/src/matchers/matcher/regex-matcher/index.spec.ts @@ -1,4 +1,4 @@ -import { regexMatcher } from './index'; +import { regexMatcher } from '.'; describe('Regex matcher', () => { it('is satisfied when the prefix is correct and regex exists', () => { diff --git a/src/matchers/matcher/regex-matcher/index.js b/src/matchers/matcher/regex-matcher/index.ts similarity index 89% rename from src/matchers/matcher/regex-matcher/index.js rename to src/matchers/matcher/regex-matcher/index.ts index 764fb745..77e2b6f6 100644 --- a/src/matchers/matcher/regex-matcher/index.js +++ b/src/matchers/matcher/regex-matcher/index.ts @@ -1,12 +1,13 @@ -import { regexBuilder } from './regex-builder'; import regex from './regex'; +import { regexBuilder } from './regex-builder'; +import { Matcher } from '../../matcher.interface'; -class RegexMatcher { - isSatisfiedBy(prefix, name) { +class RegexMatcher implements Matcher { + public isSatisfiedBy(prefix, name) { return prefix === 'r' && typeof regex[name] !== 'undefined'; } - match(element, regexName) { + public match(element, regexName) { return element.getText().then(text => { return element.getAttribute('value').then(value => { const regularExpression = regexBuilder.buildRegex(`r:${regexName}`); diff --git a/src/matchers/matcher/regex-matcher/regex-builder.js b/src/matchers/matcher/regex-matcher/regex-builder.js deleted file mode 100644 index 0d9addb2..00000000 --- a/src/matchers/matcher/regex-matcher/regex-builder.js +++ /dev/null @@ -1,17 +0,0 @@ -import regex from './regex'; - -class RegexBuilder { - buildRegex(regexTemplate) { - for (let property in regex) { - if (regex.hasOwnProperty(property)) { - if (regexTemplate === 'r:' + property) { - return new RegExp(regex[property]); - } - } - } - - throw 'Regex with template ' + regexTemplate + ' was not found'; - } -} - -export const regexBuilder = new RegexBuilder(); diff --git a/src/matchers/matcher/regex-matcher/regex-builder.spec.js b/src/matchers/matcher/regex-matcher/regex-builder.spec.ts similarity index 100% rename from src/matchers/matcher/regex-matcher/regex-builder.spec.js rename to src/matchers/matcher/regex-matcher/regex-builder.spec.ts diff --git a/src/matchers/matcher/regex-matcher/regex-builder.ts b/src/matchers/matcher/regex-matcher/regex-builder.ts new file mode 100644 index 00000000..5f33eba9 --- /dev/null +++ b/src/matchers/matcher/regex-matcher/regex-builder.ts @@ -0,0 +1,15 @@ +import regex from './regex'; + +class RegexBuilder { + public buildRegex(regexTemplate: string): RegExp { + for (const property in regex) { + if (regex.hasOwnProperty(property) && regexTemplate === 'r:' + property) { + return new RegExp(regex[property]); + } + } + + throw new Error('Regex with template ' + regexTemplate + ' was not found'); + } +} + +export const regexBuilder = new RegexBuilder(); diff --git a/src/matchers/matcher/regex-matcher/regex.js b/src/matchers/matcher/regex-matcher/regex.ts similarity index 100% rename from src/matchers/matcher/regex-matcher/regex.js rename to src/matchers/matcher/regex-matcher/regex.ts diff --git a/src/matchers/matcher/regex-matcher/regexes/default.js b/src/matchers/matcher/regex-matcher/regexes/default.ts similarity index 90% rename from src/matchers/matcher/regex-matcher/regexes/default.js rename to src/matchers/matcher/regex-matcher/regexes/default.ts index 08ba0130..5fd2abc2 100644 --- a/src/matchers/matcher/regex-matcher/regexes/default.js +++ b/src/matchers/matcher/regex-matcher/regexes/default.ts @@ -1,4 +1,3 @@ -/* eslint-disable max-len */ export const regex = { arabianCharacters: '\u0621-\u064A', arabianNumbers: '\u0660-\u0669', @@ -13,4 +12,3 @@ export const regex = { // todo: following regex should be moved to tests/regexes someRandomLinkRegex: '(http(s)?://some-random-link.com)', }; -/* eslint-enable max-len */ diff --git a/src/matchers/matcher/text.matcher.spec.js b/src/matchers/matcher/text.matcher.spec.ts similarity index 100% rename from src/matchers/matcher/text.matcher.spec.js rename to src/matchers/matcher/text.matcher.spec.ts diff --git a/src/matchers/matcher/text.matcher.js b/src/matchers/matcher/text.matcher.ts similarity index 86% rename from src/matchers/matcher/text.matcher.js rename to src/matchers/matcher/text.matcher.ts index c945b418..42fb8b4d 100644 --- a/src/matchers/matcher/text.matcher.js +++ b/src/matchers/matcher/text.matcher.ts @@ -1,11 +1,12 @@ import { separator } from '../matchers'; +import { Matcher } from '../matcher.interface'; -class TextMatcher { - isSatisfiedBy(prefix) { +class TextMatcher implements Matcher { + public isSatisfiedBy(prefix) { return prefix === 't'; } - match(element, ...params) { + public match(element, ...params) { const expectedValue = params.join(separator); return element.getTagName().then(tag => { diff --git a/src/matchers/matcher/visible.matcher.spec.js b/src/matchers/matcher/visible.matcher.spec.ts similarity index 91% rename from src/matchers/matcher/visible.matcher.spec.js rename to src/matchers/matcher/visible.matcher.spec.ts index 6c49f146..2f2bbfcb 100644 --- a/src/matchers/matcher/visible.matcher.spec.js +++ b/src/matchers/matcher/visible.matcher.spec.ts @@ -9,7 +9,7 @@ describe('Visible matcher', () => { const incorrectParameters = [{ prefix: 'f', name: 'isNotVisible' }, { prefix: 'r', name: 'isVisible' }]; incorrectParameters.forEach(parameter => - expect(visibleMatcher.isSatisfiedBy((parameter.prefix, parameter.name))).toEqual(false) + expect(visibleMatcher.isSatisfiedBy(parameter.prefix, parameter.name)).toEqual(false) ); }); diff --git a/src/matchers/matcher/visible.matcher.js b/src/matchers/matcher/visible.matcher.ts similarity index 66% rename from src/matchers/matcher/visible.matcher.js rename to src/matchers/matcher/visible.matcher.ts index b25fe23f..2dfdd22b 100644 --- a/src/matchers/matcher/visible.matcher.js +++ b/src/matchers/matcher/visible.matcher.ts @@ -1,9 +1,11 @@ -class VisibleMatcher { - isSatisfiedBy(prefix, name) { +import { Matcher } from '../matcher.interface'; + +class VisibleMatcher implements Matcher { + public isSatisfiedBy(prefix, name) { return prefix === 'f' && name === 'isVisible'; } - match(element) { + public match(element) { return element .isDisplayed() .then(() => true) diff --git a/src/matchers/matchers.spec.js b/src/matchers/matchers.spec.ts similarity index 100% rename from src/matchers/matchers.spec.js rename to src/matchers/matchers.spec.ts diff --git a/src/matchers/matchers.js b/src/matchers/matchers.ts similarity index 70% rename from src/matchers/matchers.js rename to src/matchers/matchers.ts index 8a191cae..c937a31b 100644 --- a/src/matchers/matchers.js +++ b/src/matchers/matchers.ts @@ -1,10 +1,11 @@ import * as matchers from './matcher'; +import { Matcher } from './matcher.interface'; export const separator = ':'; class Matchers { - constructor() { - this.availableMatchers = [ + constructor( + private availableMatchers: Matcher[] = [ matchers.regexMatcher, matchers.clickableMatcher, matchers.invisibleMatcher, @@ -14,16 +15,16 @@ class Matchers { matchers.visibleMatcher, matchers.attributeMatcher, matchers.currentDateMatcher, - ]; - } + ] + ) {} - addMatcher(matcher) { + public addMatcher(matcher: Matcher): void { this.availableMatchers.push(matcher); } - match(element, matcherName) { + public match(element: object, matcherName: string): Promise { const splittedValue = matcherName.split(separator); - const matcher = this.findMatcher(splittedValue[0], splittedValue.slice(1)); + const matcher = this.findMatcher(splittedValue[0], splittedValue[1]); if (matcher === undefined) { throw new Error(`Could not find matcher for ${matcherName}.`); @@ -32,8 +33,8 @@ class Matchers { return matcher.match(element, ...splittedValue.slice(1)); } - findMatcher(prefix, params) { - return this.availableMatchers.find(matcher => matcher.isSatisfiedBy(prefix, ...params)); + public findMatcher(prefix: string, param: string): Matcher { + return this.availableMatchers.find(matcher => matcher.isSatisfiedBy(prefix, param)); } } diff --git a/src/pages/base.ts b/src/pages/base.ts new file mode 100644 index 00000000..e2ec3458 --- /dev/null +++ b/src/pages/base.ts @@ -0,0 +1,113 @@ +import config from '../core/config.helper'; +import { waitForInvisibilityOf, waitForVisibilityOf } from '../web/cucumber/wait-for-condition.helper'; +import { isRelativePage, waitForUrlChangeTo } from '../web/url-parser.helper'; +import { stringify } from 'querystring'; +import { element } from 'protractor'; + +class Page { + private url: string; + + public visit() { + if (config.type === 'otherWeb' || !isRelativePage(this.url)) { + protractor.browser.ignoreSynchronization = true; + + return protractor.browser.get(this.url); + } + + return protractor.browser.get(this.url).then(() => protractor.browser.waitForAngular()); + } + + public visitWithParameters(data) { + const additionalParams = []; + + const url = + data.raw().reduce((prev, item) => { + if (prev.indexOf(`:${item[0]}`) === -1) { + additionalParams.push(item); + return prev; + } + return prev.replace(`:${item[0]}`, item[1]); + }, this.url) + (additionalParams.length > 0 ? '?' + stringify(additionalParams) : ''); + + if (config.type === 'otherWeb' || !isRelativePage(url)) { + protractor.browser.ignoreSynchronization = true; + + return protractor.browser.get(url); + } + + return protractor.browser.get(url).then(() => protractor.browser.waitForAngular()); + } + + public async isOn() { + if (isRelativePage(this.url) && config.type !== 'otherWeb') { + protractor.browser.ignoreSynchronization = false; + } + + return browser.wait(async () => { + const currentUrl = await browser.getCurrentUrl().then(url => url); + + return waitForUrlChangeTo(this.url, currentUrl)(config.baseUrl); + }, config.waitForPageTimeout * 1000); + } + + public click(elementName: string) { + return this.getElement(elementName).click(); + } + + public isDisabled(elementName: string) { + return this.getElement(elementName) + .getAttribute('disabled') + .then(disabled => ['disabled', true, 'true'].indexOf(disabled) !== -1); + } + + public isVisible(elementName: string) { + return this.getElement(elementName).isDisplayed(); + } + + public isPresent(elementName: string) { + return this.getElement(elementName).isPresent(); + } + + public getNumberOfElements(elementName: string) { + return this.getElements(elementName).count(); + } + + public scrollIntoElement(elementName: string, elementIndex?: string) { + if (elementIndex !== undefined) { + return browser.executeScript( + 'arguments[0].scrollIntoView(false);', + this.getElement(elementName) + .get(elementIndex) + .getWebElement() + ); + } + + return browser.executeScript('arguments[0].scrollIntoView(false);', this.getElement(elementName).getWebElement()); + } + + public waitForVisibilityOf(elementName: string) { + return waitForVisibilityOf(this.getElement(elementName)); + } + + public waitForInvisibilityOf(elementName: string) { + return waitForInvisibilityOf(this.getElement(elementName)); + } + + public getElement(elementName: string) { + if (!this[elementName]) { + return element(by.css(elementName)); + } + + return this[elementName]; + } + + public getElements(elementName: string) { + if (!this[elementName]) { + return element.all(by.css(elementName)); + } + + return this[elementName]; + } +} + +export default Page; diff --git a/src/pages/form.js b/src/pages/form.ts similarity index 71% rename from src/pages/form.js rename to src/pages/form.ts index b423190a..40d1b396 100644 --- a/src/pages/form.js +++ b/src/pages/form.ts @@ -1,29 +1,29 @@ -import Base from './base'; import { fromHandlers } from '../form-handlers'; import { transformers } from '../transformers'; +import Base from './base'; class FormPage extends Base { - async fillForm(formData) { - for (let item of formData) { + public async fillForm(formData) { + for (const item of formData) { await this.fillField(item[0], item[1]); } return Promise.resolve(); } - async checkForm(formData) { - for (let item of formData) { + public async checkForm(formData) { + for (const item of formData) { await this.checkField(item[0], item[1]); } return Promise.resolve(); } - fillField(name, value) { + public fillField(name, value) { return fromHandlers.handleFill(this, name, transformers.transform(value)); } - checkField(name, value) { + public checkField(name, value) { return fromHandlers.handleCheck(this, name, transformers.transform(value)); } } diff --git a/src/pages/index.js b/src/pages/index.ts similarity index 100% rename from src/pages/index.js rename to src/pages/index.ts diff --git a/src/protractor.conf.js b/src/protractor.conf.ts similarity index 64% rename from src/protractor.conf.js rename to src/protractor.conf.ts index 3c21214f..79a31412 100644 --- a/src/protractor.conf.js +++ b/src/protractor.conf.ts @@ -1,15 +1,15 @@ require('./core/prototypes'); -const path = require('path'); -const chai = require('chai'); -const config = require('./core/config.helper').default; -const modulesLoader = require('./core/modules-loader.helper.js').create(); -const { deleteReports } = require('./core/fs/delete-files.helper'); -const { prepareCatalogs } = require('./core/fs/prepare-catalogs.helper'); -const browsersConfiguration = require('./web/browsers/browsers-config.helper'); -const chaiAsPromised = require('chai-as-promised'); -const { emailService } = require('./emails'); +import * as jestExpect from 'expect'; +import * as path from 'path'; +import config from './core/config.helper'; +import { deleteReports } from './core/fs/delete-files.helper'; +import { prepareCatalogs } from './core/fs/prepare-catalogs.helper'; +import { browsersConfiguration, setSeleniumAddress } from './web/browsers/browsers-config.helper'; +import { getBrowsersDrivers } from './web/browsers/get-browser-drivers.helper'; +import { connectBrowserstack, disconnectBrowserstack } from './web/browsers/browserstack-config.helper'; +import { emailService } from './emails'; const commandArgs = require('minimist')(process.argv.slice(2)); -chai.use(chaiAsPromised); +const modulesLoader = require('./core/modules-loader.helper.js').create(); const reportsDirectory = path.join(config.projectPath, config.reports); const jsonOutputDirectory = path.join(reportsDirectory, 'json-output-folder'); @@ -17,12 +17,12 @@ const generatedReportsDirectory = path.join(reportsDirectory, 'report'); const featureReportsDirectory = path.join(generatedReportsDirectory, 'features'); const performanceReportsDirectory = path.join(reportsDirectory, 'performance'); -const prepareReportCatalogs = async () => { - await prepareCatalogs(reportsDirectory); - await prepareCatalogs(jsonOutputDirectory); - await prepareCatalogs(generatedReportsDirectory); - await prepareCatalogs(featureReportsDirectory); - await prepareCatalogs(performanceReportsDirectory); +const prepareReportCatalogs = () => { + prepareCatalogs(reportsDirectory); + prepareCatalogs(jsonOutputDirectory); + prepareCatalogs(generatedReportsDirectory); + prepareCatalogs(featureReportsDirectory); + prepareCatalogs(performanceReportsDirectory); }; const deleteReportFiles = () => { @@ -35,8 +35,12 @@ const deleteReportFiles = () => { console.log('All reports have been deleted!'); }; +const configureMultiCapabilities = () => browsersConfiguration(config, commandArgs); + exports.config = { - getMultiCapabilities: browsersConfiguration(config, commandArgs), + seleniumAddress: setSeleniumAddress(commandArgs, config), + getMultiCapabilities: configureMultiCapabilities(), + jvmArgs: getBrowsersDrivers(commandArgs), useAllAngular2AppRoots: config.type === 'ng2', @@ -50,10 +54,9 @@ exports.config = { cucumberOpts: { require: [ './web/cucumber/config.js', - './web/cucumber/hooks.js', './step_definitions/**/*.js', + './web/cucumber/hooks.js', ...config.step_definitions.map(file => path.join(config.projectPath, file, '**/*.js')), - ...config.hooks.map(file => path.join(config.projectPath, file, '**/*.js')), ], format: [`json:./${config.reports}/features-report.json`], profile: false, @@ -72,12 +75,20 @@ exports.config = { }, ], - beforeLaunch: async function() { - await prepareReportCatalogs(); - await deleteReportFiles(); + async beforeLaunch() { + prepareReportCatalogs(); + deleteReportFiles(); + + if (commandArgs.browserstack) { + await connectBrowserstack((await configureMultiCapabilities()())[0]['browserstack.key']); + } + }, + + async afterLaunch() { + await disconnectBrowserstack(commandArgs.browserstack); }, - onPrepare: function() { + onPrepare() { if (!config.headless) { browser.driver .manage() @@ -92,6 +103,7 @@ exports.config = { modulesLoader.getModules('form_handlers'); modulesLoader.getModules('transformers'); modulesLoader.getModules('emails'); + modulesLoader.getModules('hooks'); const modules = modulesLoader.getModulesAsObject(config.pages.map(page => path.join(config.projectPath, page))); @@ -100,7 +112,7 @@ exports.config = { {} ); - global.expect = chai.expect; + global.expect = jestExpect; if (config.clearEmailInboxBeforeTests) { return emailService.clearInbox(); diff --git a/src/rest/api-request.ts b/src/rest/api-request.ts new file mode 100644 index 00000000..f3255e1d --- /dev/null +++ b/src/rest/api-request.ts @@ -0,0 +1,45 @@ +import { Headers } from 'node-fetch'; +import FormData = require('form-data'); + +interface HeaderList { + [name: string]: string; +} + +export class ApiRequest { + public method: string; + public endpoint: string; + private payload: string | object; + private headers: Headers; + private formData: FormData; + + constructor() { + this.payload = null; + this.headers = new Headers(); + this.formData = new FormData(); + } + + public addHeaders(headers: HeaderList) { + for (const [key, value] of Object.entries(headers)) { + this.headers.append(key, value); + } + } + + public addFormData(payload) { + for (const table of payload) { + this.formData.append(table[0], table[1]); + } + return this.formData; + } + + get body() { + return this.payload; + } + + set body(payload) { + if (payload instanceof FormData) { + this.payload = payload; + } else { + this.payload = payload ? JSON.stringify(payload) : undefined; + } + } +} diff --git a/src/rest/api-response.spec.ts b/src/rest/api-response.spec.ts new file mode 100644 index 00000000..a5b11a70 --- /dev/null +++ b/src/rest/api-response.spec.ts @@ -0,0 +1,32 @@ +import { ApiResponse } from './api-response'; + +const response = new ApiResponse(200, { type: 'Fiat', model: '500', color: 'white' }); + +describe('apiResponse', () => { + it('returns true when statuses are the same', () => { + expect(response.hasStatus(200)).toEqual(true); + }); + + it('returns false when statuses are different', () => { + expect(response.hasStatus(100)).toEqual(false); + }); + + it('returns true when response match given object', () => { + expect( + response.hasBodyMatch({ + type: 'Fiat', + model: '500', + color: 'white', + }) + ).toEqual(true); + }); + + it('returns false when response doesnt match given object', () => { + expect( + response.hasBodyMatch({ + model: '500', + color: 'white', + }) + ).toEqual(false); + }); +}); diff --git a/src/rest/api-response.ts b/src/rest/api-response.ts new file mode 100644 index 00000000..704b69ae --- /dev/null +++ b/src/rest/api-response.ts @@ -0,0 +1,33 @@ +import * as _ from 'lodash'; +import * as Ajv from 'ajv'; +const ajv = new Ajv({ allErrors: true }); + +export class ApiResponse { + private readonly body: object; + private readonly status: number; + + constructor(responseStatus, body) { + this.body = body; + this.status = responseStatus; + } + + public hasStatus(status) { + return this.status === status; + } + + public hasBodyMatch(body) { + if (Object.keys(this.body).length === 0) { + return Error('Response from server was empty'); + } + return _.isEqual(this.body, body); + } + + public hasMatchingSchema(schema) { + const test = ajv.compile(schema); + const isValid = test(this.body); + + if (isValid === false) { + throw Error('Response doesnt match schema'); + } + } +} diff --git a/src/rest/rest-api-service.ts b/src/rest/rest-api-service.ts new file mode 100644 index 00000000..8d112d09 --- /dev/null +++ b/src/rest/rest-api-service.ts @@ -0,0 +1,28 @@ +import fetch from 'node-fetch'; +import { ApiResponse } from './api-response'; + +export class RestApiService { + private readonly baseUrl: string; + + constructor(baseUrl) { + this.baseUrl = baseUrl; + } + + public fetch(request) { + const url = this.resolveUrl(request.endpoint); + + return fetch(url, { method: request.method, body: request.body, headers: request.headers }).then(response => { + const contentType = response.headers.get('content-type'); + if (contentType && contentType.startsWith('application/json')) { + return response.json().then(requestBody => { + return new ApiResponse(response.status, requestBody); + }); + } + return new ApiResponse(response.status, {}); + }); + } + + private resolveUrl(endpoint) { + return `${this.baseUrl}${endpoint}`; + } +} diff --git a/src/step_definitions/api.ts b/src/step_definitions/api.ts new file mode 100644 index 00000000..74e55b19 --- /dev/null +++ b/src/step_definitions/api.ts @@ -0,0 +1,82 @@ +import { defineSupportCode } from 'cucumber'; +import config from '../core/config.helper'; +import { RestApiService } from '../rest/rest-api-service'; +import { ApiRequest } from '../rest/api-request'; + +const service = new RestApiService(config.apiUrl); +let apiRequest = new ApiRequest(); + +defineSupportCode(({ When, Then }) => { + let fetchResult; + + When(/^I send "([^"]*)" request on "([^"]*)" endpoint$/, (method, endpoint) => { + apiRequest.method = method; + apiRequest.endpoint = endpoint; + return service + .fetch(apiRequest) + .then(response => { + fetchResult = response; + return response; + }) + .finally(() => { + apiRequest = new ApiRequest(); + return apiRequest; + }); + }); + + When(/^I send "([^"]*)" request on "([^"]*)" endpoint with JSON body:$/, (method, endpoint, payload) => { + apiRequest.method = method; + apiRequest.endpoint = endpoint; + apiRequest.body = JSON.parse(payload); + apiRequest.addHeaders({ 'Content-Type': 'application/json' }); + + return service + .fetch(apiRequest) + .then(response => { + fetchResult = response; + return response; + }) + .finally(() => { + apiRequest = new ApiRequest(); + return apiRequest; + }); + }); + + When(/^I send "([^"]*)" request on "([^"]*)" endpoint using form data:$/, (method, endpoint, payload) => { + apiRequest.method = method; + apiRequest.endpoint = endpoint; + apiRequest.body = apiRequest.addFormData(payload.raw()); + apiRequest.addHeaders({ 'Content-Type': 'multipart/form-data' }); + + return service + .fetch(apiRequest) + .then(response => { + fetchResult = response; + return response; + }) + .finally(() => { + apiRequest = new ApiRequest(); + return apiRequest; + }); + }); + + When(/^I set request headers:$/, headers => { + return apiRequest.addHeaders(headers.rowsHash()); + }); + + Then(/^the response code should be "([^"]*)"$/, status => { + return expect(fetchResult.hasStatus(parseInt(status))).toBe(true); + }); + + Then(/^the response should exact match to body:$/, body => { + return expect(fetchResult.hasBodyMatch(JSON.parse(body))).toBe(true); + }); + + Then(/^the response should match JSON schema:$/, schema => { + try { + fetchResult.hasMatchingSchema(JSON.parse(schema)); + } catch (error) { + return Promise.reject(error); + } + }); +}); diff --git a/src/step_definitions/debug.js b/src/step_definitions/debug.js deleted file mode 100644 index b940988e..00000000 --- a/src/step_definitions/debug.js +++ /dev/null @@ -1,7 +0,0 @@ -import { defineSupportCode } from 'cucumber'; - -defineSupportCode(function({ Then }) { - Then(/^I wait for "([^"]*)" seconds$/, function(number) { - return browser.sleep(Number(number) * 1000); - }); -}); diff --git a/src/step_definitions/debug.ts b/src/step_definitions/debug.ts new file mode 100644 index 00000000..27b498e4 --- /dev/null +++ b/src/step_definitions/debug.ts @@ -0,0 +1,5 @@ +import { Then } from 'cucumber'; + +Then(/^I wait for "([^"]*)" seconds$/, seconds => { + return browser.sleep(Number(seconds) * 1000); +}); diff --git a/src/step_definitions/elements.js b/src/step_definitions/elements.js deleted file mode 100644 index f426cbe5..00000000 --- a/src/step_definitions/elements.js +++ /dev/null @@ -1,544 +0,0 @@ -import { defineSupportCode } from 'cucumber'; -import { matchers, regexBuilder } from '../matchers'; -import variableStore from '../web/variable-store.helper'; -import { comparators } from '../comparators'; -import config from '../core/config.helper'; -import chalk from 'chalk'; -import { waitForCondition } from '../web/cucumber/wait-for-condition.helper'; - -const timeout = parseInt(config.elementsVisibilityTimeout) * 1000; - -const handlePromises = (hashedData, onSuccess, onReject) => resolvedPromises => { - for (let i = 0; i < resolvedPromises.length; i += hashedData.length) { - let allFieldsMatching = true; - - for (let j = i; j < i + hashedData.length; j++) { - if (resolvedPromises[j] === false) { - allFieldsMatching = false; - break; - } - } - - if (allFieldsMatching) { - return onSuccess(); - } - } - - return onReject(); -}; - -defineSupportCode(function({ When, Then }) { - function checkNumberOfElements(numberExpression, element) { - const self = this; - const numberPattern = /\d+/g; - const numbers = numberExpression.match(numberPattern).map(item => parseInt(item)); - - const expectFunction = function(words, num) { - return expect(self.currentPage.getNumberOfElements(element)).to.eventually.be[words.pop()](...num); - }; - - return expectFunction(numberExpression.substr(0, numberExpression.indexOf(numbers[0]) - 1).split(' '), numbers); - } - - When(/^I wait for "([^"]*)" of the "([^"]*)" element$/, function(condition, elementName) { - if (this.currentPage[elementName] instanceof protractor.ElementArrayFinder) { - return waitForCondition(condition, timeout)(this.currentPage[elementName].first()); - } - - return waitForCondition(condition, timeout)(this.currentPage[elementName]); - }); - - When(/^I scroll to the "([^"]*)" element$/, function(elementName) { - return this.currentPage.scrollIntoElement(elementName); - }); - - When(/^I click the "([^"]*)" element$/, function(elementName) { - return this.currentPage - .scrollIntoElement(elementName) - .catch(() => Promise.resolve()) - .then(() => this.currentPage.waitForVisibilityOf(elementName)) - .then(() => this.currentPage.scrollIntoElement(elementName)) - .then(() => this.currentPage.click(elementName)) - .catch(() => { - return waitForCondition('elementToBeClickable', timeout)(this.currentPage[elementName]).then(() => { - return this.currentPage.click(elementName); - }); - }) - .catch(() => { - console.warn('Warning! Element was not clickable. We need to scroll it down.'); - return browser - .executeScript('window.scrollBy(0,50);') - .then(() => this.currentPage.waitForVisibilityOf(elementName)) - .then(() => this.currentPage.click(elementName)); - }) - .catch(() => { - console.warn( - 'Warning! Element was not clickable. We need use the WebDriver method to perform the click action.' - ); - return browser - .actions() - .mouseMove(this.currentPage[elementName]) - .mouseMove({ x: 5, y: 0 }) - .click() - .perform(); - }) - .catch(() => { - return Promise.reject(`Error, after scrolling the element "${elementName}" is still not clickable.`); - }); - }); - - When(/^I store the "([^"]*)" element text as "([^"]*)" variable$/, function(elementName, variable) { - return this.currentPage.waitForVisibilityOf(elementName).then(async () => { - const elementTag = await this.currentPage[elementName].getTagName(tag => tag); - - if (elementTag === 'input' || elementTag === 'textarea') { - return this.currentPage[elementName].getAttribute('value').then(value => { - variableStore.storeVariable(variable, value); - }); - } - - return this.currentPage[elementName].getText().then(text => { - variableStore.storeVariable(variable, text); - }); - }); - }); - - When(/^I update the "([^"]*)" element text as "([^"]*)" variable$/, function(elementName, variable) { - return this.currentPage.waitForVisibilityOf(elementName).then(() => { - this.currentPage[elementName].getText().then(text => { - variableStore.updateVariable(variable, text); - }); - }); - }); - - When(/^I store the "([^"]*)" element text matched by "([^"]*)" as "([^"]*)" variable$/, function( - elementName, - matcher, - variable - ) { - const regex = regexBuilder.buildRegex(matcher); - - return this.currentPage.waitForVisibilityOf(elementName).then(() => { - return this.currentPage[elementName].getText().then(text => { - const matchedText = text.match(regex); - - if (matchedText === null) { - return Promise.reject(`Could not match text ${text} with matcher ${matcher}`); - } - - if (matchedText.length <= 1) { - return Promise.reject(`Matcher ${matcher} does not contain capturing brackets`); - } - - variableStore.storeVariable(variable, matchedText[1]); - }); - }); - }); - - When(/^I wait for the "([^"]*)" element to disappear$/, function(element, sync) { - const self = this; - let maxRepeats = 10; - - const interval = setInterval(() => { - console.log('Waiting for element to disappear...'); - - return self.currentPage.isPresent(element).then(isPresent => { - if (!isPresent) { - clearInterval(interval); - sync(); - return; - } - - maxRepeats--; - - if (maxRepeats === 0) { - clearInterval(interval); - sync('Element is still visible'); - } - }); - }, 1500); - }); - - Then(/^the "([^"]*)" element is present$/, function(elementName) { - chalk.red( - 'DEPRECATED: the "([^"]*)" element is present , use I wait for "([^"]*)" of the "([^"]*)" element instead.' - ); - return expect(this.currentPage.isPresent(elementName)).to.eventually.be.true; - }); - - Then(/^the "([^"]*)" element is not present$/, function(elementName) { - chalk.red( - 'DEPRECATED: the "([^"]*)" element is not present , use I wait for the "([^"]*)" element to disappear instead.' - ); - return expect(this.currentPage.isPresent(elementName)).to.eventually.be.false; - }); - - Then(/^the "([^"]*)" element is visible$/, function(elementName) { - return this.currentPage.isVisible(elementName); - }); - - Then(/^the "([^"]*)" element is not visible$/, function(elementName) { - return this.currentPage - .isVisible(elementName) - .then(isVisible => Promise.reject(isVisible)) - .catch(isVisible => { - if (isVisible === true) { - return Promise.reject(`Element '${elementName}' should not be visible.`); - } - - return Promise.resolve(); - }); - }); - - Then(/^the "([^"]*)" element is disabled$/, function(elementName) { - return expect(this.currentPage.isDisabled(elementName)).to.eventually.be.true; - }); - - When(/^I store table "([^"]*)" rows as "([^"]*)" with columns:$/, function(table, variableName, data) { - const self = this; - const columns = data.raw().map(element => element[0]); - const promises = []; - return this.currentPage.waitForVisibilityOf(table).then(() => { - return this.currentPage[table] - .each(function(element) { - const rowPromises = []; - - for (const columnIndex in columns) { - if (columns.hasOwnProperty(columnIndex)) { - rowPromises.push(element.element(self.currentPage[columns[columnIndex]].locator()).getText()); - } - } - - promises.push(Promise.all(rowPromises)); - }) - .then(function() { - return Promise.all(promises).then(function(resolvedPromises) { - variableStore.storeVariable(variableName, resolvedPromises); - }); - }); - }); - }); - - Then(/^there are following elements in table "([^"]*)":$/, function(table, data) { - const self = this; - const allElements = this.currentPage[table]; - const hashes = data.hashes(); - return this.currentPage.waitForVisibilityOf(table).then(() => { - return checkNumberOfElements.call(this, `equal ${hashes.length}`, table).then(function() { - const promises = []; - - return allElements - .each(function(element, index) { - const hash = hashes[index]; - - for (const prop in hash) { - if (hash.hasOwnProperty(prop)) { - const propValue = hash[prop]; - - promises.push( - matchers.match( - element.element(self.currentPage[prop].locator()), - variableStore.replaceTextVariables(propValue) - ) - ); - } - } - }) - .then(function() { - return Promise.all(promises); - }); - }); - }); - }); - - Then(/^there are "([^"]*)" following elements for element "([^"]*)":$/, function( - numberExpression, - elementName, - data - ) { - const self = this; - const allElements = this.currentPage[elementName]; - const hashedData = data.raw(); - - if (hashedData.length === 0) { - return Promise.reject('Missing table under the step.'); - } - - return this.currentPage.waitForVisibilityOf(elementName).then(() => { - return checkNumberOfElements.call(this, numberExpression, elementName).then(function() { - const promises = []; - - return allElements - .each(function(element) { - hashedData.forEach(function(hash) { - promises.push( - matchers.match( - element.element(self.currentPage[hash[0]].locator()), - variableStore.replaceTextVariables(hash[1]) - ) - ); - }); - }) - .then(function() { - return Promise.all(promises); - }); - }); - }); - }); - - Then(/^there is element "([^"]*)" with value "([^"]*)"$/, function(elementName, value) { - const pageElement = this.currentPage[elementName]; - - return this.currentPage.waitForVisibilityOf(elementName).then(() => { - return matchers.match(pageElement, variableStore.replaceTextVariables(value)).then(function(matcherResult) { - return expect(matcherResult).to.be.true; - }); - }); - }); - - Then(/^there is no element "([^"]*)" with value "([^"]*)"$/, function(elementName, value) { - const pageElement = this.currentPage[elementName]; - - return matchers - .match(pageElement, variableStore.replaceTextVariables(value)) - .catch(() => Promise.resolve(false)) - .then(result => (result ? Promise.reject() : Promise.resolve())); - }); - - Then(/^there is element "([^"]*)" containing "([^"]*)" text$/, function(elementName, value) { - const pageElement = this.currentPage[elementName]; - - return this.currentPage.waitForVisibilityOf(elementName).then(() => { - return matchers.match(pageElement, variableStore.replaceTextVariables(`t:${value}`)); - }); - }); - - Then(/^there is no element "([^"]*)" containing "([^"]*)" text$/, function(elementName, value) { - const pageElement = this.currentPage[elementName]; - - return matchers - .match(pageElement, variableStore.replaceTextVariables(`t:${value}`)) - .catch(() => Promise.resolve(false)) - .then(result => (result ? Promise.reject() : Promise.resolve())); - }); - - Then(/^there is element "([^"]*)" matching "([^"]*)" matcher$/, function(elementName, matcher) { - const pageElement = this.currentPage[elementName]; - - return this.currentPage.waitForVisibilityOf(elementName).then(() => { - return matchers - .match(pageElement, variableStore.replaceTextVariables(`f:${matcher}`)) - .then(function(matcherResult) { - return expect(matcherResult).to.be.true; - }); - }); - }); - - Then(/^there is no element "([^"]*)" matching "([^"]*)" matcher$/, function(elementName, matcher) { - const pageElement = this.currentPage[elementName]; - - return this.currentPage.waitForVisibilityOf(elementName).then(() => { - return matchers - .match(pageElement, variableStore.replaceTextVariables(`f:${matcher}`)) - .catch(() => Promise.resolve(false)) - .then(result => (result ? Promise.reject() : Promise.resolve())); - }); - }); - - Then(/^there is element "([^"]*)" with "([^"]*)" regex$/, function(elementName, matcher) { - const pageElement = this.currentPage[elementName]; - - return this.currentPage.waitForVisibilityOf(elementName).then(() => { - return matchers - .match(pageElement, variableStore.replaceTextVariables(`r:${matcher}`)) - .then(function(matcherResult) { - return expect(matcherResult).to.be.true; - }); - }); - }); - - Then(/^there is no element "([^"]*)" with "([^"]*)" regex$/, function(elementName, matcher) { - const pageElement = this.currentPage[elementName]; - - return this.currentPage.waitForVisibilityOf(elementName).then(() => { - return matchers - .match(pageElement, variableStore.replaceTextVariables(`r:${matcher}`)) - .catch(() => Promise.resolve(false)) - .then(result => (result ? Promise.reject() : Promise.resolve())); - }); - }); - - Then(/^there are "([^"]*)" "([^"]*)" elements$/, checkNumberOfElements); - - Then(/^every "([^"]*)" element should have the same value for element "([^"]*)"$/, function( - containerName, - elementName - ) { - const self = this; - return this.currentPage.waitForVisibilityOf(containerName).then(() => { - return this.currentPage[containerName] - .first() - .element(self.currentPage[elementName].locator()) - .getText() - .then(function(firstElementText) { - return self.currentPage[containerName].each(function(containerElement) { - containerElement - .element(self.currentPage[elementName].locator()) - .getText() - .then(function(elementText) { - expect(elementText).to.be.equal(firstElementText); - }); - }); - }); - }); - }); - - Then(/^the element "([^"]*)" should have an item with values:$/, function(elementName, data) { - const self = this; - const allElements = this.currentPage[elementName]; - const hashedData = data.raw(); - - if (hashedData.length === 0) { - return Promise.reject('Missing table under the step.'); - } - - const promises = []; - return this.currentPage - .waitForVisibilityOf(elementName) - .then(() => { - return allElements.each(function(element) { - hashedData.forEach(function(hash) { - promises.push( - matchers - .match( - element.element(self.currentPage[hash[0]].locator()), - variableStore.replaceTextVariables(hash[1]) - ) - .catch(() => false) - ); - }); - }); - }) - .then(function() { - return Promise.all(promises).then( - handlePromises( - hashedData, - () => Promise.resolve(), - () => Promise.reject('No matching element has been found.') - ) - ); - }); - }); - - Then(/^the element "([^"]*)" should not have an item with values:$/, function(elementName, data) { - const self = this; - const allElements = this.currentPage[elementName]; - const hashedData = data.raw(); - - if (hashedData.length === 0) { - return Promise.reject('Missing table under the step.'); - } - - const promises = []; - - return allElements - .each(function(element) { - hashedData.forEach(function(hash) { - promises.push( - matchers - .match(element.element(self.currentPage[hash[0]].locator()), variableStore.replaceTextVariables(hash[1])) - .catch(() => false) - ); - }); - }) - .then(function() { - return Promise.all(promises).then( - handlePromises(hashedData, () => Promise.reject('Matching element has been found'), () => Promise.resolve()) - ); - }); - }); - - Then(/^"([^"]*)" value on the "([^"]*)" list is sorted in "([^"]*)" order$/, function( - elementValue, - elementList, - dependency - ) { - const self = this; - const promise = []; - - return this.currentPage.waitForVisibilityOf(elementList).then(() => { - return self.currentPage[elementList] - .each(function(singleElement) { - promise.push(singleElement.element(self.currentPage[elementValue].locator()).getText()); - }) - .then(function() { - return Promise.all(promise); - }) - .then(function(elementsValues) { - return comparators.compare(elementsValues, dependency); - }); - }); - }); - - When(/^I infinitely scroll to the "([^"]*)" element$/, function(elementName) { - const self = this; - - const scrollToLoader = () => { - return self.currentPage - .isPresent(elementName) - .then(isPresent => { - if (isPresent) { - return self.currentPage.scrollIntoElement(elementName); - } - - return Promise.resolve(); - }) - .then(() => self.currentPage.isPresent(elementName)) - .then(isPresent => { - if (isPresent) { - return browser.sleep(1000).then(() => scrollToLoader()); - } - - return Promise.resolve(); - }); - }; - - return scrollToLoader(); - }); - - When(/^I press the "([^"]*)" key$/, function(key) { - const keyTransformed = key.toUpperCase(); - - return Promise.resolve( - browser - .actions() - .sendKeys(protractor.Key[keyTransformed]) - .perform() - ); - }); - - When(/^I drag "([^"]*)" element and drop over "([^"]*)" element$/, async function(elementDrag, elementDrop) { - const wait = timeToWait => browser.sleep(timeToWait); - - await this.currentPage.waitForVisibilityOf(elementDrag); - await browser - .actions() - .mouseMove(this.currentPage[elementDrag]) - .perform(); - await wait(200); - await browser - .actions() - .mouseDown() - .perform(); - await wait(200); - await browser - .actions() - .mouseMove(this.currentPage[elementDrop]) - .perform(); - await wait(200); - await browser - .actions() - .mouseUp() - .perform(); - }); -}); diff --git a/src/step_definitions/elements.ts b/src/step_definitions/elements.ts new file mode 100644 index 00000000..d70d56a1 --- /dev/null +++ b/src/step_definitions/elements.ts @@ -0,0 +1,547 @@ +import * as chai from 'chai'; +import { When, Then } from 'cucumber'; +import { comparators } from '../comparators'; +import config from '../core/config.helper'; +import { matchers, regexBuilder } from '../matchers'; +import { waitForCondition } from '../web/cucumber/wait-for-condition.helper'; +import variableStore from '../web/variable-store.helper'; + +const timeout = parseInt(config.elementsVisibilityTimeout) * 1000; + +const handlePromises = (hashedData, onSuccess, onReject) => resolvedPromises => { + for (let i = 0; i < resolvedPromises.length; i += hashedData.length) { + let allFieldsMatching = true; + + for (let j = i; j < i + hashedData.length; j++) { + if (resolvedPromises[j] === false) { + allFieldsMatching = false; + break; + } + } + + if (allFieldsMatching) { + return onSuccess(); + } + } + + return onReject(); +}; + +function checkNumberOfElements(numberExpression, element) { + const self = this; + const numberPattern = /\d+/g; + const numbers = numberExpression.match(numberPattern).map(item => parseInt(item)); + + const expectFunction = async (words, num) => { + const numberOfElements = await self.currentPage.getNumberOfElements(element); + return chai.expect(numberOfElements).to.be[words.pop()](...num); + }; + + return expectFunction(numberExpression.substr(0, numberExpression.indexOf(numbers[0]) - 1).split(' '), numbers); +} + +When(/^I wait for "([^"]*)" of the "([^"]*)" element$/, function(condition, elementName) { + if (this.currentPage.getElement(elementName) instanceof protractor.ElementArrayFinder) { + return waitForCondition(condition, timeout)(this.currentPage.getElement(elementName).first()); + } + + return waitForCondition(condition, timeout)(this.currentPage.getElement(elementName)); +}); + +When(/^I scroll to the "([^"]*)" element$/, function(elementName) { + return this.currentPage.scrollIntoElement(elementName); +}); + +When(/^I click the "([^"]*)" element$/, function(elementName) { + return this.currentPage + .scrollIntoElement(elementName) + .catch(() => Promise.resolve()) + .then(() => this.currentPage.waitForVisibilityOf(elementName)) + .then(() => this.currentPage.scrollIntoElement(elementName)) + .then(() => this.currentPage.click(elementName)) + .catch(() => { + return waitForCondition('elementToBeClickable', timeout)(this.currentPage.getElement(elementName)).then(() => { + return this.currentPage.click(elementName); + }); + }) + .catch(() => { + console.warn('Warning! Element was not clickable. We need to scroll it down.'); + return browser + .executeScript('window.scrollBy(0,50);') + .then(() => this.currentPage.waitForVisibilityOf(elementName)) + .then(() => this.currentPage.click(elementName)); + }) + .catch(() => { + console.warn('Warning! Element was not clickable. We need use the WebDriver method to perform the click action.'); + return browser + .actions() + .mouseMove(this.currentPage.getElement(elementName)) + .mouseMove({ x: 5, y: 0 }) + .click() + .perform(); + }) + .catch(() => { + return Promise.reject(`Error, after scrolling the element "${elementName}" is still not clickable.`); + }); +}); + +When(/^I store the "([^"]*)" element text as "([^"]*)" variable$/, function(elementName, variable) { + return this.currentPage.waitForVisibilityOf(elementName).then(async () => { + const elementTag = await this.currentPage[elementName].getTagName(tag => tag); + + if (elementTag === 'input' || elementTag === 'textarea') { + return this.currentPage + .getElement(elementName) + .getAttribute('value') + .then(value => { + variableStore.storeVariable(variable, value); + }); + } + + return this.currentPage + .getElement(elementName) + .getText() + .then(text => { + variableStore.storeVariable(variable, text); + }); + }); +}); + +When(/^I update the "([^"]*)" element text as "([^"]*)" variable$/, function(elementName, variable) { + return this.currentPage.waitForVisibilityOf(elementName).then(() => { + this.currentPage + .getElement(elementName) + .getText() + .then(text => { + variableStore.updateVariable(variable, text); + }); + }); +}); + +When(/^I store the "([^"]*)" element text matched by "([^"]*)" as "([^"]*)" variable$/, function( + elementName, + matcher, + variable +) { + const regex = regexBuilder.buildRegex(matcher); + + return this.currentPage.waitForVisibilityOf(elementName).then(() => { + return this.currentPage + .getElement(elementName) + .getText() + .then(text => { + const matchedText = text.match(regex); + + if (matchedText === null) { + return Promise.reject(`Could not match text ${text} with matcher ${matcher}`); + } + + if (matchedText.length <= 1) { + return Promise.reject(`Matcher ${matcher} does not contain capturing brackets`); + } + + variableStore.storeVariable(variable, matchedText[1]); + }); + }); +}); + +When(/^I wait for the "([^"]*)" element to disappear$/, function(elementName, sync) { + const self = this; + let maxRepeats = 10; + + const interval = setInterval(() => { + console.log('Waiting for element to disappear...'); + + return self.currentPage.isPresent(elementName).then(isPresent => { + if (!isPresent) { + clearInterval(interval); + sync(); + return; + } + + maxRepeats--; + + if (maxRepeats === 0) { + clearInterval(interval); + sync('Element is still visible'); + } + }); + }, 1500); +}); + +Then(/^the "([^"]*)" element is visible$/, function(elementName) { + return this.currentPage.isVisible(elementName); +}); + +Then(/^the "([^"]*)" element is not visible$/, function(elementName) { + return this.currentPage + .isVisible(elementName) + .then(isVisible => Promise.reject(isVisible)) + .catch(isVisible => { + if (isVisible === true) { + return Promise.reject(`Element '${elementName}' should not be visible.`); + } + + return Promise.resolve(); + }); +}); + +Then(/^the "([^"]*)" element is disabled$/, async function(elementName) { + return await expect(this.currentPage.isDisabled(elementName)).resolves.toBe(true); +}); + +When(/^I store table "([^"]*)" rows as "([^"]*)" with columns:$/, function(table, variableName, data) { + const self = this; + const columns = data.raw().map(element => element[0]); + const promises = []; + return this.currentPage.waitForVisibilityOf(table).then(() => { + return this.currentPage + .getElement(table) + .each(element => { + const rowPromises = []; + + for (const columnIndex in columns) { + if (columns.hasOwnProperty(columnIndex)) { + rowPromises.push(element.element(self.currentPage.getElement(columns[columnIndex]).locator()).getText()); + } + } + + promises.push(Promise.all(rowPromises)); + }) + .then(() => + Promise.all(promises).then(resolvedPromises => { + variableStore.storeVariable(variableName, resolvedPromises); + }) + ); + }); +}); + +Then(/^there are following elements in table "([^"]*)":$/, function(table, data) { + const self = this; + const allElements = this.currentPage.getElements(table); + const hashes = data.hashes(); + return this.currentPage.waitForVisibilityOf(table).then(() => { + return checkNumberOfElements.call(this, `equal ${hashes.length}`, table).then(() => { + const promises = []; + + return allElements + .each((element, index) => { + const hash = hashes[index]; + + for (const prop in hash) { + if (hash.hasOwnProperty(prop)) { + const propValue = hash[prop]; + + promises.push( + matchers.match( + element.element(self.currentPage.getElement(prop).locator()), + variableStore.replaceTextVariables(propValue) + ) + ); + } + } + }) + .then(() => Promise.all(promises)); + }); + }); +}); + +Then(/^there are "([^"]*)" following elements for element "([^"]*)":$/, function(numberExpression, elementName, data) { + const self = this; + const allElements = this.currentPage.getElements(elementName); + const hashedData = data.raw(); + + if (hashedData.length === 0) { + return Promise.reject('Missing table under the step.'); + } + + return this.currentPage.waitForVisibilityOf(elementName).then(() => { + return checkNumberOfElements.call(this, numberExpression, elementName).then(() => { + const promises = []; + + return allElements + .each(element => { + hashedData.forEach(hash => { + promises.push( + matchers.match( + element.element(self.currentPage.getElement(hash[0]).locator()), + variableStore.replaceTextVariables(hash[1]) + ) + ); + }); + }) + .then(() => Promise.all(promises)); + }); + }); +}); + +Then(/^there are "([^"]*)" dropdown list elements with following options:$/, function(elementName, data) { + const allOptionElements = this.currentPage.getElement(elementName); + const hashedData = data.raw(); + + if (hashedData.length === 0) { + return Promise.reject('Missing table under the step.'); + } + + return this.currentPage.waitForVisibilityOf(elementName).then(() => { + allOptionElements.getText().then(textArray => { + if (textArray.length === hashedData.length) { + hashedData.forEach(hash => { + textArray.splice(textArray.indexOf(hash), 1); + }); + } else { + return Promise.reject("Number of options doesn't match the number of asked"); + } + expect(textArray.length).toEqual(0); + }); + }); +}); + +Then(/^there is element "([^"]*)" with value "([^"]*)"$/, function(elementName, value) { + const pageElement = this.currentPage.getElement(elementName); + + return this.currentPage.waitForVisibilityOf(elementName).then(() => { + return matchers + .match(pageElement, variableStore.replaceTextVariables(value)) + .then(matcherResult => expect(matcherResult).toBe(true)); + }); +}); + +Then(/^there is no element "([^"]*)" with value "([^"]*)"$/, function(elementName, value) { + const pageElement = this.currentPage.getElement(elementName); + + return matchers + .match(pageElement, variableStore.replaceTextVariables(value)) + .catch(() => Promise.resolve(false)) + .then(result => (result ? Promise.reject() : Promise.resolve())); +}); + +Then(/^there is element "([^"]*)" containing "([^"]*)" text$/, function(elementName, value) { + const pageElement = this.currentPage.getElement(elementName); + + return this.currentPage.waitForVisibilityOf(elementName).then(() => { + return matchers.match(pageElement, variableStore.replaceTextVariables(`t:${value}`)); + }); +}); + +Then(/^there is no element "([^"]*)" containing "([^"]*)" text$/, function(elementName, value) { + const pageElement = this.currentPage.getElement(elementName); + + return matchers + .match(pageElement, variableStore.replaceTextVariables(`t:${value}`)) + .catch(() => Promise.resolve(false)) + .then(result => (result ? Promise.reject() : Promise.resolve())); +}); + +Then(/^there is element "([^"]*)" matching "([^"]*)" matcher$/, function(elementName, matcher) { + const pageElement = this.currentPage.getElement(elementName); + + return this.currentPage.waitForVisibilityOf(elementName).then(() => { + return matchers + .match(pageElement, variableStore.replaceTextVariables(`f:${matcher}`)) + .then(matcherResult => expect(matcherResult).toBe(true)); + }); +}); + +Then(/^there is no element "([^"]*)" matching "([^"]*)" matcher$/, function(elementName, matcher) { + const pageElement = this.currentPage.getElement(elementName); + + return this.currentPage.waitForVisibilityOf(elementName).then(() => { + return matchers + .match(pageElement, variableStore.replaceTextVariables(`f:${matcher}`)) + .catch(() => Promise.resolve(false)) + .then(result => (result ? Promise.reject() : Promise.resolve())); + }); +}); + +Then(/^there is element "([^"]*)" with "([^"]*)" regex$/, function(elementName, matcher) { + const pageElement = this.currentPage.getElement(elementName); + + return this.currentPage.waitForVisibilityOf(elementName).then(() => { + return matchers + .match(pageElement, variableStore.replaceTextVariables(`r:${matcher}`)) + .then(matcherResult => expect(matcherResult).toBe(true)); + }); +}); + +Then(/^there is no element "([^"]*)" with "([^"]*)" regex$/, function(elementName, matcher) { + const pageElement = this.currentPage.getElement(elementName); + + return this.currentPage.waitForVisibilityOf(elementName).then(() => { + return matchers + .match(pageElement, variableStore.replaceTextVariables(`r:${matcher}`)) + .catch(() => Promise.resolve(false)) + .then(result => (result ? Promise.reject() : Promise.resolve())); + }); +}); + +Then(/^there are "([^"]*)" "([^"]*)" elements$/, checkNumberOfElements); + +Then(/^every "([^"]*)" element should have the same value for element "([^"]*)"$/, function( + containerName, + elementName +) { + const self = this; + return this.currentPage.waitForVisibilityOf(containerName).then(() => { + return this.currentPage + .getElements(containerName) + .first() + .element(self.currentPage.getElement(elementName).locator()) + .getText() + .then(firstElementText => { + return self.currentPage.getElements(containerName).each(containerElement => { + containerElement + .element(self.currentPage.getElement(elementName).locator()) + .getText() + .then(elementText => { + expect(elementText).toEqual(firstElementText); + }); + }); + }); + }); +}); + +Then(/^the element "([^"]*)" should have an item with values:$/, function(elementName, data) { + const self = this; + const allElements = this.currentPage.getElements(elementName); + const hashedData = data.raw(); + + if (hashedData.length === 0) { + return Promise.reject('Missing table under the step.'); + } + + const promises = []; + return this.currentPage + .waitForVisibilityOf(elementName) + .then(() => + allElements.each(element => { + hashedData.forEach(hash => { + promises.push( + matchers + .match( + element.element(self.currentPage.getElement(hash[0]).locator()), + variableStore.replaceTextVariables(hash[1]) + ) + .catch(() => false) + ); + }); + }) + ) + .then(() => + Promise.all(promises).then( + handlePromises(hashedData, () => Promise.resolve(), () => Promise.reject('No matching element has been found.')) + ) + ); +}); + +Then(/^the element "([^"]*)" should not have an item with values:$/, function(elementName, data) { + const self = this; + const allElements = this.currentPage.getElements(elementName); + const hashedData = data.raw(); + + if (hashedData.length === 0) { + return Promise.reject('Missing table under the step.'); + } + + const promises = []; + + return allElements + .each(element => { + hashedData.forEach(hash => { + promises.push( + matchers + .match( + element.element(self.currentPage.getElement(hash[0]).locator()), + variableStore.replaceTextVariables(hash[1]) + ) + .catch(() => false) + ); + }); + }) + .then(() => + Promise.all(promises).then( + handlePromises(hashedData, () => Promise.reject('Matching element has been found'), () => Promise.resolve()) + ) + ); +}); + +Then(/^"([^"]*)" value on the "([^"]*)" list is sorted in "([^"]*)" order$/, function( + elementValue, + elementList, + dependency +) { + const self = this; + const promise = []; + + return this.currentPage.waitForVisibilityOf(elementList).then(() => { + return self.currentPage + .getElements(elementList) + .each(singleElement => { + promise.push(singleElement.element(self.currentPage.getElement(elementValue).locator()).getText()); + }) + .then(() => Promise.all(promise)) + .then(elementsValues => comparators.compare(elementsValues, dependency)); + }); +}); + +When(/^I infinitely scroll to the "([^"]*)" element$/, function(elementName) { + const self = this; + + const scrollToLoader = () => { + return self.currentPage + .isPresent(elementName) + .then(isPresent => { + if (isPresent) { + return self.currentPage.scrollIntoElement(elementName); + } + + return Promise.resolve(); + }) + .then(() => self.currentPage.isPresent(elementName)) + .then(isPresent => { + if (isPresent) { + return browser.sleep(1000).then(() => scrollToLoader()); + } + + return Promise.resolve(); + }); + }; + + return scrollToLoader(); +}); + +When(/^I press the "([^"]*)" key$/, key => { + const keyTransformed = key.toUpperCase(); + + return Promise.resolve( + browser + .actions() + .sendKeys(protractor.Key[keyTransformed]) + .perform() + ); +}); + +When(/^I drag "([^"]*)" element and drop over "([^"]*)" element$/, async function(elementDrag, elementDrop) { + const wait = timeToWait => browser.sleep(timeToWait); + + await this.currentPage.waitForVisibilityOf(elementDrag); + await browser + .actions() + .mouseMove(this.currentPage.getElement(elementDrag)) + .perform(); + await wait(200); + await browser + .actions() + .mouseDown() + .perform(); + await wait(200); + await browser + .actions() + .mouseMove(this.currentPage.getElement(elementDrop)) + .perform(); + await wait(200); + await browser + .actions() + .mouseUp() + .perform(); +}); diff --git a/src/step_definitions/email.js b/src/step_definitions/email.js deleted file mode 100644 index 6031dc76..00000000 --- a/src/step_definitions/email.js +++ /dev/null @@ -1,160 +0,0 @@ -import { defineSupportCode } from 'cucumber'; -import sugar from 'sugar-date'; -import { filters } from '../emails/filters'; -import { regexBuilder } from '../matchers'; -import config from '../core/config.helper'; - -import { emailService } from '../emails'; - -defineSupportCode(function({ Then }) { - function stopInterval(interval, callback) { - clearInterval(interval); - callback(); - } - - function checkAttachmentsInEmail(email, filesExtensions, attachments) { - let fileAttachments = attachments.filter(attachment => attachment.attachment_type === 'attachment'); - - const missingFiles = filesExtensions.reduce((previous, current) => { - const expectedFile = fileAttachments.find(attachment => { - return ( - regexBuilder.buildRegex(current.name).test(attachment.filename) && - regexBuilder.buildRegex(current.type).test(attachment.content_type) && - attachment.attachment_size >= current.minimalSize - ); - }); - - if (typeof expectedFile === 'undefined') { - previous.push(current); - return previous; - } - - fileAttachments = fileAttachments.filter(attachment => attachment.id !== expectedFile.id); - - return previous; - }, []); - - if (missingFiles.length === 0) { - return emailService.markAsRead(email); - } - - return Promise.reject('Some attachments not found: ' + missingFiles.map(file => file.name).join(', ')); - } - - function filterEmails(emails, data) { - let originalEmails = emails; - const checks = data.raw().filter(elem => elem[0] !== 'file'); - - for (let i = 0; i < checks.length; i++) { - const checkType = checks[i][0]; - const checkValue = checks[i][1]; - - originalEmails = filters.filter(originalEmails, checkType, checkValue, this); - } - - return originalEmails; - } - - function getFilesExtensions(data) { - return data - .raw() - .filter(elem => elem[0] === 'file') - .map(elem => { - return { name: elem[1], type: elem[2], minimalSize: elem[3] }; - }); - } - - function rejectIfMaxRepeatsReached(filteredEmails, maxRepeats) { - if (filteredEmails.length === 0 && maxRepeats === 0) { - return Promise.reject('No emails found and maximum repeats reached'); - } - - return filteredEmails; - } - - function rejectIfMoreThanOneEmailFound(filteredEmails) { - if (filteredEmails.length > 1) { - return Promise.reject('More than one email found'); - } - - return filteredEmails; - } - - function rejectIfEmailFound(filteredEmails) { - if (filteredEmails.length > 0) { - return Promise.reject('Email has been found!'); - } - - return filteredEmails; - } - - function validateEmailDate(filteredEmails) { - if (filteredEmails.length === 1) { - if (sugar.Date.minutesFromNow(sugar.Date.create(filteredEmails[0].created_at)) < -10) { - return Promise.reject( - 'Email was sent more than 10 minutes ago. This is probably not what you are looking for.' - ); - } - } - - return filteredEmails; - } - - function validateEmailContentAndAttachments(filteredEmails, data, interval, sync) { - if (filteredEmails.length === 1) { - const filesExtensions = getFilesExtensions(data); - - if (filesExtensions.length > 0) { - return emailService - .getAttachments(filteredEmails[0]) - .then(checkAttachmentsInEmail.bind(null, filteredEmails[0], filesExtensions)) - .then(stopInterval.bind(null, interval, sync)); - } - return emailService.markAsRead(filteredEmails[0]).then(stopInterval.bind(null, interval, sync)); - } - } - - Then(/^the email has been sent and contains:$/, function(data, sync) { - const self = this; - const timeout = parseInt(config.intervalEmail) * 1000; - let maxRepeats = parseInt(config.maxEmailRepeats); - - config.maxEmailRepeats === undefined ? (maxRepeats = 5) : maxRepeats; - - const interval = setInterval(() => { - console.log('Checking mailbox for email...'); - - emailService - .getEmails() - .then(emails => filterEmails.call(self, emails, data)) - .then(filteredEmails => rejectIfMaxRepeatsReached(filteredEmails, maxRepeats)) - .then(filteredEmails => rejectIfMoreThanOneEmailFound(filteredEmails)) - .then(filteredEmails => validateEmailDate(filteredEmails)) - .then(filteredEmails => validateEmailContentAndAttachments(filteredEmails, data, interval, sync)) - .then(() => maxRepeats--) - .catch(err => stopInterval(interval, sync.bind(null, err))); - }, timeout); - }); - - Then(/^the email with the following data has not been sent:$/, function(data, sync) { - const self = this; - const timeout = parseInt(config.intervalEmail) * 1000; - let maxRepeats = 5; - - const interval = setInterval(() => { - console.log('Checking mailbox for email...'); - - emailService - .getEmails() - .then(emails => filterEmails.call(self, emails, data)) - .then(filteredEmails => rejectIfEmailFound(filteredEmails)) - .then(filteredEmails => rejectIfMaxRepeatsReached(filteredEmails, maxRepeats)) - .then(() => maxRepeats--) - .catch(err => { - err === 'No emails found and maximum repeats reached' - ? stopInterval(interval, sync) - : stopInterval(interval, sync.bind(null, err)); - }); - }, timeout); - }); -}); diff --git a/src/step_definitions/email.ts b/src/step_definitions/email.ts new file mode 100644 index 00000000..761598e8 --- /dev/null +++ b/src/step_definitions/email.ts @@ -0,0 +1,152 @@ +import { Then } from 'cucumber'; +import * as sugar from 'sugar-date/index'; +import config from '../core/config.helper'; +import { filters } from '../emails/filters'; +import { regexBuilder } from '../matchers'; + +import { emailService } from '../emails'; + +function stopInterval(interval, callback) { + clearInterval(interval); + callback(); +} + +function checkAttachmentsInEmail(email, filesExtensions, attachments) { + let fileAttachments = attachments.filter(attachment => attachment.attachment_type === 'attachment'); + + const missingFiles = filesExtensions.reduce((previous, current) => { + const expectedFile = fileAttachments.find(attachment => { + return ( + regexBuilder.buildRegex(current.name).test(attachment.filename) && + regexBuilder.buildRegex(current.type).test(attachment.content_type) && + attachment.attachment_size >= current.minimalSize + ); + }); + + if (typeof expectedFile === 'undefined') { + previous.push(current); + return previous; + } + + fileAttachments = fileAttachments.filter(attachment => attachment.id !== expectedFile.id); + + return previous; + }, []); + + if (missingFiles.length === 0) { + return emailService.markAsRead(email); + } + + return Promise.reject('Some attachments not found: ' + missingFiles.map(file => file.name).join(', ')); +} + +function filterEmails(emails, data) { + let originalEmails = emails; + const checks = data.raw().filter(elem => elem[0] !== 'file'); + + for (const check of checks) { + const checkType = check[0]; + const checkValue = check[1]; + + originalEmails = filters.filter(originalEmails, checkType, checkValue, this); + } + + return originalEmails; +} + +function getFilesExtensions(data) { + return data + .raw() + .filter(elem => elem[0] === 'file') + .map(elem => { + return { name: elem[1], type: elem[2], minimalSize: elem[3] }; + }); +} + +function rejectIfMaxRepeatsReached(filteredEmails, maxRepeats) { + if (filteredEmails.length === 0 && maxRepeats === 0) { + return Promise.reject('No emails found and maximum repeats reached'); + } + + return filteredEmails; +} + +function rejectIfMoreThanOneEmailFound(filteredEmails) { + if (filteredEmails.length > 1) { + return Promise.reject('More than one email found'); + } + + return filteredEmails; +} + +function rejectIfEmailFound(filteredEmails) { + if (filteredEmails.length > 0) { + return Promise.reject('Email has been found!'); + } + + return filteredEmails; +} + +function validateEmailDate(filteredEmails) { + if (filteredEmails.length === 1 && sugar.Date.minutesFromNow(sugar.Date.create(filteredEmails[0].created_at)) < -10) { + return Promise.reject('Email was sent more than 10 minutes ago. This is probably not what you are looking for.'); + } + + return filteredEmails; +} + +function validateEmailContentAndAttachments(filteredEmails, data, interval, sync) { + if (filteredEmails.length === 1) { + const filesExtensions = getFilesExtensions(data); + + if (filesExtensions.length > 0) { + return emailService + .getAttachments(filteredEmails[0]) + .then(checkAttachmentsInEmail.bind(null, filteredEmails[0], filesExtensions)) + .then(stopInterval.bind(null, interval, sync)); + } + return emailService.markAsRead(filteredEmails[0]).then(stopInterval.bind(null, interval, sync)); + } +} + +Then(/^the email has been sent and contains:$/, function(data, sync) { + const self = this; + const timeout = parseInt(config.intervalEmail) * 1000; + let maxRepeats = config.maxEmailRepeats === undefined ? 5 : parseInt(config.maxEmailRepeats); + + const interval = setInterval(() => { + console.log('Checking mailbox for email...'); + + emailService + .getEmails() + .then(emails => filterEmails.call(self, emails, data)) + .then(filteredEmails => rejectIfMaxRepeatsReached(filteredEmails, maxRepeats)) + .then(filteredEmails => rejectIfMoreThanOneEmailFound(filteredEmails)) + .then(filteredEmails => validateEmailDate(filteredEmails)) + .then(filteredEmails => validateEmailContentAndAttachments(filteredEmails, data, interval, sync)) + .then(() => maxRepeats--) + .catch(err => stopInterval(interval, sync.bind(null, err))); + }, timeout); +}); + +Then(/^the email with the following data has not been sent:$/, function(data, sync) { + const self = this; + const timeout = parseInt(config.intervalEmail) * 1000; + let maxRepeats = 5; + + const interval = setInterval(() => { + console.log('Checking mailbox for email...'); + + emailService + .getEmails() + .then(emails => filterEmails.call(self, emails, data)) + .then(filteredEmails => rejectIfEmailFound(filteredEmails)) + .then(filteredEmails => rejectIfMaxRepeatsReached(filteredEmails, maxRepeats)) + .then(() => maxRepeats--) + .catch(err => { + err === 'No emails found and maximum repeats reached' + ? stopInterval(interval, sync) + : stopInterval(interval, sync.bind(null, err)); + }); + }, timeout); +}); diff --git a/src/step_definitions/file.js b/src/step_definitions/file.js deleted file mode 100644 index 5a381eb7..00000000 --- a/src/step_definitions/file.js +++ /dev/null @@ -1,72 +0,0 @@ -import { defineSupportCode } from 'cucumber'; -import fileManager from '../web/fs/file-manager.helper'; -import variableStore from '../web/variable-store.helper'; - -defineSupportCode(function({ Then }) { - Then(/^the file "([^"]*)" should be downloaded$/, function(filename) { - return fileManager.wasDownloaded(variableStore.replaceTextVariables(filename)); - }); - - Then(/^the file "([^"]*)" contains table data stored under "([^"]*)" variable$/, function(filename, variableName) { - const file = fileManager.parseXLS(variableStore.replaceTextVariables(filename)); - const storedData = variableStore.getVariableValue(variableName); - const rows = file.filter((row, index) => row.length > 0 && index > 0); - - const findIndexes = () => { - const allFoundIndexesInRows = []; - - storedData.forEach(storedItems => { - const foundIndexesInRow = []; - let previousFoundIndex = null; - - storedItems.forEach(storedValue => { - for (const index in rows) { - if (storedValue.match(/^\d+$/)) { - if (previousFoundIndex !== null) { - foundIndexesInRow.push(rows[previousFoundIndex].indexOf(parseInt(storedValue))); - break; - } - - if (rows[index].includes(parseInt(storedValue))) { - previousFoundIndex = index; - foundIndexesInRow.push(rows[index].indexOf(parseInt(storedValue))); - break; - } - } - - if (previousFoundIndex !== null) { - foundIndexesInRow.push(rows[previousFoundIndex].indexOf(storedValue)); - break; - } - - if (rows[index].includes(storedValue)) { - previousFoundIndex = index; - foundIndexesInRow.push(rows[index].indexOf(storedValue)); - break; - } - } - }); - - allFoundIndexesInRows.push(foundIndexesInRow); - }); - - return Promise.resolve(allFoundIndexesInRows); - }; - - return findIndexes().then(allFoundIndexes => { - if (allFoundIndexes[0].length !== storedData[0].length) { - return Promise.reject('Values not found!'); - } - - if (allFoundIndexes.length === 1) { - return Promise.resolve(); - } - - for (let index = 1; index < allFoundIndexes.length; index++) { - if (JSON.stringify(allFoundIndexes[index]) !== JSON.stringify(allFoundIndexes[index - 1])) { - return Promise.reject('Arrays are different!'); - } - } - }); - }); -}); diff --git a/src/step_definitions/file.ts b/src/step_definitions/file.ts new file mode 100644 index 00000000..eb0ad639 --- /dev/null +++ b/src/step_definitions/file.ts @@ -0,0 +1,72 @@ +import { Then } from 'cucumber'; +import fileManager from '../web/fs/file-manager.helper'; +import variableStore from '../web/variable-store.helper'; + +Then(/^the file "([^"]*)" should be downloaded$/, filename => { + return fileManager.wasDownloaded(variableStore.replaceTextVariables(filename)); +}); + +Then(/^the file "([^"]*)" contains table data stored under "([^"]*)" variable$/, (filename, variableName) => { + const file = fileManager.parseXLS(variableStore.replaceTextVariables(filename)); + const storedData = variableStore.getVariableValue(variableName); + const rows = file.filter((row, index) => row.length > 0 && index > 0); + + const findIndexes = () => { + const allFoundIndexesInRows = []; + + storedData.forEach(storedItems => { + const foundIndexesInRow = []; + let previousFoundIndex = null; + + storedItems.forEach(storedValue => { + for (const index in rows) { + if (rows.hasOwnProperty(index)) { + if (storedValue.match(/^\d+$/)) { + if (previousFoundIndex !== null) { + foundIndexesInRow.push(rows[previousFoundIndex].indexOf(parseInt(storedValue))); + break; + } + + if (rows[index].includes(parseInt(storedValue))) { + previousFoundIndex = index; + foundIndexesInRow.push(rows[index].indexOf(parseInt(storedValue))); + break; + } + } + + if (previousFoundIndex !== null) { + foundIndexesInRow.push(rows[previousFoundIndex].indexOf(storedValue)); + break; + } + + if (rows[index].includes(storedValue)) { + previousFoundIndex = index; + foundIndexesInRow.push(rows[index].indexOf(storedValue)); + break; + } + } + } + }); + + allFoundIndexesInRows.push(foundIndexesInRow); + }); + + return Promise.resolve(allFoundIndexesInRows); + }; + + return findIndexes().then(allFoundIndexes => { + if (allFoundIndexes[0].length !== storedData[0].length) { + return Promise.reject('Values not found!'); + } + + if (allFoundIndexes.length === 1) { + return Promise.resolve(); + } + + for (let index = 1; index < allFoundIndexes.length; index++) { + if (JSON.stringify(allFoundIndexes[index]) !== JSON.stringify(allFoundIndexes[index - 1])) { + return Promise.reject('Arrays are different!'); + } + } + }); +}); diff --git a/src/step_definitions/form.js b/src/step_definitions/form.js deleted file mode 100644 index 248f732e..00000000 --- a/src/step_definitions/form.js +++ /dev/null @@ -1,49 +0,0 @@ -import { defineSupportCode } from 'cucumber'; -import { dictionaries } from '../dictionaries'; - -defineSupportCode(function({ When, Then }) { - When(/^I fill the "([^"]*)" form with:$/, function(formName, data) { - const self = this; - - return this.currentPage.waitForVisibilityOf(formName).then(function() { - return expect(self.currentPage.isVisible(formName)).to.eventually.be.fulfilled.then(function() { - return self.currentPage.fillForm(data.raw()); - }); - }); - }); - - Then(/^the "([^"]*)" form is filled with:$/, function(formName, data) { - const self = this; - - return this.currentPage.waitForVisibilityOf(formName).then(function() { - return expect(self.currentPage.isVisible(formName)).to.eventually.be.fulfilled.then(function() { - return self.currentPage.checkForm(data.raw()); - }); - }); - }); - - Then(/^the error messages should be displayed:$/, function(data) { - const self = this; - const table = data.rows(); - - const promise = []; - - table.forEach(function(item) { - promise.push( - expect(self.currentPage.isVisible(item[0])).to.eventually.be.fulfilled.then(function() { - return self.currentPage[item[0]].getText().then(function(text) { - if (text.indexOf(dictionaries.findMappedValueByPhrase(item[1])) >= 0) { - return Promise.resolve(); - } - - return Promise.reject( - `Error "${dictionaries.findMappedValueByPhrase(item[1])}" for element "${item[0]}" was not found.` - ); - }); - }) - ); - }); - - return Promise.all(promise); - }); -}); diff --git a/src/step_definitions/form.ts b/src/step_definitions/form.ts new file mode 100644 index 00000000..b78d0450 --- /dev/null +++ b/src/step_definitions/form.ts @@ -0,0 +1,40 @@ +import { When, Then } from 'cucumber'; +import { dictionaries } from '../dictionaries'; + +When(/^I fill the "([^"]*)" form with:$/, function(formName, data) { + const self = this; + + return this.currentPage.waitForVisibilityOf(formName).then(() => self.currentPage.fillForm(data.raw())); +}); + +Then(/^the "([^"]*)" form is filled with:$/, function(formName, data) { + const self = this; + + return this.currentPage.waitForVisibilityOf(formName).then(() => self.currentPage.checkForm(data.raw())); +}); + +Then(/^the error messages should be displayed:$/, function(data) { + const self = this; + const table = data.rows(); + + const promise = []; + + table.forEach(item => { + promise.push( + self.currentPage + .waitForVisibilityOf(item[0]) + .then(() => self.currentPage[item[0]].getText()) + .then(text => { + if (text.indexOf(dictionaries.findMappedValueByPhrase(item[1])) >= 0) { + return Promise.resolve(); + } + + return Promise.reject( + `Error "${dictionaries.findMappedValueByPhrase(item[1])}" for element "${item[0]}" was not found.` + ); + }) + ); + }); + + return Promise.all(promise); +}); diff --git a/src/step_definitions/generators.js b/src/step_definitions/generators.js deleted file mode 100644 index 17d95202..00000000 --- a/src/step_definitions/generators.js +++ /dev/null @@ -1,9 +0,0 @@ -import { defineSupportCode } from 'cucumber'; -import variableStore from '../web/variable-store.helper'; -import { transformers } from '../transformers'; - -defineSupportCode(function({ When }) { - When(/^I generate random "([^"]*)" as "([^"]*)"$/, function(generator, variableName) { - return transformers.transform(`g:${generator}`).then(result => variableStore.storeVariable(variableName, result)); - }); -}); diff --git a/src/step_definitions/generators.ts b/src/step_definitions/generators.ts new file mode 100644 index 00000000..a1ddf5ee --- /dev/null +++ b/src/step_definitions/generators.ts @@ -0,0 +1,7 @@ +import { When } from 'cucumber'; +import { transformers } from '../transformers'; +import variableStore from '../web/variable-store.helper'; + +When(/^I generate random "([^"]*)" as "([^"]*)"$/, (generator, variableName) => { + return transformers.transform(`g:${generator}`).then(result => variableStore.storeVariable(variableName, result)); +}); diff --git a/src/step_definitions/navigation.js b/src/step_definitions/navigation.js deleted file mode 100644 index 92aac10f..00000000 --- a/src/step_definitions/navigation.js +++ /dev/null @@ -1,32 +0,0 @@ -import { defineSupportCode } from 'cucumber'; - -defineSupportCode(function({ Then, Given }) { - Given(/^I visit the "([^"]*)" page$/, function(pageName) { - expect(browser.page[pageName]).to.not.be.undefined; - - this.currentPage = browser.page[pageName]; - - return this.currentPage.visit(); - }); - - Given(/^I visit the "([^"]*)" page with parameters:$/, function(pageName, data) { - expect(browser.page[pageName]).to.not.be.undefined; - - this.currentPage = browser.page[pageName]; - - return this.currentPage.visitWithParameters(data); - }); - - Then(/^the "([^"]*)" page is displayed$/, function(pageName) { - const self = this; - - return browser.page[pageName].isOn().then(checkResult => { - if (typeof checkResult !== 'object') { - return Promise.reject('Check result must be an object!!!'); - } - - self.currentPage = browser.page[pageName]; - self.urlParameters = checkResult.parameters; - }); - }); -}); diff --git a/src/step_definitions/navigation.ts b/src/step_definitions/navigation.ts new file mode 100644 index 00000000..e2b69001 --- /dev/null +++ b/src/step_definitions/navigation.ts @@ -0,0 +1,30 @@ +import { Then, Given } from 'cucumber'; + +Given(/^I visit the "([^"]*)" page$/, function(pageName) { + expect(browser.page[pageName]).toBeDefined(); + + this.currentPage = browser.page[pageName]; + + return this.currentPage.visit(); +}); + +Given(/^I visit the "([^"]*)" page with parameters:$/, function(pageName, data) { + expect(browser.page[pageName]).toBeDefined(); + + this.currentPage = browser.page[pageName]; + + return this.currentPage.visitWithParameters(data); +}); + +Then(/^the "([^"]*)" page is displayed$/, function(pageName) { + const self = this; + + return browser.page[pageName].isOn().then(checkResult => { + if (typeof checkResult !== 'object') { + return Promise.reject('Check result must be an object!!!'); + } + + self.currentPage = browser.page[pageName]; + self.urlParameters = checkResult.parameters; + }); +}); diff --git a/src/step_definitions/performance.js b/src/step_definitions/performance.js deleted file mode 100644 index 1a4142c5..00000000 --- a/src/step_definitions/performance.js +++ /dev/null @@ -1,82 +0,0 @@ -import { defineSupportCode } from 'cucumber'; -import chalk from 'chalk'; -import config from '../core/config.helper'; -import { create as createAnalyser } from '../web/performance/time-to-first-byte-analyser.helper'; - -const analyser = createAnalyser(); -const Browsermob = require('browsermob-proxy').Proxy; -const fs = require('fs'); -let proxy; - -defineSupportCode(function({ When, Then }) { - When(/^I start performance monitor mode$/, function() { - proxy = new Browsermob({ - port: config.browserMob.serverPort, - }); - - let proxyReady = false; - proxy.start(config.browserMob.port, err => { - if (!err) { - proxy.startHAR(config.browserMob.port, 'test', true, true, () => { - proxyReady = true; - }); - } else { - console.error(err); - } - }); - - browser.driver.wait(() => { - return proxyReady; - }); - }); - - When(/^I save performance report file as "([^"]*)"$/, function(fileName) { - const uniqueFileName = `${fileName}-${Date.now()}.har`; - let proxyDone = false; - - proxy.getHAR(config.browserMob.port, (err, resp) => { - if (!err) { - console.log(`har saved at ${uniqueFileName}`); - fs.writeFileSync(`reports/performance/${uniqueFileName}`, resp, 'utf8'); - } else { - console.err('Error getting HAR file: ' + err); - } - proxy.stop(config.browserMob.port, () => { - proxyDone = true; - }); - }); - - return browser.driver.wait(() => { - this.performanceReportFile = uniqueFileName; - return proxyDone; - }); - }); - - Then(/^the requests should take a maximum of "([^"]*)" milliseconds$/, function(maxTiming) { - try { - const slowRequests = analyser.checkTiming(this.performanceReportFile, parseFloat(maxTiming)); - - if (slowRequests.length > 0) { - slowRequests.forEach(({ url, ttfb }) => { - console.log( - chalk.white.bgRed( - '\r\n', - 'Slow request:', - '\r\n', - `URL: ${url}`, - '\r\n', - `TTFB: ${ttfb.toFixed(2)} ms`, - '\r\n' - ) - ); - }); - - return Promise.reject('TTFB value is too big! Details available above.'); - } - - return Promise.resolve(); - } catch (err) { - return Promise.reject(err); - } - }); -}); diff --git a/src/step_definitions/performance.ts b/src/step_definitions/performance.ts new file mode 100644 index 00000000..9fb7e5af --- /dev/null +++ b/src/step_definitions/performance.ts @@ -0,0 +1,80 @@ +import chalk from 'chalk'; +import { When, Then } from 'cucumber'; +import config from '../core/config.helper'; +import { create as createAnalyser } from '../web/performance/time-to-first-byte-analyser.helper'; +import * as fs from 'fs'; +import { Proxy as Browsermob } from 'browsermob-proxy'; + +const analyser = createAnalyser(); +let proxy; + +When(/^I start performance monitor mode$/, () => { + proxy = new Browsermob({ + port: config.browserMob.serverPort, + }); + + let proxyReady = false; + proxy.start(config.browserMob.port, err => { + if (!err) { + proxy.startHAR(config.browserMob.port, 'test', true, true, () => { + proxyReady = true; + }); + } else { + console.error(err); + } + }); + + browser.driver.wait(() => { + return proxyReady; + }); +}); + +When(/^I save performance report file as "([^"]*)"$/, function(fileName) { + const uniqueFileName = `${fileName}-${Date.now()}.har`; + let proxyDone = false; + + proxy.getHAR(config.browserMob.port, (err, resp) => { + if (!err) { + console.log(`har saved at ${uniqueFileName}`); + fs.writeFileSync(`reports/performance/${uniqueFileName}`, resp, 'utf8'); + } else { + console.err('Error getting HAR file: ' + err); + } + proxy.stop(config.browserMob.port, () => { + proxyDone = true; + }); + }); + + return browser.driver.wait(() => { + this.performanceReportFile = uniqueFileName; + return proxyDone; + }); +}); + +Then(/^the requests should take a maximum of "([^"]*)" milliseconds$/, function(maxTiming) { + try { + const slowRequests = analyser.checkTiming(this.performanceReportFile, parseFloat(maxTiming)); + + if (slowRequests.length > 0) { + slowRequests.forEach(({ url, ttfb }) => { + console.log( + chalk.white.bgRed( + '\r\n', + 'Slow request:', + '\r\n', + `URL: ${url}`, + '\r\n', + `TTFB: ${ttfb.toFixed(2)} ms`, + '\r\n' + ) + ); + }); + + return Promise.reject('TTFB value is too big! Details available above.'); + } + + return Promise.resolve(); + } catch (err) { + return Promise.reject(err); + } +}); diff --git a/src/step_definitions/tabs.js b/src/step_definitions/tabs.js deleted file mode 100644 index b6482483..00000000 --- a/src/step_definitions/tabs.js +++ /dev/null @@ -1,14 +0,0 @@ -const { defineSupportCode } = require('cucumber'); - -defineSupportCode(({ When }) => { - When(/^I switch to window number "([^"]*)" of a browser$/, function(tabNumber) { - return browser.getAllWindowHandles().then(handles => browser.switchTo().window(handles[tabNumber - 1])); - }); - - When(/^I close the current browser tab$/, function() { - return browser - .close() - .then(() => browser.getAllWindowHandles()) - .then(tabs => browser.switchTo().window(tabs[0])); - }); -}); diff --git a/src/step_definitions/tabs.ts b/src/step_definitions/tabs.ts new file mode 100644 index 00000000..d841313f --- /dev/null +++ b/src/step_definitions/tabs.ts @@ -0,0 +1,12 @@ +import { When } from 'cucumber'; + +When(/^I switch to window number "([^"]*)" of a browser$/, tabNumber => { + return browser.getAllWindowHandles().then(handles => browser.switchTo().window(handles[tabNumber - 1])); +}); + +When(/^I close the current browser tab$/, () => { + return browser + .close() + .then(() => browser.getAllWindowHandles()) + .then(tabs => browser.switchTo().window(tabs[0])); +}); diff --git a/src/tests/dictionaries/fake-dictionary.js b/src/tests/dictionaries/fake-dictionary.js deleted file mode 100644 index 803b1b66..00000000 --- a/src/tests/dictionaries/fake-dictionary.js +++ /dev/null @@ -1,19 +0,0 @@ -class FakeDictionary { - constructor() { - this.values = { - 'some-key': 'some-value', - }; - - this.name = 'fake-dictionary'; - } - - isSatisfiedBy(name) { - return this.name === name; - } - - getMappedValue(key) { - return this.values[key]; - } -} - -module.exports = new FakeDictionary(); diff --git a/src/tests/dictionaries/fake-dictionary.ts b/src/tests/dictionaries/fake-dictionary.ts new file mode 100644 index 00000000..0af92260 --- /dev/null +++ b/src/tests/dictionaries/fake-dictionary.ts @@ -0,0 +1,11 @@ +import BaseDictionary from '../../dictionaries/base'; + +class FakeDictionary extends BaseDictionary { + constructor() { + super('fake-dictionary', { + 'some-key': 'some-value', + }); + } +} + +export = new FakeDictionary(); diff --git a/src/tests/init.js b/src/tests/init.ts similarity index 76% rename from src/tests/init.js rename to src/tests/init.ts index fb07aff7..b10a1040 100644 --- a/src/tests/init.js +++ b/src/tests/init.ts @@ -1,4 +1,4 @@ -const protractor = require('protractor'); +import * as protractor from 'protractor'; // set global by to allow recursive call on src directory global.by = new protractor.ProtractorBy(); diff --git a/src/transformers/index.js b/src/transformers/index.ts similarity index 100% rename from src/transformers/index.js rename to src/transformers/index.ts diff --git a/src/transformers/transformer.interface.ts b/src/transformers/transformer.interface.ts new file mode 100644 index 00000000..296b2f77 --- /dev/null +++ b/src/transformers/transformer.interface.ts @@ -0,0 +1,4 @@ +export interface Transformer { + isSatisfiedBy(prefix: string): boolean; + transform(transform: string): any; +} diff --git a/src/transformers/transformer/dictionary.transformer.js b/src/transformers/transformer/dictionary.transformer.js deleted file mode 100644 index db29414a..00000000 --- a/src/transformers/transformer/dictionary.transformer.js +++ /dev/null @@ -1,17 +0,0 @@ -import { dictionaries as dicts } from '../../dictionaries'; - -class DictionaryTransformer { - constructor(dictionaries) { - this.dictionaries = dictionaries; - } - - isSatisfiedBy(prefix) { - return prefix === 'd:'; - } - - transform(value) { - const splittedValue = value.split(':'); - return this.dictionaries.getMappedValue(splittedValue[0], splittedValue[1]); - } -} -export const createDictionaryTransformer = (dictionaries = dicts) => new DictionaryTransformer(dictionaries); diff --git a/src/transformers/transformer/dictionary.transformer.spec.js b/src/transformers/transformer/dictionary.transformer.spec.ts similarity index 91% rename from src/transformers/transformer/dictionary.transformer.spec.js rename to src/transformers/transformer/dictionary.transformer.spec.ts index 5dec8de5..367f22f7 100644 --- a/src/transformers/transformer/dictionary.transformer.spec.js +++ b/src/transformers/transformer/dictionary.transformer.spec.ts @@ -1,6 +1,6 @@ import { create as createDictionaries } from '../../dictionaries/dictionaries'; import { createDictionaryTransformer } from './dictionary.transformer'; -import fakeDictionary from '../../tests/dictionaries/fake-dictionary'; +import fakeDictionary = require('../../tests/dictionaries/fake-dictionary'); const dictionaries = createDictionaries(); diff --git a/src/transformers/transformer/dictionary.transformer.ts b/src/transformers/transformer/dictionary.transformer.ts new file mode 100644 index 00000000..75629ef4 --- /dev/null +++ b/src/transformers/transformer/dictionary.transformer.ts @@ -0,0 +1,16 @@ +import { dictionaries as dicts, Dictionaries } from '../../dictionaries'; +import { Transformer } from '../transformer.interface'; + +class DictionaryTransformer implements Transformer { + constructor(private dictionaries: Dictionaries) {} + + public isSatisfiedBy(prefix) { + return prefix === 'd:'; + } + + public transform(value) { + const splittedValue = value.split(':'); + return this.dictionaries.getMappedValue(splittedValue[0], splittedValue[1]); + } +} +export const createDictionaryTransformer = (dictionaries = dicts) => new DictionaryTransformer(dictionaries); diff --git a/src/transformers/transformer/generator.transformer.spec.js b/src/transformers/transformer/generator.transformer.spec.ts similarity index 95% rename from src/transformers/transformer/generator.transformer.spec.js rename to src/transformers/transformer/generator.transformer.spec.ts index 8786d986..205c8397 100644 --- a/src/transformers/transformer/generator.transformer.spec.js +++ b/src/transformers/transformer/generator.transformer.spec.ts @@ -14,7 +14,7 @@ describe('Generator transformer', () => { }); it('returns generated value ', () => { - const mockedGenerators = { + const mockedGenerators: any = { generate: value => 'my-generated-value', }; const transformer = createGeneratorTransformer(mockedGenerators); diff --git a/src/transformers/transformer/generator.transformer.js b/src/transformers/transformer/generator.transformer.ts similarity index 52% rename from src/transformers/transformer/generator.transformer.js rename to src/transformers/transformer/generator.transformer.ts index 2775d9d8..7c7e244d 100644 --- a/src/transformers/transformer/generator.transformer.js +++ b/src/transformers/transformer/generator.transformer.ts @@ -1,15 +1,14 @@ -import { generators } from '../../generators'; +import { generators, Generators } from '../../generators'; +import { Transformer } from '../transformer.interface'; -class GeneratorTransformer { - constructor(generator) { - this.generator = generator; - } +class GeneratorTransformer implements Transformer { + constructor(public generator: Generators) {} - isSatisfiedBy(prefix) { + public isSatisfiedBy(prefix) { return prefix === 'g:'; } - transform(value) { + public transform(value) { const splittedValues = value.split(':'); const generatorName = splittedValues[0]; diff --git a/src/transformers/transformer/variable-store.transformer.js b/src/transformers/transformer/variable-store.transformer.js deleted file mode 100644 index 0d759e9d..00000000 --- a/src/transformers/transformer/variable-store.transformer.js +++ /dev/null @@ -1,16 +0,0 @@ -import store from '../../web/variable-store.helper'; - -class VariableStoreTransformer { - constructor(variableStore) { - this.variableStore = variableStore; - } - - isSatisfiedBy(prefix) { - return prefix === 'v:'; - } - - transform(value) { - return this.variableStore.getVariableValue(value); - } -} -export const createVariableStoreTransformer = (variableStore = store) => new VariableStoreTransformer(variableStore); diff --git a/src/transformers/transformer/variable-store.transformer.spec.js b/src/transformers/transformer/variable-store.transformer.spec.ts similarity index 96% rename from src/transformers/transformer/variable-store.transformer.spec.js rename to src/transformers/transformer/variable-store.transformer.spec.ts index 9dd26043..239e0d60 100644 --- a/src/transformers/transformer/variable-store.transformer.spec.js +++ b/src/transformers/transformer/variable-store.transformer.spec.ts @@ -2,7 +2,7 @@ import { createVariableStoreTransformer } from './variable-store.transformer'; describe('Variable store transformer', () => { it('returns replaced text', () => { - const fakeValue = { + const fakeValue: any = { getVariableValue: () => 'expected value', }; const transformer = createVariableStoreTransformer(fakeValue); diff --git a/src/transformers/transformer/variable-store.transformer.ts b/src/transformers/transformer/variable-store.transformer.ts new file mode 100644 index 00000000..eeff5d71 --- /dev/null +++ b/src/transformers/transformer/variable-store.transformer.ts @@ -0,0 +1,16 @@ +import store from '../../web/variable-store.helper'; +import { VariableStore } from '../../web/variable-store.helper'; +import { Transformer } from '../transformer.interface'; + +class VariableStoreTransformer implements Transformer { + constructor(private variableStore: VariableStore) {} + + public isSatisfiedBy(prefix) { + return prefix === 'v:'; + } + + public transform(value) { + return this.variableStore.getVariableValue(value); + } +} +export const createVariableStoreTransformer = (variableStore = store) => new VariableStoreTransformer(variableStore); diff --git a/src/transformers/transformers.spec.js b/src/transformers/transformers.spec.ts similarity index 96% rename from src/transformers/transformers.spec.js rename to src/transformers/transformers.spec.ts index 61099931..0ef29bf6 100644 --- a/src/transformers/transformers.spec.js +++ b/src/transformers/transformers.spec.ts @@ -10,7 +10,7 @@ describe('Value transformers', () => { }); it('returns transformed value when expected transformer has been found', () => { - const fakeTransformer = { + const fakeTransformer: any = { isSatisfiedBy: prefix => prefix === 'v:', transform: value => { expect(value).toEqual('value'); diff --git a/src/transformers/transformers.js b/src/transformers/transformers.ts similarity index 74% rename from src/transformers/transformers.js rename to src/transformers/transformers.ts index 56974379..10c646ea 100644 --- a/src/transformers/transformers.js +++ b/src/transformers/transformers.ts @@ -1,13 +1,12 @@ -import { createVariableStoreTransformer } from './transformer/variable-store.transformer'; import { createDictionaryTransformer } from './transformer/dictionary.transformer'; import { createGeneratorTransformer } from './transformer/generator.transformer'; +import { createVariableStoreTransformer } from './transformer/variable-store.transformer'; +import { Transformer } from './transformer.interface'; class Transformers { - constructor(transformers) { - this.availableTransformers = transformers; - } + constructor(private availableTransformers: Transformer[]) {} - transform(value) { + public transform(value: string): any { const transformer = this.findTransformer(value.substr(0, 2)); if (transformer === undefined) { @@ -17,11 +16,11 @@ class Transformers { return transformer.transform(value.substr(2)); } - findTransformer(prefix) { + public findTransformer(prefix: string): Transformer { return this.availableTransformers.find(transformer => transformer.isSatisfiedBy(prefix)); } - addTransformer(transformer) { + public addTransformer(transformer: Transformer): void { this.availableTransformers.push(transformer); } } diff --git a/src/web/browsers/browsers-config.helper.js b/src/web/browsers/browsers-config.helper.ts similarity index 69% rename from src/web/browsers/browsers-config.helper.js rename to src/web/browsers/browsers-config.helper.ts index 3de35093..290b05b9 100644 --- a/src/web/browsers/browsers-config.helper.js +++ b/src/web/browsers/browsers-config.helper.ts @@ -1,11 +1,11 @@ -import glob from 'glob'; -import path from 'path'; -const { createFirefoxProfile } = require('./create-firefox-profile.helper'); -const { safariBrowserConfigurator } = require('./safari-browser-configurator.helper'); -const { prepareBrowserInstance } = require('../parallel/prepare-browser-instance-specs.helper'); -const { chunkSpecs } = require('../parallel/chunk-specs.helper'); - -const getDefaultBrowsersConfigs = config => { +import * as glob from 'glob'; +import * as path from 'path'; +import { createFirefoxProfile } from './create-firefox-profile.helper'; +import { safariBrowserConfigurator } from './safari-browser-configurator.helper'; +import { prepareBrowserInstance } from '../parallel/prepare-browser-instance-specs.helper'; +import { chunkSpecs } from '../parallel/chunk-specs.helper'; + +const getDefaultBrowsersConfigs = (config): any => { const chromeConfig = { browserName: 'chrome', chromeOptions: { @@ -36,14 +36,19 @@ const getDefaultBrowsersConfigs = config => { browserName: 'safari', }; + const ieConfig = { + browserName: 'internet explorer', + }; + return { chromeConfig, firefoxConfig, safariConfig, + ieConfig, }; }; -const getExtendedBrowsersConfigs = config => { +const getExtendedBrowsersConfigs = (config, commandArgs): any => { const configs = getDefaultBrowsersConfigs(config); if (config.performance) { @@ -66,7 +71,10 @@ const getExtendedBrowsersConfigs = config => { ]; } - if (config.headless) { + if ( + (config.headless && commandArgs.headless === undefined) || + (commandArgs.headless && commandArgs.headless !== 'false') + ) { configs.chromeConfig.chromeOptions.args = [ ...configs.chromeConfig.chromeOptions.args, '--headless', @@ -83,8 +91,8 @@ const getExtendedBrowsersConfigs = config => { return configs; }; -const browsersConfiguration = (config, commandArgs) => { - return async () => { +export const browsersConfiguration = (config, commandArgs): any => { + return () => { const browsersSettings = []; const browserConfigs = getExtendedBrowsersConfigs(config, commandArgs); const allSpecs = glob.sync(config.features.map(file => path.join(config.projectPath, file, '**/*.feature'))[0]); @@ -108,8 +116,12 @@ const browsersConfiguration = (config, commandArgs) => { } }; + if (commandArgs.browserstack) { + return Promise.resolve([prepareBrowserInstance(config.browserstack.capabilities, allSpecs)]); + } + if (commandArgs.firefox) { - browserConfigs.firefoxConfig.firefox_profile = await createFirefoxProfile(config); + browserConfigs.firefoxConfig.firefox_profile = createFirefoxProfile(config); pushPreparedBrowserInstance('firefoxConfig'); } @@ -118,7 +130,14 @@ const browsersConfiguration = (config, commandArgs) => { pushPreparedBrowserInstance('safariConfig'); } - if (commandArgs.chrome || (commandArgs.firefox === undefined && commandArgs.safari === undefined)) { + if (commandArgs.ie) { + pushPreparedBrowserInstance('ieConfig'); + } + + if ( + commandArgs.chrome || + (commandArgs.firefox === undefined && commandArgs.safari === undefined && commandArgs.ie === undefined) + ) { pushPreparedBrowserInstance('chromeConfig'); } @@ -126,4 +145,6 @@ const browsersConfiguration = (config, commandArgs) => { }; }; -module.exports = browsersConfiguration; +export const setSeleniumAddress = (commandArgs, config): string => { + return commandArgs.browserstack ? config.browserstack.seleniumAddress : ''; +}; diff --git a/src/web/browsers/browserstack-config.helper.ts b/src/web/browsers/browserstack-config.helper.ts new file mode 100644 index 00000000..15ed1447 --- /dev/null +++ b/src/web/browsers/browserstack-config.helper.ts @@ -0,0 +1,37 @@ +import * as browserstack from 'browserstack-local'; +import chalk from 'chalk'; +import * as shell from 'shelljs'; +import config from '../../core/config.helper'; + +export const disconnectBrowserstack = (browserstackEnabled: boolean) => { + if (browserstackEnabled && config.browserstack) { + const browserstackPid = shell.exec(`lsof -t -i :${config.browserstack.defaultPort}`).stdout; + + if (browserstackPid.length > 0) { + return shell.exec(`kill -9 ${browserstackPid}`); + } + } + + return Promise.resolve(); +}; + +export const connectBrowserstack = (browserstackKey: string) => { + console.log( + chalk.black.bgYellow( + 'Keep in mind that Browserstack capabilities cannot be used with the local. Check the documentation for more information!' + ) + ); + + disconnectBrowserstack(true); + + return new Promise((resolve, reject) => { + const bsLocal = new browserstack.Local(); + bsLocal.start({ key: browserstackKey }, error => { + if (error) { + return reject(error); + } + console.log('Connected to the Browsertack Selenium server! Now testing...'); + resolve(); + }); + }); +}; diff --git a/src/web/browsers/create-firefox-profile.helper.js b/src/web/browsers/create-firefox-profile.helper.ts similarity index 99% rename from src/web/browsers/create-firefox-profile.helper.js rename to src/web/browsers/create-firefox-profile.helper.ts index d7cc7d94..a895eae5 100644 --- a/src/web/browsers/create-firefox-profile.helper.js +++ b/src/web/browsers/create-firefox-profile.helper.ts @@ -1,5 +1,5 @@ -const firefox = require('selenium-webdriver/firefox'); -import path from 'path'; +import * as firefox from 'selenium-webdriver/firefox'; +import * as path from 'path'; export const createFirefoxProfile = config => { const profile = new firefox.Profile(); @@ -11,12 +11,10 @@ export const createFirefoxProfile = config => { profile.setPreference('browser.helperApps.alwaysAsk.force', false); profile.setPreference('browser.download.manager.showWhenStarting', false); profile.setPreference('browser.download.manager.showAlertOnComplete', false); - /* eslint-disable max-len */ profile.setPreference( 'browser.helperApps.neverAsk.saveToDisk', 'application/vnd.hzn-3d-crossword;video/3gpp;video/3gpp2;application/vnd.mseq;application/vnd.3m.post-it-notes;application/vnd.3gpp.pic-bw-large;application/vnd.3gpp.pic-bw-small;application/vnd.3gpp.pic-bw-var;application/vnd.3gp2.tcap;application/x-7z-compressed;application/x-abiword;application/x-ace-compressed;application/vnd.americandynamics.acc;application/vnd.acucobol;application/vnd.acucorp;audio/adpcm;application/x-authorware-bin;application/x-athorware-map;application/x-authorware-seg;application/vnd.adobe.air-application-installer-package+zip;application/x-shockwave-flash;application/vnd.adobe.fxp;application/pdf;application/vnd.cups-ppd;application/x-director;applicaion/vnd.adobe.xdp+xml;application/vnd.adobe.xfdf;audio/x-aac;application/vnd.ahead.space;application/vnd.airzip.filesecure.azf;application/vnd.airzip.filesecure.azs;application/vnd.amazon.ebook;application/vnd.amiga.ami;applicatin/andrew-inset;application/vnd.android.package-archive;application/vnd.anser-web-certificate-issue-initiation;application/vnd.anser-web-funds-transfer-initiation;application/vnd.antix.game-component;application/vnd.apple.installe+xml;application/applixware;application/vnd.hhe.lesson-player;application/vnd.aristanetworks.swi;text/x-asm;application/atomcat+xml;application/atomsvc+xml;application/atom+xml;application/pkix-attr-cert;audio/x-aiff;video/x-msvieo;application/vnd.audiograph;image/vnd.dxf;model/vnd.dwf;text/plain-bas;application/x-bcpio;application/octet-stream;image/bmp;application/x-bittorrent;application/vnd.rim.cod;application/vnd.blueice.multipass;application/vnd.bm;application/x-sh;image/prs.btif;application/vnd.businessobjects;application/x-bzip;application/x-bzip2;application/x-csh;text/x-c;application/vnd.chemdraw+xml;text/css;chemical/x-cdx;chemical/x-cml;chemical/x-csml;application/vn.contact.cmsg;application/vnd.claymore;application/vnd.clonk.c4group;image/vnd.dvb.subtitle;application/cdmi-capability;application/cdmi-container;application/cdmi-domain;application/cdmi-object;application/cdmi-queue;applicationvnd.cluetrust.cartomobile-config;application/vnd.cluetrust.cartomobile-config-pkg;image/x-cmu-raster;model/vnd.collada+xml;text/csv;application/mac-compactpro;application/vnd.wap.wmlc;image/cgm;x-conference/x-cooltalk;image/x-cmx;application/vnd.xara;application/vnd.cosmocaller;application/x-cpio;application/vnd.crick.clicker;application/vnd.crick.clicker.keyboard;application/vnd.crick.clicker.palette;application/vnd.crick.clicker.template;application/vn.crick.clicker.wordbank;application/vnd.criticaltools.wbs+xml;application/vnd.rig.cryptonote;chemical/x-cif;chemical/x-cmdf;application/cu-seeme;application/prs.cww;text/vnd.curl;text/vnd.curl.dcurl;text/vnd.curl.mcurl;text/vnd.crl.scurl;application/vnd.curl.car;application/vnd.curl.pcurl;application/vnd.yellowriver-custom-menu;application/dssc+der;application/dssc+xml;application/x-debian-package;audio/vnd.dece.audio;image/vnd.dece.graphic;video/vnd.dec.hd;video/vnd.dece.mobile;video/vnd.uvvu.mp4;video/vnd.dece.pd;video/vnd.dece.sd;video/vnd.dece.video;application/x-dvi;application/vnd.fdsn.seed;application/x-dtbook+xml;application/x-dtbresource+xml;application/vnd.dvb.ait;applcation/vnd.dvb.service;audio/vnd.digital-winds;image/vnd.djvu;application/xml-dtd;application/vnd.dolby.mlp;application/x-doom;application/vnd.dpgraph;audio/vnd.dra;application/vnd.dreamfactory;audio/vnd.dts;audio/vnd.dts.hd;imag/vnd.dwg;application/vnd.dynageo;application/ecmascript;application/vnd.ecowin.chart;image/vnd.fujixerox.edmics-mmr;image/vnd.fujixerox.edmics-rlc;application/exi;application/vnd.proteus.magazine;application/epub+zip;message/rfc82;application/vnd.enliven;application/vnd.is-xpr;image/vnd.xiff;application/vnd.xfdl;application/emma+xml;application/vnd.ezpix-album;application/vnd.ezpix-package;image/vnd.fst;video/vnd.fvt;image/vnd.fastbidsheet;application/vn.denovo.fcselayout-link;video/x-f4v;video/x-flv;image/vnd.fpx;image/vnd.net-fpx;text/vnd.fmi.flexstor;video/x-fli;application/vnd.fluxtime.clip;application/vnd.fdf;text/x-fortran;application/vnd.mif;application/vnd.framemaker;imae/x-freehand;application/vnd.fsc.weblaunch;application/vnd.frogans.fnc;application/vnd.frogans.ltf;application/vnd.fujixerox.ddd;application/vnd.fujixerox.docuworks;application/vnd.fujixerox.docuworks.binder;application/vnd.fujitu.oasys;application/vnd.fujitsu.oasys2;application/vnd.fujitsu.oasys3;application/vnd.fujitsu.oasysgp;application/vnd.fujitsu.oasysprs;application/x-futuresplash;application/vnd.fuzzysheet;image/g3fax;application/vnd.gmx;model/vn.gtw;application/vnd.genomatix.tuxedo;application/vnd.geogebra.file;application/vnd.geogebra.tool;model/vnd.gdl;application/vnd.geometry-explorer;application/vnd.geonext;application/vnd.geoplan;application/vnd.geospace;applicatio/x-font-ghostscript;application/x-font-bdf;application/x-gtar;application/x-texinfo;application/x-gnumeric;application/vnd.google-earth.kml+xml;application/vnd.google-earth.kmz;application/vnd.grafeq;image/gif;text/vnd.graphviz;aplication/vnd.groove-account;application/vnd.groove-help;application/vnd.groove-identity-message;application/vnd.groove-injector;application/vnd.groove-tool-message;application/vnd.groove-tool-template;application/vnd.groove-vcar;video/h261;video/h263;video/h264;application/vnd.hp-hpid;application/vnd.hp-hps;application/x-hdf;audio/vnd.rip;application/vnd.hbci;application/vnd.hp-jlyt;application/vnd.hp-pcl;application/vnd.hp-hpgl;application/vnd.yamaha.h-script;application/vnd.yamaha.hv-dic;application/vnd.yamaha.hv-voice;application/vnd.hydrostatix.sof-data;application/hyperstudio;application/vnd.hal+xml;text/html;application/vnd.ibm.rights-management;application/vnd.ibm.securecontainer;text/calendar;application/vnd.iccprofile;image/x-icon;application/vnd.igloader;image/ief;application/vnd.immervision-ivp;application/vnd.immervision-ivu;application/reginfo+xml;text/vnd.in3d.3dml;text/vnd.in3d.spot;mode/iges;application/vnd.intergeo;application/vnd.cinderella;application/vnd.intercon.formnet;application/vnd.isac.fcs;application/ipfix;application/pkix-cert;application/pkixcmp;application/pkix-crl;application/pkix-pkipath;applicaion/vnd.insors.igm;application/vnd.ipunplugged.rcprofile;application/vnd.irepository.package+xml;text/vnd.sun.j2me.app-descriptor;application/java-archive;application/java-vm;application/x-java-jnlp-file;application/java-serializd-object;text/x-java-source,java;application/javascript;application/json;application/vnd.joost.joda-archive;video/jpm;image/jpeg;video/jpeg;application/vnd.kahootz;application/vnd.chipnuts.karaoke-mmd;application/vnd.kde.karbon;aplication/vnd.kde.kchart;application/vnd.kde.kformula;application/vnd.kde.kivio;application/vnd.kde.kontour;application/vnd.kde.kpresenter;application/vnd.kde.kspread;application/vnd.kde.kword;application/vnd.kenameaapp;applicatin/vnd.kidspiration;application/vnd.kinar;application/vnd.kodak-descriptor;application/vnd.las.las+xml;application/x-latex;application/vnd.llamagraphics.life-balance.desktop;application/vnd.llamagraphics.life-balance.exchange+xml;application/vnd.jam;application/vnd.lotus-1-2-3;application/vnd.lotus-approach;application/vnd.lotus-freelance;application/vnd.lotus-notes;application/vnd.lotus-organizer;application/vnd.lotus-screencam;application/vnd.lotus-wordro;audio/vnd.lucent.voice;audio/x-mpegurl;video/x-m4v;application/mac-binhex40;application/vnd.macports.portpkg;application/vnd.osgeo.mapguide.package;application/marc;application/marcxml+xml;application/mxf;application/vnd.wolfrm.player;application/mathematica;application/mathml+xml;application/mbox;application/vnd.medcalcdata;application/mediaservercontrol+xml;application/vnd.mediastation.cdkey;application/vnd.mfer;application/vnd.mfmp;model/mesh;appliation/mads+xml;application/mets+xml;application/mods+xml;application/metalink4+xml;application/vnd.ms-powerpoint.template.macroenabled.12;application/vnd.ms-word.document.macroenabled.12;application/vnd.ms-word.template.macroenabed.12;application/vnd.mcd;application/vnd.micrografx.flo;application/vnd.micrografx.igx;application/vnd.eszigno3+xml;application/x-msaccess;video/x-ms-asf;application/x-msdownload;application/vnd.ms-artgalry;application/vnd.ms-ca-compressed;application/vnd.ms-ims;application/x-ms-application;application/x-msclip;image/vnd.ms-modi;application/vnd.ms-fontobject;application/vnd.ms-excel;application/vnd.ms-excel.addin.macroenabled.12;application/vnd.ms-excelsheet.binary.macroenabled.12;application/vnd.ms-excel.template.macroenabled.12;application/vnd.ms-excel.sheet.macroenabled.12;application/vnd.ms-htmlhelp;application/x-mscardfile;application/vnd.ms-lrm;application/x-msmediaview;aplication/x-msmoney;application/vnd.openxmlformats-officedocument.presentationml.presentation;application/vnd.openxmlformats-officedocument.presentationml.slide;application/vnd.openxmlformats-officedocument.presentationml.slideshw;application/vnd.openxmlformats-officedocument.presentationml.template;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;application/vnd.openxmlformats-officedocument.spreadsheetml.template;application/vnd.openxmformats-officedocument.wordprocessingml.document;application/vnd.openxmlformats-officedocument.wordprocessingml.template;application/x-msbinder;application/vnd.ms-officetheme;application/onenote;audio/vnd.ms-playready.media.pya;vdeo/vnd.ms-playready.media.pyv;application/vnd.ms-powerpoint;application/vnd.ms-powerpoint.addin.macroenabled.12;application/vnd.ms-powerpoint.slide.macroenabled.12;application/vnd.ms-powerpoint.presentation.macroenabled.12;appliation/vnd.ms-powerpoint.slideshow.macroenabled.12;application/vnd.ms-project;application/x-mspublisher;application/x-msschedule;application/x-silverlight-app;application/vnd.ms-pki.stl;application/vnd.ms-pki.seccat;application/vn.visio;video/x-ms-wm;audio/x-ms-wma;audio/x-ms-wax;video/x-ms-wmx;application/x-ms-wmd;application/vnd.ms-wpl;application/x-ms-wmz;video/x-ms-wmv;video/x-ms-wvx;application/x-msmetafile;application/x-msterminal;application/msword;application/x-mswrite;application/vnd.ms-works;application/x-ms-xbap;application/vnd.ms-xpsdocument;audio/midi;application/vnd.ibm.minipay;application/vnd.ibm.modcap;application/vnd.jcp.javame.midlet-rms;application/vnd.tmobile-ivetv;application/x-mobipocket-ebook;application/vnd.mobius.mbk;application/vnd.mobius.dis;application/vnd.mobius.plc;application/vnd.mobius.mqy;application/vnd.mobius.msl;application/vnd.mobius.txf;application/vnd.mobius.daf;tex/vnd.fly;application/vnd.mophun.certificate;application/vnd.mophun.application;video/mj2;audio/mpeg;video/vnd.mpegurl;video/mpeg;application/mp21;audio/mp4;video/mp4;application/mp4;application/vnd.apple.mpegurl;application/vnd.msician;application/vnd.muvee.style;application/xv+xml;application/vnd.nokia.n-gage.data;application/vnd.nokia.n-gage.symbian.install;application/x-dtbncx+xml;application/x-netcdf;application/vnd.neurolanguage.nlu;application/vnd.na;application/vnd.noblenet-directory;application/vnd.noblenet-sealer;application/vnd.noblenet-web;application/vnd.nokia.radio-preset;application/vnd.nokia.radio-presets;text/n3;application/vnd.novadigm.edm;application/vnd.novadim.edx;application/vnd.novadigm.ext;application/vnd.flographit;audio/vnd.nuera.ecelp4800;audio/vnd.nuera.ecelp7470;audio/vnd.nuera.ecelp9600;application/oda;application/ogg;audio/ogg;video/ogg;application/vnd.oma.dd2+xml;applicatin/vnd.oasis.opendocument.text-web;application/oebps-package+xml;application/vnd.intu.qbo;application/vnd.openofficeorg.extension;application/vnd.yamaha.openscoreformat;audio/webm;video/webm;application/vnd.oasis.opendocument.char;application/vnd.oasis.opendocument.chart-template;application/vnd.oasis.opendocument.database;application/vnd.oasis.opendocument.formula;application/vnd.oasis.opendocument.formula-template;application/vnd.oasis.opendocument.grapics;application/vnd.oasis.opendocument.graphics-template;application/vnd.oasis.opendocument.image;application/vnd.oasis.opendocument.image-template;application/vnd.oasis.opendocument.presentation;application/vnd.oasis.opendocumen.presentation-template;application/vnd.oasis.opendocument.spreadsheet;application/vnd.oasis.opendocument.spreadsheet-template;application/vnd.oasis.opendocument.text;application/vnd.oasis.opendocument.text-master;application/vnd.asis.opendocument.text-template;image/ktx;application/vnd.sun.xml.calc;application/vnd.sun.xml.calc.template;application/vnd.sun.xml.draw;application/vnd.sun.xml.draw.template;application/vnd.sun.xml.impress;application/vnd.sun.xl.impress.template;application/vnd.sun.xml.math;application/vnd.sun.xml.writer;application/vnd.sun.xml.writer.global;application/vnd.sun.xml.writer.template;application/x-font-otf;application/vnd.yamaha.openscoreformat.osfpvg+xml;application/vnd.osgi.dp;application/vnd.palm;text/x-pascal;application/vnd.pawaafile;application/vnd.hp-pclxl;application/vnd.picsel;image/x-pcx;image/vnd.adobe.photoshop;application/pics-rules;image/x-pict;application/x-chat;aplication/pkcs10;application/x-pkcs12;application/pkcs7-mime;application/pkcs7-signature;application/x-pkcs7-certreqresp;application/x-pkcs7-certificates;application/pkcs8;application/vnd.pocketlearn;image/x-portable-anymap;image/-portable-bitmap;application/x-font-pcf;application/font-tdpfr;application/x-chess-pgn;image/x-portable-graymap;image/png;image/x-portable-pixmap;application/pskc+xml;application/vnd.ctc-posml;application/postscript;application/xfont-type1;application/vnd.powerbuilder6;application/pgp-encrypted;application/pgp-signature;application/vnd.previewsystems.box;application/vnd.pvi.ptid1;application/pls+xml;application/vnd.pg.format;application/vnd.pg.osasli;tex/prs.lines.tag;application/x-font-linux-psf;application/vnd.publishare-delta-tree;application/vnd.pmi.widget;application/vnd.quark.quarkxpress;application/vnd.epson.esf;application/vnd.epson.msf;application/vnd.epson.ssf;applicaton/vnd.epson.quickanime;application/vnd.intu.qfx;video/quicktime;application/x-rar-compressed;audio/x-pn-realaudio;audio/x-pn-realaudio-plugin;application/rsd+xml;application/vnd.rn-realmedia;application/vnd.realvnc.bed;applicatin/vnd.recordare.musicxml;application/vnd.recordare.musicxml+xml;application/relax-ng-compact-syntax;application/vnd.data-vision.rdz;application/rdf+xml;application/vnd.cloanto.rp9;application/vnd.jisp;application/rtf;text/richtex;application/vnd.route66.link66+xml;application/rss+xml;application/shf+xml;application/vnd.sailingtracker.track;image/svg+xml;application/vnd.sus-calendar;application/sru+xml;application/set-payment-initiation;application/set-reistration-initiation;application/vnd.sema;application/vnd.semd;application/vnd.semf;application/vnd.seemail;application/x-font-snf;application/scvp-vp-request;application/scvp-vp-response;application/scvp-cv-request;application/svp-cv-response;application/sdp;text/x-setext;video/x-sgi-movie;application/vnd.shana.informed.formdata;application/vnd.shana.informed.formtemplate;application/vnd.shana.informed.interchange;application/vnd.shana.informed.package;application/thraud+xml;application/x-shar;image/x-rgb;application/vnd.epson.salt;application/vnd.accpac.simply.aso;application/vnd.accpac.simply.imp;application/vnd.simtech-mindmapper;application/vnd.commonspace;application/vnd.ymaha.smaf-audio;application/vnd.smaf;application/vnd.yamaha.smaf-phrase;application/vnd.smart.teacher;application/vnd.svd;application/sparql-query;application/sparql-results+xml;application/srgs;application/srgs+xml;application/sml+xml;application/vnd.koan;text/sgml;application/vnd.stardivision.calc;application/vnd.stardivision.draw;application/vnd.stardivision.impress;application/vnd.stardivision.math;application/vnd.stardivision.writer;application/vnd.tardivision.writer-global;application/vnd.stepmania.stepchart;application/x-stuffit;application/x-stuffitx;application/vnd.solent.sdkm+xml;application/vnd.olpc-sugar;audio/basic;application/vnd.wqd;application/vnd.symbian.install;application/smil+xml;application/vnd.syncml+xml;application/vnd.syncml.dm+wbxml;application/vnd.syncml.dm+xml;application/x-sv4cpio;application/x-sv4crc;application/sbml+xml;text/tab-separated-values;image/tiff;application/vnd.to.intent-module-archive;application/x-tar;application/x-tcl;application/x-tex;application/x-tex-tfm;application/tei+xml;text/plain;application/vnd.spotfire.dxp;application/vnd.spotfire.sfs;application/timestamped-data;applicationvnd.trid.tpt;application/vnd.triscape.mxs;text/troff;application/vnd.trueapp;application/x-font-ttf;text/turtle;application/vnd.umajin;application/vnd.uoml+xml;application/vnd.unity;application/vnd.ufdl;text/uri-list;application/nd.uiq.theme;application/x-ustar;text/x-uuencode;text/x-vcalendar;text/x-vcard;application/x-cdlink;application/vnd.vsf;model/vrml;application/vnd.vcx;model/vnd.mts;model/vnd.vtu;application/vnd.visionary;video/vnd.vivo;applicatin/ccxml+xml,;application/voicexml+xml;application/x-wais-source;application/vnd.wap.wbxml;image/vnd.wap.wbmp;audio/x-wav;application/davmount+xml;application/x-font-woff;application/wspolicy+xml;image/webp;application/vnd.webturb;application/widget;application/winhlp;text/vnd.wap.wml;text/vnd.wap.wmlscript;application/vnd.wap.wmlscriptc;application/vnd.wordperfect;application/vnd.wt.stf;application/wsdl+xml;image/x-xbitmap;image/x-xpixmap;image/x-xwindowump;application/x-x509-ca-cert;application/x-xfig;application/xhtml+xml;application/xml;application/xcap-diff+xml;application/xenc+xml;application/patch-ops-error+xml;application/resource-lists+xml;application/rls-services+xml;aplication/resource-lists-diff+xml;application/xslt+xml;application/xop+xml;application/x-xpinstall;application/xspf+xml;application/vnd.mozilla.xul+xml;chemical/x-xyz;text/yaml;application/yang;application/yin+xml;application/vnd.ul;application/zip;application/vnd.handheld-entertainment+xml;application/vnd.zzazz.deck+xml' ); - /* eslint-enable max-len */ profile.setPreference('pdfjs.disabled', true); return profile; diff --git a/src/web/browsers/get-browser-drivers.helper.ts b/src/web/browsers/get-browser-drivers.helper.ts new file mode 100644 index 00000000..b91f70a5 --- /dev/null +++ b/src/web/browsers/get-browser-drivers.helper.ts @@ -0,0 +1,16 @@ +import * as fs from 'fs'; + +export const getBrowsersDrivers = (commandArgs): string[] => { + const drivers: string[] = []; + const pathToDrivers = './node_modules/protractor/node_modules/webdriver-manager/selenium'; + + if (commandArgs.ie) { + // This is required as Protractor cannot find IEDriverServer. The other drivers does not require any additional configuration. + const availableDrivers = fs.readdirSync(pathToDrivers); + const IEDriver = availableDrivers.filter(item => item.match('IEDriverServer([0-9].[0-9]{3}.[0-9]).exe'))[0]; + + drivers.push(`-Dwebdriver.ie.driver=${pathToDrivers}/${IEDriver}`); + } + + return drivers; +}; diff --git a/src/web/browsers/safari-browser-configurator.helper.js b/src/web/browsers/safari-browser-configurator.helper.ts similarity index 72% rename from src/web/browsers/safari-browser-configurator.helper.js rename to src/web/browsers/safari-browser-configurator.helper.ts index 1169df29..30655ae0 100644 --- a/src/web/browsers/safari-browser-configurator.helper.js +++ b/src/web/browsers/safari-browser-configurator.helper.ts @@ -1,5 +1,5 @@ -import shell from 'shelljs'; -import path from 'path'; +import * as path from 'path'; +import * as shell from 'shelljs'; export const safariBrowserConfigurator = config => { shell.exec(`defaults write -app Safari DownloadsPath ${path.join(config.projectPath, config.downloads)}`); diff --git a/src/web/cucumber/config.js b/src/web/cucumber/config.js deleted file mode 100644 index 58d41f75..00000000 --- a/src/web/cucumber/config.js +++ /dev/null @@ -1,6 +0,0 @@ -import config from '../../core/config.helper'; -const { defineSupportCode } = require('cucumber'); - -defineSupportCode(function({ setDefaultTimeout }) { - setDefaultTimeout(Number(config.timeout) * 1000); -}); diff --git a/src/web/cucumber/config.ts b/src/web/cucumber/config.ts new file mode 100644 index 00000000..1b840481 --- /dev/null +++ b/src/web/cucumber/config.ts @@ -0,0 +1,4 @@ +import config from '../../core/config.helper'; +import { setDefaultTimeout } from 'cucumber'; + +setDefaultTimeout(Number(config.timeout) * 1000); diff --git a/src/web/cucumber/hooks.js b/src/web/cucumber/hooks.js deleted file mode 100644 index cc804c2c..00000000 --- a/src/web/cucumber/hooks.js +++ /dev/null @@ -1,133 +0,0 @@ -import config from '../../core/config.helper'; -import fs from 'fs'; -import path from 'path'; -import userProvider from '../user-provider.helper'; -import fixturesLoader from '../fixtures/fixtures-loader.helper'; -import parameters from '../parameters'; -import chalk from 'chalk'; -import { defineSupportCode } from 'cucumber'; -import variableStore from '../variable-store.helper'; - -const logRequestTime = timeStart => { - const timeDiff = process.hrtime(timeStart); - - console.log(chalk.black.bgYellow('Request took ' + (timeDiff[0] + timeDiff[1] / 1000000000) + ' seconds')); -}; - -const takeScreenshot = scenario => { - return browser.takeScreenshot().then( - function(base64png) { - scenario.attach(new Buffer(base64png, 'base64'), 'image/png'); - return Promise.resolve(); - }, - function() { - return Promise.resolve(); - } - ); -}; - -const clearCookiesAndLocalStorage = callback => { - let cookiesFunc = () => Promise.resolve(true); - - if (config.clearCookiesAfterScenario) { - cookiesFunc = () => protractor.browser.manage().deleteAllCookies(); - } - - let localStorageFunc = () => Promise.resolve(true); - if (config.clearLocalStorageAfterScenario) { - localStorageFunc = () => protractor.browser.executeScript('window.localStorage.clear();'); - } - - browser - .wait( - cookiesFunc() - .then(localStorageFunc) - .catch(() => false), - config.waitForPageTimeout * 1000 - ) - .then(() => { - protractor.browser.ignoreSynchronization = config.type === 'otherWeb'; - callback(); - }); -}; - -const clearDownload = callback => { - const files = fs.readdirSync(path.join(config.projectPath, config.downloads)).filter(function(file) { - return file !== '.gitkeep'; - }); - - for (let index = 0; index < files.length; index++) { - fs.unlinkSync(path.join(config.projectPath, config.downloads, files[index])); - } - - callback(); -}; - -defineSupportCode(({ After, Before }) => { - After(function(scenario, callback) { - if (scenario.result.status !== 'passed') { - takeScreenshot(this).then(() => { - clearCookiesAndLocalStorage(callback); - }); - } else { - clearCookiesAndLocalStorage(callback); - } - }); - - Before(function(scenario, callback) { - this.currentUser = null; - - if (typeof this.userProvider === 'undefined') { - this.userProvider = userProvider; - } - - variableStore.clearVariables(); - - callback(); - }); - - Before('@downloadClearBefore', function(scenario, callback) { - clearDownload(callback); - }); - - After('@downloadClearAfter', function(scenario, callback) { - clearDownload(callback); - }); - - Before('@reloadFixtures', function(scenario, callback) { - console.log(chalk.black.bgYellow('Reloading fixtures')); - - const timeStart = process.hrtime(); - - fixturesLoader - .reloadFixtures(parameters.getReloadFixturesEndpoint()) - .then(function(response) { - if (response.status === 200) { - console.log(chalk.black.bgGreen('Fixtures reloaded')); - } else { - console.log(chalk.black.bgRed('There was a problem with fixtures reloading. The response is: '), response); - } - - logRequestTime(timeStart); - - callback(); - }) - .catch(function(error) { - console.log(chalk.black.bgRed('An error occurred during fixtures reloading: '), error); - - logRequestTime(timeStart); - - callback(); - }); - }); - - After('@reloadUsers', function(scenario, callback) { - if (this.currentUser !== null) { - this.userProvider.lockUser(this.currentUser.account, this.currentUser.type); - } - - callback(); - }); - - protractor.browser.ignoreSynchronization = config.type === 'otherWeb'; -}); diff --git a/src/web/cucumber/hooks.ts b/src/web/cucumber/hooks.ts new file mode 100644 index 00000000..b202acc4 --- /dev/null +++ b/src/web/cucumber/hooks.ts @@ -0,0 +1,3 @@ +import { hookHandlers } from './hooks/hooks'; + +hookHandlers.initializeHook(); diff --git a/src/web/cucumber/hooks/clear-download.hook.ts b/src/web/cucumber/hooks/clear-download.hook.ts new file mode 100644 index 00000000..627a9cce --- /dev/null +++ b/src/web/cucumber/hooks/clear-download.hook.ts @@ -0,0 +1,33 @@ +import { After, Before } from 'cucumber'; +import { HookHandler } from './hook.interface'; +import * as fs from 'fs'; +import * as path from 'path'; +import config from '../../../core/config.helper'; + +const clearDownload = callback => { + const files = fs.readdirSync(path.join(config.projectPath, config.downloads)).filter(file => file !== '.gitkeep'); + + for (const file of files) { + fs.unlinkSync(path.join(config.projectPath, config.downloads, file)); + } + + callback(); +}; + +class ClearDownloadHook implements HookHandler { + public initializeHook() { + Before('@downloadClearBefore', (scenario, callback) => { + clearDownload(callback); + }); + + After('@downloadClearAfter', (scenario, callback) => { + clearDownload(callback); + }); + } + + public getPriority() { + return 1; + } +} + +export const clearDownloadHook = new ClearDownloadHook(); diff --git a/src/web/cucumber/hooks/clear-variables.hook.ts b/src/web/cucumber/hooks/clear-variables.hook.ts new file mode 100644 index 00000000..514fe380 --- /dev/null +++ b/src/web/cucumber/hooks/clear-variables.hook.ts @@ -0,0 +1,26 @@ +import { Before } from 'cucumber'; +import { HookHandler } from './hook.interface'; +import userProvider from '../../user-provider.helper'; +import variableStore from '../../variable-store.helper'; + +class ClearVariablesHook implements HookHandler { + public initializeHook() { + Before(function(scenario, callback) { + this.currentUser = null; + + if (typeof this.userProvider === 'undefined') { + this.userProvider = userProvider; + } + + variableStore.clearVariables(); + + callback(); + }); + } + + public getPriority() { + return 1; + } +} + +export const clearVariablesHook = new ClearVariablesHook(); diff --git a/src/web/cucumber/hooks/hook.interface.ts b/src/web/cucumber/hooks/hook.interface.ts new file mode 100644 index 00000000..3cf47e8b --- /dev/null +++ b/src/web/cucumber/hooks/hook.interface.ts @@ -0,0 +1,4 @@ +export interface HookHandler { + initializeHook(): void; + getPriority(): number; +} diff --git a/src/web/cucumber/hooks/hooks.ts b/src/web/cucumber/hooks/hooks.ts new file mode 100644 index 00000000..6b15e94f --- /dev/null +++ b/src/web/cucumber/hooks/hooks.ts @@ -0,0 +1,32 @@ +import * as hookHandler from './index'; +import { HookHandler } from './hook.interface'; + +class HookHandlers { + constructor( + private availableHandlers: HookHandler[] = [ + hookHandler.takeScreenshotHook, + hookHandler.reloadFixturesHook, + hookHandler.clearDownloadHook, + hookHandler.reloadUserHook, + hookHandler.clearVariablesHook, + ] + ) {} + + public addHook(handler: HookHandler): void { + this.availableHandlers.push(handler); + } + + public initializeHook(): void { + const handlers = this.getHooks(); + + for (const handler of handlers) { + handler.initializeHook(); + } + } + + public getHooks(): HookHandler[] { + return this.availableHandlers.sort((handler, otherHandler) => handler.getPriority() - otherHandler.getPriority()); + } +} + +export const hookHandlers = new HookHandlers(); diff --git a/src/web/cucumber/hooks/index.ts b/src/web/cucumber/hooks/index.ts new file mode 100644 index 00000000..f3468ac9 --- /dev/null +++ b/src/web/cucumber/hooks/index.ts @@ -0,0 +1,5 @@ +export * from './take-screenshots.hook'; +export * from './reload-fixtures.hook'; +export * from './reload-user.hook'; +export * from './clear-download.hook'; +export * from './clear-variables.hook'; diff --git a/src/web/cucumber/hooks/reload-fixtures.hook.ts b/src/web/cucumber/hooks/reload-fixtures.hook.ts new file mode 100644 index 00000000..474966d3 --- /dev/null +++ b/src/web/cucumber/hooks/reload-fixtures.hook.ts @@ -0,0 +1,48 @@ +import { Before } from 'cucumber'; +import { HookHandler } from './hook.interface'; +import chalk from 'chalk'; +import parameters from '../../parameters'; +import fixturesLoader from '../../fixtures/fixtures-loader.helper'; + +const logRequestTime = timeStart => { + const timeDiff = process.hrtime(timeStart); + + console.log(chalk.black.bgYellow('Request took ' + (timeDiff[0] + timeDiff[1] / 1000000000) + ' seconds')); +}; + +class ReloadFixturesHook implements HookHandler { + public initializeHook() { + Before('@reloadFixtures', (scenario, callback) => { + console.log(chalk.black.bgYellow('Reloading fixtures')); + + const timeStart = process.hrtime(); + + fixturesLoader + .reloadFixtures(parameters.getReloadFixturesEndpoint()) + .then(response => { + if (response.status === 200) { + console.log(chalk.black.bgGreen('Fixtures reloaded')); + } else { + console.log(chalk.black.bgRed('There was a problem with fixtures reloading. The response is: '), response); + } + + logRequestTime(timeStart); + + callback(); + }) + .catch(error => { + console.log(chalk.black.bgRed('An error occurred during fixtures reloading: '), error); + + logRequestTime(timeStart); + + callback(); + }); + }); + } + + public getPriority() { + return 2; + } +} + +export const reloadFixturesHook = new ReloadFixturesHook(); diff --git a/src/web/cucumber/hooks/reload-user.hook.ts b/src/web/cucumber/hooks/reload-user.hook.ts new file mode 100644 index 00000000..e0cb6db9 --- /dev/null +++ b/src/web/cucumber/hooks/reload-user.hook.ts @@ -0,0 +1,20 @@ +import { After } from 'cucumber'; +import { HookHandler } from './hook.interface'; + +class ReloadUserHook implements HookHandler { + public initializeHook() { + After('@reloadUsers', function(scenario, callback) { + if (this.currentUser !== null) { + this.userProvider.lockUser(this.currentUser.account, this.currentUser.type); + } + + callback(); + }); + } + + public getPriority() { + return 1; + } +} + +export const reloadUserHook = new ReloadUserHook(); diff --git a/src/web/cucumber/hooks/take-screenshots.hook.ts b/src/web/cucumber/hooks/take-screenshots.hook.ts new file mode 100644 index 00000000..0839dc6b --- /dev/null +++ b/src/web/cucumber/hooks/take-screenshots.hook.ts @@ -0,0 +1,58 @@ +import { HookHandler } from './hook.interface'; +import config from '../../../core/config.helper'; +import { After } from 'cucumber'; + +const takeScreenshot = scenario => { + return browser.takeScreenshot().then( + base64png => { + scenario.attach(new Buffer(base64png, 'base64'), 'image/png'); + return Promise.resolve(); + }, + () => Promise.resolve() + ); +}; + +const clearCookiesAndLocalStorage = callback => { + let cookiesFunc = () => Promise.resolve(true); + + if (config.clearCookiesAfterScenario) { + cookiesFunc = () => protractor.browser.manage().deleteAllCookies(); + } + + let localStorageFunc = () => Promise.resolve(true); + if (config.clearLocalStorageAfterScenario) { + localStorageFunc = () => protractor.browser.executeScript('window.localStorage.clear();'); + } + + browser + .wait( + cookiesFunc() + .then(localStorageFunc) + .catch(() => false), + config.waitForPageTimeout * 1000 + ) + .then(() => { + protractor.browser.ignoreSynchronization = config.type === 'otherWeb'; + callback(); + }); +}; + +class TakeScreenshotHook implements HookHandler { + public initializeHook() { + return After(function(scenario, callback) { + if (scenario.result.status !== 'passed') { + takeScreenshot(this).then(() => { + clearCookiesAndLocalStorage(callback); + }); + } else { + clearCookiesAndLocalStorage(callback); + } + }); + } + + public getPriority() { + return 1; + } +} + +export const takeScreenshotHook = new TakeScreenshotHook(); diff --git a/src/web/cucumber/wait-for-condition.helper.js b/src/web/cucumber/wait-for-condition.helper.ts similarity index 100% rename from src/web/cucumber/wait-for-condition.helper.js rename to src/web/cucumber/wait-for-condition.helper.ts diff --git a/src/web/fixtures/fixtures-loader.helper.js b/src/web/fixtures/fixtures-loader.helper.ts similarity index 76% rename from src/web/fixtures/fixtures-loader.helper.js rename to src/web/fixtures/fixtures-loader.helper.ts index f001ff46..1a5d570a 100644 --- a/src/web/fixtures/fixtures-loader.helper.js +++ b/src/web/fixtures/fixtures-loader.helper.ts @@ -1,7 +1,7 @@ import fetch from 'node-fetch'; const FixturesLoader = { - reloadFixtures: function(endpoint) { + reloadFixtures(endpoint) { return fetch(endpoint); }, }; diff --git a/src/web/fs/download-checker.helper.js b/src/web/fs/download-checker.helper.ts similarity index 64% rename from src/web/fs/download-checker.helper.js rename to src/web/fs/download-checker.helper.ts index 8f11f7a3..33aa8e14 100644 --- a/src/web/fs/download-checker.helper.js +++ b/src/web/fs/download-checker.helper.ts @@ -1,10 +1,10 @@ -import fs from 'fs'; -import path from 'path'; +import * as fs from 'fs'; +import * as path from 'path'; import config from '../../core/config.helper'; const DownloadChecker = { - wasDownloaded: function(expectedFileName) { - return browser.driver.wait(function() { + wasDownloaded(expectedFileName) { + return browser.driver.wait(() => { return fs.existsSync(path.join(config.projectPath, config.downloads, expectedFileName)); }, config.downloadTimeout * 1000); }, diff --git a/src/web/fs/file-manager.helper.js b/src/web/fs/file-manager.helper.ts similarity index 62% rename from src/web/fs/file-manager.helper.js rename to src/web/fs/file-manager.helper.ts index 24b5a802..d0d1ea15 100644 --- a/src/web/fs/file-manager.helper.js +++ b/src/web/fs/file-manager.helper.ts @@ -1,16 +1,16 @@ -import fs from 'fs'; -import path from 'path'; -import xlsx from 'node-xlsx'; +import * as fs from 'fs'; +import * as xlsx from 'node-xlsx'; +import * as path from 'path'; import config from '../../core/config.helper'; const FileManager = { - wasDownloaded: function(expectedFileName) { - return browser.driver.wait(function() { + wasDownloaded(expectedFileName) { + return browser.driver.wait(() => { return fs.existsSync(path.join(config.projectPath, config.downloads, expectedFileName)); }, config.downloadTimeout * 1000); }, - parseXLS: function(expectedFileName) { + parseXLS(expectedFileName) { return xlsx.parse(path.join(config.projectPath, config.downloads, expectedFileName))[0].data; }, }; diff --git a/src/web/parallel/chunk-specs.helper.spec.js b/src/web/parallel/chunk-specs.helper.spec.ts similarity index 100% rename from src/web/parallel/chunk-specs.helper.spec.js rename to src/web/parallel/chunk-specs.helper.spec.ts diff --git a/src/web/parallel/chunk-specs.helper.js b/src/web/parallel/chunk-specs.helper.ts similarity index 95% rename from src/web/parallel/chunk-specs.helper.js rename to src/web/parallel/chunk-specs.helper.ts index 68f4406c..840b0ba8 100644 --- a/src/web/parallel/chunk-specs.helper.js +++ b/src/web/parallel/chunk-specs.helper.ts @@ -1,4 +1,4 @@ -import _ from 'lodash'; +import * as _ from 'lodash'; export const chunkSpecs = (commandArgs, allSpecs, expectedArrayLength, numberOfInstances) => { if (commandArgs.pattern !== undefined && typeof commandArgs.pattern !== 'boolean') { diff --git a/src/web/parallel/prepare-browser-instance-specs.helper.js b/src/web/parallel/prepare-browser-instance-specs.helper.ts similarity index 84% rename from src/web/parallel/prepare-browser-instance-specs.helper.js rename to src/web/parallel/prepare-browser-instance-specs.helper.ts index 219f8bfa..d1af2e0e 100644 --- a/src/web/parallel/prepare-browser-instance-specs.helper.js +++ b/src/web/parallel/prepare-browser-instance-specs.helper.ts @@ -1,4 +1,4 @@ -import _ from 'lodash'; +import * as _ from 'lodash'; export const prepareBrowserInstance = (browserConfig, specs) => { const instance = _.cloneDeep(browserConfig); diff --git a/src/web/parameters.js b/src/web/parameters.ts similarity index 90% rename from src/web/parameters.js rename to src/web/parameters.ts index e3d45dc3..a075d118 100644 --- a/src/web/parameters.js +++ b/src/web/parameters.ts @@ -1,5 +1,5 @@ const Parameters = { - getReloadFixturesEndpoint: function() { + getReloadFixturesEndpoint() { const config = this.getConfig(); return config.fixturesReloadHost; diff --git a/src/web/performance/JSON-performance-report-parser.helper.spec.js b/src/web/performance/JSON-performance-report-parser.helper.spec.ts similarity index 55% rename from src/web/performance/JSON-performance-report-parser.helper.spec.js rename to src/web/performance/JSON-performance-report-parser.helper.spec.ts index 68ce37d6..6b54148f 100644 --- a/src/web/performance/JSON-performance-report-parser.helper.spec.js +++ b/src/web/performance/JSON-performance-report-parser.helper.spec.ts @@ -3,11 +3,11 @@ import JSONPerformanceReportParser from './JSON-performance-report-parser.helper const parser = new JSONPerformanceReportParser('src/tests/reports/performance'); describe('JSON performance report parser', () => { - it('returns found objects with TTFB and URL values', (fileName = 'performance-report.har') => { - expect(parser.parse(fileName, fileName)).toContainEqual({ ttfb: 0, url: 'http://localhost:8080/' }); + it('returns found objects with TTFB and URL values', (fileName: any = 'performance-report.har') => { + expect(parser.parse(fileName)).toContainEqual({ ttfb: 0, url: 'http://localhost:8080/' }); }); - it('returns error message - file contains incorrect data', (fileName = 'incorrect-performance-report.har') => { - expect(() => parser.parse(fileName, fileName)).toThrow(`${fileName} contains incorrect data!`); + it('returns error message - file contains incorrect data', (fileName: any = 'incorrect-performance-report.har') => { + expect(() => parser.parse(fileName)).toThrow(`${fileName} contains incorrect data!`); }); }); diff --git a/src/web/performance/JSON-performance-report-parser.helper.js b/src/web/performance/JSON-performance-report-parser.helper.ts similarity index 86% rename from src/web/performance/JSON-performance-report-parser.helper.js rename to src/web/performance/JSON-performance-report-parser.helper.ts index 526f0f02..364b13aa 100644 --- a/src/web/performance/JSON-performance-report-parser.helper.js +++ b/src/web/performance/JSON-performance-report-parser.helper.ts @@ -1,15 +1,17 @@ -import fs from 'fs'; +import * as fs from 'fs'; const getReport = (fileName, path) => { return JSON.parse(fs.readFileSync(`${path}/${fileName}`, 'utf8')); }; class JSONPerformanceReportParser { + private readonly path: string; + constructor(path = 'reports/performance') { this.path = path; } - parse(fileName) { + public parse(fileName) { const reportFile = getReport(fileName, this.path); const requests = reportFile.log.entries.map(item => ({ ttfb: item.timings.wait, diff --git a/src/web/performance/time-to-first-byte-analyser.helper.spec.js b/src/web/performance/time-to-first-byte-analyser.helper.spec.ts similarity index 97% rename from src/web/performance/time-to-first-byte-analyser.helper.spec.js rename to src/web/performance/time-to-first-byte-analyser.helper.spec.ts index 1706c7b2..97310e20 100644 --- a/src/web/performance/time-to-first-byte-analyser.helper.spec.js +++ b/src/web/performance/time-to-first-byte-analyser.helper.spec.ts @@ -1,6 +1,6 @@ import { create as createAnalyser } from './time-to-first-byte-analyser.helper'; -const myFakeParser = { +const myFakeParser: any = { parse: () => { return [ { ttfb: 0, url: 'http://localhost:8080/' }, diff --git a/src/web/performance/time-to-first-byte-analyser.helper.js b/src/web/performance/time-to-first-byte-analyser.helper.ts similarity index 87% rename from src/web/performance/time-to-first-byte-analyser.helper.js rename to src/web/performance/time-to-first-byte-analyser.helper.ts index 890c5e4c..f63525d0 100644 --- a/src/web/performance/time-to-first-byte-analyser.helper.js +++ b/src/web/performance/time-to-first-byte-analyser.helper.ts @@ -1,11 +1,13 @@ import JSONPerformanceReportParser from './JSON-performance-report-parser.helper'; class TimeToFirstByteAnalyser { + private reader: any; + constructor(jsonPerformanceReportParser) { this.reader = jsonPerformanceReportParser; } - checkTiming(fileName, maxTiming) { + public checkTiming(fileName, maxTiming) { const parsedReport = this.reader.parse(fileName); return parsedReport.filter(report => report.ttfb > maxTiming); diff --git a/src/web/url-parser.helper.spec.js b/src/web/url-parser.helper.spec.ts similarity index 100% rename from src/web/url-parser.helper.spec.js rename to src/web/url-parser.helper.spec.ts diff --git a/src/web/url-parser.helper.js b/src/web/url-parser.helper.ts similarity index 74% rename from src/web/url-parser.helper.js rename to src/web/url-parser.helper.ts index fac1e194..df756995 100644 --- a/src/web/url-parser.helper.js +++ b/src/web/url-parser.helper.ts @@ -1,4 +1,4 @@ -import Url from 'url'; +import * as Url from 'url'; const extractDomain = url => Url.parse(url).host; const extractUrl = url => Url.parse(url).pathname; @@ -17,14 +17,16 @@ const normalizeUrl = url => { const compareUrls = (urlSplit, baseUrlSplit) => { const resultParameters = {}; - for (let i in urlSplit) { - const template = baseUrlSplit[i]; - const actual = urlSplit[i]; + for (const i in urlSplit) { + if (urlSplit.hasOwnProperty(i) && baseUrlSplit.hasOwnProperty(i)) { + const template = baseUrlSplit[i]; + const actual = urlSplit[i]; - if (template.startsWith(':')) { - resultParameters[template.substr(1)] = actual; - } else if (template !== actual) { - return false; + if (template.startsWith(':')) { + resultParameters[template.substr(1)] = actual; + } else if (template !== actual) { + return false; + } } } diff --git a/src/web/user-provider.helper.js b/src/web/user-provider.helper.ts similarity index 91% rename from src/web/user-provider.helper.js rename to src/web/user-provider.helper.ts index 8f5d3b24..41fc1219 100644 --- a/src/web/user-provider.helper.js +++ b/src/web/user-provider.helper.ts @@ -2,7 +2,7 @@ import config from '../core/config.helper'; const accounts = config.accounts; const userProvider = { - getUser: function(userType) { + getUser(userType) { const user = accounts[userType]; if (user.accounts.length > 1) { @@ -21,7 +21,7 @@ const userProvider = { return user.accounts[0]; }, - lockUser: function(user, userType) { + lockUser(user, userType) { if (accounts[userType].accounts.length > 1) { accounts[userType].accounts.forEach((account, index) => { if (account.email === user.email) { diff --git a/src/web/variable-store.helper.spec.js b/src/web/variable-store.helper.spec.ts similarity index 100% rename from src/web/variable-store.helper.spec.js rename to src/web/variable-store.helper.spec.ts diff --git a/src/web/variable-store.helper.js b/src/web/variable-store.helper.ts similarity index 55% rename from src/web/variable-store.helper.js rename to src/web/variable-store.helper.ts index 083325f9..e90dd76e 100644 --- a/src/web/variable-store.helper.js +++ b/src/web/variable-store.helper.ts @@ -1,29 +1,27 @@ -class VariableStore { - constructor() { - this.variables = []; - } +export class VariableStore { + constructor(public variables: any[] = []) {} - storeVariable(name, value) { + public storeVariable(name: string, value: any): void { const foundVariable = this.variables.find(variable => variable.name === name); if (typeof foundVariable !== 'undefined') { throw new Error(`Variable ${name} is stored already`); } - this.variables.push({ name: name, value: value }); + this.variables.push({ name, value }); } - updateVariable(name, value) { + public updateVariable(name: string, value: any): void { const foundVariable = this.variables.find(variable => variable.name === name); if (typeof foundVariable === 'undefined') { throw new Error(`Variable ${name} does not exist.`); } - this.variables.push({ name: name, value: value }); + this.variables.push({ name, value }); } - getVariableValue(name) { + public getVariableValue(name: string): any { const foundVariable = this.variables.find(variable => variable.name === name); if (typeof foundVariable === 'undefined') { @@ -33,26 +31,28 @@ class VariableStore { return foundVariable.value; } - isStored(name) { + public isStored(name: string): boolean { const foundVariable = this.variables.find(variable => variable.name === name); return typeof foundVariable !== 'undefined'; } - clearVariables() { + public clearVariables(): void { this.variables = []; } - replaceTextVariables(text) { + public replaceTextVariables(text: string): any { let newText = text; const variableNames = this.variables.map(variable => variable.name); - for (let variableNameIndex in variableNames) { - const variableName = variableNames[variableNameIndex]; + for (const variableNameIndex in variableNames) { + if (variableNames.hasOwnProperty(variableNameIndex)) { + const variableName = variableNames[variableNameIndex]; - if (newText.indexOf(variableName) > -1) { - newText = text.replace(`v:${variableName}`, this.getVariableValue(variableName)); - break; + if (newText.indexOf(variableName) > -1) { + newText = text.replace(`v:${variableName}`, this.getVariableValue(variableName)); + break; + } } } diff --git a/templates/example.feature b/templates/example.feature index 6c400206..cd957c6a 100644 --- a/templates/example.feature +++ b/templates/example.feature @@ -1,5 +1,5 @@ -Feature: - Scenario: +Feature: Example feature file + Scenario: Example scenario When I visit the "page" page And I generate random "name" as "myName" Then my matcher "e:name" matches "v:myName" diff --git a/templates/hook.js b/templates/hook.js index 643ffb89..3dcf86ea 100644 --- a/templates/hook.js +++ b/templates/hook.js @@ -1,7 +1,15 @@ -const { defineSupportCode } = require('kakunin'); +const { hookHandlers, Before } = require('kakunin'); -defineSupportCode(({ Before }) => { - Before(function () { - console.log('If you can see this in console then hook is working properly.'); - }); -}); +class TestHook { + initializeHook() { + Before(() => { + console.log('Standard hook'); + }); + } + + getPriority() { + return 990; + } +} + +hookHandlers.addHook(new TestHook()); diff --git a/templates/login.js b/templates/login.js index aca4254e..3d9b3348 100644 --- a/templates/login.js +++ b/templates/login.js @@ -1,27 +1,19 @@ -const { defineSupportCode } = require('kakunin'); +const { Given } = require('kakunin'); -defineSupportCode(({ Given }) => { - Given(/^I am logged in as a "([^"]*)$/, function (user) { - this.currentUser = { - account: this.userProvider.getUser(user), - type: user - }; +Given(/^I am logged in as a "([^"]*)$/, async function(user) { + this.currentUser = { + account: this.userProvider.getUser(user), + type: user, + }; - const mainPage = browser.page.main; - const loginPage = browser.page.login; - const self = this; + const mainPage = browser.page.main; + const loginPage = browser.page.login; - return mainPage.visit().then(function () { - return mainPage.isVisible('login'); - }).then(function () { - return mainPage.click('login'); - }).then(function () { - return loginPage.login(self.currentUser.account.email, self.currentUser.account.password); - }).then(function () { - return expect(mainPage.isPresent('login')).not.to.eventually.be.ok; - }).then(function () { - self.currentPage = mainPage; - return Promise.resolve(); - }); - }); + await mainPage.visit(); + await mainPage.waitForVisibilityOf('login'); + await mainPage.click('login'); + await loginPage.login(this.currentUser.account.email, this.currentUser.account.password); + await mainPage.waitForInvisibilityOf('login'); + + this.currentPage = mainPage; }); diff --git a/templates/steps.js b/templates/steps.js index 461e6942..5cf49b31 100644 --- a/templates/steps.js +++ b/templates/steps.js @@ -1,7 +1,5 @@ -const { matchers, variableStore, defineSupportCode } = require('kakunin'); +const { matchers, variableStore, Then } = require('kakunin'); -defineSupportCode(({ Then }) => { - Then(/^my matcher "([^"]*)" matches "([^"]*)"$/, function (matcher, text) { - return expect(matchers.match(variableStore.replaceTextVariables(text), matcher)).to.be.true; - }); +Then(/^my matcher "([^"]*)" matches "([^"]*)"$/, function (matcher, text) { + return expect(matchers.match(variableStore.replaceTextVariables(text), matcher)).toBe(true); }); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..554f6644 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "esnext", + "module": "commonjs", + "allowSyntheticDefaultImports": false, + "outDir": "dist", + "noUnusedLocals": true, + "noImplicitAny": false, + "removeComments": false + }, + "exclude": [ + "node_modules", + "**/*.spec.ts", + "dist/**" + ], + "include": [ + "./src/kakunin.d.ts", + "./src/**/*.ts" + ] +} diff --git a/tsconfig.test.json b/tsconfig.test.json new file mode 100644 index 00000000..85d69c78 --- /dev/null +++ b/tsconfig.test.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "target": "es6" + } +} \ No newline at end of file diff --git a/tslint.json b/tslint.json new file mode 100644 index 00000000..8becffca --- /dev/null +++ b/tslint.json @@ -0,0 +1,34 @@ +{ + "defaultSeverity": "error", + "extends": [ + "tslint:recommended", + "tslint-config-prettier", + "tslint-sonarts" + ], + "linterOptions": { + "exclude": [ + "**/*.spec.ts", + "**/*.d.ts" + ] + }, + "jsRules": {}, + "rules": { + "no-extra-semicolon": false, + "no-empty-interface": false, + "object-literal-sort-keys": false, + "radix": false, + "interface-name": [true, "never-prefix"], + "ordered-imports": false, + "no-duplicate-string": false, + "variable-name": [true, "ban-keywords", "allow-leading-underscore", "allow-pascal-case"], + "interface-over-type-literal": false, + "no-angle-bracket-type-assertion": false, + "max-union-size": false, + "no-identical-functions": false, + "no-console": false, + "no-var-requires": false, + "cognitive-complexity": false, + "no-big-function": false + }, + "rulesDirectory": [] +} diff --git a/website/README.md b/website/README.md index 4848df9c..d4f837f3 100644 --- a/website/README.md +++ b/website/README.md @@ -121,7 +121,7 @@ Id should be in lowercase - it is used in `website/sidebars.json`. # Versifying -Docusaurus support versifying, right know we started to using this feature from `2.4.0` Kakunin version. +Docusaurus support versifying, right now we started to using this feature from `2.4.0` Kakunin version. 1. To add new version of documentation open `website/` folder 2. Run `yarn run version [version]` example `yarn run version 2.4.0-1` diff --git a/website/build/Kakunin/docs/2.4.0/configuration.html b/website/build/Kakunin/docs/2.4.0/configuration.html index 5d376d16..8da742c7 100644 --- a/website/build/Kakunin/docs/2.4.0/configuration.html +++ b/website/build/Kakunin/docs/2.4.0/configuration.html @@ -1,6 +1,6 @@ Configuration · Kakunin

2.4.0