diff --git a/.babelrc b/.babelrc index a935db3..582252c 100644 --- a/.babelrc +++ b/.babelrc @@ -5,6 +5,7 @@ ], "plugins": [ "transform-runtime", - "external-helpers" + "external-helpers", + "array-includes" ] } diff --git a/Makefile b/Makefile index b696acc..a166037 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,8 @@ test: coverage test-coverage code-coverage: # if there's no instance source maps files then build the files with source maps @[ -f ./dist/index.js.map ] || (echo "building files with source maps" && make build-source-maps) - NODE_ENV="test" nyc make test -- --verbose + NODE_ENV="test" nyc --silent -- ava --verbose --no-cache + # These commands only run the report of the code coverage report-coverage report-code-coverage: @@ -69,7 +70,13 @@ report-coverage report-code-coverage: # The command the ci server runs ci: - make lint build-source-maps coverage -i + make lint build-source-maps -i + # if the tests fail then it will exit with an error + make coverage || exit 1 + # show the coverage report + nyc report + # check check-coverage and if it fails then exit + nyc check-coverage --statements 95 --functions 95 --lines 95 || exit 1 # "patch", "minor", "major", "prepatch", VERS ?= "patch" diff --git a/app/base.js b/app/base.js index 031aa00..21bdd8d 100644 --- a/app/base.js +++ b/app/base.js @@ -12,14 +12,17 @@ export default class Base extends Logger { /// @raw-code constructor(options = {}) { super(options); + const root = process.cwd(); this.options = to.extend({ - root: process.cwd(), + root, log: true, verbose: false, timestamp: true, }, this.options || {}); this.options = to.extend(this.options, options); + this.options.root = path.resolve(root, this.options.root); + if (this.options.verbose) { this.options.log = true; } diff --git a/app/models.js b/app/models.js index 672cb62..776d03a 100644 --- a/app/models.js +++ b/app/models.js @@ -8,6 +8,7 @@ import { set, get, find } from 'lodash'; import to, { is } from 'to-js'; import { transform } from 'babel-core'; import globby from 'globby'; +import findRoot from 'find-root'; //// /// @name Models @@ -64,14 +65,27 @@ export default class Models extends Base { return; } - const dir = path.join(__dirname.split('node_modules')[0], '..'); - let file = await globby(this.resolvePaths(babel_config, dir), { dot: true }); + let file = [ process.cwd(), this.options.root ] + .reduce((prev, next) => { + try { + return prev.concat(path.join(findRoot(next), babel_config)); + } catch (e) { + return prev; + } + }, []); + + file = await globby(to.unique(file), { dot: true }); file = file[0]; - let config = await fs.readJson(file); - if (file.includes('package.json')) { - config = config.babelConfig || {}; + + if (file) { + let config = await fs.readJson(file); + if (file.includes('package.json')) { + config = config.babelConfig || {}; + } + + this.options.babel_config = config; } - this.options.babel_config = config; + this.prepared = true; } diff --git a/package.json b/package.json index 47ec498..a8cbc3a 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "es6-promise-pool": "^2.4.4", "es6-promisify": "^5.0.0", "faker": "^3.1.0", + "find-root": "~1.0.0", "fs-extra-promisify": "^0.0.2", "globby": "^6.1.0", "highlight-es": "~1.0.0", @@ -77,7 +78,9 @@ "ava": "^0.16.0", "ava-spec": "github:tjbenton/ava-spec", "babel-cli": "^6.18.0", + "babel-plugin-array-includes": "~2.0.3", "babel-plugin-external-helpers": "~6.18.0", + "babel-plugin-transform-runtime": "~6.15.0", "babel-preset-latest": "^6.16.0", "babel-preset-stage-0": "^6.16.0", "coveralls": "^2.11.15", @@ -98,7 +101,8 @@ ], "plugins": [ "transform-runtime", - "external-helpers" + "external-helpers", + "array-includes" ] }, "ava": { @@ -111,7 +115,8 @@ "test/utils.js" ], "failFast": true, - "concurrency": 5 + "concurrency": 5, + "babel": "inherit" }, "nyc": { "exclude": [ diff --git a/test/cli.test.js b/test/cli.test.js index b2f682e..4cfe99d 100644 --- a/test/cli.test.js +++ b/test/cli.test.js @@ -32,7 +32,7 @@ test.group('console', (test) => { doc_type: 'contact', channels: [ 'ufp-555555555' ], contact_id: '1d54ed12-b65a-5085-a895-5c8c626f0efb', - details: { prefix: 'Dr.', first_name: 'Daphnee', middle_name: 'Dale', last_name: 'O\'Hara', company: 'Hackett - Effertz', job_title: null, dob: '2016-08-21', nickname: null }, + details: { prefix: 'Dr.', first_name: 'Daphnee', middle_name: 'Dale', last_name: 'O\'Hara', company: 'Hackett - Effertz', job_title: null, nickname: null }, phones: [ { type: 'Mobile', phone_number: '076-099-8620', extension: null }, { type: 'Other', phone_number: '965-618-1647', extension: null } ], emails: [ 'Abigale.Bashirian@gmail.com', 'Demetris12@gmail.com' ], addresses: [ { type: 'Work', address_1: '96735 Caroline Fields Springs', address_2: null, locality: 'Montanastad', region: 'SD', postal_code: '11307-4822', country: 'LA' } ], @@ -102,6 +102,7 @@ test.group('console', (test) => { // remove the dates because they can't be correct stdout = _.omit(stdout[0], [ 'created_on', 'modified_on' ]); + stdout.details = _.omit(stdout.details, [ 'dob' ]); t.deepEqual(stdout, expected_abc_seed); }) .end(t.end); @@ -126,6 +127,8 @@ test.group('console', (test) => { 'doc_type', 'channels', ]); + // removed the dob because it's a date + stdout.details = _.omit(stdout.details, [ 'dob' ]); for (let key in stdout) { if (stdout.hasOwnProperty(key)) { @@ -195,7 +198,7 @@ test.cb('throws error when something goes wrong', (t) => { /* eslint-disable quotes */ bin.clone() .run(`folder 'error-test' 'simple/models/*' --count 1 --archive 'woohoo'`) - .stderr(/The archive file must have a file extention of \`\.zip\`/) + .stdout(/The archive file must have a file extention of \`\.zip\`/) .end(t.end); /* eslint-enable quotes */ }); diff --git a/test/models.test.js b/test/models.test.js index cae1d2d..d065022 100644 --- a/test/models.test.js +++ b/test/models.test.js @@ -82,7 +82,7 @@ test('prepare', async (t) => { t.deepEqual(t.context.options.babel_config, babel_config); }); -test.group('setup', (test) => { +test.serial.group('setup', (test) => { test('babel_config as a string', async (t) => { t.is(t.context.prepared, false); t.is(t.context.preparing, undefined); @@ -123,6 +123,21 @@ test.group('setup', (test) => { t.is(to.type(t.context.options.babel_config), 'object'); t.deepEqual(t.context.options.babel_config, babel_config); }); + + test('babel_config process.cwd failed to find a babel config', async (t) => { + t.is(t.context.prepared, false); + t.is(t.context.preparing, undefined); + t.context.options.root = t.context.options.root.split('fakeit')[0].slice(0, -1); + t.context.options.babel_config = 'package.json'; + t.is(typeof t.context.options.babel_config, 'string'); + const preparing = t.context.setup(); + t.is(typeof t.context.preparing.then, 'function'); + t.is(t.context.prepared, false); + await preparing; + t.is(t.context.prepared, true); + t.is(to.type(t.context.options.babel_config), 'object'); + t.deepEqual(t.context.options.babel_config, babel_config); + }); }); @@ -292,7 +307,7 @@ test.group('parseModelFunctions', (test) => { const model = to.clone(contents[file]); const paths = utils.getPaths(model, /((pre|post)_run)|(pre_|post_)?build$/); const obj = _.pick(model, paths); - parseModelFunctions(obj); + parseModelFunctions(obj, babel_config); for (let str of paths) { let fn = _.get(obj, str); diff --git a/test/output/console.test.js b/test/output/console.test.js index 99f920f..62cd3c6 100644 --- a/test/output/console.test.js +++ b/test/output/console.test.js @@ -30,7 +30,7 @@ test('prepare', async (t) => { t.is(t.context.prepared, true); }); -test('setup', async (t) => { +test.serial('setup', async (t) => { t.is(t.context.prepared, false); t.is(t.context.preparing, undefined); // eslint-disable-line const preparing = t.context.setup(); diff --git a/test/output/couchbase.test.js b/test/output/couchbase.test.js index 772fda2..88eaebe 100644 --- a/test/output/couchbase.test.js +++ b/test/output/couchbase.test.js @@ -161,12 +161,12 @@ test.group('finalize', (test) => { await t.context.prepare(); t.is(to.type(t.context.bucket), 'object'); t.is(t.context.prepared, true); - t.is(t.context.preparing.toString(), '[object Promise]'); + t.is(typeof t.context.preparing.then, 'function'); t.is(t.context.bucket.connected, true); await t.context.finalize(); t.is(to.type(t.context.bucket), 'object'); t.is(t.context.prepared, true); - t.is(t.context.preparing.toString(), '[object Promise]'); + t.is(typeof t.context.preparing.then, 'function'); t.is(t.context.bucket.connected, false); }); }); diff --git a/test/output/index.test.js b/test/output/index.test.js index 2918ec9..e8d291c 100644 --- a/test/output/index.test.js +++ b/test/output/index.test.js @@ -451,7 +451,7 @@ test.group('validation', (test) => { }); -test.group('prepare', (test) => { +test.serial.group('prepare', (test) => { const root = p(output_root, 'prepare'); test('without options', async (t) => { @@ -513,7 +513,7 @@ test.group('prepare', (test) => { }); -test.group('setup', (test) => { +test.serial.group('setup', (test) => { test('without options', async (t) => { t.is(t.context.prepared, false); t.is(t.context.preparing, undefined); @@ -547,7 +547,7 @@ test.group('output', (test) => { data = await getData(); }); - test.group('return', languages((test, language) => { + test.serial.group('return', languages((test, language) => { test(language, async (t) => { const { raw, node } = data[language]; t.context.output_options.output = 'return'; diff --git a/test/output/sync-gateway.test.js b/test/output/sync-gateway.test.js index 4d54a58..ec120bb 100644 --- a/test/output/sync-gateway.test.js +++ b/test/output/sync-gateway.test.js @@ -36,7 +36,7 @@ test.group('prepare', (test) => { }); }); -test.group('setup', (test) => { +test.serial.group('setup', (test) => { test('no username and password', async (t) => { t.context.output_options.bucket = 'setup'; t.is(t.context.prepared, false); diff --git a/test/utils.js b/test/utils.js index 882a775..c18b7f8 100644 --- a/test/utils.js +++ b/test/utils.js @@ -108,14 +108,14 @@ module.exports.models = function(settings) { item = settings.modules[item]; } - return !!item && item.includes(model); + return !!item && item.indexOf(model) >= 0; }).filter(Boolean).length; // if the model isn't in the todo list then run the tests if ( - should_test && !options.todo.includes(model) + should_test && options.todo.indexOf(model) < 0 ) { - let schema; + var schema; // get the schema to use for validating that the output is correct try { schemas[model] = schema = schemas[model] || require(p(settings.root, settings.validation(model))); @@ -146,7 +146,9 @@ module.exports.models = function(settings) { // find the keys that still need to be validated var omitted = _.difference(to.keys(actual), schema_keys) - .filter((key) => ![ '__key', '__name' ].includes(key)); + .filter(function(key) { + return [ '__key', '__name' ].indexOf(key) < 0; + }); // test the keys that exsit var picked = _.pick(actual, schema_keys); @@ -160,13 +162,13 @@ module.exports.models = function(settings) { // validate the object that can be validated function validate(err) { if (err) { - let segments = err.message.match(/(?:child\s+(?:"))([^"]+)(?:")/g); + var segments = err.message.match(/(?:child\s+(?:"))([^"]+)(?:")/g); if (segments) { segments = segments.map(function(segment) { return segment.replace(/child\s+|"/g, ''); }); - let item_path = segments.join('.'); - let item = _.get(picked, item_path); + var item_path = segments.join('.'); + var item = _.get(picked, item_path); if (item) { console.log(' ', item_path, '=', item); } else { @@ -233,11 +235,11 @@ module.exports.models = function(settings) { module.exports.getPaths = function getPaths(model, regex) { return to.keys(model).concat(to.keys(to.flatten(model))) .reduce((result, next) => { - let current = ''; - for (let key of next.split('.')) { + var current = ''; + for (var key of next.split('.')) { current = current.split('.').concat(key).filter(Boolean).join('.'); if (regex == null || regex.test(current)) { - if (!result.includes(current)) { + if (result.indexOf(current) < 0) { result.push(current); } }