pax_global_header00006660000000000000000000000064124737364740014533gustar00rootroot0000000000000052 comment=276ac5972315a85963982900b42ffafcdeb60fb7 node-tap-0.7.1/000077500000000000000000000000001247373647400132475ustar00rootroot00000000000000node-tap-0.7.1/.gitignore000066400000000000000000000000631247373647400152360ustar00rootroot00000000000000node_modules/ coverage/ coverage-example/coverage/ node-tap-0.7.1/.npmignore000066400000000000000000000000001247373647400152340ustar00rootroot00000000000000node-tap-0.7.1/AUTHORS000066400000000000000000000006231247373647400143200ustar00rootroot00000000000000# contributors sorted by whether or not they're me Isaac Z. Schlueter baudehlo James Halliday Jason Smith (air) Pedro P. Candel Stein Martin Hustad Trent Mick Corey Richardson Raynos Siddharth Mahendraker node-tap-0.7.1/LICENSE000066400000000000000000000021041247373647400142510ustar00rootroot00000000000000Copyright 2009, 2010, 2011 Isaac Z. Schlueter. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. node-tap-0.7.1/README.md000066400000000000000000000067241247373647400145370ustar00rootroot00000000000000This is a mix-and-match set of utilities that you can use to write test harnesses and frameworks that communicate with one another using the Test Anything Protocol. If you don't yet know what TAP is, [you better ask somebody](http://testanything.org/). Default Usage: 1. Make a directory. Maybe call it 'test'. That'd be nice and obvious. 2. Put a bunch of test scripts in there. If they're node programs, then they should be ".js". Anything else is assumed to be some kind of shell script, which should have a shebang line. 3. `npm install tap` 4. Update package.json scripts.test to include `tap ./test` [example gist](https://gist.github.com/4469613) 5. `npm test` The output will be TAP-compliant. For extra special bonus points, you can do something like this: var test = require("tap").test test("make sure the thingie is a thing", function (t) { t.equal(thingie, "thing", "thingie should be thing") t.deepEqual(array, ["foo", "bar"], "array has foo and bar elements") t.strictDeepEqual(object, {foo: 42, bar: "thingie"}, "object has foo (Number) and bar (String) property") t.type(thingie, "string", "type of thingie is string") t.ok(true, "this is always true") t.notOk(false, "this is never true") t.test("a child test", function (t) { t.equal(this, superEasy, "right!?") t.similar(7, 2, "ever notice 7 is kinda like 2?", {todo: true}) t.test("so skippable", {skip: true}, function (t) { t.plan(1) // only one test in this block t.ok(true, "but when the flag changes, it'll pass") // no need to end, since we had a plan. }) t.end() }) t.ok(99, "can also skip individual assertions", {skip: true}) // end lets it know it's over. t.end() }) test("another one", function (t) { t.plan(1) t.ok(true, "It's ok to plan, and also end. Watch.") t.end() // but it must match the plan! }) Node-tap is actually a collection of several modules, any of which may be mixed and matched however you please. If you don't like this test framework, and think you can do much much better, *I strongly encourage you to do so!* If you use this library, however, at least to output TAP-compliant results when `process.env.TAP` is set, then the data coming out of your framework will be much more consumable by machines. You can also use this to build programs that *consume* the TAP data, so this is very useful for CI systems and such. * tap-assert: A collection of assert functions that return TAP result objects. * tap-consumer: A stream interface for consuming TAP data. * tap-producer: A class that produces a TAP stream by taking in result objects. * tap-results: A class for keeping track of TAP result objects as they pass by, counting up skips, passes, fails, and so on. * tap-runner: A program that runs through a directory running all the tests in it. (Tests which may or may not be TAP-outputting tests. But it's better if they are.) * tap-test: A class for actually running tests. * tap-harness: A class that runs tests. (Tests are also Harnesses, which is how sub-tests run.) * tap-global-harness: A default harness that provides the top-level support for running TAP tests. ## Experimental Code Coverage with runforcover & bunker: ``` TAP_COV=1 tap ./test [--cover=./lib,foo.js] [--coverage-dir=./coverage] ``` This feature is experimental, and will most likely change somewhat before being finalized. Feedback welcome. node-tap-0.7.1/bin/000077500000000000000000000000001247373647400140175ustar00rootroot00000000000000node-tap-0.7.1/bin/tap-http.js000066400000000000000000000010701247373647400161140ustar00rootroot00000000000000#!/usr/bin/env node // just an example, really // Run with `node tap-http.js path/to/tests/` var argv = process.argv.slice(2) , path = require("path") , Runner = require("../lib/tap-runner") , http = require("http") , server = http.createServer(function (req, res) { // it'd be nice to return a non-200 if the tests fail, but we don't // know the status until it's done, so that would mean not being able // to pipe the output res.writeHead(200, {'content-type': 'text/plain'}) new Runner(argv, null).pipe(res) }) server.listen(1337) node-tap-0.7.1/bin/tap-reader.js000077500000000000000000000013071247373647400164050ustar00rootroot00000000000000#!/usr/bin/env node // read a tap stream from stdin. var TapConsumer = require("../lib/tap-consumer") , TapProducer = require("../lib/tap-producer") var tc = new TapConsumer , tp = new TapProducer //process.stdin.pipe(tc) process.stdin.on("data", function (c) { c = c + "" // console.error(JSON.stringify(c).substr(0, 100)) tc.write(c) }) process.stdin.on("end", function () { tc.end() }) process.stdin.resume() //tc.pipe(tp) tc.on("data", function (c) { tp.write(c) }) tc.on("end", function () { tp.end() }) tp.on("data", function (c) { console.error(["output write", c]) process.stdout.write(c) }) tp.on("end", function (er, total, ok) { if (er) throw er process.exit(total - ok) }) node-tap-0.7.1/bin/tap.js000077500000000000000000000076711247373647400151570ustar00rootroot00000000000000#!/usr/bin/env node var argv = process.argv.slice(2) , path = require("path") , Runner = require("../lib/tap-runner") , nopt = require("nopt") , knownOpts = { cover: [path, false] , "cover-dir": path , stderr: Boolean , stdout: Boolean , diag: Boolean , version: Boolean , tap: Boolean , timeout: Number , gc: Boolean , debug: Boolean , "debug-brk": Boolean , strict: Boolean , harmony: Boolean } , shorthands = // debugging 1: show stderr { d: ["--stderr"] // debugging 2: show stderr and tap , dd: ["--stderr", "--tap"] // debugging 3: show stderr, tap, AND always show diagnostics. , ddd: ["--stderr", "--tap", "--diag"] , "expose-gc": ["--gc"] , g: ["--gc"] , e: ["--stderr"] , t: ["--timeout"] , o: ["--tap"] , c: ["--cover"] , v: ["--version"] , "?": ["--help"] , h: ["--help"] } , defaults = { cover: "./lib" , "cover-dir": "./coverage" , stderr: process.env.TAP_STDERR !== '0' , tap: process.env.TAP , diag: process.env.TAP_DIAG , timeout: +process.env.TAP_TIMEOUT || 30 , gc: false , debug: false , "debug-brk": false , strict: false , harmony: false , version: false , help: false } , options = nopt(knownOpts, shorthands) if (options.version) { console.log(require("../package.json").version) process.exit(0) } if (options.help) { console.log(function(){/* Usage: tap Run the files as tap tests, parse the output, and report the results Options: --stderr Print standard error output of tests to standard error. --tap Print raw tap output. --diag Print diagnostic output for passed tests, as well as failed. (Implies --tap) --gc Expose the garbage collector to tests. --timeout Maximum time to wait for a subtest, in seconds. Default: 30 --debug Pass the '--debug' flag to node for debugging --debug-brk Pass the '--debug-brk' flag to node for debugging --strict Enforce strict mode when running tests. --harmony Enable harmony features for tests. --version Print the version of node tap. --help Print this help. Please report bugs! https://github.com/isaacs/node-tap/issues */}.toString().split(/\n/).slice(1, -1).join("\n")) process.exit(0) } Object.keys(defaults).forEach(function (k) { if (!options.hasOwnProperty(k)) options[k] = defaults[k] }) // other tests that might rely on these if (options.diag) process.env.TAP_DIAG = true if (options.tap) process.env.TAP = true if (options.timeout) process.env.TAP_TIMEOUT = options.timeout var r = new Runner(options) , TapProducer = require("../lib/tap-producer") if (options.tap || options.diag) { r.pipe(process.stdout) } else { r.on("file", function (file, results, details) { var s = (details.ok ? "" : "not ") + "ok "+results.name , n = details.pass + "/" + details.testsTotal , dots = new Array(Math.max(1, 60 - s.length - n.length)).join(".") console.log("%s %s %s", s, dots, n) if (details.ok) { if (details.skip) { console.log(" skipped: %s", details.skip) } if (details.todo) { console.log(" todo: %s", details.todo) } } else { // console.error(details) console.log(" Command: %s", results.command) console.log(" " + TapProducer.encode(details.list) .split(/\n/).join("\n ")) } }) r.on("end", function () { //console.log(r) var s = "total" , n = r.results.pass + "/" + r.results.testsTotal , dots = new Array(60 - s.length - n.length).join(".") , ok = r.results.ok ? "ok" : "not ok" console.log("%s %s %s\n\n%s", s, dots, n, ok) if (r.doCoverage) { console.error( "\nCoverage: %s\n" , path.resolve(r.coverageOutDir, "index.html") ) } }) } r.on("end", function () { process.exit(r.results.ok ? 0 : 1) }) node-tap-0.7.1/coverage-example/000077500000000000000000000000001247373647400164735ustar00rootroot00000000000000node-tap-0.7.1/coverage-example/lib/000077500000000000000000000000001247373647400172415ustar00rootroot00000000000000node-tap-0.7.1/coverage-example/lib/bar.js000066400000000000000000000003511247373647400203420ustar00rootroot00000000000000var Bar = module.exports = function(str) { this.bar = str; this.str = str; }; Bar.prototype.foo = function() { var self = this; return self.bar; }; Bar.prototype.baz = function() { var self = this; return self.str; }; node-tap-0.7.1/coverage-example/lib/foo.js000066400000000000000000000003511247373647400203610ustar00rootroot00000000000000var Foo = module.exports = function(str) { this.foo = str; this.str = str; }; Foo.prototype.bar = function() { var self = this; return self.foo; }; Foo.prototype.baz = function() { var self = this; return self.str; }; node-tap-0.7.1/coverage-example/test/000077500000000000000000000000001247373647400174525ustar00rootroot00000000000000node-tap-0.7.1/coverage-example/test/bar.test.js000066400000000000000000000004401247373647400215300ustar00rootroot00000000000000var test = require('tap').test, Bar = require('../lib/bar'), bar; test('setup', function(t) { bar = new Bar('baz'); t.ok(bar); t.end(); }); test('bar', function(t) { t.equal('baz', bar.foo()); t.end(); }); test('teardown', function(t) { t.ok(true); t.end(); }); node-tap-0.7.1/coverage-example/test/baz.test.js000066400000000000000000000007051247373647400215440ustar00rootroot00000000000000var test = require('tap').test, Foo = require('../lib/foo'), Bar = require('../lib/bar'), foo, bar; test('setup', function(t) { foo = new Foo('baz'); t.ok(foo); bar = new Bar('baz'); t.ok(bar); t.end(); }); test('baz from Foo', function(t) { t.equal('baz', foo.baz()); t.end(); }); test('baz from Bar', function(t) { t.equal('baz', bar.baz()); t.end(); }); test('teardown', function(t) { t.ok(true); t.end(); }); node-tap-0.7.1/coverage-example/test/foo.test.js000066400000000000000000000004401247373647400215470ustar00rootroot00000000000000var test = require('tap').test, Foo = require('../lib/foo'), foo; test('setup', function(t) { foo = new Foo('baz'); t.ok(foo); t.end(); }); test('bar', function(t) { t.equal('baz', foo.bar()); t.end(); }); test('teardown', function(t) { t.ok(true); t.end(); }); node-tap-0.7.1/example/000077500000000000000000000000001247373647400147025ustar00rootroot00000000000000node-tap-0.7.1/example/lib/000077500000000000000000000000001247373647400154505ustar00rootroot00000000000000node-tap-0.7.1/example/lib/math.js000066400000000000000000000000261247373647400167350ustar00rootroot00000000000000module.exports = Math node-tap-0.7.1/example/test/000077500000000000000000000000001247373647400156615ustar00rootroot00000000000000node-tap-0.7.1/example/test/test-example.js000066400000000000000000000162341247373647400206350ustar00rootroot00000000000000var tap = require("tap") , test = tap.test , plan = tap.plan , math test("load sut", function (t) { math = require("../lib/math") t.ok(math, "object loaded") t.end() }) test("validate constants", function (t) { t.equal(math.LN10, 2.302585092994046, "ln 10") t.equal(math.PI, 3.141592653589793, "pi") t.equal(math.E, 2.718281828459045, "e") t.equal(math.LOG10E, 0.4342944819032518, "log 10 e") t.equal(math.SQRT2, 1.4142135623730951, "sqrt 2") t.equal(math.SQRT1_2, 0.7071067811865476, "sqrt 1/2") t.equal(math.LN2, 0.6931471805599453, "ln2") t.end() }) test("using this", function (t) { // this also works. this.equal(t, this, "call in scope of test obj") this.end() }) // test setTimeout, just a trivial example. test("setTimeout", function (t) { var start = Date.now() setTimeout(function () { t.ok(Date.now() >= start + 50, "timeout fired after delay") t.end() }, 50) }) // another way to do the same, using a plan. // this is more robust, but annoying when you have a long list // of tests for something. For async stuff, it's generally better, // since there's a higher risk of the control flowing off to lala land. test("setTimeout planned", function (t) { t.plan(1) var start = Date.now() setTimeout(function () { t.ok(Date.now() >= start + 50, "timeout fired after delay") }, 50) }) // plans also are good for cases where things may fire in a non-deterministic // order, since it won't be as obvious when everything is done. test("setTimeout parallel", function (t) { t.plan(2) var start = Date.now() setTimeout(function A () { t.ok(Date.now() >= start + 50, "timeout A fired after delay") }, 50) setTimeout(function B () { t.ok(Date.now() >= start + 50, "timeout B fired after delay") }, 50) }) // something slightly less hello worldy test("async test", function (t) { t.plan(4) var fs = require("fs") t.ok(fs, "fs library should load") var rs = fs.createReadStream(__filename) t.ok(rs, "read stream should start fine.") rs.on("open", function (fd) { t.type(fd, "number", "file descriptor should be a number") t.equal(fd, rs.fd, "fd should match stream fd") }) }) // you can bail out of the entire everything if something is just // Not Right (db not installed, etc.) test("tarp", function (parent) { if (7 === 5) { parent.bailout("math is broken") } // bailout bubbles up a bit like "error" events // if unhandled, then the parent will bail, as well. parent.test("child bailouts", function (child) { child.on("bailout", function (s) { parent.fail("children shouldn't bail.") }) child.bailout("try to bail out, but instead just fail a test") }) parent.test("child bailout 2", function (child) { child.bailout("this one will bail out") }) }) // tests marked "todo" can fail without counting against the overall score // never ever ever write tests to "verify" incorrect behavior! test("unfinished test", function (t) { t.equal(math.cos(math.PI), -1, "cos(PI)") t.equal(math.sin(math.PI), 0, "sin(PI)") t.equal(math.face, "your face", "math.face should be your face # TODO") t.end() }) // tests can have children. test("http server", function (t) { // one test plus 4 children. t.plan(5) var http = require("http") , PORT = 12346 t.ok(http, "http module should load") var server t.test("set up server", function (t) { t.plan(2) server = http.createServer(function (req, res) { t.comment("Request: "+req.url) res.writeHead(200, {}) res.end(req.method + " " + req.url) }) t.ok(server, "createServer should create a server") server.listen(PORT, t.cb("listen should fire callback")) }) // set the "parallel" flag on this one. // That signals the harness to proceed immediately to the next test, // and run them in parallel. // Default behavior is to wait for each test to complete before proceeding // to the next one. // The first not-parallel test encountered will cause it to wait for that // test, as well as all the parallel tests before it. // A, B', C', D', E (where ' means "parallel") // Runs A, and then B, C, and D in parallel, and then E. t.test("testing POST", {parallel: true}, function (t) { t.plan(1) http.request("POST", { method: "POST" , host: "localhost" , path: "/foo" , port: PORT }).on("response", function (res) { t.bufferStream(res, function (s) { t.equal(s, "POST /foo") }) }).end() }) t.test("testing GET", {parallel: true}, function (t) { t.plan(1) http.request("POST", { method: "GET" , host: "localhost" , path: "/foo" , port: PORT }).on("response", function (res) { t.bufferStream(res, function (s) { t.equal(s, "GET /foo") }) }).end() }) // wrap in a test so that if this throws, it'll log as a failed test. t.test("teardown", function (t) { server.close() t.end() }) }) // yo dawg! test("meta-tests", function (t) { t.plan(5) // t.fails() wraps a child test and succeeds if it fails. t.fails(t.test("this should fail", function (t) { t.ok(false, "assert false") t.end() })) // t.timesOut() wraps a child test and succeeds if it times out. // if t.end() is called, or if a plan is completed, then it fails. // set the timeout really low so that it will not take forever. t.timesOut(t.test("this should timeout", { timeout: 1 }, function (t) { t.ok(true, "assert true") // t.end() never called. })) // t.incomplete() wraps a child test and succeeds if it ends before // the plan is finished. t.incomplete(t.test("this should be incomplete", function (t) { t.plan(100) t.ok(true, "assert true") // calling end prematurely. t.end() })) // t.bailsOut() wraps a child test and succeeds if it calls bailout() t.bailsOut(t.test("this should bailout", function (t) { t.bailout("oh noes, bailing out!") })) // low-level analysis of subtests t.test("verifying test success/failure expectations", function (t) { t.once("end", function () { var res = t.results , is = t.equal // hijack! t.clear() is(res.ok, false, "ok") is(res.bailedOut, false, "bailed out") is(res.skip, 2, "skips") is(res.skipPass, 1, "skip that passed") is(res.skipFail, 1, "skip that failed") is(res.todo, 2, "todos") is(res.todoPass, 1, "todo that passed") is(res.todoFail, 1, "todo that failed") is(res.failTotal, 3, "failures total") is(res.fail, 1, "relevant failure") is(res.passTotal, 3, "passes total") is(res.pass, 1, "relevant pass") is(res.testsTotal, 6, "total tests") is(res.tests, 2, "should be 2 relevant tests") t.end() }) // run the metatest. // *this* is the actual SUT in this case. t.ok(false, "failing todo #todo") // can also set #todo or #skip explicitly t.ok(true, "succeeding todo", {todo: true}) t.ok(false, "failing skip #skip", {skip: true}) t.ok(true, "suceeding skip #skip") t.ok(false, "failing test") t.ok(true, "succeeding test") t.end() }) }) node-tap-0.7.1/lib/000077500000000000000000000000001247373647400140155ustar00rootroot00000000000000node-tap-0.7.1/lib/main.js000066400000000000000000000011631247373647400153000ustar00rootroot00000000000000 var GlobalHarness = require("./tap-global-harness") // this lets you do stuff like: // var test = require("tap").test // test(...) // to run stuff in the global harness. exports = module.exports = new GlobalHarness() exports.createProducer = exports.Producer = require("./tap-producer") exports.createConsumer = exports.Consumer = require("./tap-consumer") exports.yamlish = require("yamlish") exports.createTest = exports.Test = require("./tap-test") exports.createHarness = exports.Harness = require("./tap-harness") exports.createRunner = exports.Runner = require("./tap-runner") exports.assert = require("./tap-assert") node-tap-0.7.1/lib/tap-assert.js000066400000000000000000000306271247373647400164460ustar00rootroot00000000000000// an assert module that returns tappable data for each assertion. var difflet = require('difflet') , deepEqual = require('deep-equal') , bufferEqual = require('buffer-equal') , Buffer = require('buffer').Buffer module.exports = assert var syns = {} , id = 1 function assert (ok, message, extra) { if (extra && extra.skip) return assert.skip(message, extra) //console.error("assert %j", [ok, message, extra]) //if (extra && extra.skip) return assert.skip(message, extra) //console.error("assert", [ok, message, extra]) ok = !!ok var res = { id : id ++, ok: ok } var caller = getCaller(extra && extra.error) if (extra && extra.error) { res.type = extra.error.name res.message = extra.error.message res.code = extra.error.code || extra.error.type res.errno = extra.error.errno delete extra.error } if (caller.file) { res.file = caller.file res.line = +caller.line res.column = +caller.column } res.stack = caller.stack res.name = message || "(unnamed assert)" if (extra) Object.keys(extra).forEach(function (k) { if (!res.hasOwnProperty(k)) res[k] = extra[k] }) // strings and objects are hard to diff by eye if (!ok && res.hasOwnProperty("found") && res.hasOwnProperty("wanted") && res.found !== res.wanted) { if (typeof res.wanted !== typeof res.found || typeof res.wanted === "object" && (!res.found || !res.wanted)) { res.type = { found: typeof found , wanted: typeof wanted } } else if (typeof res.wanted === "string") { res.diff = diffString(res.found, res.wanted) } else if (typeof res.wanted === "object") { res.diff = diffObject(res.found, res.wanted) } } //console.error("assert return", res) return res } assert.ok = assert syns.ok = [ "true", "assert" ] function notOk (ok, message, extra) { return assert(!ok, message, extra) } assert.notOk = notOk syns.notOk = [ "false", "notok" ] function error (er, message, extra) { if (!er) { // just like notOk(er) return assert(!er, message, extra) } message = message || er.message extra = extra || {} extra.error = er return assert.fail(message, extra) } assert.error = error syns.error = [ "ifError", "ifErr", "iferror" ] function pass (message, extra) { return assert(true, message, extra) } assert.pass = pass function fail (message, extra) { //console.error("assert.fail", [message, extra]) //if (extra && extra.skip) return assert.skip(message, extra) return assert(false, message, extra) } assert.fail = fail function skip (message, extra) { //console.error("assert.skip", message, extra) if (!extra) extra = {} return { id: id ++, skip: true, name: message || "", explanation: extra.explanation || "" } } assert.skip = skip function throws (fn, wanted, message, extra) { if (typeof wanted === "string") { extra = message message = wanted wanted = null } if (extra && extra.skip) return assert.skip(message, extra) var found = null try { fn() } catch (e) { found = { name: e.name, message: e.message } } extra = extra || {} extra.found = found if (wanted) { wanted = { name: wanted.name, message: wanted.message } extra.wanted = wanted } if (!message) { message = "Expected to throw" if (wanted) message += ": "+wanted.name + " " + wanted.message } return (wanted) ? assert.similar(found, wanted, message, extra) : assert.ok(found, message, extra) } assert.throws = throws function doesNotThrow (fn, message, extra) { if (extra && extra.skip) return assert.skip(message, extra) var found = null try { fn() } catch (e) { found = {name: e.name, message: e.message} } message = message || "Should not throw" return assert.equal(found, null, message, extra) } assert.doesNotThrow = doesNotThrow function equal (a, b, message, extra) { if (extra && extra.skip) return assert.skip(message, extra) extra = extra || {} message = message || "should be equal" extra.found = a extra.wanted = b return assert(a === b, message, extra) } assert.equal = equal syns.equal = ["equals" ,"isEqual" ,"is" ,"strictEqual" ,"strictEquals"] function equivalent (a, b, message, extra) { if (extra && extra.skip) return assert.skip(message, extra) var extra = extra || {} message = message || "should be equivalent" extra.found = a extra.wanted = b if (Buffer.isBuffer(a) && Buffer.isBuffer(b)) { return assert(bufferEqual(a, b), message, extra) } else { return assert(deepEqual(a, b), message, extra) } } assert.equivalent = equivalent syns.equivalent = ["isEquivalent" ,"looseEqual" ,"looseEquals" ,"isDeeply" ,"same" ,"deepEqual" ,"deepEquals"] function strictDeepEqual (a, b, message, extra) { if (extra && extra.skip) return assert.skip(message, extra) var extra = extra || {} message = message || "should be strictly equal" extra.found = a extra.wanted = b if (Buffer.isBuffer(a) && Buffer.isBuffer(b)) { return assert(bufferEqual(a, b), message, extra) } else { return assert(deepEqual(a, b, {strict: true}), message, extra) } } assert.strictDeepEqual = strictDeepEqual syns.strictDeepEqual = ["isStrictEquivalent" ,"isStrictly" ,"exactSame" ,"strictDeepEqual" ,"strictDeepEquals"] function inequal (a, b, message, extra) { if (extra && extra.skip) return assert.skip(message, extra) extra = extra || {} message = message || "should not be equal" extra.found = a extra.doNotWant = b return assert(a !== b, message, extra) } assert.inequal = inequal syns.inequal = ["notEqual" ,"notEquals" ,"notStrictEqual" ,"notStrictEquals" ,"isNotEqual" ,"isNot" ,"not" ,"doesNotEqual" ,"isInequal"] function inequivalent (a, b, message, extra) { if (extra && extra.skip) return assert.skip(message, extra) extra = extra || {} message = message || "should not be equivalent" extra.found = a extra.doNotWant = b if (Buffer.isBuffer(a) && Buffer.isBuffer(b)) { return assert(!bufferEqual(a, b), message, extra) } else { return assert(!deepEqual(a, b), message, extra) } } assert.inequivalent = inequivalent syns.inequivalent = ["notEquivalent" ,"notDeepEqual" ,"notDeeply" ,"notSame" ,"isNotDeepEqual" ,"isNotDeeply" ,"isNotEquivalent" ,"isInequivalent"] function similar (a, b, message, extra, flip) { if (extra && extra.skip) return assert.skip(message, extra) // test that a has all the fields in b message = message || "should be similar" if (typeof a === "string" && (Object.prototype.toString.call(b) === "[object RegExp]")) { extra = extra || {} extra.pattern = b extra.string = a var ok = a.match(b) extra.match = ok if (flip) ok = !ok return assert.ok(ok, message, extra) } var isObj = assert(a && typeof a === "object", message, extra) if (!isObj.ok) { // not an object if (a == b) isObj.ok = true if (flip) isObj.ok = !isObj.ok return isObj } var eq = flip ? inequivalent : equivalent return eq(selectFields(a, b), b, message, extra) } assert.similar = similar syns.similar = ["isSimilar" ,"has" ,"hasFields" ,"like" ,"isLike"] function dissimilar (a, b, message, extra) { if (extra && extra.skip) return assert.skip(message, extra) message = message || "should be dissimilar" return similar(a, b, message, extra, true) } assert.dissimilar = dissimilar syns.dissimilar = ["unsimilar" ,"notSimilar" ,"unlike" ,"isUnlike" ,"notLike" ,"isNotLike" ,"doesNotHave" ,"isNotSimilar" ,"isDissimilar"] function type (thing, t, message, extra) { if (extra && extra.skip) return assert.skip(message, extra) var name = t if (typeof name === "function") name = name.name || "(anonymous ctor)" //console.error("name=%s", name) message = message || "type is "+name var type = typeof thing //console.error("type=%s", type) if (!thing && type === "object") type = "null" if (type === "object" && t !== "object") { if (typeof t === "function") { //console.error("it is a function!") extra = extra || {} extra.found = Object.getPrototypeOf(thing).constructor.name extra.wanted = name //console.error(thing instanceof t, name) return assert.ok(thing instanceof t, message, extra) } //console.error("check prototype chain") // check against classnames or objects in prototype chain, as well. // type(new Error("asdf"), "Error") // type(Object.create(foo), foo) var p = thing while (p = Object.getPrototypeOf(p)) { if (p === t || p.constructor && p.constructor.name === t) { type = name break } } } //console.error(type, name, type === name) return assert.equal(type, name, message, extra) } assert.type = type syns.type = ["isa"] // synonyms are helpful. Object.keys(syns).forEach(function (c) { syns[c].forEach(function (s) { Object.defineProperty(assert, s, { value: assert[c], enumerable: false }) }) }) // helpers below function selectFields (a, b) { // get the values in A of the fields in B var ret = Array.isArray(b) ? [] : {} Object.keys(b).forEach(function (k) { if (!a.hasOwnProperty(k)) return var v = b[k] , av = a[k] if (v && av && typeof v === "object" && typeof av === "object" && !(v instanceof Date) && !(v instanceof RegExp) && !(v instanceof String) && !(v instanceof Boolean) && !(v instanceof Number) && !(Array.isArray(v))) { ret[k] = selectFields(av, v) } else ret[k] = av }) return ret } function sortObject (obj) { if (typeof obj !== 'object' || Array.isArray(obj) || obj === null) { return obj } return Object.keys(obj).sort().reduce(function (acc, key) { acc[key] = sortObject(obj[key]) return acc }, {}) } function stringify (a) { return JSON.stringify(sortObject(a), (function () { var seen = [] , keys = [] return function (key, val) { var s = seen.indexOf(val) if (s !== -1) { return "[Circular: "+keys[s]+"]" } if (val && typeof val === "object" || typeof val === "function") { seen.push(val) keys.push(val["!"] || val.name || key || "") if (typeof val === "function") { return val.toString().split(/\n/)[0] } else if (typeof val.toUTCString === "function") { return val.toUTCString() } } return val }})()) } function diffString (f, w) { if (w === f) return null var p = 0 , l = w.length while (p < l && w.charAt(p) === f.charAt(p)) p ++ w = stringify(w).substr(1).replace(/"$/, "") f = stringify(f).substr(1).replace(/"$/, "") return diff(f, w, p) } function diffObject (f, w) { return difflet({ indent : 2, comment : true }).compare(w, f) } function diff (f, w, p) { if (w === f) return null var i = p || 0 // it's going to be at least p. JSON can only be bigger. , l = w.length while (i < l && w.charAt(i) === f.charAt(i)) i ++ var pos = Math.max(0, i - 20) w = w.substr(pos, 40) f = f.substr(pos, 40) var pointer = i - pos return "FOUND: "+f+"\n" + "WANTED: "+w+"\n" + (new Array(pointer + 9).join(" ")) + "^ (at position = "+p+")" } function getCaller (er) { // get the first file/line that isn't this file. if (!er) er = new Error var stack = er.stack || "" stack = stack.split(/\n/) for (var i = 1, l = stack.length; i < l; i ++) { var s = stack[i].match(/\(([^):]+):([0-9]+):([0-9]+)\)$/) if (!s) continue var file = s[1] , line = +s[2] , col = +s[3] if (file.indexOf(__dirname) === 0) continue if (file.match(/tap-test\/test.js$/)) continue else break } var res = {} if (file && file !== __filename && !file.match(/tap-test\/test.js$/)) { res.file = file res.line = line res.column = col } res.stack = stack.slice(1).map(function (s) { return s.replace(/^\s*at\s*/, "") }) return res } node-tap-0.7.1/lib/tap-browser-harness.js000066400000000000000000000034431247373647400202650ustar00rootroot00000000000000// this is just a harness that pipes to stdout. // It's the default one. module.exports = BrowserHarness var BrowserHarness = global.TAP_Browser_Harness , inherits = require("inherits") , Results = require("./tap-results") , Harness = require("./tap-harness") , Test = require("./tap-test") inherits(BrowserHarness, Harness) function BrowserHarness (outPipe) { //console.error("calling BrowserHarness") if (browserHarness) return browserHarness if (!(this instanceof BrowserHarness)) { return browserHarness = new BrowserHarness } browserHarness = global.TAP_Browser_Harness = this Harness.call(this, Test) if (outPipe) this.output.pipe(outPipe) this.test = this.test.bind(this) this.plan = this.plan.bind(this) var output = this.output this.on("childEnd", function (child) { //console.error("childEnd in global harness") //console.error(child.results) // write out the stuff for this child. //console.error("child.conf", child.conf) // maybe write some other stuff about the number of tests in this // thing, etc. I dunno. //console.error("child results", child.results) this.results.list.forEach(function (res) { //delete res.error //console.error("child resuilt", res) output.write(res) }) //console.error("wrote child results") this.results.list.length = 0 }) var streamEnded = false this.on("end", function () { //console.error("global ending the stream") if (!streamEnded) { this.results.list.forEach(function (res) { output.write(res) }) this.results.list.length = 0 output.end() streamEnded = true } }) // TODO: handle global errors // process.on("unhandledException", function (e) { // this.bailout("unhandled exception: " + e.message) // }) } node-tap-0.7.1/lib/tap-consumer.js000066400000000000000000000155101247373647400167720ustar00rootroot00000000000000module.exports = TapConsumer // pipe a stream into this that's emitting tap-formatted data, // and it'll emit "data" events with test objects or comment strings // and an "end" event with the final results. var yamlish = require("yamlish") , Results = require("./tap-results") , inherits = require("inherits") TapConsumer.decode = TapConsumer.parse = function (str) { var tc = new TapConsumer , list = [] tc.on("data", function (res) { list.push(res) }) tc.end(str) tc.results.list = list return tc.results } var Stream = require("stream").Stream inherits(TapConsumer, Stream) function TapConsumer () { if (!(this instanceof TapConsumer)) { return new TapConsumer } Stream.call(this) this.results = new Results this.readable = this.writable = true this.on("data", function (res) { if (typeof res === "object") this.results.add(res) }) this._plan = null this._buffer = "" this._indent = [] this._current = null this._actualCount = 0 this._passed = [] this._failed = [] //console.error("TapConsumer ctor done") } TapConsumer.prototype.bailedOut = false TapConsumer.prototype.write = function (chunk) { if (!this.writable) this.emit("error", new Error("not writable")) if (this.bailedOut) return true this._buffer = this._buffer + chunk // split it up into lines. var lines = this._buffer.split(/\r?\n/) // ignore the last line, since it might be incomplete. this._buffer = lines.pop() for (var i = 0, l = lines.length; i < l; i ++) { //console.error([i, lines[i]]) // see if it's indented. var line = lines[i] , spaces = (this._indent.length && !line.trim()) || line.match(/^\s/) // at this level, only interested in fully undented stuff. if (spaces) { var c = i while (c < l && (!lines[c].trim() || lines[c].match(/^\s/))) { this._indent.push(lines[c++]) } //console.error(c-i, "indented", this._indent, this._current) i = c - 1 continue } // some kind of line. summary, ok, notok, comment, or garbage. // this also finishes parsing any of the indented lines from before this._parseLine(line) } return true } TapConsumer.prototype.end = function () { // finish up any hanging indented sections or final buffer if (this._buffer.match(/^\s/)) this._indent.push(this.buffer) else this._parseLine(this._buffer) if (!this.bailedOut && this._plan !== null && this.results.testsTotal !== this._plan) { while (this._actualCount < this._plan) { this.emit("data", {ok: false, name:"MISSING TEST", id:this._actualCount ++ }) } } this._parseLine("") this._buffer = "" this.writable = false this.emit("end", null, this._actualCount, this._passed) } TapConsumer.prototype._parseLine = function (line) { if (this.bailedOut) return //console.error("_parseLine", [line]) // if there are any indented lines, and there is a // current object already, then they belong to it. // if there is not a current object, then they're garbage. if (this._current && this._indent.length) { this._parseIndented() } this._indent.length = 0 if (this._current) { if (this._current.ok) this._passed.push(this._current.id) else this._failed.push(this._current.id) this.emit("data", this._current) } this._current = null line = line.trim() if (!line) return // try to see what kind of line this is. var bo if (bo = line.match(/^bail out!\s*(.*)$/i)) { this.bailedOut = true // this.emit("error", new Error(line)) this.emit("bailout", bo[1]) return } if (line.match(/^#/)) { // just a comment line = line.replace(/^#+/, "").trim() // console.error("outputting comment", [line]) if (line) this.emit("data", line) return } var plan = line.match(/^([0-9]+)\.\.([0-9]+)(?:\s+#(.*))?$/) if (plan) { var start = +(plan[1]) , end = +(plan[2]) , comment = plan[3] // TODO: maybe do something else with this? // it might be something like: "1..0 #Skip because of reasons" this._plan = end this.emit("plan", end, comment) // plan must come before or after all tests. if (this._actualCount !== 0) { this._sawPlan = true } return } if (line.match(/^(not )?ok(?:\s+([0-9]+))?/)) { this._parseResultLine(line) return } // garbage. emit as a comment. //console.error("emitting", [line.trim()]) if (line.trim()) this.emit("data", line.trim()) } TapConsumer.prototype._parseDirective = function (line) { line = line.trim() if (line.match(/^TODO\b/i)) { return { todo:true, explanation: line.replace(/^TODO\s*/i, "") } } else if (line.match(/^SKIP\b/i)) { return { skip:true, explanation: line.replace(/^SKIP\s*/i, "") } } } TapConsumer.prototype._parseResultLine = function (line) { this._actualCount ++ if (this._sawPlan) { this.emit("data", {ok: false, name:"plan in the middle of tests" ,id:this._actualCount ++}) } var parsed = line.match(/^(not )?ok(?: ([0-9]+))?(?:(?: - )?(.*))?$/) , ok = !parsed[1] , id = +(parsed[2] || this._actualCount) , rest = parsed[3] || "" , name , res = { id:id, ok:ok } // split on un-escaped # characters //console.log("# "+JSON.stringify([name, rest])) rest = rest.replace(/([^\\])((?:\\\\)*)#/g, "$1\n$2").split("\n") name = rest.shift() rest = rest.filter(function (r) { return r.trim() }).join("#") //console.log("# "+JSON.stringify([name, rest])) // now, let's see if there's a directive in there. var dir = this._parseDirective(rest.trim()) if (!dir) name += rest ? "#" + rest : "" else { res.ok = true if (dir.skip) res.skip = true else if (dir.todo) res.todo = true if (dir.explanation) res.explanation = dir.explanation } res.name = name //console.error(line, [ok, id, name]) this._current = res } TapConsumer.prototype._parseIndented = function () { // pull yamlish block out var ind = this._indent , ys , ye , yind , diag //console.error(ind, this._indent) for (var i = 0, l = ind.length; i < l; i ++) { var line = ind[i] if (line === undefined) continue var lt = line.trim() if (!ys) { ys = line.match(/^(\s*)---(.*)$/) if (ys) { yind = ys[1] diag = [ys[2]] //console.error([line,ys, diag]) continue } else if (lt) this.emit("data", lt) } else if (ys && !ye) { if (line === yind + "...") ye = true else { diag.push(line.substr(yind.length)) } } else if (ys && ye && lt) this.emit("data", lt) } if (diag) { //console.error('about to parse', diag) diag = yamlish.decode(diag.join("\n")) //console.error('parsed', diag) Object.keys(diag).forEach(function (k) { //console.error(this._current, k) if (!this._current.hasOwnProperty(k)) this._current[k] = diag[k] }, this) } } node-tap-0.7.1/lib/tap-cov-html.js000066400000000000000000000046401247373647400166720ustar00rootroot00000000000000var fs = require('fs'), path = require('path'), asyncMap = require("slide").asyncMap, util = require('util'); var CovHtml = module.exports = function(cov_stats, cov_dir, cb) { var index = []; asyncMap( Object.keys(cov_stats), function(f, cb) { var st = cov_stats[f], missing_lines = st.missing.map(function(l) { return l.number; }), out = '\n\n\n ' + '\n ' + f + ' (' + st.loc + ')\n' + '\n' + '\n\n' + '

' + f + ' (' + st.loc + ')' + '

' + '

Run: ' + (st.missing.length ? st.loc - st.missing.length : st.loc) + ', Missing: ' + st.missing.length + ', Percentage: ' + st.percentage + '

' + '

Source:

\n' + '
    \n' + st.lines.map(function(line) { var number = line.number, color = (missing_lines.indexOf(number) !== -1) ? '#fcc' : '#cfc'; return '
  1. ' + line.source.replace(/'; }).join('\n') + '
\n' + '

Data

\n'+ '
' + util.inspect(st, true, Infinity, false).replace(/\n';

      fs.writeFile(
        cov_dir + '/' + 
        f.replace(process.cwd() + '/', '').replace(/\//g, '+') + '.html',
        out,
        'utf8',
        function(err) {
          if (err) {
            throw err;
          }
          index.push(f);
          cb();
        });
    },
    function(err) {
      if (err) {
        throw err;
      }
      var out = '\n\n\n  ' +
          '\n  Coverage Index\n\n' +
          '\n

Code Coverage Information

\n
    ' + index.map(function(fname) { return '
  • ' + fname + '
  • '; }).join('\n') + '
\n\n'; fs.writeFile(cov_dir + '/index.html', out, 'utf8', function(err) { if (err) { throw err; } cb(); }); } ); }; node-tap-0.7.1/lib/tap-global-harness.js000066400000000000000000000043271247373647400200440ustar00rootroot00000000000000// this is just a harness that pipes to stdout. // It's the default one. module.exports = GlobalHarness var globalHarness = global.TAP_Global_Harness , inherits = require("inherits") , Results = require("./tap-results") , Harness = require("./tap-harness") , Test = require("./tap-test") inherits(GlobalHarness, Harness) function GlobalHarness () { //console.error("calling GlobalHarness") if (globalHarness) return globalHarness if (!(this instanceof GlobalHarness)) { return globalHarness = new GlobalHarness } globalHarness = global.TAP_Global_Harness = this Harness.call(this, Test) this.output.pipe(process.stdout) //this.output.on("data", function () { // process.nextTick(process.stdout.flush.bind(process.stdout)) //}) this.test = this.test.bind(this) this.plan = this.plan.bind(this) var output = this.output this.on("childEnd", function (child) { //console.error("childEnd in global harness") //console.error(child.results) // write out the stuff for this child. //console.error("child.conf", child.conf) // maybe write some other stuff about the number of tests in this // thing, etc. I dunno. //console.error("child results", child.results) this.results.list.forEach(function (res) { //delete res.error //console.error("child resuilt", res) output.write(res) }) //console.error("wrote child results") this.results.list.length = 0 }) var streamEnded = false this.on("end", function () { //console.error("global ending the stream") if (!streamEnded) { this.results.list.forEach(function (res) { output.write(res) }) this.results.list.length = 0 output.end() streamEnded = true // If we had fails, then make sure that the exit code // reflects that failure. var exitCode if (!this.results.ok) exitCode = process.exitCode = 1 if (exitCode !== 0) { process.on('exit', function (code) { if (code === 0) process.exit(exitCode) }) } } }) //this.on("end", this.output.end.bind(this.output)) process.on("unhandledException", function (e) { this.bailout("unhandled exception: " + e.message) }) } node-tap-0.7.1/lib/tap-harness.js000066400000000000000000000146101247373647400166020ustar00rootroot00000000000000// a thing that runs tests. // Every "test" is also a harness. If they do not have a harness, // then they are attached to the defaut "global harness", // which writes its results to stdout. // TODO: // - Bailout should stop running any tests. // - "skip" in the test config obj should skip it. module.exports = Harness var EE = require("events").EventEmitter require("inherits")(Harness, EE) var Results = require("./tap-results") , TapProducer = require("./tap-producer") , assert = require("./tap-assert") function Harness (Test) { if (!(this instanceof Harness)) return new Harness(Test) //console.error("Test in "+this.constructor.name, Test) this._Test = Test this._plan = null this._children = [] this._processing = false this._testCount = 0 this._planSum = 0 this.results = new Results() // emit result events on the harness. //this.results.on("result", function (res) { // console.error("proxying result ev from res to harness") // this.emit("result", res) //}.bind(this)) var me = this this.results.on("result", this.emit.bind(this, "result")) var p = this.process.bind(this) this.process = function () { this._processing = true process.nextTick(p) } this.output = new TapProducer() EE.call(this) } // this function actually only gets called bound to // the Harness object, and on process.nextTick. Even if // passed as an event handler, everything *else* will // happen before it gets called. Harness.prototype.process = function () { //console.error("harness process") // "end" can emit multiple times, so only actually move on // to the next test if the current one is actually over. // TODO: multiple in-process tests, if all are marked "async" if (this._current) { if (!this._current._ended) return // handle the current one before moving onto the next. this.childEnd(this._current) } var skip = true while (skip) { //console.error("checking for skips") var current = this._current = this._children.shift() if (current) { skip = current.conf.skip if (skip) { //console.error("add a failure for the skipping") this.results.add(assert.fail(current.conf.name ,{skip:true, diag:false})) } } else skip = false } // keep processing through skipped tests, instead of running them. if (current && this._bailedOut) { return this.process() } //console.error("got current?", !!current) if (current) { current.on("end", this.process) current.emit("ready") //console.error("emitted ready") //console.error("_plan", this._plan, this.constructor.name) } else if (!this._plan || (this._plan && this._plan === this._testCount)) { //console.error("Harness process: no more left. ending") if (this._endNice) { this._endNice() } else { this.end() } } else { this._processing = false; } } Harness.prototype.end = function () { if (this._children.length) { return this.process() } //console.error("harness end", this.constructor.name) if (this._bailedOut) return // can't call .end() more than once. if (this._ended) { //console.error("adding failure for end calling") this.results.add(assert.fail("end called more than once")) } // see if the plan is completed properly, if there was one. if (this._plan !== null) { var total = this._testCount if (total !== this._plan) { this.results.add(assert.equal(total, this._plan, "test count != plan")) } this._plan = total } //console.error("setting ended true", this.constructor.name) this._ended = true this.emit("end") } Harness.prototype.plan = function (p) { //console.error("setting plan", new Error().stack) if (this._plan !== null) { //console.error("about to add failure for calling plan") return this.results.add(assert.fail("plan set multiple times")) } this._plan = p if (p === 0 || this.results.testsTotal) { this.end() } } Harness.prototype.childEnd = function (child) { //console.error("childEnd") this._testCount ++ this._planSum += child._plan //console.error("adding set of child.results") this.results.add(child.conf.name || "(unnamed test)") this.results.addSet(child.results) this.emit("childEnd", child) // was this planned? if (this._plan === this._testCount) { //console.error("plan", [this._plan, this._testCount]) return this.end() } } function copyObj(o) { var copied = {} Object.keys(o).forEach(function (k) { copied[k] = o[k] }) return copied } Harness.prototype.test = function test (name, conf, cb) { if (this._bailedOut) return if (typeof conf === "function") cb = conf, conf = null if (typeof name === "object") conf = name, name = null if (typeof name === "function") cb = name, name = null conf = (conf ? copyObj(conf) : {}) name = name || "" //console.error("making test", [name, conf, cb]) // timeout: value in milliseconds. Defaults to 30s // Set to Infinity to have no timeout. if (isNaN(conf.timeout)) conf.timeout = 30000 var t = new this._Test(this, name, conf) var self = this if (cb) { //console.error("attaching cb to ready event") t.on("ready", function () { if (!isNaN(conf.timeout) && isFinite(conf.timeout)) { var timer = setTimeout(this.timeout.bind(this), conf.timeout) var clear = function () { clearTimeout(timer) } t.on("end", clear) t.on("bailout", function (message) { self.bailout(message) clear() }) } }) t.on("ready", cb.bind(t, t)) // proxy the child results to this object. //t.on("result", function (res) { // console.error("in harness, proxying result up") // t.results.add(res) //}) } return t } Harness.prototype.bailout = function (message) { // console.error("Harness bailout", this.constructor.name) message = message || "" //console.error("adding bailout message result") this.results.add({bailout: message}) // console.error(">>> results after bailout" , this.results) this._bailedOut = true this.emit("bailout", message) this.output.end({bailout: message}) } Harness.prototype.add = function (child) { //console.error("adding child") this._children.push(child) if (!this._processing) this.process() } // the tearDown function is *always* guaranteed to happen. // Even if there's a bailout. Harness.prototype.tearDown = function (fn) { this.on("end", fn) } node-tap-0.7.1/lib/tap-producer.js000066400000000000000000000066741247373647400167750ustar00rootroot00000000000000module.exports = TapProducer var Results = require("./tap-results") , inherits = require("inherits") , yamlish = require("yamlish") TapProducer.encode = function (result, diag) { var tp = new TapProducer(diag) , out = "" tp.on("data", function (c) { out += c }) if (Array.isArray(result)) { result.forEach(tp.write, tp) } else tp.write(result) tp.end() return out } var Stream = require("stream").Stream inherits(TapProducer, Stream) function TapProducer (diag) { Stream.call(this) this.diag = diag this.count = 0 this.readable = this.writable = true this.results = new Results } TapProducer.prototype.trailer = true TapProducer.prototype.write = function (res) { // console.error("TapProducer.write", res) if (typeof res === "function") throw new Error("wtf?") if (!this.writable) this.emit("error", new Error("not writable")) if (!this._didHead) { this.emit("data", "TAP version 13\n") this._didHead = true } var diag = res.diag if (diag === undefined) diag = this.diag this.emit("data", encodeResult(res, this.count + 1, diag)) if (typeof res === "string") return true if (res.bailout) { var bo = "bail out!" if (typeof res.bailout === "string") bo += " " + res.bailout this.emit("data", bo) return } this.results.add(res, false) this.count ++ } TapProducer.prototype.end = function (res) { if (res) this.write(res) // console.error("TapProducer end", res, this.results) this.emit("data", "\n1.."+this.results.testsTotal+"\n") if (this.trailer && typeof this.trailer !== "string") { // summary trailer. var trailer = "tests "+this.results.testsTotal + "\n" if (this.results.pass) { trailer += "pass " + this.results.pass + "\n" } if (this.results.fail) { trailer += "fail " + this.results.fail + "\n" } if (this.results.skip) { trailer += "skip "+this.results.skip + "\n" } if (this.results.todo) { trailer += "todo "+this.results.todo + "\n" } if (this.results.bailedOut) { trailer += "bailed out" + "\n" } if (this.results.testsTotal === this.results.pass) { trailer += "\nok\n" } this.trailer = trailer } if (this.trailer) this.write(this.trailer) this.writable = false this.emit("end", null, this.count, this.ok) } function encodeResult (res, count, diag) { // console.error(res, count, diag) if (typeof res === "string") { res = res.split(/\r?\n/).map(function (l) { if (!l.trim()) return l.trim() return "# " + l }).join("\n") if (res.substr(-1) !== "\n") res += "\n" return res } if (res.bailout) return "" if (!!process.env.TAP_NODIAG) diag = false else if (!!process.env.TAP_DIAG) diag = true else if (diag === undefined) diag = !res.ok var output = "" res.name = res.name && ("" + res.name).trim() output += ( !res.ok ? "not " : "") + "ok " + count + ( !res.name ? "" : " " + res.name.replace(/[\r\n]/g, " ") ) + ( res.skip ? " # SKIP " + ( res.explanation || "" ) : res.todo ? " # TODO " + ( res.explanation || "" ) : "" ) + "\n" if (!diag) return output var d = {} , dc = 0 Object.keys(res).filter(function (k) { return k !== "ok" && k !== "name" && k !== "id" }).forEach(function (k) { dc ++ d[k] = res[k] }) //console.error(d, "about to encode") if (dc > 0) output += " ---"+yamlish.encode(d)+"\n ...\n" return output } node-tap-0.7.1/lib/tap-results.js000066400000000000000000000031541247373647400166410ustar00rootroot00000000000000// A class for counting up results in a test harness. module.exports = Results var inherits = require("inherits") , EventEmitter = require("events").EventEmitter inherits(Results, EventEmitter) function Results (r) { //console.error("result constructor", r) this.ok = true this.addSet(r) } Results.prototype.addSet = function (r) { //console.error("add set of results", r) r = r || {ok: true} ; [ "todo" , "todoPass" , "todoFail" , "skip" , "skipPass" , "skipFail" , "pass" , "passTotal" , "fail" , "failTotal" , "tests" , "testsTotal" ].forEach(function (k) { this[k] = (this[k] || 0) + (r[k] || 0) //console.error([k, this[k]]) }, this) this.ok = this.ok && r.ok && true this.bailedOut = this.bailedOut || r.bailedOut || false this.list = (this.list || []).concat(r.list || []) this.emit("set", this.list) //console.error("after addSet", this) } Results.prototype.add = function (r, addToList) { if (typeof r === 'object') { var pf = r.ok ? "pass" : "fail" , PF = r.ok ? "Pass" : "Fail" this.testsTotal ++ this[pf + "Total"] ++ if (r.skip) { this["skip" + PF] ++ this.skip ++ } else if (r.todo) { this["todo" + PF] ++ this.todo ++ } else { this.tests ++ this[pf] ++ } if (r.bailout || typeof r.bailout === "string") { // console.error("Bailing out in result") this.bailedOut = true } this.ok = !!(this.ok && (r.ok || r.skip || r.todo)) } if (addToList === false) return this.list = this.list || [] this.list.push(r) this.emit("result", r) } node-tap-0.7.1/lib/tap-runner.js000066400000000000000000000344421247373647400164550ustar00rootroot00000000000000var fs = require("fs") , child_process = require("child_process") , path = require("path") , chain = require("slide").chain , asyncMap = require("slide").asyncMap , TapProducer = require("./tap-producer.js") , TapConsumer = require("./tap-consumer.js") , assert = require("./tap-assert.js") , inherits = require("inherits") , util = require("util") , CovHtml = require("./tap-cov-html.js") , glob = require("glob") // XXX Clean up the coverage options , doCoverage = process.env.TAP_COV || process.env.npm_package_config_coverage || process.env.npm_config_coverage module.exports = Runner inherits(Runner, TapProducer) function Runner (options, cb) { this.options = options var diag = this.options.diag var dir = this.options.argv.remain TapProducer.call(this, diag) this.doCoverage = doCoverage // An array of full paths to files to obtain coverage this.coverageFiles = [] // The source of these files this.coverageFilesSource = {} // Where to write coverage information this.coverageOutDir = this.options["coverage-dir"] // Temporary test files bunkerified we'll remove later this.f2delete = [] // Raw coverage stats, as read from JSON files this.rawCovStats = [] // Processed coverage information, per file to cover: this.covStats = {} if (dir) { var filesToCover = this.options.cover if (doCoverage) { var mkdirp = require("mkdirp") this.coverageOutDir = path.resolve(this.coverageOutDir) this.getFilesToCover(filesToCover) var self = this return mkdirp(this.coverageOutDir, '0755', function (er) { if (er) return self.emit("error", er) self.run(dir, cb) }) } this.run(dir, cb) } } Runner.prototype.run = function() { var self = this , args = Array.prototype.slice.call(arguments) , cb = args.pop() || finish function finish (er) { if (er) { self.emit("error", er) } if (!doCoverage) return self.end() // Cleanup temporary test files with coverage: self.f2delete.forEach(function(f) { fs.unlinkSync(f) }) self.getFilesToCoverSource(function(err, data) { if (err) { self.emit("error", err) } self.getPerFileCovInfo(function(err, data) { if (err) { self.emit("error", err) } self.mergeCovStats(function(err, data) { if (err) { self.emit("error", err) } CovHtml(self.covStats, self.coverageOutDir, function() { self.end() }) }) }) }) } if (Array.isArray(args[0])) { args = args[0] } self.runFiles(args, "", cb) } Runner.prototype.runDir = function (dir, cb) { var self = this fs.readdir(dir, function (er, files) { if (er) { self.write(assert.fail("failed to readdir " + dir, { error: er })) self.end() return } files = files.sort(function(a, b) { return a > b ? 1 : -1 }) files = files.filter(function(f) { return !f.match(/^\./) }) files = files.map(function(file) { return path.resolve(dir, file) }) self.runFiles(files, path.resolve(dir), cb) }) } // glob the filenames so that test/*.js works on windows Runner.prototype.runFiles = function (files, dir, cb) { var self = this var globRes = [] chain(files.map(function (f) { return function (cb) { glob(f, function (er, files) { if (er) return cb(er) globRes.push.apply(globRes, files) cb() }) } }), function (er) { if (er) return cb(er) runFiles(self, globRes, dir, cb) }) } // set some default options for node debugging tests function setOptionsForDebug(self) { // Note: we automatically increase the default timeout here. Yes // the user can specify --timeout to increase, but by default, // 30 seconds is not a long time to debug your test. self.options.timeout = 1000000; // Note: we automatically turn on stderr so user can see the 'debugger listening on port' message. // Without this it looks like tap has hung.. self.options.stderr = true; } function runFiles(self, files, dir, cb) { chain(files.map(function(f) { return function (cb) { if (self._bailedOut) return var relDir = dir || path.dirname(f) , fileName = relDir === "." ? f : f.substr(relDir.length + 1) self.write(fileName) fs.lstat(f, function(er, st) { if (er) { self.write(assert.fail("failed to stat " + f, {error: er})) return cb() } var cmd = f, args = [], env = {} if (path.extname(f) === ".js") { cmd = process.execPath if (self.options.gc) { args.push("--expose-gc") } if (self.options.debug) { args.push("--debug") setOptionsForDebug(self) } if (self.options["debug-brk"]) { args.push("--debug-brk") setOptionsForDebug(self) } if (self.options.strict) { args.push("--use-strict") } if (self.options.harmony) { args.push("--harmony") } args.push(fileName) } else if (path.extname(f) === ".coffee") { cmd = "coffee" args.push(fileName) } else { // Check if file is executable if ((st.mode & parseInt('0100', 8)) && process.getuid) { if (process.getuid() != st.uid) { return cb() } } else if ((st.mode & parseInt('0010', 8)) && process.getgid) { if (process.getgid() != st.gid) { return cb() } } else if ((st.mode & parseInt('0001', 8)) == 0) { return cb() } cmd = path.resolve(cmd) } if (st.isDirectory()) { return self.runDir(f, cb) } if (doCoverage && path.extname(f) === ".js") { var foriginal = fs.readFileSync(f, "utf8") , fcontents = self.coverHeader() + foriginal + self.coverFooter() , tmpBaseName = path.basename(f, path.extname(f)) + ".with-coverage." + process.pid + path.extname(f) , tmpFname = path.resolve(path.dirname(f), tmpBaseName) fs.writeFileSync(tmpFname, fcontents, "utf8") args.splice(-1, 1, tmpFname) } for (var i in process.env) { env[i] = process.env[i] } env.TAP = 1 var cp = child_process.spawn(cmd, args, { env: env, cwd: relDir }) , out = "" , err = "" , tc = new TapConsumer() , childTests = [f] var timeout = setTimeout(function () { if (!cp._ended) { cp._timedOut = true cp.kill() } }, self.options.timeout * 1000) tc.on("data", function(c) { self.emit("result", c) self.write(c) }) tc.on("bailout", function (message) { clearTimeout(timeout) console.log("# " + f.substr(process.cwd().length + 1)) process.stderr.write(err) process.stdout.write(out + "\n") self._bailedOut = true cp._ended = true cp.kill() }) cp.stdout.pipe(tc) cp.stdout.on("data", function (c) { out += c }) cp.stderr.on("data", function (c) { if (self.options.stderr) process.stderr.write(c) err += c }) cp.on("close", function (code, signal) { if (cp._ended) return cp._ended = true var ok = !cp._timedOut && code === 0 clearTimeout(timeout) //childTests.forEach(function (c) { self.write(c) }) var res = { name: path.dirname(f).replace(process.cwd() + "/", "") + "/" + fileName , ok: ok , exit: code } if (cp._timedOut) res.timedOut = cp._timedOut if (signal) res.signal = signal if (err) { res.stderr = err if (tc.results.ok && tc.results.tests === 0 && !self.options.stderr) { // perhaps a compilation error or something else failed. // no need if stderr is set, since it will have been // output already anyway. console.error(err) } } // tc.results.ok = tc.results.ok && ok tc.results.add(res) res.command = '"'+[cmd].concat(args).join(" ")+'"' self.emit("result", res) self.emit("file", f, res, tc.results) self.write(res) self.write("\n") if (doCoverage) { self.f2delete.push(tmpFname) } cb() }) }) } }), cb) return self } // Get an array of full paths to files we are interested into obtain // code coverage. Runner.prototype.getFilesToCover = function(filesToCover) { var self = this filesToCover = filesToCover.split(",").map(function(f) { return path.resolve(f) }).filter(function(f) { var existsSync = fs.existsSync || path.existsSync; return existsSync(f) }) function recursive(f) { if (path.extname(f) === "") { // Is a directory: fs.readdirSync(f).forEach(function(p) { recursive(f + "/" + p) }) } else { self.coverageFiles.push(f) } } filesToCover.forEach(function(f) { recursive(f) }) } // Prepend to every test file to run. Note tap.test at the very top due it // "plays" with include paths. Runner.prototype.coverHeader = function() { // semi here since we're injecting it before the first line, // and don't want to mess up line numbers in the test files. return "var ___TAP_COVERAGE = require(" + JSON.stringify(require.resolve("runforcover")) + ").cover(/.*/g);" } // Append at the end of every test file to run. Actually, the stuff which gets // the coverage information. // Maybe it would be better to move into a separate file template so editing // could be easier. Runner.prototype.coverFooter = function() { var self = this // This needs to be a string with proper interpolations: return [ "" , "var ___TAP = require(" + JSON.stringify(require.resolve("./main.js")) + ")" , "if (typeof ___TAP._plan === 'number') ___TAP._plan ++" , "___TAP.test(" + JSON.stringify("___coverage") + ", function(t) {" , " var covFiles = " + JSON.stringify(self.coverageFiles) , " , covDir = " + JSON.stringify(self.coverageOutDir) , " , path = require('path')" , " , fs = require('fs')" , " , testFnBase = path.basename(__filename, '.js') + '.json'" , " , testFn = path.resolve(covDir, testFnBase)" , "" , " function asyncForEach(arr, fn, callback) {" , " if (!arr.length) {" , " return callback()" , " }" , " var completed = 0" , " arr.forEach(function(i) {" , " fn(i, function (err) {" , " if (err) {" , " callback(err)" , " callback = function () {}" , " } else {" , " completed += 1" , " if (completed === arr.length) {" , " callback()" , " }" , " }" , " })" , " })" , " }" , "" , " ___TAP_COVERAGE(function(coverageData) {" , " var outObj = {}" , " asyncForEach(covFiles, function(f, cb) {" , " if (coverageData[f]) {" , " var stats = coverageData[f].stats()" , " , stObj = stats" , " stObj.lines = stats.lines.map(function (l) {" , " return { number: l.lineno, source: l.source() }" , " })" , " outObj[f] = stObj" , " }" , " cb()" , " }, function(err) {" , " ___TAP_COVERAGE.release()" , " fs.writeFileSync(testFn, JSON.stringify(outObj))" , " t.end()" , " })" , " })" , "})" ].join("\n") } Runner.prototype.getFilesToCoverSource = function(cb) { var self = this asyncMap(self.coverageFiles, function(f, cb) { fs.readFile(f, "utf8", function(err, data) { var lc = 0 if (err) { cb(err) } self.coverageFilesSource[f] = data.split("\n").map(function(l) { lc += 1 return { number: lc, source: l } }) cb() }) }, cb) } Runner.prototype.getPerFileCovInfo = function(cb) { var self = this , covPath = path.resolve(self.coverageOutDir) fs.readdir(covPath, function(err, files) { if (err) { self.emit("error", err) } var covFiles = files.filter(function(f) { return path.extname(f) === ".json" }) asyncMap(covFiles, function(f, cb) { fs.readFile(path.resolve(covPath, f), "utf8", function(err, data) { if (err) { cb(err) } self.rawCovStats.push(JSON.parse(data)) cb() }) }, function(f, cb) { fs.unlink(path.resolve(covPath, f), cb) }, cb) }) } Runner.prototype.mergeCovStats = function(cb) { var self = this self.rawCovStats.forEach(function(st) { Object.keys(st).forEach(function(i) { // If this is the first time we reach this file, just add the info: if (!self.covStats[i]) { self.covStats[i] = { missing: st[i].lines } } else { // If we already added info for this file before, we need to remove // from self.covStats any line not duplicated again (since it has // run on such case) self.covStats[i].missing = self.covStats[i].missing.filter( function(l) { return (st[i].lines.indexOf(l)) }) } }) }) // This is due to a bug into // chrisdickinson/node-bunker/blob/feature/add-coverage-interface // which is using array indexes for line numbers instead of the right number Object.keys(self.covStats).forEach(function(f) { self.covStats[f].missing = self.covStats[f].missing.map(function(line) { return { number: line.number, source: line.source } }) }) Object.keys(self.coverageFilesSource).forEach(function(f) { if (!self.covStats[f]) { self.covStats[f] = { missing: self.coverageFilesSource[f] , percentage: 0 } } self.covStats[f].lines = self.coverageFilesSource[f] self.covStats[f].loc = self.coverageFilesSource[f].length if (!self.covStats[f].percentage) { self.covStats[f].percentage = 1 - (self.covStats[f].missing.length / self.covStats[f].loc) } }) cb() } node-tap-0.7.1/lib/tap-test.js000066400000000000000000000055531247373647400161240ustar00rootroot00000000000000// This is a very simple test framework that leverages the tap framework // to run tests and output tap-parseable results. module.exports = Test var assert = require("./tap-assert") , inherits = require("inherits") , Results = require("./tap-results") , Harness = require("./tap-harness") // tests are also test harnesses inherits(Test, Harness) function Test (harness, name, conf) { //console.error("test ctor") if (!(this instanceof Test)) return new Test(harness, name, conf) Harness.call(this, Test) conf.name = name || conf.name || "(anonymous)" this.conf = conf this.harness = harness this.harness.add(this) } // it's taking too long! Test.prototype.timeout = function () { // detect false alarms if (this._ended) return this.fail("Timeout!") this.end() } Test.prototype.clear = function () { this._started = false this._ended = false this._plan = null this._bailedOut = false this._testCount = 0 this.results = new Results() } // this gets called if a test throws ever Test.prototype.threw = function (ex) { //console.error("threw!", ex.stack) this.fail(ex.name + ": " + ex.message, { error: ex, thrown: true }) // may emit further failing tests if the plan is not completed //console.error("end, because it threw") if (!this._ended) this.end() } Test.prototype.comment = function (m) { if (typeof m !== "string") { return this.fail("Test.comment argument must be a string") } this.result("\n" + m.trim()) } Test.prototype.result = function (res) { this.results.add(res) this._testCount ++ this.emit("result", res) if (this._plan === this._testCount) { process.nextTick(this._endNice.bind(this)) } } Test.prototype._endNice = function () { if (!this._ended) this.end() } // parasitic // Who says you can't do multiple inheritance in js? Object.getOwnPropertyNames(assert).forEach(function (k) { if (k === "prototype" || k === "name") return var d = Object.getOwnPropertyDescriptor(assert, k) , v = d.value if (!v) return d.value = assertParasite(v) Object.defineProperty(Test.prototype, k, d) }) function assertParasite (fn) { return function _testAssert () { //console.error("_testAssert", fn.name, arguments) if (this._bailedOut) return var res = fn.apply(assert, arguments) this.result(res) return res }} // a few tweaks on the EE emit function, because // we want to catch all thrown errors and bubble up "bailout" Test.prototype.emit = (function (em) { return function (t) { // bailouts bubble until handled if (t === "bailout" && this.listeners(t).length === 0 && this.harness) { return this.harness.bailout(arguments[1]) } if (t === "error") return em.apply(this, arguments) try { em.apply(this, arguments) } catch (ex) { // any exceptions in a test are a failure //console.error("caught!", ex.stack) this.threw(ex) } }})(Harness.prototype.emit) node-tap-0.7.1/package.json000066400000000000000000000016721247373647400155430ustar00rootroot00000000000000{ "name": "tap", "version": "0.7.1", "author": "Isaac Z. Schlueter (http://blog.izs.me)", "description": "A Test-Anything-Protocol library", "bin": "bin/tap.js", "main": "lib/main.js", "engines": { "node": ">=0.8" }, "dependencies": { "buffer-equal": "~0.0.0", "deep-equal": "^1.0.0", "difflet": "~0.2.0", "glob": "^4.3.5", "inherits": "*", "mkdirp": "^0.5.0", "nopt": "^3.0.1", "runforcover": "~0.0.2", "slide": "*", "yamlish": "*" }, "keywords": [ "assert", "test", "tap" ], "contributors": [ "Isaac Z. Schlueter (http://blog.izs.me)", "baudehlo " ], "license": { "type": "MIT", "url": "https://github.com/isaacs/node-tap/raw/master/LICENSE" }, "repository": "https://github.com/isaacs/node-tap.git", "scripts": { "test": "node --use_strict bin/tap.js test/*.*" }, "devDependencies": {} } node-tap-0.7.1/test-disabled/000077500000000000000000000000001247373647400157735ustar00rootroot00000000000000node-tap-0.7.1/test-disabled/bailout.js000066400000000000000000000012671247373647400177760ustar00rootroot00000000000000var tap = require("tap") , test = tap.test test("bailout test", { skip: false }, function (t) { // t.once("bailout", function () { // console.error("bailout event")//, t) // t.clear() // }) // t.once("end", function () { // console.error("end event") // }) // simulate three tests where the second bails out. t.test("first", function (t) { t.pass("this is ok") t.end() }) t.test("bailout", function (t) { console.error("bailout test") t.pass("pass") t.bailout("bail out message") t.fail("fail") t.end() }) t.test("second (should not happen)", function (t) { t.fail("this should not happen") t.end() }) t.end() }) node-tap-0.7.1/test-disabled/foo.js000066400000000000000000000000161247373647400171110ustar00rootroot00000000000000process.stdin node-tap-0.7.1/test-disabled/t.js000066400000000000000000000004201247373647400165700ustar00rootroot00000000000000var test = require('tap').test; function foo() { throw new Error('one'); } test('demonstrate bug in t.throws', function (t) { t.throws( function () { foo(); }, new Error('two')), // "this should throw", // {}); // not 'one'! t.end(); }); node-tap-0.7.1/test/000077500000000000000000000000001247373647400142265ustar00rootroot00000000000000node-tap-0.7.1/test/buffer_compare.js000066400000000000000000000003701247373647400175430ustar00rootroot00000000000000var test = require("../").test test("same buffers", function (t) { t.same(new Buffer([3,4,243]), new Buffer([3,4,243])) t.end() }) test("not same buffers", function (t) { t.notSame(new Buffer([3,5,243]), new Buffer([3,4,243])) t.end() }) node-tap-0.7.1/test/common.js000066400000000000000000000026751247373647400160660ustar00rootroot00000000000000exports.taps = ["Tests for the foo module" ,{ok:true, name:"test that the foo is fooish" ,file:"foo.js", line:8, name:"fooish test" ,stack:new Error("fooish").stack} ,{ok:false, name:"a test that the bar is barish" ,file:"bar.js", line:25 ,expected:"bar\nbar\nbaz", actual:"rab\nrib\nzib" ,hash:{more:"\nstuff\nhere\n",regexp:/asdf/}} ,"Quux module tests" ,"This is a longer comment" ,{ok:true, name:"an easy one."} ,{ok:false, name:"bloooooo" ,expected:"blerggeyyy" ,actual:"blorggeyy"} ,{ok:false, name:"array test" ,expected:[{ok:true},{ok:true},{stack:new Error().stack}] ,actual:[1234567890,123456789,{error:new Error("yikes")}]} ,{ok:true, name:"nulltest" ,expected:undefined, actual:null} ,{ok:true, name:"weird key test" ,expected:"weird key" ,actual:"weird key" ,"this object":{"has a ":"weird key" ,"and a looooooooonnnnnnnnnggg":"jacket"}} ,{ok:true, name:"regexp test" ,regexp:/asdf/,function:function (a,b) { return a + b }} ] if (require.main === module) { console.log("1..1") console.log("ok 1 - just setup, nothing relevant") } node-tap-0.7.1/test/debug-test.js000066400000000000000000000010231247373647400166230ustar00rootroot00000000000000var tap = require("../") , fs = require("fs") , cp = require("child_process") , util = require("util") tap.test("debug test", function (t) { console.error("debug test") t.plan(1) console.error("t.plan="+t._plan) cp.exec("../bin/tap.js --debug meta-test.js", function (err, stdo, stde) { console.error(util.inspect(stde)) // node 0.10 print "debugger", 0.12 and iojs are printing "Debugger" t.notEqual(stde.indexOf("ebugger listening on port"), -1, "Should output debugger message") t.end(); }) }) node-tap-0.7.1/test/deep-strict.js000066400000000000000000000015551247373647400170150ustar00rootroot00000000000000var tap = require("../") , test = tap.test test("strictDeepEquals shouldn't care about key order", function (t) { t.strictDeepEqual({ a : 1, b : 2 }, { b : 2, a : 1 }) t.end() }) test("strictDeepEquals shouldn't care about key order recursively", function (t) { t.strictDeepEqual( { x : { a : 1, b : 2 }, y : { c : 3, d : 4 } }, { y : { d : 4, c : 3 }, x : { b : 2, a : 1 } } ) t.end() }) test("strictDeepEquals shoudn't care about key order (but still might)", function (t) { t.strictDeepEqual( [ { foo: { z: 100 , y: 200 , x: 300 } } , "bar" , 11 , { baz: { d : 4 , a: 1 , b: 2 , c: 3 } } ] , [ { foo : { z: 100 , y: 200 , x: 300 } } , "bar" , 11 , { baz: { a: 1 , b: 2 , c: 3 , d: 4 } } ] ) t.end() }); node-tap-0.7.1/test/deep.js000066400000000000000000000015651247373647400155100ustar00rootroot00000000000000var tap = require("../") , test = tap.test test("deepEquals shouldn't care about key order and types", function (t) { t.deepEqual({ a : 1, b : 2 }, { b : 2, a : "1" }) t.end() }) test("deepEquals shouldn't care about key order recursively and types", function (t) { t.deepEqual( { x : { a : 1, b : 2 }, y : { c : 3, d : 4 } }, { y : { d : 4, c : 3 }, x : { b : "2", a : "1" } } ) t.end() }) test("deepEquals shoudn't care about key order (but still might) and types", function (t) { t.deepEqual( [ { foo: { z: 100 , y: 200 , x: 300 } } , "bar" , 11 , { baz: { d : 4 , a: 1 , b: 2 , c: 3 } } ] , [ { foo : { z: 100 , y: 200 , x: 300 } } , "bar" , 11 , { baz: { a: "1" , b: "2" , c: "3" , d: "4" } } ] ) t.end() }); node-tap-0.7.1/test/end-exception/000077500000000000000000000000001247373647400167705ustar00rootroot00000000000000node-tap-0.7.1/test/end-exception/t.js000066400000000000000000000002561247373647400175740ustar00rootroot00000000000000var test = require("../../").test test(function (t) { t.plan(1) t.on('end', function () { console.log('end()') throw new Error('beep') }) t.equal(3, 3) }) node-tap-0.7.1/test/executed.sh000077500000000000000000000001171247373647400163720ustar00rootroot00000000000000#!/bin/sh echo "1..1" echo "ok 1 File with executable bit should be executed" node-tap-0.7.1/test/exit-code.js000066400000000000000000000035411247373647400164500ustar00rootroot00000000000000var spawn = require('child_process').spawn var node = process.execPath var bin = require.resolve('../bin/tap.js') var test = require('../').test var path = require('path') var fixtures = path.resolve(__dirname, 'fixtures') test('exit code 1 when tap results show failure', function (t) { t.plan(3) t.test('test exits 0, has failures', function (t) { t.plan(2) var file = path.resolve(fixtures, 'fail-zero-exit.js') spawn(node, [bin, file]).on('exit', function (code) { t.equal(code, 1) }) spawn(node, [file]).on('exit', function (code) { t.equal(code, 0) }) }) t.test('test exits 1, has failures', function (t) { t.plan(2) var file = path.resolve(fixtures, 'fail-correct-exit.js') spawn(node, [bin, file]).on('exit', function (code) { t.equal(code, 1) }) spawn(node, [file]).on('exit', function (code) { t.equal(code, 1) }) }) t.test('test exits 1, has no failures', function (t) { t.plan(2) var file = path.resolve(fixtures, 'fail-exit.js') spawn(node, [bin, file]).on('exit', function (code) { t.equal(code, 1) }) spawn(node, [file]).on('exit', function (code) { t.equal(code, 1) }) }) }) test('successes exit 0', function (t) { t.plan(2) t.test('test that does nothing, but exits 0', function (t) { t.plan(2) var file = path.resolve(fixtures, 'trivial-success.js') spawn(node, [bin, file]).on('exit', function (code) { t.equal(code, 0) }) spawn(node, [file]).on('exit', function (code) { t.equal(code, 0) }) }) t.test('test that succeeds, and exits 0', function (t) { t.plan(2) var file = path.resolve(fixtures, 'success.js') spawn(node, [bin, file]).on('exit', function (code) { t.equal(code, 0) }) spawn(node, [file]).on('exit', function (code) { t.equal(code, 0) }) }) }) node-tap-0.7.1/test/expose-gc-test.js000066400000000000000000000026141247373647400174360ustar00rootroot00000000000000var tap = require("../") , fs = require("fs") , cp = require("child_process") , path = require("path") , dir = path.resolve(__dirname, "..") , script = path.resolve(dir, "gc-script.js") , opt = { cwd: dir } fs.writeFileSync(script, "console.error(!!global.gc)", "utf8") tap.test("gc test when the gc isn't there", function (t) { console.error("gc test") t.plan(1) console.error("t.plan="+t._plan) cp.exec("bin/tap.js ./gc-script.js", opt, function (err, stdo, stde) { console.error("assert gc does not exist") t.equal(stde, "false\n") }) }) tap.test("gc test when the gc should be there", function (t) { console.error("gc test") t.plan(2) console.error("t.plan="+t._plan) t.test("test for gc using --gc", function (t) { console.error("gc test using --gc") t.plan(1) console.error("t.plan="+t._plan) cp.exec("bin/tap.js --gc ./gc-script.js", opt, function (err, stdo, stde) { console.error("assert gc exists") t.equal(stde, "true\n") }) }) t.test("test for gc using --expose-gc", function (t) { console.error("gc test using --expose-gc") t.plan(1) console.error("t.plan="+t._plan) cp.exec("bin/tap.js --expose-gc ./gc-script.js", opt, function (err, stdo, stde) { console.error("assert gc exists") t.equal(stde, "true\n") }) }) }) tap.test("cleanup", function (t) { fs.unlinkSync(script) t.end() }); node-tap-0.7.1/test/fixtures/000077500000000000000000000000001247373647400160775ustar00rootroot00000000000000node-tap-0.7.1/test/fixtures/fail-correct-exit.js000066400000000000000000000001661247373647400217610ustar00rootroot00000000000000console.log('TAP Version 13') console.log('not ok - 1 and it will exit non-zero') console.log('1..1') process.exit(1) node-tap-0.7.1/test/fixtures/fail-exit.js000066400000000000000000000001621247373647400203160ustar00rootroot00000000000000console.log('TAP Version 13') console.log('ok - 1 but it will exit non-zero') console.log('1..1') process.exit(1) node-tap-0.7.1/test/fixtures/fail-zero-exit.js000066400000000000000000000001621247373647400212730ustar00rootroot00000000000000console.log('TAP Version 13') console.log('not ok - 1 but it will exit zero') console.log('1..1') process.exit(0) node-tap-0.7.1/test/fixtures/success.js000066400000000000000000000001231247373647400201010ustar00rootroot00000000000000console.log('TAP Version 13') console.log('ok - 1 and exit 0') console.log('1..1') node-tap-0.7.1/test/fixtures/todo-skip-descriptions.js000066400000000000000000000003421247373647400230510ustar00rootroot00000000000000console.log('ok - always passes # SKIP skip it, skip it good') console.log('not ok - false # SKIP always fails') console.log('ok - bonus # TODO remove todo directive') console.log('not ok - expected # TODO implement a thing') node-tap-0.7.1/test/fixtures/trivial-success.js000066400000000000000000000000021247373647400215450ustar00rootroot00000000000000; node-tap-0.7.1/test/independent-timeouts.js000066400000000000000000000004761247373647400207370ustar00rootroot00000000000000// https://github.com/isaacs/node-tap/issues/23 var tap = require("../") , test = tap.test test("finishes in time", {timeout: 500}, function(t) { setTimeout(function () { t.end(); }, 300); }) test("finishes in time too", {timeout: 500}, function(t) { setTimeout(function () { t.end(); }, 300); }) node-tap-0.7.1/test/isolated-conf-test.js000066400000000000000000000005601247373647400202710ustar00rootroot00000000000000// https://github.com/isaacs/node-tap/issues/24 var tap = require("../") , test = tap.test var config = {foo: "bar"} test("one", config, function(t) { t.equal(t.conf.foo, "bar") t.equal(t.conf.name, "one") // before fix this would be "two" t.end() }) test("two", config, function(t) { t.equal(t.conf.foo, "bar") t.equal(t.conf.name, "two") t.end() }) node-tap-0.7.1/test/meta-test.js000066400000000000000000000044351247373647400164750ustar00rootroot00000000000000var tap = require("../") , test = tap.test test("meta test", { skip: false }, function (t) { function thr0w() { throw new Error('raburt') } function noop () {} // this also tests the ok/notOk functions t.once("end", section2) t.ok(true, "true is ok") t.ok(noop, "function is ok") t.ok({}, "object is ok") t.ok(t, "t is ok") t.ok(100, "number is ok") t.ok("asdf", "string is ok") t.notOk(false, "false is notOk") t.notOk(0, "0 is notOk") t.notOk(null, "null is notOk") t.notOk(undefined, "undefined is notOk") t.notOk(NaN, "NaN is notOk") t.notOk("", "empty string is notOk") t.throws(thr0w, "Thrower throws"); t.doesNotThrow(noop, "noop does not throw"); t.similar({foo:"bar", bar:"foo"}, {foo:"bar"}, "similar objects are ok"); t.dissimilar({}, {mandatory:"value"}, "dissimilar objects are ok"); t.dissimilar(null, {}, "null is dissimilar from an object, even with no keys"); // a few failures. t.ifError(new Error("this is an error")) t.ifError({ message: "this is a custom error" }) t.ok(false, "false is not ok") t.notOk(true, "true is not not ok") t.similar(null, {}, "Null is not similar to an object, even with no keys"); t.throws(noop, "noop does not throw"); t.throws(noop, new Error("Whoops!"), "noop does not throw an Error"); t.throws(noop, {name:"MyError", message:"Whoops!"}, "noop does not throw a MyError"); t.doesNotThrow(thr0w, "thrower does throw"); // things that are like other things t.like("asdf", "asdf") t.like("asdf", /^a.*f$/) t.like(100, 100) t.like(100, '100') t.like(100, 100.0) t.unlike("asdf", "fdsa") t.unlike("asdf", /^you jelly, bro?/) t.unlike(100, 100.1) t.like(true, 1) t.like(null, undefined) t.like(true, [1]) t.like(false, []) t.like('', []) t.end() function section2 () { var results = t.results t.clear() t.ok(true, "sanity check") t.notOk(results.ok, "not ok") t.equal(results.tests, 39, "total test count") t.equal(results.passTotal, 30, "tests passed") t.equal(results.fail, 9, "tests failed") t.type(results.ok, "boolean", "ok is boolean") t.type(results.skip, "number", "skip is number") t.type(results, "Results", "results isa Results") t.type(t, "Test", "test isa Test") t.type(t, "Harness", "test isa Harness") t.end() } }) node-tap-0.7.1/test/nested-async.js000066400000000000000000000013731247373647400171650ustar00rootroot00000000000000var test = require("../").test test('Harness async test support', function(t) { t.plan(3); t.ok(true, 'sync child A'); t.test('sync child B', function(tt) { tt.plan(2); setTimeout(function(){ tt.test('async grandchild A', function(ttt) { ttt.plan(1); ttt.ok(true); }); }, 50); setTimeout(function() { tt.test('async grandchild B', function(ttt) { ttt.plan(1); ttt.ok(true); }); }, 100); }); setTimeout(function() { t.test('async child', function(tt) { tt.plan(2); tt.ok(true, 'sync grandchild in async child A'); tt.test('sync grandchild in async child B', function(ttt) { ttt.plan(1); ttt.ok(true); }); }); }, 200); }); node-tap-0.7.1/test/nested-test.js000066400000000000000000000006711247373647400170270ustar00rootroot00000000000000var tap = require("../"), test = tap.test; test("parent", function (t) { // TODO: Make grandchildren tests count? t.plan(3); t.ok(true, 'p test'); t.test("subtest", function (t) { t.ok(true, 'ch test'); t.test('nested subtest', function(t) { t.ok(true, 'grch test'); t.end(); }); t.end(); }); t.test('another subtest', function(t) { t.ok(true, 'ch test 2'); t.end(); }); t.end(); }) node-tap-0.7.1/test/non-tap-output.js000066400000000000000000000006401247373647400174760ustar00rootroot00000000000000console.log("everything is fine\n" +"there are no errors\n" +"this output is not haiku.\n\n" +"is 8 ok?\n" +"ok, 8 can stay.\n" +"ok 100 might be confusing\n" +" but: nevertheless, here we are\n" +" this: is indented\n" +" and: it\n" +" might: ~\n" +" be: yaml?\n" +"ok done now, exiting") node-tap-0.7.1/test/not-executed.sh000066400000000000000000000001341247373647400171640ustar00rootroot00000000000000#!/bin/sh echo "1..1" echo "not ok 1 File without executable bit should not be run" exit 1 node-tap-0.7.1/test/output-childtest-description.js000066400000000000000000000032161247373647400224300ustar00rootroot00000000000000var tap = require("../") , fs = require("fs") , path = require('path') , cp = require("child_process") , nestedTests = [ "var test = require('..').test" , "test('parent test description', function (t) {" , " t.plan(2)" , " t.ok(true, 'test in parent')" , " t.test('child test description', function (t) {" , " t.plan(1)" , " t.ok(true, 'test in child') " , " })" , "})" ].join("\n") , nestedTestsFile = path.join(__dirname, "nested-tests-fixture.js") fs.writeFileSync(nestedTestsFile, nestedTests, "utf8") console.log(nestedTestsFile); tap.test("nested tests, parent and child pass", function (t) { /* * Ensure the output includes the following lines in the right order: * '# parent test description' * 'ok 1 test in parent' * '# child test description' * 'ok 2 test in child' */ t.plan(5) cp.exec("node " + nestedTestsFile, function (err, stdo, stde) { var lines = stdo.split("\n") , parentDes = lines.indexOf("# parent test description") , parentRes = lines.indexOf("ok 1 test in parent") , childDes = lines.indexOf("# child test description") , childRes = lines.indexOf("ok 2 test in child") t.notEqual(parentDes, -1, "outputs parent description") t.notEqual(childDes, -1, "outputs child description") t.ok(parentDes < parentRes , "outputs parent description before parent result") t.ok(parentRes < childDes , "outputs parent result before child description") t.ok(childDes < childRes , "outputs child description before child result") fs.unlinkSync(nestedTestsFile); t.end() }) }) node-tap-0.7.1/test/result-trap.js000066400000000000000000000005211247373647400170440ustar00rootroot00000000000000var tap = require("../") tap.test("trap result", function (t0) { var t1 = new(tap.Harness)(tap.Test).test() var emitted = false t1.on("result", function (res) { if (!emitted) { emitted = true t0.equal(res.found, 3) t0.equal(res.wanted, 4) t0.end() t1.end() } }) t1.equal(1 + 2, 4) }) node-tap-0.7.1/test/segv.js000066400000000000000000000032121247373647400155260ustar00rootroot00000000000000var test = require('../').test var Runner = require('../lib/tap-runner.js') var TC = require('../lib/tap-consumer.js') var fs = require('fs') var path = require('path') var spawn = require('child_process').spawn var segv = 'int main (void) {\n' + ' char *s = "hello world";\n' + ' *s = \'H\';\n' + '}\n' var compiled = false test('setup', function (t) { fs.writeFile('segv.c', segv, 'utf8', function (er) { if (er) throw er var cp = spawn('gcc', ['segv.c', '-o', 'segv']) cp.on('exit', function (code, sig) { if (code !== 0) { t.bailout('failed to compile segv program') return } t.pass('compiled seg faulter') t.end() }) }) }) test('segv', function (t) { var r = new Runner({argv:{remain:['./segv']}}) var tc = new TC() var expect = [ 'TAP version 13' , './segv' , { 'id': 1, 'ok': false, 'name': ' ././segv', 'exit': null, 'timedOut': true, 'signal': process.platform === 'linux' ? 'SIGSEGV' : 'SIGTERM', 'command': '"' + path.resolve('./segv') + '"' } , 'tests 1' , 'fail 1' ] r.pipe(tc) tc.on('data', function (d) { var e = expect.shift() // specific signal can be either term or bus if (d.signal && e.signal) e.signal = d.signal === "SIGTERM" || d.signal === "SIGBUS" ? d.signal : e.signal t.same(d, e) }) tc.on('end', function () { t.equal(expect.length, 0) t.end() }) }) test('cleanup', function (t) { fs.unlink('segv.c', function () { fs.unlink('segv', function () { t.pass('cleaned up') t.end() }) }) }) node-tap-0.7.1/test/simple-harness-test-with-plan.js000066400000000000000000000004331247373647400223740ustar00rootroot00000000000000var tap = require("../") , test = tap.test , plan = tap.plan plan(2) test("trivial success", function (t) { t.ok(true, "it works") t.end() }) test("two tests", function (t) { t.equal(255, 0xFF, "math should work") t.notOk(false, "false should not be ok") t.end() }) node-tap-0.7.1/test/simple-harness-test.js000066400000000000000000000003761247373647400205010ustar00rootroot00000000000000var tap = require("../") , test = tap.test test("trivial success", function (t) { t.ok(true, "it works") t.end() }) test("two tests", function (t) { t.equal(255, 0xFF, "math should work") t.notOk(false, "false should not be ok") t.end() }) node-tap-0.7.1/test/test-assert-todo-skip.js000066400000000000000000000011301247373647400207440ustar00rootroot00000000000000var test = require('../').test test('not much', function(t) { t.ok(true, 'always passes', {skip: true, explanation: 'skip it good'}) t.ok(false, 'false', {skip: true, explanation: 'always fails'}) t.ok(true, 'bonus', {todo: true, explanation: 'remove todo directive'}) t.ok(false, 'expected', {todo: true, explanation: 'implement a thing'}) t.ok(true, 'always passes without explanation', {skip: true}) t.ok(false, 'false without explanation', {skip: true}) t.ok(true, 'bonus without explanation', {todo: true}) t.ok(false, 'expected without explanation', {todo: true}) t.end() }) node-tap-0.7.1/test/test-directives.js000066400000000000000000000037341247373647400177110ustar00rootroot00000000000000var execFile = require('child_process').execFile var node = process.execPath var bin = require.resolve('../bin/tap.js') var test = require('../').test var path = require('path') var fixtures = path.resolve(__dirname, 'fixtures') test('captures test descriptions', function (t) { var useConsole = path.resolve(fixtures, 'todo-skip-descriptions.js') var useTap = require.resolve('./test-assert-todo-skip.js') t.test('raw TAP > TAP consumer > TAP producer', function(t) { var args = [bin, '--tap', useConsole] execFile(node, args, assertTapDirectives.bind(this, t)) }) t.test('raw TAP > TAP consumer > summary', function(t) { var args = [bin, '--no-tap', useConsole] execFile(node, args, assertDirectivesSummary.bind(this, t)) }) t.test('TAP producer via require("tap")', function(t) { var args = [useTap] execFile(node, args, assertTapDirectives.bind(this, t)) }) function assertTapDirectives(t, err, stdout, stderr) { t.ifError(err, 'overall result is PASS') t.assert(/passes # SKIP skip/i.test(stdout), 'captures ok SKIP') t.assert(/false # SKIP always/i.test(stdout), 'captures not ok SKIP') t.assert(!/skipped: \d+/.test(stdout), 'skip summary not in TAP output') t.assert(/bonus # TODO remove/i.test(stdout), 'captures ok TODO') t.assert(/expected # TODO implem/i.test(stdout), 'captures not ok TODO') t.assert(!/todo: \d+/.test(stdout), 'todo summary is not in TAP output') t.assert(!/undefined/.test(stdout), 'no ugly "undefined" in output') t.end() } function assertDirectivesSummary(t, err, stdout, stderr) { t.ifError(err, 'overall result is PASS') t.assert(!/# SKIP/i.test(stdout), 'no SKIP in summary') t.assert(/skipped: 2/.test(stdout), 'skip summary is not in TAP output') t.assert(!/# TODO/i.test(stdout), 'no TODO in summary') t.assert(/todo: 2/.test(stdout), 'todo summary is not in TAP output') t.assert(!/undefined/.test(stdout), 'no ugly "undefined" in output') t.end() } }) node-tap-0.7.1/test/test-skip.js000066400000000000000000000001551247373647400165100ustar00rootroot00000000000000var tap = require('../'); tap.test('does not count as failure', { skip: true }, function(t) { t.end(); }) node-tap-0.7.1/test/test-test.js000066400000000000000000000033701247373647400165230ustar00rootroot00000000000000var tap = require("../") , test = tap.test , Test = require("../lib/tap-test") , Harness = require("../lib/tap-harness") test("testing the test object", function (t) { t.isa(t, Test, "test object should be instanceof Test") t.isa(t, Harness, "test object should be instanceof Harness") t.is(t._Test, Test, "test._Test should be the Test class") // now test all the methods. ; [ "isNotDeepEqual" , "equals" , "inequivalent" , "threw" , "strictEqual" , "emit" , "fail" , "strictEquals" , "notLike" , "dissimilar" , "true" , "assert" , "is" , "ok" , "isEqual" , "isDeeply" , "deepEqual" , "deepEquals" , "pass" , "length" , "skip" , "isNotEqual" , "looseEquals" , "false" , "notDeeply" , "ifErr" , "hasFields" , "isNotDeeply" , "like" , "similar" , "notOk" , "isDissimilar" , "isEquivalent" , "doesNotEqual" , "isSimilar" , "notDeepEqual" , "type" , "notok" , "isInequivalent" , "isNot" , "same" , "isInequal" , "_endNice" , "ifError" , "iferror" , "clear" , "has" , "not" , "timeout" , "notSimilar" , "isUnlike" , "notEquals" , "unsimilar" , "result" , "doesNotThrow" , "error" , "constructor" , "notEqual" , "throws" , "isLike" , "isNotSimilar" , "isNotEquivalent" , "inequal" , "notEquivalent" , "isNotLike" , "equivalent" , "looseEqual" , "equal" , "unlike" , "doesNotHave" , "comment" , "isa" ].forEach(function (method) { t.ok(t[method], "should have "+method+" method") t.isa(t[method], "function", method+" method should be a function") }) t.end() }) node-tap-0.7.1/test/timeout.js000066400000000000000000000013301247373647400162470ustar00rootroot00000000000000var tap = require("../") tap.test("timeout test with plan only", function (t) { console.error("timeout test") t.plan(2) console.error("t.plan="+t._plan) setTimeout(function () { console.error("a assert") t.ok(true, "a") }, 1000) setTimeout(function () { console.error("b assert") t.ok(true, "b") }, 1000) }) tap.test("timeout test with plan and end", function (t) { console.error("timeout test") t.plan(2) var tc = 2 console.error("t.plan="+t._plan) setTimeout(function () { console.error("a assert") t.ok(true, "a") if (-- tc === 0) t.end() }, 1000) setTimeout(function () { console.error("b assert") t.ok(true, "b") if (-- tc === 0) t.end() }, 1000) }) node-tap-0.7.1/test/trivial-success.js000066400000000000000000000000001247373647400176720ustar00rootroot00000000000000node-tap-0.7.1/test/undefined_indented.js000066400000000000000000000007511247373647400204020ustar00rootroot00000000000000var tap = require("../") tap.test("consume yaml", function (t) { t.plan(1) var s = [ "not ok 1 beep boop" , " ---" , " stack:" , " - rawr" , " - dinosaurs" , " ..." ].join("\n") , c = tap.createConsumer() c.on("data", function (res) { t.same(res, { id: 1 , ok: false , name: " beep boop" // <-- should perhaps .trim() this? , stack: [ "rawr", "dinosaurs" ] }) t.end() }) c.write(s) c.end() }) node-tap-0.7.1/test/valid-command.js000066400000000000000000000015341247373647400173020ustar00rootroot00000000000000var test = require('../').test var Runner = require('../lib/tap-runner.js') var TC = require('../lib/tap-consumer.js') test('valid command', function (t) { var r = new Runner({argv:{remain:['./end-exception/t.js']}}) var tc = new TC() var node = process.execPath var expectObj ={ 'id': 1, 'ok': false, 'name': ' ./end-exception/t.js', 'timedOut': true, 'command': '"' + node + ' t.js"', exit: null } if (process.platform === 'linux' && process.version < 'v0.11.0') { expectObj.exit = 143 } else { expectObj.signal = 'SIGTERM' } var expect = [ 'TAP version 13' , 't.js' , expectObj , 'tests 1' , 'fail 1' ] r.pipe(tc) tc.on('data', function (d) { var e = expect.shift() t.same(d, e) }) tc.on('end', function () { t.equal(expect.length, 0) t.end() }) })