diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..95b68ff --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +**/node_modules/* +src/emulator/* diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..a5b82de --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + "extends": "standard" +}; \ No newline at end of file diff --git a/bin/testmybot.js b/bin/testmybot.js index 77ca868..e6b5cd9 100644 --- a/bin/testmybot.js +++ b/bin/testmybot.js @@ -1,23 +1,30 @@ #!/usr/bin/env node const yargsCmd = require('yargs') -const async = require('async') +const Mocha = require('mocha') const debug = require('debug') -const log = require('../src/util/log') -const testmybot = require('../src/testmybot') +const path = require('path') -yargsCmd - .usage('TestMyBot CLI\n\nUsage: $0 [options]') +const outputTypes = [ + 'tap', + 'json', + 'xunit', + 'spec', + 'list', + 'html' +] + +yargsCmd.usage('TestMyBot CLI\n\nUsage: $0 [options]') // eslint-disable-line .help('help').alias('help', 'h') .version('version', require('../package.json').version).alias('version', 'V') .command('run [output]', 'Run TestMyBot convo files and output test report', (yargs) => { yargs.positional('output', { - describe: 'Output report type, supported: "csv", "junit"', - default: 'csv' + describe: 'Output report type, supported: ' + outputTypes.join(), + default: 'spec' }) }, (argv) => { handleOptions(argv) - if (argv.output !== 'csv' && argv.output !== 'junit') { + if (outputTypes.findIndex((o) => o === argv.output) < 0) { yargsCmd.showHelp() } else { runTestsuite(argv) @@ -30,7 +37,7 @@ yargsCmd }) }, (argv) => { handleOptions(argv) - + if (argv.type !== 'console' && argv.type !== 'browser') { yargsCmd.showHelp() } else if (argv.type === 'console') { @@ -48,29 +55,18 @@ yargsCmd alias: 'C', describe: 'Path to the directory holding your convo files', default: './spec/convo' - }) + }) .option('config', { alias: 'c', describe: 'Path to the TestMyBot configuration file (testmybot.json)', default: './testmybot.json' - }) - .option('out', { - alias: 'o', - describe: 'Path to the output directory', - default: './' }) - .option('outfile', { - alias: 'O', - describe: 'Filename for the output report', - default: 'testmybot.out.[csv|xml]' - }) .demandCommand() .argv -function handleOptions(argv) { +function handleOptions (argv) { if (argv.verbose) { - debug.enable('botium') - process.env.DEBUG = 'true' + debug.enable('testmybot*,botium*') } if (argv.convos) { require('../src/convo').setConvoDir(argv.convos) @@ -80,110 +76,15 @@ function handleOptions(argv) { } } -function runTestsuite(argv) { - - const testcases = [] - - testmybot.setupTestSuite( - (testcaseName, testcaseFunction) => { - testcases.push({ - name: testcaseName, - exec: testcaseFunction - }) - }, - (check, tomatch) => { - if (!check && !tomatch) { - return - } - if (check.match(tomatch)) { - return - } - throw new Error(`assert failed: "${check}" not matching "${tomatch}"`) - }, - (err) => { - throw new Error(err) - } - ) - - async.series([ - (beforeAllDone) => { - testmybot.beforeAll().then( - () => beforeAllDone(), - (err) => beforeAllDone('before all failed: ' + err) - ) - }, - - (testcasesDone) => { - async.eachSeries(testcases, (testcase, testcaseDone) => { - async.series([ - (beforeEachDone) => { - testmybot.beforeEach().then( - () => beforeEachDone(), - (err) => beforeEachDone('before each failed: ' + err) - ) - }, - - (testcaseExecDone) => { - testcase.exec((err) => { - if (err) { - testcase.success = false - if (err.message) { - testcase.err = err.message - } else { - testcase.err = err - } - if (err.stack) { - testcase.stack = err.stack - } - } else { - testcase.success = true - } - testcaseExecDone() - }) - }, - - (afterEachDone) => { - testmybot.afterEach().then( - () => afterEachDone(), - (err) => afterEachDone('after each failed: ' + err) - ) - } - ], - (err) => { - if (err) { - testcase.success = false - testcase.err = err - } - testcaseDone() - }) - }, - (err) => { - log.info('all testcases ready') - testcasesDone() - }) - }, - - (afterAllDone) => { - testmybot.afterAll().then( - () => afterAllDone(), - (err) => afterAllDone('after all failed: ' + err) - ) - } - ], - (err) => { - if (err) { - log.error(err) - } else { - log.info('testsuite ready') - - testcases.forEach((testcase) => { - if (testcase.success) { - console.log(testcase.name + ' OK') - } else { - console.log(testcase.name + ' FAILED: ' + testcase.err) - } - }) - - } +function runTestsuite (argv) { + const mocha = new Mocha({ + reporter: argv.output + }) + mocha.addFile(path.resolve(__dirname, 'testmybot.spec.js')) + + mocha.run((failures) => { + process.on('exit', () => { + process.exit(failures) + }) }) } diff --git a/bin/testmybot.spec.js b/bin/testmybot.spec.js new file mode 100644 index 0000000..4eb0d9f --- /dev/null +++ b/bin/testmybot.spec.js @@ -0,0 +1,2 @@ +const mochaHelper = require('../src/helpers/mocha') +mochaHelper.setupMochaTestSuite() diff --git a/package-lock.json b/package-lock.json index 3592a5e..0931e4c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "testmybot", - "version": "1.1.1", + "version": "1.1.2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -118,6 +118,12 @@ "json-schema-traverse": "0.3.1" } }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", @@ -130,6 +136,12 @@ "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz", "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=" }, + "ansi-escapes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", + "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", + "dev": true + }, "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", @@ -206,6 +218,12 @@ "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, "asn1": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", @@ -216,6 +234,11 @@ "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==" + }, "async": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", @@ -249,6 +272,59 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" }, + "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" + }, + "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 + }, + "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.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "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=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "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-runtime": { "version": "6.25.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.25.0.tgz", @@ -352,9 +428,9 @@ } }, "botium-core": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/botium-core/-/botium-core-1.1.1.tgz", - "integrity": "sha1-R9zNKzaiJxAmaKhe9vUcZcroKjQ=", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/botium-core/-/botium-core-1.1.4.tgz", + "integrity": "sha1-9JYNNCfFD8BER+/svsqEOY9E8Ag=", "requires": { "async": "2.6.0", "body-parser": "1.18.2", @@ -439,6 +515,11 @@ } } }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=" + }, "buble": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/buble/-/buble-0.18.0.tgz", @@ -493,11 +574,26 @@ "resolved": "https://registry.npmjs.org/cached-constructors-x/-/cached-constructors-x-1.0.0.tgz", "integrity": "sha512-JVP0oilYlPgBTD8bkQ+of7hSIJRtydCCJiMtzdRMXVQ98gdj0NyrJTZzbu5wtlO26Ev/1HXRTtbBNsVlLJ3+3A==" }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + } + }, "callsite": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, "camelcase": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", @@ -508,6 +604,19 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, + "chai": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "requires": { + "assertion-error": "1.1.0", + "check-error": "1.0.2", + "deep-eql": "3.0.1", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.6" + } + }, "chalk": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", @@ -518,6 +627,17 @@ "supports-color": "4.5.0" } }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" + }, "cheerio": { "version": "0.19.0", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.19.0.tgz", @@ -537,11 +657,32 @@ } } }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, "clear": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/clear/-/clear-0.0.1.tgz", "integrity": "sha1-5RhuIp2ZRIF5wTAxG2+dML/2sLo=" }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, "cliui": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.0.0.tgz", @@ -583,6 +724,11 @@ "delayed-stream": "1.0.0" } }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" + }, "component-bind": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", @@ -603,6 +749,61 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "typedarray": "0.0.6" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", @@ -715,11 +916,50 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "requires": { + "type-detect": "4.0.6" + } + }, "deep-is": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.2.tgz", "integrity": "sha1-nO1l6gvAsJ9CptecGxkD+dkTzBg=" }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + }, + "dependencies": { + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + } + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -740,6 +980,20 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "diff": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==" + }, + "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" + } + }, "dom-serializer": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", @@ -879,6 +1133,15 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -910,11 +1173,250 @@ } } }, + "eslint": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.15.0.tgz", + "integrity": "sha512-zEO/Z1ZUxIQ+MhDVKkVTUYpIPDTEJLXGMrkID+5v1NeQHtCz6FZikWuFRgxE1Q/RV2V4zVl1u3xmpPADHhMZ6A==", + "dev": true, + "requires": { + "ajv": "5.5.2", + "babel-code-frame": "6.26.0", + "chalk": "2.3.0", + "concat-stream": "1.6.0", + "cross-spawn": "5.1.0", + "debug": "3.1.0", + "doctrine": "2.1.0", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "1.0.0", + "espree": "3.5.2", + "esquery": "1.0.0", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.2", + "globals": "11.1.0", + "ignore": "3.3.7", + "imurmurhash": "0.1.4", + "inquirer": "3.3.0", + "is-resolvable": "1.0.1", + "js-yaml": "3.10.0", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.4", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.0", + "require-uncached": "1.0.3", + "semver": "5.4.1", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", + "table": "4.0.2", + "text-table": "0.2.0" + } + }, + "eslint-config-standard": { + "version": "11.0.0-beta.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-11.0.0-beta.0.tgz", + "integrity": "sha512-f+vs5HAHQo7NRZ3hVe+UVdT5DbebMNaFTWFp95orJ0LUdYPoWdM8xw/bMeO/IZMvHOPmIteGKGc2QOhSXd5nRg==", + "dev": true + }, + "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" + } + } + } + }, + "eslint-module-utils": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", + "integrity": "sha512-jDI/X5l/6D1rRD/3T43q8Qgbls2nq5km5KSqiwlyUbGo5+04fXhMKdCPhjwbqAa6HXWaMxj8Q4hQDIh7IadJQw==", + "dev": true, + "requires": { + "debug": "2.6.9", + "pkg-dir": "1.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" + } + } + } + }, + "eslint-plugin-import": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz", + "integrity": "sha512-Rf7dfKJxZ16QuTgVv1OYNxkZcsu/hULFnC+e+w0Gzi6jMC3guQoWQgxYxc54IDRinlb6/0v5z/PxxIKmVctN+g==", + "dev": true, + "requires": { + "builtin-modules": "1.1.1", + "contains-path": "0.1.0", + "debug": "2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "0.3.2", + "eslint-module-utils": "2.1.1", + "has": "1.0.1", + "lodash.cond": "4.5.2", + "minimatch": "3.0.4", + "read-pkg-up": "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" + } + }, + "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" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "eslint-plugin-node": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", + "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", + "dev": true, + "requires": { + "ignore": "3.3.7", + "minimatch": "3.0.4", + "resolve": "1.5.0", + "semver": "5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, + "eslint-plugin-promise": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.6.0.tgz", + "integrity": "sha512-YQzM6TLTlApAr7Li8vWKR+K3WghjwKcYzY0d2roWap4SLK+kzuagJX/leTetIDWsFcTFnKNJXWupDCD6aZkP2Q==", + "dev": true + }, + "eslint-plugin-standard": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", + "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=", + "dev": true + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true, + "requires": { + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "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": "3.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz", + "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==", + "dev": true, + "requires": { + "acorn": "5.2.1", + "acorn-jsx": "3.0.1" + } + }, "esprima": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" }, + "esquery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "dev": true, + "requires": { + "estraverse": "4.2.0" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, "estraverse": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", @@ -1053,7 +1555,18 @@ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "requires": { - "is-extendable": "0.1.1" + "is-extendable": "0.1.1" + } + }, + "external-editor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", + "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", + "dev": true, + "requires": { + "chardet": "0.4.2", + "iconv-lite": "0.4.19", + "tmp": "0.0.33" } }, "extglob": { @@ -1102,6 +1615,25 @@ "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.2.0.tgz", "integrity": "sha1-bEZTc3j6tkkUa1phQ92gGbQwtBA=" }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, "file-type": { "version": "7.4.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-7.4.0.tgz", @@ -1173,6 +1705,29 @@ "locate-path": "2.0.0" } }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + }, + "dependencies": { + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + } + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -1234,6 +1789,18 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "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 + }, "gauge": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", @@ -1251,6 +1818,11 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" + }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", @@ -1303,6 +1875,12 @@ "is-glob": "2.0.1" } }, + "globals": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.1.0.tgz", + "integrity": "sha512-uEuWt9mqTlPDwSqi+sHjD4nWU/1N+q0fiWI9T1mZpD2UENqX20CFD5T/ziLZvztPaBKl7ZylUi1q6Qfm7E2CiQ==", + "dev": true + }, "globby": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", @@ -1322,6 +1900,11 @@ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", "dev": true }, + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==" + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -1336,6 +1919,32 @@ "har-schema": "2.0.0" } }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "dev": true, + "requires": { + "function-bind": "1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "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 + } + } + }, "has-binary2": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.2.tgz", @@ -1400,11 +2009,22 @@ "sntp": "2.1.0" } }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" + }, "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, "htmlparser2": { "version": "3.8.3", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", @@ -1459,6 +2079,18 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" }, + "ignore": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, "in-publish": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", @@ -1488,6 +2120,28 @@ "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "dev": true, + "requires": { + "ansi-escapes": "3.0.0", + "chalk": "2.3.0", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.1.0", + "figures": "2.0.0", + "lodash": "4.17.4", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + } + }, "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", @@ -1510,12 +2164,27 @@ "to-string-tag-x": "1.4.2" } }, + "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-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 }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", @@ -1648,6 +2317,30 @@ "is-primitive": "2.0.0" } }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.1" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -1674,6 +2367,18 @@ "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-resolvable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.1.tgz", + "integrity": "sha512-y5CXYbzvB3jTnWAZH1Nl7ykUWb6T3BcTs56HUruwBf8MhF56n1HWqhDWnVFo8GHrUPDgvUUNVhrc2U8W7iqz5g==", + "dev": true + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -1739,6 +2444,12 @@ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, + "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 + }, "js-yaml": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", @@ -1773,6 +2484,12 @@ "jsonify": "0.0.0" } }, + "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", @@ -1831,6 +2548,18 @@ "type-check": "0.3.2" } }, + "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, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", @@ -1845,6 +2574,12 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" }, + "lodash.cond": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", + "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=", + "dev": true + }, "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", @@ -2011,6 +2746,33 @@ } } }, + "mocha": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.0.0.tgz", + "integrity": "sha512-ukB2dF+u4aeJjc6IGtPNnJXfeby5d4ZqySlIBT0OEyva/DrMjVm5HkQxKnHDLKEfEQBsEnwTg9HHhtPHJdTd8w==", + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", + "mkdirp": "0.5.1", + "supports-color": "4.4.0" + }, + "dependencies": { + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "requires": { + "has-flag": "2.0.0" + } + } + } + }, "mockery": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mockery/-/mockery-2.1.0.tgz", @@ -2079,6 +2841,12 @@ "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.0.tgz", "integrity": "sha1-QCj3d4sXcIpImTCm5SrDvKDaQdA=" }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, "n-readlines": { "version": "0.2.8", "resolved": "https://registry.npmjs.org/n-readlines/-/n-readlines-0.2.8.tgz", @@ -2094,11 +2862,29 @@ "resolved": "https://registry.npmjs.org/nan-x/-/nan-x-1.0.0.tgz", "integrity": "sha512-yw4Fhe2/UTzanQ4f0yHWkRnfTuHZFAi4GZDjXS4G+qv5BqXTqPJBbSxpa7MyyW9v4Y4ZySZQik1vcbNkhdnIOg==" }, + "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 + }, "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.1" + } + }, "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", @@ -2223,6 +3009,15 @@ "wrappy": "1.0.2" } }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, "opn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.1.0.tgz", @@ -2324,6 +3119,15 @@ "trim-left-x": "3.0.0" } }, + "parse-json": { + "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.3.1" + } + }, "parseqs": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", @@ -2355,6 +3159,12 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", @@ -2371,6 +3181,20 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -2446,6 +3270,36 @@ } } }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true, + "requires": { + "find-up": "1.1.2" + }, + "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.1.0", + "pinkie-promise": "2.0.1" + } + }, + "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.1" + } + } + } + }, "pkg-fetch": { "version": "2.5.4", "resolved": "https://registry.npmjs.org/pkg-fetch/-/pkg-fetch-2.5.4.tgz", @@ -2626,6 +3480,12 @@ } } }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -2745,6 +3605,27 @@ "unpipe": "1.0.0" } }, + "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.4.0", + "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.1.0", + "read-pkg": "2.0.0" + } + }, "readable-stream": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", @@ -2875,6 +3756,16 @@ "is-nil-x": "1.4.1" } }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, "resolve": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", @@ -2884,6 +3775,22 @@ "path-parse": "1.0.5" } }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", @@ -2960,6 +3867,30 @@ "micromatch": "2.3.11" } }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "2.1.0" + } + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "4.0.8" + } + }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", @@ -3056,6 +3987,15 @@ "integrity": "sha1-XKsQ6FGqccZnt3th/hux2QpguqQ=", "dev": true }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0" + } + }, "slug": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/slug/-/slug-0.9.1.tgz", @@ -3189,6 +4129,27 @@ "amdefine": "1.0.1" } }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -3288,11 +4249,23 @@ "ansi-regex": "3.0.0" } }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, "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 + }, "supports-color": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", @@ -3301,6 +4274,20 @@ "has-flag": "2.0.0" } }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "dev": true, + "requires": { + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "chalk": "2.3.0", + "lodash": "4.17.4", + "slice-ansi": "1.0.0", + "string-width": "2.1.1" + } + }, "tcp-port-used": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-0.1.2.tgz", @@ -3318,12 +4305,33 @@ } } }, + "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 + }, "throttleit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", "dev": true }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2" + } + }, "to-array": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", @@ -3478,6 +4486,11 @@ "prelude-ls": "1.1.2" } }, + "type-detect": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.6.tgz", + "integrity": "sha512-qZ3bAurt2IXGPR3c57PyaSYEnQiLRwPeS60G9TahElBZsdOABo+iKYch/PhRjSTZJ5/DF08x43XMt9qec2g3ig==" + }, "type-is": { "version": "1.6.15", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", @@ -3487,6 +4500,12 @@ "mime-types": "2.1.17" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, "typedarray-to-buffer": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.2.tgz", @@ -3555,6 +4574,16 @@ "integrity": "sha1-Z6rzPEaypYel9mZtAPdpEyjxSdw=", "optional": true }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, "validate.io-undefined": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/validate.io-undefined/-/validate.io-undefined-1.0.3.tgz", diff --git a/package.json b/package.json index 7af6f08..b2fbf5d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "testmybot", - "version": "1.1.1", + "version": "1.1.2", "engines": { "node": ">=6.0" }, @@ -8,17 +8,20 @@ "testmybot": "./bin/testmybot.js" }, "scripts": { - "build": "rollup -c", - "buildbin": "./node_modules/.bin/pkg --out-path dist ./package.json", + "build": "npm run eslint && rollup -c", + "eslint": "eslint \"./src/**/*.js\" \"./bin/**/*.js\"", + "buildbin": "./node_modules/.bin/pkg --targets linux-x64,linux-x86,win-x64,win-x86,macos-x64,macos-x86 --out-path dist ./package.json", "newpatch": "npm version patch" }, "pkg": { "scripts": "src/**/*.js", "assets": [ + "bin/**/*", "src/emulator/browser/public/**/*", "src/emulator/browser/views/**/*", "node_modules/figlet/fonts/*", "node_modules/opn/xdg-open", + "node_modules/botium-core", "*.json" ] }, @@ -29,7 +32,8 @@ "dependencies": { "async": "^2.1.5", "body-parser": "^1.18.2", - "botium-core": "1.1.1", + "botium-core": "1.1.4", + "chai": "^4.1.2", "chalk": "^2.3.0", "clear": "0.0.1", "debug": "^3.1.0", @@ -40,6 +44,7 @@ "is-json": "^2.0.1", "lodash": "^4.17.4", "mkdirp": "^0.5.1", + "mocha": "^5.0.0", "mockery": "^2.1.0", "n-readlines": "^0.2.7", "opn": "^5.1.0", @@ -47,6 +52,12 @@ "yargs": "^10.1.1" }, "devDependencies": { + "eslint": "^4.15.0", + "eslint-config-standard": "^11.0.0-beta.0", + "eslint-plugin-import": "^2.8.0", + "eslint-plugin-node": "^5.2.1", + "eslint-plugin-promise": "^3.6.0", + "eslint-plugin-standard": "^3.0.1", "pkg": "^4.3.0-beta.5", "rollup": "^0.53.0", "rollup-plugin-buble": "^0.18.0", diff --git a/src/convo.js b/src/convo.js index fe949b6..b8663a5 100644 --- a/src/convo.js +++ b/src/convo.js @@ -1,239 +1,224 @@ -'use strict' - -const log = require('./util/log'); -const slugify = require('./util/slugify'); -const firstline = require('./util/firstline'); +const slugify = require('./util/slugify') +const firstline = require('./util/firstline') const fs = require('fs') const path = require('path') -const readdirSync = require('fs').readdirSync; -const mkdirp = require('mkdirp'); -const async = require('async'); -const EOL = "\n"; -const isJSON = require('is-json'); -const _ = require('lodash'); - -var convodir = './spec/convo/'; -var suffix = '.convo.txt'; - -function setConvoDir(c) { - convodir = c; +const readdirSync = require('fs').readdirSync +const mkdirp = require('mkdirp') +const async = require('async') +const isJSON = require('is-json') +const _ = require('lodash') +const debug = require('debug')('testmybot-convo') + +const EOL = '\n' + +var convodir = './spec/convo/' +var suffix = '.convo.txt' + +function setConvoDir (c) { + convodir = c } -function readConvos() { - return new Promise(function(readConvosResolve, readConvosReject) { +function readConvos () { + return new Promise((resolve, reject) => { fs.access(convodir, (err) => { - if (err) return readConvosResolve([]); - + if (err) return resolve([]) + fs.readdir(convodir, (err, filenames) => { - if (err) return readConvosReject(err); - - var convos = []; - - async.each(filenames, - (filename, callback) => { - if (!filename.endsWith(suffix)) { - callback(); - return; - } - firstline.firstline(path.resolve(convodir, filename)).then( - (header) => { - convos.push(createConvoEntry(filename, header)); - callback(); - }).catch( - (err) => { - log.warn('error reading first line of file ' + filename + ': ' + err); - callback(); - }); - }, - (err) => { - if (err) { - readConvosReject(err) - } else { - readConvosResolve(convos); - } - }); - }); - }); - }); + if (err) return reject(err) + + var convos = [] + + async.each(filenames, (filename, callback) => { + if (!filename.endsWith(suffix)) { + callback() + return + } + firstline.firstline(path.resolve(convodir, filename)).then( + (header) => { + convos.push(createConvoEntry(filename, header)) + callback() + }).catch( + (err) => { + debug('error reading first line of file ' + filename + ': ' + err) + callback() + }) + }, + (err) => { + if (err) reject(err) + else resolve(convos) + }) + }) + }) + }) } -function readConvosSync() { - var filenames = readdirSync(convodir).filter((filename) => filename.endsWith(suffix)); - var convos = []; - filenames.forEach(function (filename) { - var header = firstline.firstlineSync(path.resolve(convodir, filename)); - convos.push(createConvoEntry(filename, header)); - }); - return convos; +function readConvosSync () { + var filenames = readdirSync(convodir).filter((filename) => filename.endsWith(suffix)) + var convos = [] + filenames.forEach((filename) => { + var header = firstline.firstlineSync(path.resolve(convodir, filename)) + convos.push(createConvoEntry(filename, header)) + }) + return convos } -function createConvoEntry(filename, header) { - if (!header || header.startsWith('#')) - header = filename; - +function createConvoEntry (filename, header) { + if (!header || header.startsWith('#')) header = filename + return { name: header.trim(), filename: filename - }; + } } -function readConvo(filename) { - - var convofilename = path.resolve(convodir, filename); - - var parseMsg = function(lines) { - if (!lines) return null; - - var content = lines.join(' '); +function readConvo (filename) { + var convofilename = path.resolve(convodir, filename) + + var parseMsg = (lines) => { + if (!lines) return null + + var content = lines.join(' ') if (isJSON(content)) { - return JSON.parse(content); + return JSON.parse(content) } else { - return lines.join(EOL); + return lines.join(EOL) } - }; - - return new Promise(function(readConvoResolve, readConvoReject) { - + } + + return new Promise((resolve, reject) => { fs.readFile(convofilename, (err, content) => { - if (err) return readConvoReject(err); - - var lines = content.toString().split(EOL); + if (err) return reject(err) + + var lines = content.toString().split(EOL) var convo = { filename: filename, conversation: [] - }; - - var currentLines = []; - var currentFrom = null; - var currentChannel = null; + } + + var currentLines = [] + var currentFrom = null + var currentChannel = null lines.forEach((line) => { - line = line.trim(); + line = line.trim() if (!line) { - return; } else if (line.startsWith('#')) { if (currentFrom && currentLines) { convo.conversation.push({ from: currentFrom, channel: currentChannel, msg: parseMsg(currentLines) - }); + }) } else if (!currentFrom && currentLines) { - convo.name = currentLines[0]; + convo.name = currentLines[0] if (currentLines.length > 1) { - convo.description = currentLines.slice(1).join(EOL); + convo.description = currentLines.slice(1).join(EOL) } } - currentFrom = line.substr(1); - currentChannel = null; + currentFrom = line.substr(1) + currentChannel = null if (currentFrom.indexOf(' ') > 0) { - currentChannel = currentFrom.substr(currentFrom.indexOf(' ') + 1).trim(); - currentFrom = currentFrom.substr(0, currentFrom.indexOf(' ')).trim(); + currentChannel = currentFrom.substr(currentFrom.indexOf(' ') + 1).trim() + currentFrom = currentFrom.substr(0, currentFrom.indexOf(' ')).trim() } - currentLines = []; + currentLines = [] } else { - currentLines.push(line); + currentLines.push(line) } - }); + }) if (currentFrom && currentLines) { convo.conversation.push({ from: currentFrom, channel: currentChannel, msg: parseMsg(currentLines) - }); + }) } else if (!currentFrom && currentLines) { - convo.name = currentLines[0]; + convo.name = currentLines[0] if (currentLines.length > 1) { - convo.description = currentLines.slice(1).join(EOL); + convo.description = currentLines.slice(1).join(EOL) } } - - if (convo.conversation.length === 0) { - readConvoReject('empty conversation file ' + convofilename); - } else { - readConvoResolve(convo); + + if (convo.conversation.length === 0) { + reject(new Error('empty conversation file ' + convofilename)) + } else { + resolve(convo) } - }); - }); + }) + }) } -function writeConvo(convo, errorIfExists) { - +function writeConvo (convo, errorIfExists) { if (!convo.filename) { - convo.filename = slugify(convo.name); + convo.filename = slugify(convo.name) + } + if (!convo.filename.endsWith(suffix)) { + convo.filename += suffix } - if (!convo.filename.endsWith(suffix)) - convo.filename += suffix; - var filename = path.resolve(convodir, convo.filename); - - return new Promise(function(writeConvoResolve, writeConvoReject) { + var filename = path.resolve(convodir, convo.filename) + return new Promise((resolve, reject) => { async.series([ - - function(existsCheckDone) { - if (errorIfExists) + (existsCheckDone) => { + if (errorIfExists) { fs.access(filename, (err) => { - if (err) return existsCheckDone(); - existsCheckDone(filename + ' already exists'); - }); - else { - existsCheckDone(); + if (err) return existsCheckDone() + existsCheckDone(filename + ' already exists') + }) + } else { + existsCheckDone() } }, - - function(createDirectoryDone) { - mkdirp(convodir, (err) => { - if (err) return createDirectoryDone(err); - createDirectoryDone(); - }); + + (createDirectoryDone) => { + mkdirp(convodir, (err) => { + if (err) return createDirectoryDone(err) + createDirectoryDone() + }) }, - - function(writeConvoDone) { - - var contents = ''; - - contents += convo.name + EOL; - if (convo.description) - contents += convo.description + EOL; - contents += EOL; - - convo.conversation.forEach(function (set) { - contents += '#' + set.from; + + (writeConvoDone) => { + var contents = '' + + contents += convo.name + EOL + if (convo.description) { + contents += convo.description + EOL + } + contents += EOL + + convo.conversation.forEach((set) => { + contents += '#' + set.from if (set.channel) { - contents += ' ' + set.channel; + contents += ' ' + set.channel } - contents += EOL; - + contents += EOL + if (_.isString(set.msg)) { - contents += set.msg + EOL + EOL; + contents += set.msg + EOL + EOL } else { - contents += JSON.stringify(set.msg, null, 2) + EOL + EOL; + contents += JSON.stringify(set.msg, null, 2) + EOL + EOL } - }); - - fs.writeFile(filename, contents, (err) => { - if (err) return writeConvoDone(err); - writeConvoDone(); - }); - }, + }) + fs.writeFile(filename, contents, (err) => { + if (err) return writeConvoDone(err) + writeConvoDone() + }) + } ], - function(err) { - if (err) - writeConvoReject(err); - else - writeConvoResolve(filename); - }); - }); + (err) => { + if (err) reject(err) + else resolve(filename) + }) + }) } - module.exports = { setConvoDir: setConvoDir, - writeConvo: writeConvo, + writeConvo: writeConvo, readConvos: readConvos, readConvo: readConvo, readConvosSync: readConvosSync -}; +} diff --git a/src/emulator/browser/index.js b/src/emulator/browser/index.js index f956ba4..2fb7474 100644 --- a/src/emulator/browser/index.js +++ b/src/emulator/browser/index.js @@ -1,5 +1,6 @@ const testmybot = require('../../testmybot'); const convo = require('../../convo'); +const moduleinfo = require('../../util/moduleinfo') const path = require('path') const chalk = require('chalk'); const clear = require('clear'); @@ -79,16 +80,8 @@ module.exports = () => { appIde.use("/public", express.static(__dirname + '/public')); appIde.get('/', function (req, res) { - let packageJson = { - name: 'TestMyBot module', - version: 'unknown' - }; - try { - packageJson = require(path.resolve(process.cwd(), 'package.json')); - } catch (e) { - } const data = { - module: packageJson, + module: moduleinfo(), config: { } }; diff --git a/src/helpers/botkit.js b/src/helpers/botkit.js index b5ab003..38c1cdd 100644 --- a/src/helpers/botkit.js +++ b/src/helpers/botkit.js @@ -1,14 +1,13 @@ -const mockery = require('mockery'); -const _ = require('lodash'); +const mockery = require('mockery') +const _ = require('lodash') -const tmb = require('../testmybot'); -const testbuilder = require('../testbuilder'); -const Queue = require('botium-core/src/helpers/Queue'); +const tmb = require('../testmybot') +const Queue = require('botium-core/src/helpers/Queue') -let controller = null; -let msgqueue = null; -let bot = null; -let timeoutMillisDefault = 5000; +let controller = null +let msgqueue = null +let bot = null +let timeoutMillisDefault = 5000 /** * Setup TestMyBot and wire it with Botkit @@ -19,92 +18,92 @@ let tmbMock = { afterEach: () => Promise.resolve(), afterAll: () => Promise.resolve(), hears: (arg) => { - let message = null; - let postback = null; - + let message = null + let postback = null + if (_.isString(arg)) { message = { text: arg, seq: 1, is_echo: false, mid: 1 - }; + } } else if (arg.messageText) { message = { text: arg.messageText, seq: 1, is_echo: false, mid: 1 - }; + } } else if (arg.sourceData && arg.sourceData.postback) { - postback = arg.sourceData.postback; + postback = arg.sourceData.postback } else if (arg.sourceData) { message = { text: arg.sourceData, seq: 1, is_echo: false, mid: 1 - }; + } } else { - return Promise.resolve(); + return Promise.resolve() } - + controller.handleWebhookPayload( - { - body: { - entry: [ - { - messaging: [ - { - sender: { id: arg.sender }, - recipient: { id: 1 }, - timestamp: 1, - message: message, - postback: postback - } - ] - } - ] - } - }, null, bot); - return Promise.resolve(); + { + body: { + entry: [ + { + messaging: [ + { + sender: { id: arg.sender }, + recipient: { id: 1 }, + timestamp: 1, + message: message, + postback: postback + } + ] + } + ] + } + }, null, bot) + return Promise.resolve() }, says: (channel, timeoutMillis) => { - return msgqueue.pop(timeoutMillis ? timeoutMillis : timeoutMillisDefault); + return msgqueue.pop(timeoutMillis || timeoutMillisDefault) } -}; -tmbMock = Object.assign(tmb, tmbMock); +} +tmbMock = Object.assign(tmb, tmbMock) -mockery.registerMock('testmybot', tmbMock); +mockery.registerMock('testmybot', tmbMock) mockery.enable({ - warnOnReplace: false, - warnOnUnregistered: false -}); + warnOnReplace: false, + warnOnUnregistered: false +}) -module.exports.wireWithBotkit = function(beforeEachCallback, _timeoutMillisDefault) { +module.exports.wireWithBotkit = (beforeEachCallback, _timeoutMillisDefault) => { tmb.beforeEach = () => { - msgqueue = new Queue(); + msgqueue = new Queue() if (_timeoutMillisDefault) { - timeoutMillisDefault = _timeoutMillisDefault; + timeoutMillisDefault = _timeoutMillisDefault } - - controller = beforeEachCallback(); - controller.startTicking(); - controller.on('spawned', function(worker) { - worker.send = function(message, cb) { + controller = beforeEachCallback() + controller.startTicking() + + controller.on('spawned', (worker) => { + worker.send = (message, cb) => { if (message.message && message.message.text) { - msgqueue.push({ messageText: message.message.text }); + msgqueue.push({ messageText: message.message.text }) } else { - msgqueue.push({ sourceData: message }); + msgqueue.push({ sourceData: message }) } if (cb) { - cb(); + cb() } - }; - }); - bot = controller.spawn({}); - - return Promise.resolve(); - }; -}; + } + }) + bot = controller.spawn({}) + + return Promise.resolve() + } +} diff --git a/src/helpers/jasmine.js b/src/helpers/jasmine.js index 9cc9513..1c84e0f 100644 --- a/src/helpers/jasmine.js +++ b/src/helpers/jasmine.js @@ -1,65 +1,65 @@ -const path = require('path') +/* global describe it beforeAll beforeEach afterAll afterEach expect fail */ -const testbuilder = require('../testbuilder'); -const testmybot = require('../testmybot'); +const testbuilder = require('../testbuilder') +const testmybot = require('../testmybot') +const moduleinfo = require('../util/moduleinfo') -module.exports.setupJasmineTestCases = function(timeout, matcher) { - - if (!timeout) timeout = 60000; - if (!(matcher && typeof matcher === 'function')) matcher = (response, tomatch) => { - expect(response).toContain(tomatch); - }; +module.exports.setupJasmineTestCases = (timeout, matcher) => { + if (!timeout) timeout = 60000 + if (!(matcher && typeof matcher === 'function')) { + matcher = (response, tomatch) => { + expect(response).toContain(tomatch) + } + } testbuilder.setupTestSuite( (testcaseName, testcaseFunction) => { - it(testcaseName, testcaseFunction, timeout); + it(testcaseName, testcaseFunction, timeout) }, matcher, (err) => fail(err), testmybot.hears, testmybot.says - ); -}; + ) +} -module.exports.setupJasmineTestSuite = function(timeout, matcher) { +module.exports.setupJasmineTestSuite = (timeout, matcher) => { + if (!timeout) timeout = 60000 - if (!timeout) timeout = 60000; + var packageJson = moduleinfo() - var packageJson = require(path.resolve(process.cwd(), 'package.json')); - - describe('TestMyBot Test Suite for ' + packageJson.name, function() { - - beforeAll(function(done) { - testmybot.beforeAll().then(done, done.fail); - }, timeout); + describe('TestMyBot Test Suite for ' + packageJson.name, () => { + beforeAll((done) => { + testmybot.beforeAll().then(done, done.fail) + }, timeout) - beforeEach(function(done) { - testmybot.beforeEach().then(done, done.fail); - }, timeout); + beforeEach((done) => { + testmybot.beforeEach().then(done, done.fail) + }, timeout) - afterEach(function(done) { - testmybot.afterEach().then(done, done.fail); - }, timeout); - - afterAll(function(done) { - testmybot.afterAll().then(done, done.fail); - }, timeout); - - module.exports.setupJasmineTestCases(timeout, matcher); - }); -}; + afterEach((done) => { + testmybot.afterEach().then(done, done.fail) + }, timeout) -module.exports.generateJUnit = function() { - const Jasmine = require.main.require('jasmine'); - const JasmineReporters = require.main.require('jasmine-reporters'); + afterAll((done) => { + testmybot.afterAll().then(done, done.fail) + }, timeout) + + module.exports.setupJasmineTestCases(timeout, matcher) + }) +} + +module.exports.generateJUnit = () => { + const Jasmine = require.main.require('jasmine') + const JasmineReporters = require.main.require('jasmine-reporters') var junitReporter = new JasmineReporters.JUnitXmlReporter({ savePath: process.cwd(), consolidateAll: true - }); + }) - const jasmine = new Jasmine(); - jasmine.addReporter(junitReporter); - jasmine.loadConfigFile(process.cwd() + '/spec/support/jasmine.json'); - jasmine.execute(); -}; + const jasmine = new Jasmine() + jasmine.addReporter(junitReporter) + jasmine.loadConfigFile(process.cwd() + '/spec/support/jasmine.json') + jasmine.execute() +} diff --git a/src/helpers/mocha.js b/src/helpers/mocha.js index bd22d4c..6bbf9c5 100644 --- a/src/helpers/mocha.js +++ b/src/helpers/mocha.js @@ -1,53 +1,54 @@ -const path = require('path') -const expect = require.main.require('chai').expect; -const testbuilder = require('../testbuilder'); -const testmybot = require('../testmybot'); +/* global describe it before beforeEach after afterEach */ -module.exports.setupMochaTestCases = function(timeout, matcher) { +const expect = require('chai').expect +const testbuilder = require('../testbuilder') +const testmybot = require('../testmybot') +const moduleinfo = require('../util/moduleinfo') - if (!timeout) timeout = 60000; - if (!(matcher && typeof matcher === 'function')) matcher = (response, tomatch, msg) => { - expect(response).to.include(tomatch, msg); - }; +module.exports.setupMochaTestCases = (timeout, matcher) => { + if (!timeout) timeout = 60000 + if (!(matcher && typeof matcher === 'function')) { + matcher = (response, tomatch, msg) => { + expect(response).to.include(tomatch, msg) + } + } testbuilder.setupTestSuite( (testcaseName, testcaseFunction) => { - it(testcaseName, testcaseFunction).timeout(timeout); + it(testcaseName, testcaseFunction).timeout(timeout) }, matcher, (err) => { - expect.fail(null, null, err); - }, + expect.fail(null, null, err) + }, testmybot.hears, testmybot.says - ); -}; + ) +} + +module.exports.setupMochaTestSuite = (timeout, matcher) => { + if (!timeout) timeout = 60000 -module.exports.setupMochaTestSuite = function(timeout, matcher) { + var packageJson = moduleinfo() - if (!timeout) timeout = 60000; + describe('TestMyBot Test Suite for ' + packageJson.name, () => { + before(function (done) { + this.timeout(timeout) + testmybot.beforeAll().then(() => done()).catch(done) + }) + beforeEach(function (done) { + this.timeout(timeout) + testmybot.beforeEach().then(() => done()).catch(done) + }) + afterEach(function (done) { + this.timeout(timeout) + testmybot.afterEach().then(() => done()).catch(done) + }) + after(function (done) { + this.timeout(timeout) + testmybot.afterAll().then(() => done()).catch(done) + }) - var packageJson = require(path.resolve(process.cwd(), 'package.json')); - - describe('TestMyBot Test Suite for ' + packageJson.name, function() { - - before(function(done) { - this.timeout(timeout); - testmybot.beforeAll().then(() => done()).catch(done); - }); - beforeEach(function(done) { - this.timeout(timeout); - testmybot.beforeEach().then(() => done()).catch(done); - }); - afterEach(function(done) { - this.timeout(timeout); - testmybot.afterEach().then(() => done()).catch(done); - }); - after(function(done) { - this.timeout(timeout); - testmybot.afterAll().then(() => done()).catch(done); - }); - - module.exports.setupMochaTestCases(timeout, matcher); - }); -}; + module.exports.setupMochaTestCases(timeout, matcher) + }) +} diff --git a/src/readconfig.js b/src/readconfig.js index 6bb62bb..dd09101 100644 --- a/src/readconfig.js +++ b/src/readconfig.js @@ -1,73 +1,65 @@ -'use strict' +const path = require('path') +const fs = require('fs') +const async = require('async') +const _ = require('lodash') +const debug = require('debug')('testmybot-readconfig') -const log = require('./util/log'); +let configfile = 'testmybot.json' -const path = require('path'); -const fs = require('fs'); -const async = require('async'); -const _ = require('lodash'); - -let configfile = 'testmybot.json'; - -function setConfigFile(c) { - configfile = c; +function setConfigFile (c) { + configfile = c } -function readAndMergeConfig(configToSet) { - return new Promise(function(getConfigResolve, getConfigReject) { +function readAndMergeConfig (configToSet) { + return new Promise((resolve, reject) => { + var resolvedConfig = {} - var resolvedConfig = {}; - async.series([ - - function(readDefaultConfigDone) { + (readDefaultConfigDone) => { fs.readFile(path.resolve(__dirname, '../testmybot.default.json'), (err, contents) => { if (err) { - log.info('could not read file testmybot.default.json: ' + err); - readDefaultConfigDone(); + debug('could not read file testmybot.default.json: ' + err) + readDefaultConfigDone() } else { - var configJson = JSON.parse(contents); + var configJson = JSON.parse(contents) if (configJson) { - _.merge(resolvedConfig, configJson); + _.merge(resolvedConfig, configJson) } - readDefaultConfigDone(); + readDefaultConfigDone() } - }); + }) }, - - function(readConfigDone) { + + (readConfigDone) => { fs.readFile(configfile, (err, contents) => { if (err) { - log.warn('could not read file testmybot.json: ' + err); - readConfigDone(); + debug('could not read file testmybot.json: ' + err) + readConfigDone() } else { - var configJson = JSON.parse(contents); + var configJson = JSON.parse(contents) if (configJson) { - _.merge(resolvedConfig, configJson); + _.merge(resolvedConfig, configJson) } - readConfigDone(); + readConfigDone() } - }); + }) }, - - function(mergeManualConfigDone) { + + (mergeManualConfigDone) => { if (configToSet) { - _.merge(resolvedConfig, configToSet); + _.merge(resolvedConfig, configToSet) } - mergeManualConfigDone(); + mergeManualConfigDone() } - ], - function(err) { - if (err) - getConfigReject(err); - else - getConfigResolve(resolvedConfig); - }); - }); + (err) => { + if (err) reject(err) + else resolve(resolvedConfig) + }) + }) } module.exports = { setConfigFile: setConfigFile, readAndMergeConfig: readAndMergeConfig -}; \ No newline at end of file +} diff --git a/src/testbuilder.js b/src/testbuilder.js index 2d6c0fc..1ae73aa 100644 --- a/src/testbuilder.js +++ b/src/testbuilder.js @@ -1,96 +1,88 @@ -'use strict'; +const convo = require('./convo') -const log = require('./util/log'); -const convo = require('./convo'); +const util = require('util') +const async = require('async') +const _ = require('lodash') +const debug = require('debug')('testmybot-readconfig') -const util = require('util'); -const async = require('async'); -const _ = require('lodash'); +function setupTestSuite (testcaseCb, assertCb, failCb, hears, says) { + var testcaseConvos = convo.readConvosSync() + + testcaseConvos.forEach((testcaseConvo) => { + debug('adding test case ' + testcaseConvo.name + ' (file: ' + testcaseConvo.filename + ')') + + testcaseCb(testcaseConvo.name, (testcaseDone) => { + debug('running testcase ' + testcaseConvo.name) -function setupTestSuite(testcaseCb, assertCb, failCb, hears, says) { - - var testcaseConvos = convo.readConvosSync(); - - testcaseConvos.forEach(function(testcaseConvo) { - log.info('adding test case ' + testcaseConvo.name + ' (file: ' + testcaseConvo.filename + ')'); - - testcaseCb(testcaseConvo.name, function(testcaseDone) { - log.info('running testcase ' + testcaseConvo.name); - convo.readConvo(testcaseConvo.filename).then( (testcase) => { - async.eachSeries(testcase.conversation, (convomsg, convomsgDone) => { - if (convomsg.from === 'me') { - log.debug(testcase.name + ': user says ' + convomsg.msg); + debug(testcase.name + ': user says ' + convomsg.msg) if (_.isString(convomsg.msg)) { - hears({ messageText: convomsg.msg, sender: convomsg.from, channel: convomsg.channel }).then(() => convomsgDone()).catch(convomsgDone); + hears({ messageText: convomsg.msg, sender: convomsg.from, channel: convomsg.channel }).then(() => convomsgDone()).catch(convomsgDone) } else { - hears({ sourceData: convomsg.msg, sender: convomsg.from, channel: convomsg.channel }).then(() => convomsgDone()).catch(convomsgDone); + hears({ sourceData: convomsg.msg, sender: convomsg.from, channel: convomsg.channel }).then(() => convomsgDone()).catch(convomsgDone) } } else if (convomsg.from === 'bot') { - log.debug(testcase.name + ': wait for bot says (channel: ' + convomsg.channel + ')'); + debug(testcase.name + ': wait for bot says (channel: ' + convomsg.channel + ')') says(convomsg.channel).then((saysmsg) => { if (saysmsg && saysmsg.messageText) { - log.debug(testcase.name + ': bot says ' + saysmsg.messageText); + debug(testcase.name + ': bot says ' + saysmsg.messageText) - var response = saysmsg.messageText.split(/\r?\n/).map((line) => line.trim()).join(' ').trim(); - var tomatch = convomsg.msg.split(/\r?\n/).map((line) => line.trim()).join(' ').trim(); - assertCb(response, tomatch); + var response = saysmsg.messageText.split(/\r?\n/).map((line) => line.trim()).join(' ').trim() + var tomatch = convomsg.msg.split(/\r?\n/).map((line) => line.trim()).join(' ').trim() + assertCb(response, tomatch) } else if (saysmsg && saysmsg.sourceData) { - log.debug(testcase.name + ': bot says ' + JSON.stringify(saysmsg.sourceData)); + debug(testcase.name + ': bot says ' + JSON.stringify(saysmsg.sourceData)) - compareObject(assertCb, failCb, saysmsg.sourceData, convomsg.msg); + compareObject(assertCb, failCb, saysmsg.sourceData, convomsg.msg) } else { - log.debug(testcase.name + ': bot says nothing'); - - failCb('bot says nothing'); + debug(testcase.name + ': bot says nothing') + + failCb('bot says nothing') } - convomsgDone(); + convomsgDone() }).catch((err) => { - convomsgDone(err); - }); + convomsgDone(err) + }) } }, (err) => { if (err) { - log.info(testcase.name + ' failed: ' + util.inspect(err)); - testcaseDone(err); + debug(testcase.name + ' failed: ' + util.inspect(err)) + testcaseDone(err) } else { - log.info(testcase.name + ' ready, calling done function.'); - testcaseDone(); - } - }); - }, + debug(testcase.name + ' ready, calling done function.') + testcaseDone() + } + }) + }, (err) => { - log.info(testcaseConvo.name + ' failed reading ' + testcaseConvo.filename + ': ' + err); - testcaseDone(err); - }); - }); - }); + debug(testcaseConvo.name + ' failed reading ' + testcaseConvo.filename + ': ' + err) + testcaseDone(err) + }) + }) + }) } -function compareObject(assertCb, failCb, result, expected) { +function compareObject (assertCb, failCb, result, expected) { + if (expected === null || expected === undefined) return - if (expected === null || expected === undefined) - return; - if (_.isObject(expected)) { - _.forOwn(expected, function(value, key) { - + _.forOwn(expected, (value, key) => { if (result.hasOwnProperty(key)) { - compareObject(assertCb, failCb, result[key], expected[key]); + compareObject(assertCb, failCb, result[key], expected[key]) } else { - failCb('missing property: ' + key); + failCb('missing property: ' + key) } - }); + }) } else { - assertCb(result, expected); + assertCb(result, expected) } } module.exports = { setupTestSuite: setupTestSuite -}; \ No newline at end of file +} diff --git a/src/testmybot.js b/src/testmybot.js index f742862..7a146aa 100644 --- a/src/testmybot.js +++ b/src/testmybot.js @@ -1,120 +1,113 @@ -'use strict'; +const readConfig = require('./readconfig') +const testbuilder = require('./testbuilder') +const BotDriver = require('botium-core').BotDriver -const log = require('./util/log'); -const readConfig = require('./readconfig'); -const testbuilder = require('./testbuilder'); -const BotDriver = require('botium-core').BotDriver; +const async = require('async') +const _ = require('lodash') +const debug = require('debug')('testmybot-readconfig') -const async = require('async'); -const _ = require('lodash'); +var config = { } +var driver = null +var container = null -var config = { }; -var driver = null; -var container = null; - -function beforeAll(configToSet) { - return new Promise(function(beforeAllResolve, beforeAllReject) { - +function beforeAll (configToSet) { + return new Promise((resolve, reject) => { async.series([ - - function(readConfigDone) { - readConfig.readAndMergeConfig(configToSet).then(function(resolvedConfig) { - config = resolvedConfig; - readConfigDone(); - }).catch(function(err) { - readConfigDone(err); - }); + (readConfigDone) => { + readConfig.readAndMergeConfig(configToSet).then((resolvedConfig) => { + config = resolvedConfig + readConfigDone() + }).catch((err) => { + readConfigDone(err) + }) }, - - function(containerReady) { - log.debug(JSON.stringify(config, null, 2)); - - driver = new BotDriver() - .setCapabilities(config.botium.Capabilities) - .setEnvs(config.botium.Envs) - .setSources(config.botium.Sources); - driver.Build() - .then((c) => { - container = c; - containerReady(); - }) - .catch(containerReady); - }, + (containerReady) => { + debug(JSON.stringify(config, null, 2)) + + driver = new BotDriver() + .setCapabilities(config.botium.Capabilities) + .setEnvs(config.botium.Envs) + .setSources(config.botium.Sources) + + driver.Build() + .then((c) => { + container = c + containerReady() + }) + .catch(containerReady) + } ], - function(err) { - if (err) - beforeAllReject(err); - else - beforeAllResolve(config); - }); - }); - + (err) => { + if (err) reject(err) + else resolve(config) + }) + }) } -function on(event, listener) { +function on (event, listener) { if (driver) { - driver.on(event, listener); + driver.on(event, listener) } } -function afterAll() { - let result = Promise.resolve(); +function afterAll () { + let result = Promise.resolve() if (container) { - result = container.Clean(); + result = container.Clean() } - container = null; - driver = null; - return result; + container = null + driver = null + return result } -function beforeEach() { +function beforeEach () { if (container) { - return container.Start(); + return container.Start() } else { - return Promise.reject('container not available'); + return Promise.reject(new Error('container not available')) } } -function afterEach() { +function afterEach () { if (container) { - return container.Stop(); + return container.Stop() } else { - return Promise.resolve(); + return Promise.resolve() } } -function setupTestSuite(testcaseCb, assertCb, failCb) { - testbuilder.setupTestSuite(testcaseCb, assertCb, failCb, hears, says); +function setupTestSuite (testcaseCb, assertCb, failCb) { + testbuilder.setupTestSuite(testcaseCb, assertCb, failCb, hears, says) } -function hears(arg) { +function hears (arg) { if (container) { if (_.isString(arg)) { - return container.UserSaysText(arg); + return container.UserSaysText(arg) } else { - return container.UserSays(arg); + return container.UserSays(arg) } } else { - return Promise.reject('container not available'); + return Promise.reject(new Error('container not available')) } } -function says(channel, timeoutMillis) { +function says (channel, timeoutMillis) { if (container) { - return container.WaitBotSays(channel, timeoutMillis); + return container.WaitBotSays(channel, timeoutMillis) } else { - return Promise.reject('container not available'); + return Promise.reject(new Error('container not available')) } } module.exports = { beforeAll: beforeAll, afterAll: afterAll, - beforeEach : beforeEach, + beforeEach: beforeEach, afterEach: afterEach, setupTestSuite: setupTestSuite, on: on, hears: hears, says: says -}; \ No newline at end of file +} diff --git a/src/util/firstline.js b/src/util/firstline.js index a741f55..4c7ca7c 100644 --- a/src/util/firstline.js +++ b/src/util/firstline.js @@ -1,44 +1,42 @@ -'use strict'; +const fs = require('fs') +const EOL = require('os').EOL +const LineByLine = require('n-readlines') -const fs = require('fs'); -const EOL = require('os').EOL; -const lineByLine = require('n-readlines'); - -function firstline(path) { +function firstline (path) { return new Promise(function (resolve, reject) { - var rs = fs.createReadStream(path); - var acc = ''; - var pos = 0; - var index; + var rs = fs.createReadStream(path) + var acc = '' + var pos = 0 + var index rs .on('data', function (chunk) { - index = chunk.indexOf(EOL); - acc += chunk; + index = chunk.indexOf(EOL) + acc += chunk if (index === -1) { - pos += chunk.length; + pos += chunk.length } else { - pos += index; - rs.close(); + pos += index + rs.close() } }) .on('close', function () { - resolve(acc.slice(0, pos)); + resolve(acc.slice(0, pos)) }) .on('error', function (err) { - reject(err); + reject(err) }) - }); + }) } -function firstlineSync(path) { - var liner = new lineByLine(path); - var line = liner.next(); +function firstlineSync (path) { + var liner = new LineByLine(path) + var line = liner.next() if (line) { - return line.toString(); + return line.toString() } } module.exports = { firstline: firstline, firstlineSync: firstlineSync -}; \ No newline at end of file +} diff --git a/src/util/log.js b/src/util/log.js deleted file mode 100644 index 0c4e9b1..0000000 --- a/src/util/log.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict'; - -const url = require('url'); - -function debug(message) { - if (process.env.DEBUG) - console.log('DEBUG: ' + message); -} - -function info(message) { - console.log('INFO: ' + message); -} - -function warn(message) { - console.log('WARN: ' + message); -} - -function error(message) { - console.log('ERROR: ' + message); -} - -function debugReq(req) { - var fullUrl = url.format({ - protocol: req.protocol, - host: req.get('host'), - pathname: req.url - }); - - debug('METHOD: ' + req.method); - debug('URL: ' + fullUrl); - if (req.body) { - debug('BODY: ' + JSON.stringify(req.body)); - } - debug('--------------'); -} - -module.exports = { - debug: debug, - debugReq: debugReq, - info: info, - warn: warn, - error: error -}; diff --git a/src/util/moduleinfo.js b/src/util/moduleinfo.js new file mode 100644 index 0000000..a229108 --- /dev/null +++ b/src/util/moduleinfo.js @@ -0,0 +1,23 @@ +const path = require('path') + +module.exports = () => { + let packageJson = null + + try { + packageJson = require(path.resolve(process.cwd(), 'package.json')) + } catch (e) { + } + if (!packageJson) { + try { + let tmb = require(path.resolve(process.cwd(), 'testmybot.json')) + packageJson = { + name: tmb.botium.Capabilities.PROJECTNAME + } + } catch (e) { + } + } + if (!packageJson) packageJson = {} + if (!packageJson.name) packageJson.name = '' + if (!packageJson.version) packageJson.version = 'unknown' + return packageJson +} diff --git a/src/util/slugify.js b/src/util/slugify.js index 7310c18..bc66272 100644 --- a/src/util/slugify.js +++ b/src/util/slugify.js @@ -1,12 +1,10 @@ -'use strict' +const slugifyStripRe = /[^\w\s-]/g +const slugifyHyphenateRe = /[-\s]+/g -var _slugify_strip_re = /[^\w\s-]/g; -var _slugify_hyphenate_re = /[-\s]+/g; - -function slugify(s) { - s = s.replace(_slugify_strip_re, '').trim().toLowerCase(); - s = s.replace(_slugify_hyphenate_re, '-'); - return s; +function slugify (s) { + s = s.replace(slugifyStripRe, '').trim().toLowerCase() + s = s.replace(slugifyHyphenateRe, '-') + return s } -module.exports = slugify; +module.exports = slugify