From 81690b50a153f9dcb76a6f6a630914be09574ec4 Mon Sep 17 00:00:00 2001 From: "Jeremy@marzhillstudios.com" Date: Wed, 22 Oct 2008 23:15:04 +0000 Subject: [PATCH] initial import to Google Code git-svn-id: https://test-tap.googlecode.com/svn/trunk@2 62346678-a08d-11dd-9c66-c9f8973bfffa --- Changes | 44 +++++ META.yml | 8 + Makefile | 2 + README | 57 +++++++ TODO | 0 harness/prove_rhino.t | 3 + harness/rhino_harness.js | 24 +++ lib/Test/TAP.js | 348 +++++++++++++++++++++++++++++++++++++++ lib/Test/TAP/Class.js | 204 +++++++++++++++++++++++ lib/Test/TAP/Runner.js | 104 ++++++++++++ lib/Test/TAPBrowser.js | 99 +++++++++++ scripts/addtoproject.sh | 73 ++++++++ scripts/mkdist.sh | 74 +++++++++ scripts/updateproject.sh | 54 ++++++ tests/01_tap.t.js | 176 ++++++++++++++++++++ tests/TapHarness.html | 52 ++++++ tmpl/TapHarness.html | 57 +++++++ tmpl/prove_rhino.t | 3 + tmpl/rhino_harness.js | 35 ++++ 19 files changed, 1417 insertions(+) create mode 100644 Changes create mode 100644 META.yml create mode 100644 Makefile create mode 100644 README create mode 100644 TODO create mode 100644 harness/prove_rhino.t create mode 100755 harness/rhino_harness.js create mode 100644 lib/Test/TAP.js create mode 100644 lib/Test/TAP/Class.js create mode 100644 lib/Test/TAP/Runner.js create mode 100644 lib/Test/TAPBrowser.js create mode 100755 scripts/addtoproject.sh create mode 100755 scripts/mkdist.sh create mode 100755 scripts/updateproject.sh create mode 100644 tests/01_tap.t.js create mode 100644 tests/TapHarness.html create mode 100644 tmpl/TapHarness.html create mode 100644 tmpl/prove_rhino.t create mode 100755 tmpl/rhino_harness.js diff --git a/Changes b/Changes new file mode 100644 index 0000000..02499dd --- /dev/null +++ b/Changes @@ -0,0 +1,44 @@ +Mon Sep 10 14:09:01 CDT 2007 jeremy@marzhillstudios.com + tagged first release + +Mon Sep 10 14:05:21 CDT 2007 jeremy@marzhillstudios.com + * additional debugging output + +Mon Sep 10 14:03:42 CDT 2007 jeremy@marzhillstudios.com + * Runner bugfix and the tests that revealed the bug; + +Sat Sep 8 14:00:38 CDT 2007 jeremy@marzhillstudios.com + * fixed mut[_^H_]l[_^H_][_^H_][_^H_] + +Fri Sep 7 20:59:27 CDT 2007 jeremy@marzhillstudios.com + * readded the running tests tests message + +Fri Sep 7 20:46:40 CDT 2007 jeremy@marzhillstudios.com + * added a new message about the name of the test running + +Fri Sep 7 20:45:33 CDT 2007 jeremy@marzhillstudios.com + * whitespace cleanup of a mock testobj definition + +Fri Sep 7 20:44:17 CDT 2007 jeremy@marzhillstudios.com + * removed test for the running test message + +Fri Sep 7 20:35:54 CDT 2007 jeremy@marzhillstudios.com + * added Test.TAP.Runner Library + +Fri Sep 7 20:35:13 CDT 2007 jeremy@marzhillstudios.com + * added TAP Directory + +Fri Sep 7 20:34:48 CDT 2007 jeremy@marzhillstudios.com + * added tests for Test.TAP.Runner + +Fri Sep 7 19:17:50 CDT 2007 jeremy@marzhillstudios.com + * additional META for the library + +Fri Sep 7 19:16:54 CDT 2007 jeremy@marzhillstudios.com + * minor changes to the counter and bugfix for throws_ok + +Fri Sep 7 19:16:00 CDT 2007 jeremy@marzhillstudios.com + * More tests for Test.TAP test functions [can_ok throws_ok plan] + +Wed Sep 5 19:08:11 CDT 2007 jeremy@marzhillstudios.com + * initial start of repository diff --git a/META.yml b/META.yml new file mode 100644 index 0000000..b78a9b7 --- /dev/null +++ b/META.yml @@ -0,0 +1,8 @@ +--- #YAML:1.0 +name: Test.TAP +version: 0.12 +author: + - Jeremy Wall +abstract: A zero dependency TAP compliant test library. Useable from commandline with no mocking +license: perl +generated_by: Jeremy Wall diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..80db69f --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +test: + rhino harness/rhino_harness.js diff --git a/README b/README new file mode 100644 index 0000000..510153a --- /dev/null +++ b/README @@ -0,0 +1,57 @@ +NAME + JSAN.Example - Example Library for the JavaScript Archive Network + +SYNOPSIS + // Functional Example + JSAN.Example.functionOne([ + 'do', 'stuff', 'with', + 'this', 'example' + ]); + + // Class Example + var ex = new JSAN.Example; + ex.useMeHere(); + + // JSAN Example + var jsan = new JSAN; + jsan.use('JSAN.Example'); + + var ex = new JSAN.Example; + ex.useMeHere(); + +DESCRIPTION + This library is really lame. Please update the docs. + + Constructor + var ex = new JSAN.Example(); + + Create a new "JSAN.Example" object. + + Class Properties + DEBUG + JSAN.Example.DEBUG = 11; // This one goes... + + blah blah + + Methods + useMeHere() + ex.useMeHere(); + + blah blah + + EXPORTS + When used with "JSAN" this will export "functionOne" and "functionTwo" + by default. + +SEE ALSO + "JSAN" + +AUTHOR + A. Thor + +COPYRIGHT + Copyright (c) 2005 A. Thor. All rights reserved. + This module is free software; you can redistribute it and/or modify it + under the terms of the Artistic license. Or whatever license I choose, + which I will do instead of keeping this documentation like it is. + diff --git a/TODO b/TODO new file mode 100644 index 0000000..e69de29 diff --git a/harness/prove_rhino.t b/harness/prove_rhino.t new file mode 100644 index 0000000..cf881a7 --- /dev/null +++ b/harness/prove_rhino.t @@ -0,0 +1,3 @@ +#!/bin/bash + +rhino harness/rhino_harness.js diff --git a/harness/rhino_harness.js b/harness/rhino_harness.js new file mode 100755 index 0000000..c23d6e0 --- /dev/null +++ b/harness/rhino_harness.js @@ -0,0 +1,24 @@ +var path = 'lib'; +var testpath = 'tests'; + +var libs = [ + 'Test/TAP.js', + 'Test/TAP/Class.js', + 'Test/TAP/Runner.js' + ]; + +var tests = [ + '01_tap.t.js', + ]; + +for (i in libs) { + var lib = libs[i]; + load(path+'/'+lib); +} + +for (i in tests) { + var test = tests[i]; + var script = readFile(testpath+'/'+test); + t = eval(script); + t.run_tests(); +} diff --git a/lib/Test/TAP.js b/lib/Test/TAP.js new file mode 100644 index 0000000..aa5e442 --- /dev/null +++ b/lib/Test/TAP.js @@ -0,0 +1,348 @@ +//grab the global scope +var testtop = this; + +Test = function() {}; + +Test.prototype.top = function() { + return testtop; +} + +Test.prototype.out = function(text) { + this.print(text); +}; + +Test.prototype.diag = function(msg){ + if (!msg) { + msg = " "; + } + this.out('# ' + msg); +}; + +Test.prototype.mk_tap = function(ok, description){ + if(!this.planned){ + this.out("You tried to run tests without a plan. Gotta have a plan."); + throw new Error("You tried to run tests without a plan. Gotta have a plan."); + } + this.counter++; + this.out(ok + ' ' + this.counter + ' - ' + description); +}; + +/* + +=head1 NAME + + Test.TAP - a 0 dependency TAP compliant test library useable from the commandline + +=head1 Synopsis + + var t = new Test.TAP; + t.plan(3); + + t.ok(true, 'True is True'); # test will pass + t.is(1, 2, 'one is two'); # test will fail + + var obj = {}; + obj.method1 = function() { return true; }; + + t.can_ok(obj, 'method1'); # test will pass + +=head1 DESCRIPTION + +Test.TAP is a javascript testing library that meets the needs of TDD for a commandline environment. + +=head1 METHODS + +=cut + +*/ + + +Test.TAP = function(out) { + this.planned = 0; + this.counter = 0; + this.passed = 0; + this.failed = 0; + this.print = out || function(text) { + if(typeof document == 'undefined') { + document = {}; + } + if(typeof document.write == 'undefined') { + document.write = print; + } + if (typeof print == 'undefined' + || document.write != print) { + text += '\n'; + } + document.write(text); + }; +}; + +Test.TAP.prototype = new Test; + +Test.TAP.prototype.pass = function(description) { + this.mk_tap('ok', description); +}; + +Test.TAP.prototype.fail = function(description) { + this.mk_tap('not ok', description); +}; + +Test.TAP.prototype.todo = function(func) { + var self = this; + var tapper = self.mk_tap; + self.mk_tap = function(ok, desc) { + tapper.apply(self, [ok, "# TODO: "+desc]); + } + func(); + self.mk_tap = tapper; +} + +Test.TAP.prototype.skip = function(crit, reason, func) { + var self = this; + if (crit) { + var tapper = self.mk_tap; + self.mk_tap = function(ok, desc) { + tapper.apply(self, [ok, "# SKIP: "+reason]); + } + func(); + self.mk_tap = tapper; + } +} + +/* + +=head2 plan() + + t.plan(3); + +Sets the test plan. Once set this can not be reset again. An attempt to change the plan once already set will throw an exception. + +=cut + +*/ + +Test.TAP.prototype.plan = function(tests) { + if (tests == 'no_plan') { + this.planned = tests; + } else { + if(this.planned > 0 || this.planned == 'no_plan'){ + throw new Error("you tried to set the plan twice!"); + } + this.planned = tests; + this.out('1..' + tests); + } +}; + +Test.TAP.prototype._pass_if = function(func, desc){ + var result = func(); + if(result){ this.pass(desc) } + else { this.fail(desc) } +} + + +/* + +=head2 diag() + + t.diag('a diagnostic message'); + +prints out a TAP compliant diagnostic message. + +=cut + +*/ + + +/* + +=head2 is() + + t.is(got, expected, 'test description'); + +tests that what we got matches what we expected. An equality test. + +=cut + +*/ + +Test.TAP.prototype.is = function(got, expected, desc) { + this._pass_if(function(){ return got == expected; }, desc); +}; + + +/* + +=head2 ok() + + t.ok(expression, 'test description'); + +Test that expression evaluates to true value + +=cut + +*/ + +Test.TAP.prototype.ok = function(got, desc) { + this._pass_if(function(){ return !!got; }, desc); +}; + + +/* + +=head2 like() + + t.like('string', /regex/, 'test description'); + +Tests that a string matches the regex. + +=cut + +*/ + +Test.TAP.prototype.like = function(string, regex, desc) { + this._pass_if(function(){ + return string.match(regex); + }, desc) +} + +/* + +=head2 unlike() + + t.unlike('string', /regex/, 'test description'); + +The opposite of like. tests that the string doesn't match the regex + +=cut + +*/ + +Test.TAP.prototype.unlike = function(string, regex, desc) { + this._pass_if(function(){ + return !string.match(regex); + }, desc) +} + +/* + +=head2 can_ok() + + t.can_ok(obj, 'method1', method2'); + +tests that the object has the list of methods. outputs diagnostics about which ones are missing if the test fails. + +=cut + +*/ + + +Test.TAP.prototype.can_ok = function(obj) { + var desc = 'object can ['; + var pass = true; + for (i=1; i +L + +=head1 AUTHOR + +Jeremy Wall L<< jeremy@marzhillstudios.com >> + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2007 Jeremy Wall + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.8.4 or, +at your option, any later version of Perl 5 you may have available. + +=cut + +*/ + diff --git a/lib/Test/TAP/Class.js b/lib/Test/TAP/Class.js new file mode 100644 index 0000000..46c78a6 --- /dev/null +++ b/lib/Test/TAP/Class.js @@ -0,0 +1,204 @@ +if (typeof Test == 'undefined') { + Test = {}; +} +if (typeof Test.TAP == 'undefined') { + if (typeof JSAN != 'undefined') { + JSAN.use('Test.TAP'); + } else { + throw new ReferenceError('Test.TAP.Runner is dependent on Test.TAP'); + } +} + +/* + +=head1 NAME + + Test.TAP.Runner - A Simple Test Harness for Test.TAP + +=head1 Synopsis + + var r = new Test.TAP.Runner(). + + var testobj = {}; + testobj.runtests = function() { + var t = new Test.TAP(); + t.plan(2); + t.ok(true, 'true is true'); + t.is(1, 1, 'one is one'); + return t; + } + r.run_tests(obj); +=cut + +*/ + +Test.TAP.Class = function() { + var self = this; + // call our superclasses constructor as well + Test.TAP.apply(self, arguments); +}; + +/* + +=head1 Methods + +=head2 out() + +internal method inherited from L see L for useage + +=cut + +=head2 diag() + +internal method inherited from L see L for useage + +=cut + +=head2 run_it() + +runs the tests in a test object and reports on the results + +=cut + +*/ + +Test.TAP.Class.prototype = new Test.TAP(); + +Test.TAP.Class.prototype.run_it = function(method) { + var self = this; + var fun = self[method]; + self.diag("trying to run "+method+" tests"); + + // remember the globals that existed before the test execution + var originalGlobal = {}; + var top = self.top(); + for(var name in top ) { + originalGlobal[name] = true; + } + + try { + if (typeof this.setup == 'function') { + self.setup(); + } + fun.call(self); + if (typeof this.teardown == 'function') { + self.teardown(); + } + } + catch(err) { + this.diag("Test Suite Crashed!!! (" + err + ")"); + } + finally { + // Delete globals which were created during test execution + // THis avoid conflicts between tests when running multiple tests in a r + for(var name in top) { + if(!originalGlobal[name]) { + delete top[name] + } + } + } +}; + +/* + +=head2 run_tests() + + r.run_tests(obj1, obj2); + +runs the tests in a list of test objects and reports on the results + +=cut + +*/ + +Test.TAP.Class.prototype.run_tests = function() { + var self = this; + var counter = 0; + + var methods = []; + for (m in self) { + if (m.match(/^test.+/)) { + methods.push(m) + } + } + + this.finished = true; + + var onFinish = function () { + if (self.planned > self.counter) { + self.diag('looks like you planned ' + self.planned + ' tests but only ran ' + + self.counter + ' tests'); + } else if (self.planned < self.counter) { + self.diag('looks like you planned ' + self.planned + ' tests but ran ' + + (self.counter - self.planned) + ' tests extra'); + } + self.diag('ran ' + self.counter + ' tests out of ' + self.planned); + self.diag('passed ' + self.passed + ' tests out of ' + self.planned) + self.diag('failed ' + self.failed + ' tests out of ' + self.planned) + } + + var count = 0; + var testRunInterval + if (typeof setInterval == 'undefined') { + setInterval = function() { + }; + } + if (typeof clearInterval == 'undefined') { + clearInterval = function() { + } + } + var run = function () { + if(self.finished) { + if(count > 0) { + if(self.on_finished) { + onFinish() + self.on_finished() + } + } + if(methods.length == 0) { + clearInterval(testRunInterval) + if(self.on_finished_all) { + self.on_finished_all() + } + } else { + self.finished = false; + } + } else { + if(self.planned == "no_plan" || self.planned == 0 || self.counter >= self.planned) { + self.finished = true + } + } + }; + testRunInterval = setInterval(run, 10) + run(); + var methodname; + while (methodname = methods.shift()) { + self.run_it(methodname); + count++ + } + + return self; +}; + +/* + +=head1 SEE ALSO + +L +L + +=head1 AUTHOR + +Jeremy Wall L<< jeremy@marzhillstudios.com >> + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2007 Jeremy Wall + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.8.4 or, +at your option, any later version of Perl 5 you may have available. + +=cut + +*/ diff --git a/lib/Test/TAP/Runner.js b/lib/Test/TAP/Runner.js new file mode 100644 index 0000000..5a1aa28 --- /dev/null +++ b/lib/Test/TAP/Runner.js @@ -0,0 +1,104 @@ +if (typeof Test == 'undefined') { + Test = {}; +} +if (typeof Test.TAP == 'undefined') { + if (typeof JSAN != 'undefined') { + JSAN.use('Test.TAP'); + } else { + throw new Error('Test.TAP.Runner is dependent on Test.TAP'); + } +} +/* + +=head1 NAME + + Test.TAP.Runner - A Simple Test Harness for Test.TAP + +=head1 Synopsis + + var r = new Test.TAP.Runner(). + + var testobj = {}; + testobj.runtests = function() { + var t = new Test.TAP(); + t.plan(2); + t.ok(true, 'true is true'); + t.is(1, 1, 'one is one'); + return t; + } + r.run_tests(obj); +=cut + +*/ + +Test.TAP.Runner = function() {}; + +Test.TAP.Runner.prototype = new Test(); + +/* + +=head1 Methods + +=head2 out() + +internal method inherited from L see L for useage + +=cut + +=head2 diag() + +internal method inherited from L see L for useage + +=cut + +=head2 run_it() + +runs the tests in a test object and reports on the results + +=cut + +*/ + +Test.TAP.Runner.prototype.run_it = function(obj) { + this.diag('running ' + obj.name + ' tests'); + var tester; + try { + tester = obj.runtests(); + if (tester.planned > tester.counter) { + tester.diag('looks like you planned ' + tester.planned + ' tests but only ran ' + + tester.counter + ' tests'); + } else if (tester.planned < tester.counter) { + tester.diag('looks like you planned ' + tester.planned + ' tests but ran ' + + (tester.counter - tester.planned) + ' tests extra'); + } + this.diag('ran ' + tester.counter + ' tests out of ' + tester.planned); + this.diag('passed ' + tester.passed + ' tests out of ' + tester.planned) + this.diag('failed ' + tester.failed + ' tests out of ' + tester.planned) + } + catch(err) { + this.diag("Test Suite Crashed!!! (" + err + ")"); + } + + return tester; +}; + +/* + +=head2 run_tests() + + r.run_tests(obj1, obj2); + +runs the tests in a list of test objects and reports on the results + +=cut + +*/ + +Test.TAP.Runner.prototype.run_tests = function() { + var all = []; + for (i=0; i(run in a single window)...'); + var req = new XMLHttpRequest(); + req.open("GET", path, false); + req.send(null); + if (req.readyState == 4) { + var testobj = eval(req.responseText); + return testobj; + } +} + +function createScriptTag(library) { + var path = library.replace(/\./g, '/')+'.js'; + var script = document.createElement("script"); + script.src = lib+'/'+path; + return script; +} + +function loadlib(library) { + document.body.appendChild(createScriptTag(library)); +} + +function loadTest(test) { + var path = testlib+'/'+test; + return load(path); +} + +function loadComponents() { + for (c in toLoad) { + var comp = toLoad[c]; + loadlib(comp); + } +} + +function runtest(t) { + var outtxt = ""; + var div = document.createElement("div"); + + var onclick = function () { + var c = div.className; + if (c.match(/big/)) { + c = c.replace(/big/, "small"); + } else if (c.match(/small/)) { + c = c.replace(/small/, "big"); + } + div.className = c; + }; + div.addEventListener('click', onclick, true); + + div.className = 'test small'; + document.body.appendChild(div); + + var outfunc = function(text) { + if (text) { + outtxt += text; + div.innerHTML = div.innerHTML + "\n" + text + "
" + } + } + + // set globally for synchronous run + Test.TAP.prototype.out = outfunc; + var testobj = loadTest(t); + if (!testobj) { + alert ("Test Object: "+t+" did not load"); + throw new ReferenceError("Test Object did now load"); + } + // also set to instance for asynchronous output + testobj.out = outfunc + + testobj.on_finished = function () { + if (outtxt.match(/(not ok|Test Suite Crashed)/g) ) { + div.className += ' fail'; + div.className.replace(/small/, 'big'); + } else { + div.className += ' pass'; + } + results.push(div); + } + + setTimeout(function () { + testobj.run_tests() + }, 0) +} + +var test = loc.match(/.+[#?](.*)\??.*/); + +loadComponents(); + +window.onload = function() { + var testlist = []; + if (test) { + runtest(test[1]); + } else { + for (t in tests) { + runtest(tests[t]); + } + } +} diff --git a/scripts/addtoproject.sh b/scripts/addtoproject.sh new file mode 100755 index 0000000..2f8e717 --- /dev/null +++ b/scripts/addtoproject.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +usage() +{ + cat << HELPMSG +Usage: + add this library to a javascript project for you + $0 -d + + print this help + $0 -h +HELPMSG +} + +while getopts "d:h" OPTION +do + case $OPTION in + d) + DIRNAME=$OPTARG + ;; + h) + usage + exit 0 + ;; + ?) + usage + exit 1 + esac +done + +if [[ -z $DIRNAME ]] +then + echo "No -d option was present. You must provide a Project path."; + usage + exit 1 +fi + +echo "Setting up in project: ${DIRNAME}" + + +#create our project directory +cd $DIRNAME + +#set up the directory structure +if [[ ! -d ext ]] +then + mkdir ext +fi + +if [[ ! -d harness ]] +then + mkdir harness +fi + +if [[ ! -d t || -d tests ]] +then + mkdir t +fi + +#copy the files we need for initial setup +cp -r -f ~/sandbox/Test-TAP/lib/Test ext/ +if [[ -d t ]] +then + cp -r -f ~/sandbox/Test-TAP/tmpl/TapHarness.html t/ +elif [[ -d tests ]] +then + cp -r -f ~/sandbox/Test-TAP/tmpl/TapHarness.html tests/ +fi + +cp -r -f ~/sandbox/Test-TAP/tmpl/*rhino* harness/ + +#now go back to where we started +cd $WORKING diff --git a/scripts/mkdist.sh b/scripts/mkdist.sh new file mode 100755 index 0000000..15fe0b5 --- /dev/null +++ b/scripts/mkdist.sh @@ -0,0 +1,74 @@ +#!bash + +usage() +{ + cat << HELPMSG +Usage: + create a distribution directory with the specified version + $0 -d -v + + print this help + $0 -h +HELPMSG +} + +while getopts ":d:v:h" OPTION +do + case $OPTION in + d) + DIRNAME=$OPTARG + ;; + v) + VERSION=$OPTARG + ;; + h) + usage + exit 1 + ;; + ?) + usage + exit 1 + ;; + esac +done + +if [[ -z $DIRNAME ]] +then + usage + exit 1 +fi + +if [[ -z $VERSION ]] +then + usage + exit 1 +fi + +DIST="$DIRNAME-$VERSION" +ROOT="$(dirname $0)/.." +LIB="${ROOT}/lib"; +TLIB="${ROOT}/tests"; +SCRIPTS="Test/TAP.js Test/TAP/Class.js Test/TAP/Runner.js"; + +if [[ ! -d $DIST ]] +then + mkdir $DIST +else + rm -rf $DIST + mkdir $DIST +fi + +for s in $SCRIPTS +do + cat - $LIB/$s >> $DIST/test_tap.js < + + print this help + $0 -h +HELPMSG +} + +while getopts "d:h" OPTION +do + case $OPTION in + d) + DIRNAME=$OPTARG + ;; + h) + usage + exit 0 + ;; + ?) + usage + exit 1 + esac +done + +if [[ -z $DIRNAME ]] +then + echo "No -d option was present. You must provide a Project path."; + usage + exit 1 +fi + +echo "Setting up in project: ${DIRNAME}" + + +#create our project directory +cd $DIRNAME + +#set up the directory structure +if [[ ! -d ext ]] +then + mkdir ext +fi + +#copy the files we need for initial setup +cp -r -f ~/sandbox/Test-TAP/lib/Test ext/ + +#now go back to where we started +cd $WORKING diff --git a/tests/01_tap.t.js b/tests/01_tap.t.js new file mode 100644 index 0000000..678781c --- /dev/null +++ b/tests/01_tap.t.js @@ -0,0 +1,176 @@ +(function() { +var out = "nothing yet"; +var diag = ""; +var t = new Test.TAP.Class(); // the real TAP +//t.plan('no_plan'); +t.plan(27); +//t.plan()); + +t.testCan = function () { + var self = this; + // setup fake test object + var f = new Test.TAP(); // the TAP thats failing + f.out = function(newout) { out = newout }; + f.diag = function(newdiag) { diag += newdiag }; + f.plan(4); + + //mock a fake object to run test against + var obj = new Object; + obj.run = function() {}; + var method = 'run'; + + // begin real tests! + f.can_ok(obj, 'not_there'); + t.like(out, /not ok 1 - object can \[ not_there \]/, 'can_ok failed'); + f.can_ok(obj, method); + diag = ''; + self.like(out, /ok 2 - object can \[ run \]/, 'can_ok passed'); + + //Now we need to test the whole prototype method assignment thing + + function MockObj() { + this.attr = 1; + } + + MockObj.prototype.fakeme = function () {}; + + f.can_ok(MockObj, 'fakeme'); + diag = ''; + self.like(out, /^ok .* \[ fakeme \]/, + 'can_ok recognized prototype methods'); + f.can_ok(MockObj, 'fakeme2'); + diag = ''; + self.like(out, /^not ok .* \[ fakeme2 \]/, + 'can_ok prototype recognization doesnt break methods'); +} + +t.testClassTests = function() { + var self = this; + self.ok(Test.TAP.Class, 'Test.TAP.Class namespace exists'); + + var rout = ''; + var fun = function (value) { + rout += value; + } + + var testclass = new Test.TAP.Class(fun); + testclass.plan('no_plan'); + testclass.out = fun; + self.is(testclass.print, fun, 'testclass has our own printer'); + self.is(testclass.planned, 'no_plan', 'testclass has no plan'); + + testclass.testMyTest = function() { + testclass.ok(1 === 1, 'it worked'); + } + testclass.run_tests(); + //self.diag("here is rout"); + //self.diag(rout); + self.like(rout, /ok 1 - it worked/, 'we printed the correct output'); +} + +t.testDescApears = function() { + var self = this; + // setup fake test object + var f = new Test.TAP(); // the TAP that's failing + f.out = function(newout) { out = newout }; + f.plan(1); + self.id = "t"; + f.id = "f"; + + // begin real tests! + f.like("hello", /hello/, "hello matches hello"); + self.like(out, /ok 1 - hello matches hello/, 'got description in TAP output'); +} + +t.testDiag = function() { + // setup fake test object + var f = new Test.TAP(); // the TAP that's failing + f.out = function(newout) { out = newout }; + f.plan(10); + // begin real tests! + f.diag("hello"); + t.like(out, /# hello/, 'got hello'); +} + +t.testException = function() { + // setup fake test object + var f = new Test.TAP(); // the TAP that's failing + f.out = function(newout) { out = newout }; + f.plan(2); + + // begin real tests! + f.throws_ok(function() {throw new Error('I made a boo boo')}, 'I made a boo boo'); + //t.diag(out); + this.like(out, /ok 1 - code threw \[Error: I made a boo boo\]/, 'uncaught exception'); + f.throws_ok(function() {}, 'I made a boo boo'); + //t.diag(out); + this.like(out, /not ok 2 - code threw \[ \]/, 'false failed'); +} + +t.testFails = function() { + // setup fake test object + var f = new Test.TAP(); // the TAP that's failing + f.out = function(newout) { out = newout }; + f.plan(3); + + // begin real tests! + f.ok(false, 'false fails'); + t.like(out, /not ok 1 - false fails/, 'false failed'); + + f.ok(0, 'zero fails'); + t.like(out, /not ok 2 - zero fails/, '0 failed'); + + f.is(0, 1, 'zero is one'); + t.like(out, /not ok 3 - zero is one/, '0 != 1'); +} + +t.testPass = function() { + this.ok(true, 'true is true'); + this.is(1,1, '1 is 1'); + this.pass('pass passes'); + this.like("hello world", /hel+o/, 'regexen work'); + this.unlike("hello there", /world/, 'no world'); +} + +t.testPlan = function() { + // setup fake test object + var f = new Test.TAP(); // the TAP that's failing + f.out = function(newout) { out = newout }; + f.plan(2); + + // begin real tests! + f.ok(false, 'false fails'); + this.is(f.counter, 1, 'counter increments by one'); + this.is(f.planned, 2, 'planned = 2'); +} + +t.testTodo = function() { + var self = this; + var out; + self.can_ok(Test.TAP, 'todo', 'skip'); + var f = new Test.TAP(); // the TAP that's failing + f.out = function(newout) { out = newout }; + f.plan(4); + + f.todo(function() { + f.ok(true, 'true is true'); + self.like(out, /ok 1 - # TODO: true is true/g, + 'the non todo output is suitably formatted'); + }); + f.ok(!false, 'not false is true'); + self.like(out, /ok 2 -/g, 'the regular output is suitably formatted'); + + f.skip(true, 'because I said so', + function() { + f.is(1, 2, 'one is two'); + self.like(out, /^not ok 3 - # SKIP: because I said so$/, + 'the skipped output is suitably formatted'); + } + ); + f.is(1, 1, 'one is one'); + self.like(out, /ok 4 - one is one/, + 'the non skipped output is suitable formatted'); +} + +return t; +})() diff --git a/tests/TapHarness.html b/tests/TapHarness.html new file mode 100644 index 0000000..4a1ed1d --- /dev/null +++ b/tests/TapHarness.html @@ -0,0 +1,52 @@ + + + + + + + + + + + +This is the Test.TAP.Class and company test harness for the browser. + + + diff --git a/tmpl/TapHarness.html b/tmpl/TapHarness.html new file mode 100644 index 0000000..f418164 --- /dev/null +++ b/tmpl/TapHarness.html @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + diff --git a/tmpl/prove_rhino.t b/tmpl/prove_rhino.t new file mode 100644 index 0000000..cf881a7 --- /dev/null +++ b/tmpl/prove_rhino.t @@ -0,0 +1,3 @@ +#!/bin/bash + +rhino harness/rhino_harness.js diff --git a/tmpl/rhino_harness.js b/tmpl/rhino_harness.js new file mode 100755 index 0000000..1c9468f --- /dev/null +++ b/tmpl/rhino_harness.js @@ -0,0 +1,35 @@ +var libpath = 'lib'; +var extpath = 'ext'; +var testpath = 't'; + +var extlibs = [ + 'Test/TAP.js', + 'Test/TAP/Class.js', + 'Test/TAP/Runner.js', + 'joose.js' + ]; + +var libs = [ + '' + ]; + +var tests = [ + '', + ]; + +for (i in extlibs) { + var lib = extlibs[i]; + load(extpath+'/'+lib); +} + +for (i in libs) { + var lib = libs[i]; + load(libpath+'/'+lib); +} + +for (i in tests) { + var test = tests[i]; + var script = readFile(testpath+'/'+test); + t = eval(script); + t.run_tests(); +}