From 737aa4273e43e5c5faa825729c4f5ecb2e3ab519 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Sat, 19 Dec 2015 21:43:29 +0100 Subject: [PATCH 01/10] Added rudimentary source map support The `source-map-support` module enables some rudimentary support for source maps in call stacks, which greatly enhances the developer experience of working with compiled code. --- bin/tape | 1 + package.json | 1 + 2 files changed, 2 insertions(+) diff --git a/bin/tape b/bin/tape index 500f1b14..8101d1a2 100755 --- a/bin/tape +++ b/bin/tape @@ -1,4 +1,5 @@ #!/usr/bin/env node +require('source-map-support/register'); var path = require('path'); var glob = require('glob'); diff --git a/package.json b/package.json index 0be3595b..66dc0eb9 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "inherits": "~2.0.1", "object-inspect": "~1.0.0", "resumer": "~0.0.0", + "source-map-support": "~0.4.0", "string.prototype.trim": "^1.1.1", "through": "~2.3.4" }, From 3f02033f6024a526951ed6ad7606bdcb6d589f91 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Mon, 21 Dec 2015 19:56:05 +0100 Subject: [PATCH 02/10] Revert "Added rudimentary source map support" This reverts commit 737aa4273e43e5c5faa825729c4f5ecb2e3ab519. --- bin/tape | 1 - package.json | 1 - 2 files changed, 2 deletions(-) diff --git a/bin/tape b/bin/tape index 8101d1a2..500f1b14 100755 --- a/bin/tape +++ b/bin/tape @@ -1,5 +1,4 @@ #!/usr/bin/env node -require('source-map-support/register'); var path = require('path'); var glob = require('glob'); diff --git a/package.json b/package.json index 66dc0eb9..0be3595b 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,6 @@ "inherits": "~2.0.1", "object-inspect": "~1.0.0", "resumer": "~0.0.0", - "source-map-support": "~0.4.0", "string.prototype.trim": "^1.1.1", "through": "~2.3.4" }, From 7ae60f5ff63b6bfd9c7811eb8977ed60bfeaa5ac Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Mon, 21 Dec 2015 21:53:03 +0100 Subject: [PATCH 03/10] This implements `-r` and `--require` as command line options @Raynos accurately pointed out that the source map support was a bit too specific, and felt outside of the purview of tape. As a more general solution, this implements the `-r` and `--require` CLI flags, which will allow a user to load node modules before any tests are run. For example, if someon wants to enable source map support in node, they might do: tape -r source-map-support/register test/*.js --- bin/tape | 26 +++++++++++-- package.json | 2 + test/require.js | 83 ++++++++++++++++++++++++++++++++++++++++++ test/require/a.js | 8 ++++ test/require/b.js | 8 ++++ test/require/test-a.js | 7 ++++ test/require/test-b.js | 7 ++++ 7 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 test/require.js create mode 100644 test/require/a.js create mode 100644 test/require/b.js create mode 100644 test/require/test-a.js create mode 100644 test/require/test-b.js diff --git a/bin/tape b/bin/tape index 500f1b14..df3f0c1f 100755 --- a/bin/tape +++ b/bin/tape @@ -1,12 +1,32 @@ #!/usr/bin/env node -var path = require('path'); +var resolveModule = require('resolve').sync; +var resolvePath = require('path').resolve; +var parseOpts = require('minimist'); var glob = require('glob'); -process.argv.slice(2).forEach(function (arg) { +var opts = parseOpts(process.argv.slice(2), { + alias: { 'r': 'require' }, + string: 'require', + default: {'r': [] } + }); + +var cwd = process.cwd(); + +/* If only one require is specified, the value of `opts.require` + * will be a string. This is why we concatenate. + */ +;[].concat(opts.require).forEach(function(module) { + /* The `module &&` ensures we ignore `-r ""`, trailing `-r` or other + * silly things the user might (inadvertedly) be doing. + */ + module && require(resolveModule(module, { basedir: cwd })); +}); + +opts._.forEach(function (arg) { glob(arg, function (err, files) { files.forEach(function (file) { - require(path.resolve(process.cwd(), file)); + require(resolvePath(cwd, file)); }); }); }); diff --git a/package.json b/package.json index 0be3595b..66a65290 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,9 @@ "glob": "~5.0.3", "has": "~1.0.1", "inherits": "~2.0.1", + "minimist": "1.2.0", "object-inspect": "~1.0.0", + "resolve": "1.1.6", "resumer": "~0.0.0", "string.prototype.trim": "^1.1.1", "through": "~2.3.4" diff --git a/test/require.js b/test/require.js new file mode 100644 index 00000000..0385ea45 --- /dev/null +++ b/test/require.js @@ -0,0 +1,83 @@ +var tap = require('tap'); +var spawn = require('child_process').spawn; +var trim = require('string.prototype.trim'); + +tap.test('requiring a single module', function (t) { + t.plan(2); + + var tc = tap.createConsumer(); + + var rows = []; + tc.on('data', function (r) { rows.push(r) }); + tc.on('end', function () { + var rs = rows.map(function (r) { + if (r && typeof r === 'object') { + return { id : r.id, ok : r.ok, name : trim(r.name) }; + } + else return r; + }); + t.same(rs, [ + 'TAP version 13', + 'module-a', + { id: 1, ok: true, name: 'loaded module a' }, + 'test-a', + { id: 2, ok: true, name: 'module-a loaded in same context'}, + { id: 3, ok: true, name: 'test ran after module-a was loaded'}, + 'tests 3', + 'pass 3', + 'ok' + ]); + }); + + var ps = tape('-r ./require/a require/test-a.js'); + ps.stdout.pipe(tc); + ps.on('exit', function (code) { + t.equal(code, 0); + }); +}); + +tap.test('requiring multiple modules', function (t) { + t.plan(2); + + var tc = tap.createConsumer(); + + var rows = []; + tc.on('data', function (r) { rows.push(r) }); + tc.on('end', function () { + var rs = rows.map(function (r) { + if (r && typeof r === 'object') { + return { id : r.id, ok : r.ok, name : trim(r.name) }; + } + else return r; + }); + t.same(rs, [ + 'TAP version 13', + 'module-a', + { id: 1, ok: true, name: 'loaded module a' }, + 'module-b', + { id: 2, ok: true, name: 'loaded module b' }, + 'test-a', + { id: 3, ok: true, name: 'module-a loaded in same context'}, + { id: 4, ok: true, name: 'test ran after module-a was loaded'}, + 'test-b', + { id: 5, ok: true, name: 'module-b loaded in same context'}, + { id: 6, ok: true, name: 'test ran after module-b was loaded'}, + 'tests 6', + 'pass 6', + 'ok' + ]); + }); + + var ps = tape('-r ./require/a -r ./require/b require/test-a.js require/test-b.js'); + ps.stdout.pipe(tc); + ps.on('exit', function (code) { + t.equal(code, 0); + }); +}); + +function tape(args) { + var proc = require('child_process') + var bin = __dirname + '/../bin/tape' + + return proc.spawn(bin, args.split(' '), { cwd: __dirname }) +} \ No newline at end of file diff --git a/test/require/a.js b/test/require/a.js new file mode 100644 index 00000000..0947b7b9 --- /dev/null +++ b/test/require/a.js @@ -0,0 +1,8 @@ +var tape = require('../..'); + +tape.test('module-a', function(t) { + t.pass('loaded module a') + t.end() +}) + +global.module_a = true \ No newline at end of file diff --git a/test/require/b.js b/test/require/b.js new file mode 100644 index 00000000..18942e0c --- /dev/null +++ b/test/require/b.js @@ -0,0 +1,8 @@ +var tape = require('../..'); + +tape.test('module-b', function(t) { + t.pass('loaded module b') + t.end() +}) + +global.module_b = true \ No newline at end of file diff --git a/test/require/test-a.js b/test/require/test-a.js new file mode 100644 index 00000000..822ef540 --- /dev/null +++ b/test/require/test-a.js @@ -0,0 +1,7 @@ +var tape = require('../..'); + +tape.test('test-a', function(t) { + t.ok(global.module_a, 'module-a loaded in same context') + t.pass('test ran after module-a was loaded') + t.end() +}) \ No newline at end of file diff --git a/test/require/test-b.js b/test/require/test-b.js new file mode 100644 index 00000000..8efcba1c --- /dev/null +++ b/test/require/test-b.js @@ -0,0 +1,7 @@ +var tape = require('../..'); + +tape.test('test-b', function(t) { + t.ok(global.module_b, 'module-b loaded in same context') + t.pass('test ran after module-b was loaded') + t.end() +}) \ No newline at end of file From 4f81dbc5f9344b3dc9d56943d96249577d39f852 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Mon, 21 Dec 2015 22:59:44 +0100 Subject: [PATCH 04/10] Use ~ for minimist and resolve dependency versions. --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 66a65290..892dfca5 100644 --- a/package.json +++ b/package.json @@ -15,9 +15,9 @@ "glob": "~5.0.3", "has": "~1.0.1", "inherits": "~2.0.1", - "minimist": "1.2.0", + "minimist": "~1.2.0", "object-inspect": "~1.0.0", - "resolve": "1.1.6", + "resolve": "~1.1.6", "resumer": "~0.0.0", "string.prototype.trim": "^1.1.1", "through": "~2.3.4" From d0ca885a1f1e646a886aaae243c40ae03b3cc94f Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Mon, 21 Dec 2015 23:00:21 +0100 Subject: [PATCH 05/10] Make single require check more readable --- bin/tape | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/bin/tape b/bin/tape index df3f0c1f..a910b8f9 100755 --- a/bin/tape +++ b/bin/tape @@ -13,10 +13,11 @@ var opts = parseOpts(process.argv.slice(2), { var cwd = process.cwd(); -/* If only one require is specified, the value of `opts.require` - * will be a string. This is why we concatenate. - */ -;[].concat(opts.require).forEach(function(module) { +if (typeof opts.require === 'string') { + opts.require = [opts.require]; +} + +opts.require.forEach(function(module) { /* The `module &&` ensures we ignore `-r ""`, trailing `-r` or other * silly things the user might (inadvertedly) be doing. */ From 096d2e70bf7c73123156f6ffe3044e81adce7e1b Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Mon, 21 Dec 2015 23:20:11 +0100 Subject: [PATCH 06/10] Add `-r,--require` documentation to README.md This can probably be done better, but I think it covers all aspects of this feature. --- readme.markdown | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/readme.markdown b/readme.markdown index ca774862..04368de0 100644 --- a/readme.markdown +++ b/readme.markdown @@ -64,6 +64,26 @@ $ tape 'tests/**/*.js' $ tape "tests/**/*.js" ``` +## Preloading modules + +Additionally, it is possible to make `tape` load one or more modules before running any tests, by using the `-r` or `--require` flag. Here's an example that loads [babel-register](http://babeljs.io/docs/usage/require/) before running any tests, to allow for JIT compilation: + +```sh +$ tape -r babel-register tests/**/*.js +``` + +Depending on the module you're loading, you may be able to paramaterize it using environment variables or auxiliary files. Babel, for instance, will load options from [`.babelrc`](http://babeljs.io/docs/usage/babelrc/) at runtime. + +The `-r` flag behaves exactly like node's `require`, and uses the same module resolution algorithm. This means that if you need to load local modules, you have to prepend their path with `./` or `../` accordingly. + +For example: + +```sh +$ tape -r ./my/local/module tests/**/*.js +``` + +Please note that modules that all modules loaded using the `-r` flag will run *before* any tests, regardless of when they are specified. For example, `tape -r a b -r c` will actually load `a` and `c` *before` loading `b`, since they are flagged as required modules. + # things that go well with tape tape maintains a fairly minimal core. Additional features are usually added by using another module alongside tape. From 2e57f22b9690e828c42f6d3c28e22c3f01948ea7 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Mon, 21 Dec 2015 23:33:58 +0100 Subject: [PATCH 07/10] Fix indent mistake --- bin/tape | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/tape b/bin/tape index a910b8f9..cfa90a91 100755 --- a/bin/tape +++ b/bin/tape @@ -14,7 +14,7 @@ var opts = parseOpts(process.argv.slice(2), { var cwd = process.cwd(); if (typeof opts.require === 'string') { - opts.require = [opts.require]; + opts.require = [opts.require]; } opts.require.forEach(function(module) { From ffa503ad8acb22fe3108748189c0e1888511d8ba Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Mon, 21 Dec 2015 23:35:10 +0100 Subject: [PATCH 08/10] Use regular ol' `if` instead of boolean operator in sanity check --- bin/tape | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/bin/tape b/bin/tape index cfa90a91..215b9572 100755 --- a/bin/tape +++ b/bin/tape @@ -18,10 +18,11 @@ if (typeof opts.require === 'string') { } opts.require.forEach(function(module) { - /* The `module &&` ensures we ignore `-r ""`, trailing `-r` or other - * silly things the user might (inadvertedly) be doing. - */ - module && require(resolveModule(module, { basedir: cwd })); + if (module) { + /* This check ensures we ignore `-r ""`, trailing `-r`, or + * other silly things the user might (inadvertedly) be doing. */ + require(resolveModule(module, { basedir: cwd })); + } }); opts._.forEach(function (arg) { From 4077efe19fe914a4b344ce3da1710478bed5f734 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Mon, 21 Dec 2015 23:36:57 +0100 Subject: [PATCH 09/10] Fix spelling mistake in comment --- bin/tape | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/tape b/bin/tape index 215b9572..d5674d33 100755 --- a/bin/tape +++ b/bin/tape @@ -20,7 +20,7 @@ if (typeof opts.require === 'string') { opts.require.forEach(function(module) { if (module) { /* This check ensures we ignore `-r ""`, trailing `-r`, or - * other silly things the user might (inadvertedly) be doing. */ + * other silly things the user might (inadvertently) be doing. */ require(resolveModule(module, { basedir: cwd })); } }); From 9f02249f1e99f88eae26d39527768820f9b58c89 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Mon, 21 Dec 2015 23:38:28 +0100 Subject: [PATCH 10/10] Unquote keys in object literals --- bin/tape | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/tape b/bin/tape index d5674d33..498910cd 100755 --- a/bin/tape +++ b/bin/tape @@ -6,9 +6,9 @@ var parseOpts = require('minimist'); var glob = require('glob'); var opts = parseOpts(process.argv.slice(2), { - alias: { 'r': 'require' }, + alias: { r: 'require' }, string: 'require', - default: {'r': [] } + default: { r: [] } }); var cwd = process.cwd();