diff --git a/.eslintrc b/.eslintrc index 5b749b5f..d4840579 100644 --- a/.eslintrc +++ b/.eslintrc @@ -28,6 +28,7 @@ }], "strict": "error", }, + "ignorePatterns": [ "syntax-error.*" ], "overrides": [ { "files": ["*.mjs", "test/import/package_type/*.js"], diff --git a/package.json b/package.json index 8292e6e9..7d7f1eba 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "prepublishOnly": "safe-publish-latest", "prepublish": "!(type not-in-publish) || not-in-publish || npm run prepublishOnly", "prelint": "eclint check", - "lint": "eslint . bin/*", + "lint": "eslint --ext .js,.cjs,.mjs . bin/*", "pretest": "npm run lint", "test": "npm run tests-only", "posttest": "aud --production", diff --git a/test/import.js b/test/import.js index b30952be..b76e5bc9 100644 --- a/test/import.js +++ b/test/import.js @@ -4,8 +4,9 @@ var tap = require('tap'); var spawn = require('child_process').spawn; var concat = require('concat-stream'); var hasDynamicImport = require('has-dynamic-import'); +var assign = require('object.assign'); -tap.test('importing mjs files', function (t) { +tap.test('importing mjs files', function (t) { hasDynamicImport().then(function (hasSupport) { if (hasSupport) { var tc = function (rows) { @@ -36,7 +37,7 @@ tap.test('importing mjs files', function (t) { ].join('\n') + '\n\n'); }; - var ps = tape('import/*.mjs'); + var ps = tape('import/mjs-*.mjs'); ps.stdout.pipe(concat(tc)); ps.stderr.pipe(process.stderr); ps.on('exit', function (code) { @@ -85,9 +86,113 @@ tap.test('importing type: "module" files', function (t) { }); }); -function tape(args) { +tap.test('errors importing test files', function (t) { + hasDynamicImport().then(function (hasSupport) { + var createTest = function (options) { + var message = options.error + ' in `' + options.mode + '` mode`'; + var ps = tape(options.files, { env: { NODE_OPTIONS: '--unhandled-rejections=' + options.mode } }); + ps.stderr.pipe(concat(options.unhandledRejection(message))); + ps.on('exit', function (code, sig) { + t.equal(code, options.exitCode, message + ' has exit code ' + options.exitCode); + }); + }; + + var warning = function (message) { + return function (rows) { + t.match(rows.toString('utf8'), 'UnhandledPromiseRejectionWarning', 'should have unhandled rejection warning: ' + message); + }; + }; + + var noWarning = function (message) { + return function (rows) { + t.notMatch(rows.toString('utf8'), 'UnhandledPromiseRejectionWarning', 'should not have unhandled rejection warning: ' + message); + }; + }; + + if (hasSupport) { + var tests = [{ + files: 'import/syntax-error.mjs import/mjs-a.mjs import/mjs-b.mjs', + error: 'syntax errors in first imported esm file', + mode: 'warn', + exitCode: 0, + unhandledRejection: warning + }, { + files: 'import/throws.mjs import/mjs-a.mjs import/mjs-b.mjs', + error: 'thrown errors in first imported esm file', + mode: 'warn', + exitCode: 0, + unhandledRejection: warning + }, { + files: 'import/mjs-a.mjs import/syntax-error.mjs', + error: 'syntax error in esm file', + mode: 'warn', + exitCode: 1, + unhandledRejection: warning + }, { + files: 'import/syntax-error.mjs', + error: 'syntax error in esm file', + mode: 'strict', + exitCode: 1, + unhandledRejection: noWarning + }, { + files: 'import/throws.mjs', + error: 'thrown error in esm file', + mode: 'strict', + exitCode: 1, + unhandledRejection: noWarning + }, { + files: 'import/syntax-error.cjs', + error: 'syntax error in cjs file', + mode: 'warn', + exitCode: 1, + unhandledRejection: noWarning + }, { + files: 'import/throws.cjs', + error: 'thrown error in cjs file', + mode: 'warn', + exitCode: 1, + unhandledRejection: noWarning + }, { + files: 'import/syntax-error.cjs', + error: 'syntax error in cjs file', + mode: 'strict', + exitCode: 1, + unhandledRejection: noWarning + }, { + files: 'import/throws.cjs', + error: 'thrown error in cjs file', + mode: 'strict', + exitCode: 1, + unhandledRejection: noWarning + }, { + files: 'import/mjs-a.mjs import/syntax-error.cjs', + error: 'syntax error in cjs file in loading promise', + mode: 'warn', + exitCode: 1, + unhandledRejection: warning + }, { + files: 'import/mjs-a.mjs import/syntax-error.cjs', + error: 'syntax error in cjs file in loading promise', + mode: 'strict', + exitCode: 1, + unhandledRejection: noWarning + }]; + + t.plan(tests.length * 2); + + tests.map(createTest); + } else { + t.pass('does not support dynamic import'); + t.end(); + } + }); +}); + +function tape(args, options) { + options = assign({ cwd: __dirname }, options); + var proc = require('child_process'); var bin = __dirname + '/../bin/tape'; - return proc.spawn('node', [bin].concat(args.split(' ')), { cwd: __dirname }); + return proc.spawn('node', [bin].concat(args.split(' ')), options); } diff --git a/test/import/syntax-error.cjs b/test/import/syntax-error.cjs new file mode 100644 index 00000000..9c5df868 --- /dev/null +++ b/test/import/syntax-error.cjs @@ -0,0 +1 @@ +)) diff --git a/test/import/syntax-error.mjs b/test/import/syntax-error.mjs new file mode 100644 index 00000000..9c5df868 --- /dev/null +++ b/test/import/syntax-error.mjs @@ -0,0 +1 @@ +)) diff --git a/test/import/throws.cjs b/test/import/throws.cjs new file mode 100644 index 00000000..007f9a03 --- /dev/null +++ b/test/import/throws.cjs @@ -0,0 +1,3 @@ +'use strict'; + +throw new Error('thrown'); diff --git a/test/import/throws.mjs b/test/import/throws.mjs new file mode 100644 index 00000000..cbfa6d27 --- /dev/null +++ b/test/import/throws.mjs @@ -0,0 +1 @@ +throw new Error('thrown');