Nettoyage exemple tests-unitaires
This commit is contained in:
parent
f4e96ea040
commit
bbcccf4586
|
@ -0,0 +1,6 @@
|
||||||
|
# Tests unitiaires, exemple NodeUnit
|
||||||
|
|
||||||
|
```
|
||||||
|
npm install
|
||||||
|
./node_modules/.bin/nodeunit math-suite.js
|
||||||
|
```
|
|
@ -1 +0,0 @@
|
||||||
../nodeunit/bin/nodeunit
|
|
|
@ -1,3 +0,0 @@
|
||||||
dist
|
|
||||||
stamp-build
|
|
||||||
test/fixtures/dir2
|
|
68
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/CONTRIBUTORS.md
generated
vendored
68
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/CONTRIBUTORS.md
generated
vendored
|
@ -1,68 +0,0 @@
|
||||||
Nodeunit contributors (sorted alphabeticaly)
|
|
||||||
============================================
|
|
||||||
|
|
||||||
* **[Alex Gorbatchev](https://github.com/alexgorbatchev)**
|
|
||||||
|
|
||||||
* Deeper default object inspection
|
|
||||||
* Timeout to ensure flushing of console output (default reporter)
|
|
||||||
|
|
||||||
* **[Alex Wolfe](https://github.com/alexkwolfe)**
|
|
||||||
|
|
||||||
* HTML test reporter
|
|
||||||
|
|
||||||
* **[Caolan McMahon](https://github.com/caolan)**
|
|
||||||
|
|
||||||
* Author and maintainer
|
|
||||||
* Most features develpopment
|
|
||||||
|
|
||||||
* **[Carl Fürstenberg](https://github.com/azatoth)**
|
|
||||||
|
|
||||||
* Debian-friendly Makefile, supports both 'node' and 'nodejs' executables
|
|
||||||
* Sandbox utility
|
|
||||||
* Minimal test reporter
|
|
||||||
|
|
||||||
* **[Gerad Suyderhoud](https://github.com/gerad)**
|
|
||||||
|
|
||||||
* First comand-line tool
|
|
||||||
|
|
||||||
* **[Kadir Pekel](https://github.com/kadirpekel)**
|
|
||||||
|
|
||||||
* Improvements to default test reporter
|
|
||||||
* HTTP test utility
|
|
||||||
|
|
||||||
* **[Λlisue](https://github.com/lambdalisue)**
|
|
||||||
|
|
||||||
* Add machineout reporter
|
|
||||||
|
|
||||||
* **[Matthias Lübken](https://github.com/luebken)**
|
|
||||||
|
|
||||||
* Utility functions for tracking incomplete tests on exit
|
|
||||||
|
|
||||||
* **[Oleg Efimov](https://github.com/Sannis)**
|
|
||||||
|
|
||||||
* Adding 'make lint' and fixing nodelint errors
|
|
||||||
* Option parsing, --help text and config file support
|
|
||||||
* Reporters option for command-line tool
|
|
||||||
|
|
||||||
* **[Orlando Vazquez](https://github.com/orlandov)**
|
|
||||||
|
|
||||||
* Added jUnit XML reporter
|
|
||||||
|
|
||||||
* **[Ryan Dahl](https://github.com/ry)**
|
|
||||||
|
|
||||||
* Add package.json
|
|
||||||
|
|
||||||
* **[Sam Stephenson](https://github.com/sstephenson)**
|
|
||||||
|
|
||||||
* Coffee-script support
|
|
||||||
|
|
||||||
* **[Thomas Mayfield](https://github.com/thegreatape)**
|
|
||||||
|
|
||||||
* Async setUp and tearDown support for testCase
|
|
||||||
|
|
||||||
* **[Maciej Małecki](https://github.com/mmalecki)**
|
|
||||||
|
|
||||||
* Removal of `testCase`
|
|
||||||
|
|
||||||
**[Full contributors list](https://github.com/caolan/nodeunit/contributors).**
|
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
Copyright (c) 2010 Caolan McMahon
|
|
||||||
|
|
||||||
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.
|
|
|
@ -1,177 +0,0 @@
|
||||||
PACKAGE = nodeunit
|
|
||||||
NODEJS = $(if $(shell test -f /usr/bin/nodejs && echo "true"),nodejs,node)
|
|
||||||
|
|
||||||
PREFIX ?= /usr/local
|
|
||||||
BINDIR ?= $(PREFIX)/bin
|
|
||||||
DATADIR ?= $(PREFIX)/share
|
|
||||||
MANDIR ?= $(PREFIX)/share/man
|
|
||||||
LIBDIR ?= $(PREFIX)/lib
|
|
||||||
NODEJSLIBDIR ?= $(LIBDIR)/$(NODEJS)
|
|
||||||
|
|
||||||
BUILDDIR = dist
|
|
||||||
|
|
||||||
DOCS = $(shell find doc -name '*.md' \
|
|
||||||
|sed 's|.md|.1|g' \
|
|
||||||
|sed 's|doc/|man1/|g' \
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
$(shell if [ ! -d $(BUILDDIR) ]; then mkdir $(BUILDDIR); fi)
|
|
||||||
|
|
||||||
all: build doc
|
|
||||||
|
|
||||||
browser:
|
|
||||||
# super hacky build script for browser version!
|
|
||||||
mkdir -p $(BUILDDIR)/browser
|
|
||||||
rm -rf $(BUILDDIR)/browser/*
|
|
||||||
# build browser version of nodeunit.js
|
|
||||||
cat share/license.js >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
echo "nodeunit = (function(){" >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
cat deps/json2.js >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
# make assert global
|
|
||||||
echo "var assert = this.assert = {};" >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
echo "var types = {};" >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
echo "var core = {};" >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
echo "var nodeunit = {};" >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
echo "var reporter = {};" >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
cat deps/async.js >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
echo "(function(exports){" >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
cat lib/assert.js >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
echo "})(assert);" >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
echo "(function(exports){" >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
cat lib/types.js >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
echo "})(types);" >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
echo "(function(exports){" >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
cat lib/core.js >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
echo "})(core);" >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
echo "(function(exports){" >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
cat lib/reporters/browser.js >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
echo "})(reporter);" >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
echo "nodeunit = core;" >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
echo "nodeunit.assert = assert;" >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
echo "nodeunit.reporter = reporter;" >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
echo "nodeunit.run = reporter.run;" >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
echo "return nodeunit; })();" >> $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
cp $(BUILDDIR)/browser/nodeunit.js $(BUILDDIR)/browser/.nodeunit.js
|
|
||||||
sed "/\@REMOVE_LINE_FOR_BROWSER/d" <$(BUILDDIR)/browser/.nodeunit.js > $(BUILDDIR)/browser/nodeunit.js
|
|
||||||
rm $(BUILDDIR)/browser/.nodeunit.js
|
|
||||||
# copy nodeunit.css
|
|
||||||
cp share/nodeunit.css $(BUILDDIR)/browser/nodeunit.css
|
|
||||||
# create nodeunit.min.js
|
|
||||||
node_modules/uglify-js/bin/uglifyjs $(BUILDDIR)/browser/nodeunit.js > $(BUILDDIR)/browser/nodeunit.min.js
|
|
||||||
# create test scripts
|
|
||||||
mkdir -p $(BUILDDIR)/browser/test
|
|
||||||
cp test/test.html $(BUILDDIR)/browser/test/test.html
|
|
||||||
# test-base.js
|
|
||||||
echo "(function (exports) {" > $(BUILDDIR)/browser/test/test-base.js
|
|
||||||
cat test/test-base.js >> $(BUILDDIR)/browser/test/test-base.js
|
|
||||||
echo "})(this.test_base = {});" >> $(BUILDDIR)/browser/test/test-base.js
|
|
||||||
cp $(BUILDDIR)/browser/test/test-base.js $(BUILDDIR)/browser/.test-base.js
|
|
||||||
sed "/\@REMOVE_LINE_FOR_BROWSER/d" <$(BUILDDIR)/browser/.test-base.js > $(BUILDDIR)/browser/test/test-base.js
|
|
||||||
rm $(BUILDDIR)/browser/.test-base.js
|
|
||||||
# test-runmodule.js
|
|
||||||
echo "(function (exports) {" > $(BUILDDIR)/browser/test/test-runmodule.js
|
|
||||||
cat test/test-runmodule.js >> $(BUILDDIR)/browser/test/test-runmodule.js
|
|
||||||
echo "})(this.test_runmodule = {});" >> $(BUILDDIR)/browser/test/test-runmodule.js
|
|
||||||
cp $(BUILDDIR)/browser/test/test-runmodule.js $(BUILDDIR)/browser/.test-runmodule.js
|
|
||||||
sed "/\@REMOVE_LINE_FOR_BROWSER/d" <$(BUILDDIR)/browser/.test-runmodule.js > $(BUILDDIR)/browser/test/test-runmodule.js
|
|
||||||
rm $(BUILDDIR)/browser/.test-runmodule.js
|
|
||||||
# test-runtest.js
|
|
||||||
echo "(function (exports) {" > $(BUILDDIR)/browser/test/test-runtest.js
|
|
||||||
cat test/test-runtest.js >> $(BUILDDIR)/browser/test/test-runtest.js
|
|
||||||
echo "})(this.test_runtest = {});" >> $(BUILDDIR)/browser/test/test-runtest.js
|
|
||||||
cp $(BUILDDIR)/browser/test/test-runtest.js $(BUILDDIR)/browser/.test-runtest.js
|
|
||||||
sed "/\@REMOVE_LINE_FOR_BROWSER/d" <$(BUILDDIR)/browser/.test-runtest.js > $(BUILDDIR)/browser/test/test-runtest.js
|
|
||||||
rm $(BUILDDIR)/browser/.test-runtest.js
|
|
||||||
# test-testcase.js
|
|
||||||
echo "(function (exports) {" > $(BUILDDIR)/browser/test/test-testcase.js
|
|
||||||
cat test/test-testcase.js >> $(BUILDDIR)/browser/test/test-testcase.js
|
|
||||||
echo "})(this.test_testcase = {});" >> $(BUILDDIR)/browser/test/test-testcase.js
|
|
||||||
cp $(BUILDDIR)/browser/test/test-testcase.js $(BUILDDIR)/browser/.test-testcase.js
|
|
||||||
sed "/\@REMOVE_LINE_FOR_BROWSER/d" <$(BUILDDIR)/browser/.test-testcase.js > $(BUILDDIR)/browser/test/test-testcase.js
|
|
||||||
rm $(BUILDDIR)/browser/.test-testcase.js
|
|
||||||
# test-testcase-legacy.js
|
|
||||||
echo "(function (exports) {" > $(BUILDDIR)/browser/test/test-testcase-legacy.js
|
|
||||||
cat test/test-testcase-legacy.js >> $(BUILDDIR)/browser/test/test-testcase-legacy.js
|
|
||||||
echo "})(this.test_testcase_legacy = {});" >> $(BUILDDIR)/browser/test/test-testcase-legacy.js
|
|
||||||
cp $(BUILDDIR)/browser/test/test-testcase-legacy.js $(BUILDDIR)/browser/.test-testcase-legacy.js
|
|
||||||
sed "/\@REMOVE_LINE_FOR_BROWSER/d" <$(BUILDDIR)/browser/.test-testcase-legacy.js > $(BUILDDIR)/browser/test/test-testcase-legacy.js
|
|
||||||
rm $(BUILDDIR)/browser/.test-testcase-legacy.js
|
|
||||||
# copy nodeunit.js to dist/browser/test to make it easier for me to host and
|
|
||||||
# run on windows VMs with IE
|
|
||||||
cp $(BUILDDIR)/browser/nodeunit.js $(BUILDDIR)/browser/test/nodeunit.js
|
|
||||||
cp $(BUILDDIR)/browser/nodeunit.css $(BUILDDIR)/browser/test/nodeunit.css
|
|
||||||
|
|
||||||
commonjs:
|
|
||||||
# super hacky build script for browser commonjs version!
|
|
||||||
##### make commonjs browser module ######
|
|
||||||
mkdir -p $(BUILDDIR)/commonjs
|
|
||||||
rm -rf $(BUILDDIR)/commonjs/*
|
|
||||||
mkdir -p $(BUILDDIR)/commonjs/deps
|
|
||||||
cp deps/json2.js $(BUILDDIR)/commonjs/deps
|
|
||||||
cp deps/async.js $(BUILDDIR)/commonjs/deps
|
|
||||||
echo "var async = require('async');" >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
echo "var assert = {};" >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
echo "var types = {};" >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
echo "var core = {};" >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
echo "var nodeunit = {};" >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
echo "var reporter = {};" >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
echo "(function(exports){" >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
cat lib/assert.js >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
echo "})(assert);" >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
echo "(function(exports){" >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
cat lib/types.js >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
echo "})(types);" >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
echo "(function(exports){" >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
cat lib/core.js >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
echo "})(core);" >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
echo "module.exports = core;" >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
echo "(function(exports, nodeunit){" >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
cat lib/reporters/browser.js >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
echo "})(reporter, module.exports);" >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
echo "module.exports.assert = assert;" >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
echo "module.exports.reporter = reporter;" >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
echo "module.exports.run = reporter.run;" >> $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
sed -i "/\@REMOVE_LINE_FOR_BROWSER/d" $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
sed -i "/\@REMOVE_LINE_FOR_COMMONJS/d" $(BUILDDIR)/commonjs/nodeunit.js
|
|
||||||
##### end of commonjs browser module #####
|
|
||||||
|
|
||||||
build: stamp-build
|
|
||||||
|
|
||||||
stamp-build: $(wildcard deps/* lib/*.js)
|
|
||||||
touch $@;
|
|
||||||
mkdir -p $(BUILDDIR)/nodeunit
|
|
||||||
cp -R bin node_modules deps index.js lib package.json share $(BUILDDIR)/nodeunit
|
|
||||||
printf '#!/bin/sh\n$(NODEJS) $(NODEJSLIBDIR)/$(PACKAGE)/bin/nodeunit $$@' > $(BUILDDIR)/nodeunit.sh
|
|
||||||
|
|
||||||
test:
|
|
||||||
$(NODEJS) ./bin/nodeunit test
|
|
||||||
|
|
||||||
install: build
|
|
||||||
install -d $(NODEJSLIBDIR)
|
|
||||||
cp -a $(BUILDDIR)/nodeunit $(NODEJSLIBDIR)
|
|
||||||
install -m 0755 $(BUILDDIR)/nodeunit.sh $(BINDIR)/nodeunit
|
|
||||||
install -d $(MANDIR)/man1/
|
|
||||||
cp -a man1/nodeunit.1 $(MANDIR)/man1/
|
|
||||||
|
|
||||||
uninstall:
|
|
||||||
rm -rf $(NODEJSLIBDIR)/nodeunit $(NODEJSLIBDIR)/nodeunit.js $(BINDIR)/nodeunit
|
|
||||||
rm -rf $(MANDIR)/man1/nodeunit.1
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf $(BUILDDIR) stamp-build
|
|
||||||
|
|
||||||
lint:
|
|
||||||
nodelint --config nodelint.cfg ./index.js ./bin/nodeunit ./bin/nodeunit.json ./lib/*.js ./lib/reporters/*.js ./test/*.js
|
|
||||||
|
|
||||||
doc: man1 $(DOCS)
|
|
||||||
@true
|
|
||||||
|
|
||||||
man1:
|
|
||||||
@if ! test -d man1 ; then mkdir -p man1 ; fi
|
|
||||||
|
|
||||||
# use `npm install ronn` for this to work.
|
|
||||||
man1/%.1: doc/%.md
|
|
||||||
ronn --roff $< > $@
|
|
||||||
|
|
||||||
.PHONY: browser test install uninstall build all
|
|
|
@ -1,468 +0,0 @@
|
||||||
Nodeunit
|
|
||||||
========
|
|
||||||
|
|
||||||
Simple syntax, powerful tools. Nodeunit provides easy async unit testing for
|
|
||||||
node.js and the browser.
|
|
||||||
|
|
||||||
* Simple to use
|
|
||||||
* Just export the tests from a module
|
|
||||||
* Works with node.js and in the browser
|
|
||||||
* Helps you avoid common pitfalls when testing asynchronous code
|
|
||||||
* Easy to add test cases with setUp and tearDown functions if you wish
|
|
||||||
* Flexible reporters for custom output, built-in support for HTML and jUnit XML
|
|
||||||
* Allows the use of mocks and stubs
|
|
||||||
|
|
||||||
__Contributors__
|
|
||||||
|
|
||||||
* [alexgorbatchev](https://github.com/alexgorbatchev)
|
|
||||||
* [alexkwolfe](https://github.com/alexkwolfe)
|
|
||||||
* [azatoth](https://github.com/azatoth)
|
|
||||||
* [kadirpekel](https://github.com/kadirpekel)
|
|
||||||
* [lambdalisue](https://github.com/lambdalisue)
|
|
||||||
* [luebken](https://github.com/luebken)
|
|
||||||
* [orlandov](https://github.com/orlandov)
|
|
||||||
* [Sannis](https://github.com/Sannis)
|
|
||||||
* [sstephenson](https://github.com/sstephenson)
|
|
||||||
* [thegreatape](https://github.com/thegreatape)
|
|
||||||
* [mmalecki](https://github.com/mmalecki)
|
|
||||||
* and thanks to [cjohansen](https://github.com/cjohansen) for input and advice
|
|
||||||
on implementing setUp and tearDown functions. See
|
|
||||||
[cjohansen's fork](https://github.com/cjohansen/nodeunit).
|
|
||||||
|
|
||||||
Also, check out gerad's [nodeunit-dsl](https://github.com/gerad/nodeunit-dsl)
|
|
||||||
project, which implements a 'pretty dsl on top of nodeunit'.
|
|
||||||
|
|
||||||
More contributor information can be found in the
|
|
||||||
[CONTRIBUTORS.md](https://github.com/caolan/nodeunit/blob/master/CONTRIBUTORS.md)
|
|
||||||
file.
|
|
||||||
|
|
||||||
Usage
|
|
||||||
-----
|
|
||||||
|
|
||||||
Here is an example unit test module:
|
|
||||||
|
|
||||||
exports.testSomething = function(test){
|
|
||||||
test.expect(1);
|
|
||||||
test.ok(true, "this assertion should pass");
|
|
||||||
test.done();
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.testSomethingElse = function(test){
|
|
||||||
test.ok(false, "this assertion should fail");
|
|
||||||
test.done();
|
|
||||||
};
|
|
||||||
|
|
||||||
When run using the included test runner, this will output the following:
|
|
||||||
|
|
||||||
<img src="https://github.com/caolan/nodeunit/raw/master/img/example_fail.png" />
|
|
||||||
|
|
||||||
Installation
|
|
||||||
------------
|
|
||||||
|
|
||||||
There are two options for installing nodeunit:
|
|
||||||
|
|
||||||
1. Clone / download nodeunit from [github](https://github.com/caolan/nodeunit),
|
|
||||||
then:
|
|
||||||
|
|
||||||
make && sudo make install
|
|
||||||
|
|
||||||
2. Install via npm:
|
|
||||||
|
|
||||||
npm install nodeunit -g
|
|
||||||
|
|
||||||
API Documentation
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
Nodeunit uses the functions available in the node.js
|
|
||||||
[assert module](http://nodejs.org/docs/v0.4.2/api/assert.html):
|
|
||||||
|
|
||||||
* __ok(value, [message])__ - Tests if value is a true value.
|
|
||||||
* __equal(actual, expected, [message])__ - Tests shallow, coercive equality
|
|
||||||
with the equal comparison operator ( == ).
|
|
||||||
* __notEqual(actual, expected, [message])__ - Tests shallow, coercive
|
|
||||||
non-equality with the not equal comparison operator ( != ).
|
|
||||||
* __deepEqual(actual, expected, [message])__ - Tests for deep equality.
|
|
||||||
* __notDeepEqual(actual, expected, [message])__ - Tests for any deep
|
|
||||||
inequality.
|
|
||||||
* __strictEqual(actual, expected, [message])__ - Tests strict equality, as
|
|
||||||
determined by the strict equality operator ( === )
|
|
||||||
* __notStrictEqual(actual, expected, [message])__ - Tests strict non-equality,
|
|
||||||
as determined by the strict not equal operator ( !== )
|
|
||||||
* __throws(block, [error], [message])__ - Expects block to throw an error.
|
|
||||||
* __doesNotThrow(block, [error], [message])__ - Expects block not to throw an
|
|
||||||
error.
|
|
||||||
* __ifError(value)__ - Tests if value is not a false value, throws if it is a
|
|
||||||
true value. Useful when testing the first argument, error in callbacks.
|
|
||||||
|
|
||||||
Nodeunit also provides the following functions within tests:
|
|
||||||
|
|
||||||
* __expect(amount)__ - Specify how many assertions are expected to run within a
|
|
||||||
test. Very useful for ensuring that all your callbacks and assertions are
|
|
||||||
run.
|
|
||||||
* __done()__ - Finish the current test function, and move on to the next. ALL
|
|
||||||
tests should call this!
|
|
||||||
|
|
||||||
Nodeunit aims to be simple and easy to learn. This is achieved through using
|
|
||||||
existing structures (such as node.js modules) to maximum effect, and reducing
|
|
||||||
the API where possible, to make it easier to digest.
|
|
||||||
|
|
||||||
Tests are simply exported from a module, but they are still run in the order
|
|
||||||
they are defined.
|
|
||||||
|
|
||||||
__Note:__ Users of old nodeunit versions may remember using `ok`, `equals` and
|
|
||||||
`same` in the style of qunit, instead of the assert functions above. These
|
|
||||||
functions still exist for backwards compatibility, and are simply aliases to
|
|
||||||
their assert module counterparts.
|
|
||||||
|
|
||||||
|
|
||||||
Asynchronous Testing
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
When testing asynchronous code, there are a number of sharp edges to watch out
|
|
||||||
for. Thankfully, nodeunit is designed to help you avoid as many of these
|
|
||||||
pitfalls as possible. For the most part, testing asynchronous code in nodeunit
|
|
||||||
_just works_.
|
|
||||||
|
|
||||||
|
|
||||||
### Tests run in series
|
|
||||||
|
|
||||||
While running tests in parallel seems like a good idea for speeding up your
|
|
||||||
test suite, in practice I've found it means writing much more complicated
|
|
||||||
tests. Because of node's module cache, running tests in parallel means mocking
|
|
||||||
and stubbing is pretty much impossible. One of the nicest things about testing
|
|
||||||
in javascript is the ease of doing stubs:
|
|
||||||
|
|
||||||
var _readFile = fs.readFile;
|
|
||||||
fs.readFile = function(path, callback){
|
|
||||||
// it's a stub!
|
|
||||||
};
|
|
||||||
// test function that uses fs.readFile
|
|
||||||
|
|
||||||
// we're done
|
|
||||||
fs.readFile = _readFile;
|
|
||||||
|
|
||||||
You cannot do this when running tests in parallel. In order to keep testing as
|
|
||||||
simple as possible, nodeunit avoids it. Thankfully, most unit-test suites run
|
|
||||||
fast anyway.
|
|
||||||
|
|
||||||
|
|
||||||
### Explicit ending of tests
|
|
||||||
|
|
||||||
When testing async code it's important that tests end at the correct point, not
|
|
||||||
just after a given number of assertions. Otherwise your tests can run short,
|
|
||||||
ending before all assertions have completed. It's important to detect too
|
|
||||||
many assertions as well as too few. Combining explicit ending of tests with
|
|
||||||
an expected number of assertions helps to avoid false test passes, so be sure
|
|
||||||
to use the `test.expect()` method at the start of your test functions, and
|
|
||||||
`test.done()` when finished.
|
|
||||||
|
|
||||||
|
|
||||||
Groups, setUp and tearDown
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
Nodeunit allows the nesting of test functions:
|
|
||||||
|
|
||||||
exports.test1 = function (test) {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.group = {
|
|
||||||
test2: function (test) {
|
|
||||||
...
|
|
||||||
},
|
|
||||||
test3: function (test) {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
This would be run as:
|
|
||||||
|
|
||||||
test1
|
|
||||||
group - test2
|
|
||||||
group - test3
|
|
||||||
|
|
||||||
Using these groups, Nodeunit allows you to define a `setUp` function, which is
|
|
||||||
run before each test, and a `tearDown` function, which is run after each test
|
|
||||||
calls `test.done()`:
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
setUp: function (callback) {
|
|
||||||
this.foo = 'bar';
|
|
||||||
callback();
|
|
||||||
},
|
|
||||||
tearDown: function (callback) {
|
|
||||||
// clean up
|
|
||||||
callback();
|
|
||||||
},
|
|
||||||
test1: function (test) {
|
|
||||||
test.equals(this.foo, 'bar');
|
|
||||||
test.done();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
In this way, it's possible to have multiple groups of tests in a module, each
|
|
||||||
group with its own setUp and tearDown functions.
|
|
||||||
|
|
||||||
|
|
||||||
Running Tests
|
|
||||||
-------------
|
|
||||||
|
|
||||||
Nodeunit comes with a basic command-line test runner, which can be installed
|
|
||||||
using `sudo make install`. Example usage:
|
|
||||||
|
|
||||||
nodeunit testmodule1.js testfolder [...]
|
|
||||||
|
|
||||||
If no entry file specified, `test` defaults.
|
|
||||||
|
|
||||||
The default test reporter uses color output, because I think that's more fun :) I
|
|
||||||
intend to add a no-color option in future. To give you a feeling of the fun you'll
|
|
||||||
be having writing tests, lets fix the example at the start of the README:
|
|
||||||
|
|
||||||
<img src="https://github.com/caolan/nodeunit/raw/master/img/example_pass.png" />
|
|
||||||
|
|
||||||
Ahhh, Doesn't that feel better?
|
|
||||||
|
|
||||||
When using the included test runner, it will exit using the failed number of
|
|
||||||
assertions as the exit code. This means it exits with 0 when all tests pass.
|
|
||||||
|
|
||||||
|
|
||||||
### Command-line Options
|
|
||||||
|
|
||||||
* __--reporter FILE__ - you can set the test reporter to a custom module or
|
|
||||||
on of the modules in nodeunit/lib/reporters, when omitted, the default test runner
|
|
||||||
is used.
|
|
||||||
* __--list-reporters__ - list available built-in reporters.
|
|
||||||
* __--config FILE__ - load config options from a JSON file, allows
|
|
||||||
the customisation of color schemes for the default test reporter etc. See
|
|
||||||
bin/nodeunit.json for current available options.
|
|
||||||
* __-t testName__ - run specifc test only.
|
|
||||||
* __-f fullTestName__ - run specific test only. fullTestName is built so: "outerGroup - .. - innerGroup - testName".
|
|
||||||
* __--version__ or __-v__ - report nodeunit version
|
|
||||||
* __--help__ - show nodeunit help
|
|
||||||
|
|
||||||
|
|
||||||
Running tests in the browser
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
Nodeunit tests can also be run inside the browser. For example usage, see
|
|
||||||
the examples/browser folder. The basic syntax is as follows:
|
|
||||||
|
|
||||||
__test.html__
|
|
||||||
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Example Test Suite</title>
|
|
||||||
<link rel="stylesheet" href="nodeunit.css" type="text/css" />
|
|
||||||
<script src="nodeunit.js"></script>
|
|
||||||
<script src="suite1.js"></script>
|
|
||||||
<script src="suite2.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1 id="nodeunit-header">Example Test Suite</h1>
|
|
||||||
<script>
|
|
||||||
nodeunit.run({
|
|
||||||
'Suite One': suite1,
|
|
||||||
'Suite Two': suite2
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
Here, `suite1` and `suite2` are just object literals containing test functions
|
|
||||||
or groups, as would be returned if you did `require('test-suite')` in node.js:
|
|
||||||
|
|
||||||
__suite1.js__
|
|
||||||
|
|
||||||
this.suite1 = {
|
|
||||||
'example test': function (test) {
|
|
||||||
test.ok(true, 'everything is ok');
|
|
||||||
test.done();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
If you wish to use a commonjs format for your test suites (using exports), it is
|
|
||||||
up to you to define the commonjs tools for the browser. There are a number of
|
|
||||||
alternatives and it's important it fits with your existing code, which is
|
|
||||||
why nodeunit does not currently provide this out of the box.
|
|
||||||
|
|
||||||
In the example above, the tests will run when the page is loaded.
|
|
||||||
|
|
||||||
The browser-version of nodeunit.js is created in dist/browser when you do, `make
|
|
||||||
browser`. You'll need [UglifyJS](https://github.com/mishoo/UglifyJS) installed in
|
|
||||||
order for it to automatically create nodeunit.min.js.
|
|
||||||
|
|
||||||
|
|
||||||
Adding nodeunit to Your Projects
|
|
||||||
--------------------------------
|
|
||||||
|
|
||||||
If you don't want people to have to install the nodeunit command-line tool,
|
|
||||||
you'll want to create a script that runs the tests for your project with the
|
|
||||||
correct require paths set up. Here's an example test script, that assumes you
|
|
||||||
have nodeunit in a suitably located node_modules directory.
|
|
||||||
|
|
||||||
#!/usr/bin/env node
|
|
||||||
var reporter = require('nodeunit').reporters.default;
|
|
||||||
reporter.run(['test']);
|
|
||||||
|
|
||||||
If you're using git, you might find it useful to include nodeunit as a
|
|
||||||
submodule. Using submodules makes it easy for developers to download nodeunit
|
|
||||||
and run your test suite, without cluttering up your repository with
|
|
||||||
the source code. To add nodeunit as a git submodule do the following:
|
|
||||||
|
|
||||||
git submodule add git://github.com/caolan/nodeunit.git node_modules/nodeunit
|
|
||||||
|
|
||||||
This will add nodeunit to the node_modules folder of your project. Now, when
|
|
||||||
cloning the repository, nodeunit can be downloaded by doing the following:
|
|
||||||
|
|
||||||
git submodule init
|
|
||||||
git submodule update
|
|
||||||
|
|
||||||
Let's update the test script above with a helpful hint on how to get nodeunit,
|
|
||||||
if it's missing:
|
|
||||||
|
|
||||||
#!/usr/bin/env node
|
|
||||||
try {
|
|
||||||
var reporter = require('nodeunit').reporters.default;
|
|
||||||
}
|
|
||||||
catch(e) {
|
|
||||||
console.log("Cannot find nodeunit module.");
|
|
||||||
console.log("You can download submodules for this project by doing:");
|
|
||||||
console.log("");
|
|
||||||
console.log(" git submodule init");
|
|
||||||
console.log(" git submodule update");
|
|
||||||
console.log("");
|
|
||||||
process.exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
process.chdir(__dirname);
|
|
||||||
reporter.run(['test']);
|
|
||||||
|
|
||||||
Now if someone attempts to run your test suite without nodeunit installed they
|
|
||||||
will be prompted to download the submodules for your project.
|
|
||||||
|
|
||||||
|
|
||||||
Built-in Test Reporters
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
* __default__ - The standard reporter seen in the nodeunit screenshots
|
|
||||||
* __minimal__ - Pretty, minimal output, shows errors and progress only
|
|
||||||
* __html__ - Outputs a HTML report to stdout
|
|
||||||
* __junit__ - Creates jUnit compatible XML reports, which can be used with
|
|
||||||
continuous integration tools such as [Hudson](http://hudson-ci.org/).
|
|
||||||
* __machineout__ - Simple reporter for machine analysis. There is
|
|
||||||
[nodeunit.vim](https://github.com/lambdalisue/nodeunit.vim) which is useful for TDD on VIM.
|
|
||||||
|
|
||||||
|
|
||||||
Writing a Test Reporter
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
Nodeunit exports runTest(fn, options), runModule(mod, options) and
|
|
||||||
runFiles(paths, options). You'll most likely want to run test suites from
|
|
||||||
files, which can be done using the latter function. The _options_ argument can
|
|
||||||
contain callbacks which run during testing. Nodeunit provides the following
|
|
||||||
callbacks:
|
|
||||||
|
|
||||||
* __moduleStart(name)__ - called before a module is tested
|
|
||||||
* __moduleDone(name, assertions)__ - called once all test functions within the
|
|
||||||
module have completed (see assertions object reference below)
|
|
||||||
ALL tests within the module
|
|
||||||
* __testStart(name)__ - called before a test function is run
|
|
||||||
* __testReady(test)__ - called before a test function is run with the test object that will be passed to the test function
|
|
||||||
* __testDone(name, assertions)__ - called once a test function has completed
|
|
||||||
(by calling test.done())
|
|
||||||
* __log(assertion)__ - called whenever an assertion is made (see assertion
|
|
||||||
object reference below)
|
|
||||||
* __done(assertions)__ - called after all tests/modules are complete
|
|
||||||
|
|
||||||
The __assertion__ object:
|
|
||||||
|
|
||||||
* __passed()__ - did the assertion pass?
|
|
||||||
* __failed()__ - did the assertion fail?
|
|
||||||
* __error__ - the AssertionError if the assertion failed
|
|
||||||
* __method__ - the nodeunit assertion method used (ok, same, equals...)
|
|
||||||
* __message__ - the message the assertion method was called with (optional)
|
|
||||||
|
|
||||||
The __assertionList__ object:
|
|
||||||
|
|
||||||
* An array-like object with the following new attributes:
|
|
||||||
* __failures()__ - the number of assertions which failed
|
|
||||||
* __duration__ - the time taken for the test to complete in msecs
|
|
||||||
|
|
||||||
For a reference implementation of a test reporter, see lib/reporters/default.js in
|
|
||||||
the nodeunit project directory.
|
|
||||||
|
|
||||||
|
|
||||||
Sandbox utility
|
|
||||||
---------------
|
|
||||||
|
|
||||||
This is a function which evaluates JavaScript files in a sandbox and returns the
|
|
||||||
context. The sandbox function can be used for testing client-side code or private
|
|
||||||
un-exported functions within a module.
|
|
||||||
|
|
||||||
var sandbox = require('nodeunit').utils.sandbox;
|
|
||||||
var example = sandbox('example.js');
|
|
||||||
|
|
||||||
__sandbox(files, sandbox)__ - Evaluates JavaScript files in a sandbox, returning
|
|
||||||
the context. The first argument can either be a single filename or an array of
|
|
||||||
filenames. If multiple filenames are given their contents are concatenated before
|
|
||||||
evaluation. The second argument is an optional context to use for the sandbox.
|
|
||||||
|
|
||||||
Note: When working with the sandbox if your script depends on outside sources
|
|
||||||
(i.e. using `require`) then you will want to pass that into the optional
|
|
||||||
context when setting up the sandbox.
|
|
||||||
|
|
||||||
var sandbox = require('nodeunit').utils.sandbox;
|
|
||||||
// pass in some node globals
|
|
||||||
var box_globals = {
|
|
||||||
// Passing module.exports into the sandbox will give your code access to it.
|
|
||||||
module: {exports: exports},
|
|
||||||
// Passing require into the sandbox will give your code access to use it AND
|
|
||||||
// will share the cache with modules already required from outside the sandbox.
|
|
||||||
require: require,
|
|
||||||
// Passing console into the sandbox will give your code access to it
|
|
||||||
console: console
|
|
||||||
};
|
|
||||||
var example = sandbox('example.js', box_globals);
|
|
||||||
|
|
||||||
|
|
||||||
Running the nodeunit Tests
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
The tests for nodeunit are written using nodeunit itself as the test framework.
|
|
||||||
However, the module test-base.js first does some basic tests using the assert
|
|
||||||
module to ensure that test functions are actually run, and a basic level of
|
|
||||||
nodeunit functionality is available.
|
|
||||||
|
|
||||||
To run the nodeunit tests do:
|
|
||||||
|
|
||||||
make test
|
|
||||||
|
|
||||||
__Note:__ There was a bug in node v0.2.0 causing the tests to hang, upgrading
|
|
||||||
to v0.2.1 fixes this.
|
|
||||||
|
|
||||||
|
|
||||||
__machineout__ reporter
|
|
||||||
----------------------------------------------
|
|
||||||
|
|
||||||
The default reporter is readable for human but not for machine analysis.
|
|
||||||
When you want to analyze the output of nodeunit, use __machineout__ reporter and you will get
|
|
||||||
|
|
||||||
<img src="https://github.com/caolan/nodeunit/raw/master/img/example_machineout.png" />
|
|
||||||
|
|
||||||
|
|
||||||
nodeunit with vim
|
|
||||||
----------------------------------
|
|
||||||
There is [nodeunit.vim](https://github.com/lambdalisue/nodeunit.vim) so you can use
|
|
||||||
nodeunit with VIM.
|
|
||||||
|
|
||||||
That compiler uses __machineout__ reporter and it is useful to use
|
|
||||||
with [vim-makegreen](https://github.com/reinh/vim-makegreen).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Contributing
|
|
||||||
------------
|
|
||||||
|
|
||||||
Contributions to the project are most welcome, so feel free to fork and improve.
|
|
||||||
When submitting a pull request, please run `make lint` first to ensure
|
|
||||||
we're following a consistent coding style.
|
|
|
@ -1,132 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
var
|
|
||||||
fs = require('fs'),
|
|
||||||
path = require('path');
|
|
||||||
|
|
||||||
// TODO: remove this when https://github.com/joyent/node/pull/1312
|
|
||||||
// lands in core.
|
|
||||||
//
|
|
||||||
// Until then, use console.log from npm (https://gist.github.com/1077544)
|
|
||||||
require('../deps/console.log');
|
|
||||||
|
|
||||||
//require.paths.push(process.cwd());
|
|
||||||
var args = (process.ARGV || process.argv).slice(2);
|
|
||||||
|
|
||||||
var files = [];
|
|
||||||
|
|
||||||
var testrunner,
|
|
||||||
config_file,
|
|
||||||
config_param_found = false,
|
|
||||||
output_param_found = false,
|
|
||||||
reporter_file = 'default',
|
|
||||||
reporter_param_found = false,
|
|
||||||
testspec_param_found = false;
|
|
||||||
testFullSpec_param_found = false;
|
|
||||||
|
|
||||||
var usage = "Usage: nodeunit [options] testmodule1.js testfolder [...] \n" +
|
|
||||||
"Options:\n\n" +
|
|
||||||
" --config FILE the path to a JSON file with options\n" +
|
|
||||||
" --reporter FILE optional path to a reporter file to customize the output\n" +
|
|
||||||
" --list-reporters list available build-in reporters\n" +
|
|
||||||
" -t testName, specify a test to run\n" +
|
|
||||||
" -f fullTestName, specify a specific test to run. fullTestName is built so: \"outerGroup - .. - innerGroup - testName\"\n" +
|
|
||||||
" -h, --help display this help and exit\n" +
|
|
||||||
" -v, --version output version information and exit";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// load default options
|
|
||||||
var content = fs.readFileSync(__dirname + '/nodeunit.json', 'utf8');
|
|
||||||
var options = JSON.parse(content);
|
|
||||||
|
|
||||||
// a very basic pseudo --options parser
|
|
||||||
args.forEach(function (arg) {
|
|
||||||
if (arg.slice(0, 9) === "--config=") {
|
|
||||||
config_file = arg.slice(9);
|
|
||||||
} else if (arg === '--config') {
|
|
||||||
config_param_found = true;
|
|
||||||
} else if (config_param_found) {
|
|
||||||
config_file = arg;
|
|
||||||
config_param_found = false;
|
|
||||||
} else if (arg.slice(0, 9) === "--output=") {
|
|
||||||
options.output = arg.slice(9);
|
|
||||||
} else if (arg === '--output') {
|
|
||||||
output_param_found = true;
|
|
||||||
} else if (output_param_found) {
|
|
||||||
options.output = arg;
|
|
||||||
output_param_found = false;
|
|
||||||
} else if (arg.slice(0, 11) === "--reporter=") {
|
|
||||||
reporter_file = arg.slice(11);
|
|
||||||
} else if (arg === '--reporter') {
|
|
||||||
reporter_param_found = true;
|
|
||||||
} else if (reporter_param_found) {
|
|
||||||
reporter_file = arg;
|
|
||||||
reporter_param_found = false;
|
|
||||||
} else if (arg === '-t') {
|
|
||||||
testspec_param_found = true;
|
|
||||||
} else if (testspec_param_found) {
|
|
||||||
options.testspec = arg;
|
|
||||||
testspec_param_found = false;
|
|
||||||
} else if (arg === '-f') {
|
|
||||||
testFullSpec_param_found = true;
|
|
||||||
} else if (testFullSpec_param_found) {
|
|
||||||
options.testFullSpec= arg;
|
|
||||||
testFullSpec_param_found = false;
|
|
||||||
} else if (arg === '--list-reporters') {
|
|
||||||
var reporters = fs.readdirSync(__dirname + '/../lib/reporters');
|
|
||||||
reporters = reporters.filter(function (reporter_file) {
|
|
||||||
return (/\.js$/).test(reporter_file);
|
|
||||||
}).map(function (reporter_file) {
|
|
||||||
return reporter_file.replace(/\.js$/, '');
|
|
||||||
}).filter(function (reporter_file) {
|
|
||||||
return reporter_file !== 'index';
|
|
||||||
});
|
|
||||||
console.log('Build-in reporters: ');
|
|
||||||
reporters.forEach(function (reporter_file) {
|
|
||||||
var reporter = require('../lib/reporters/' + reporter_file);
|
|
||||||
console.log(' * ' + reporter_file + (reporter.info ? ': ' + reporter.info : ''));
|
|
||||||
});
|
|
||||||
process.exit(0);
|
|
||||||
} else if ((arg === '-v') || (arg === '--version')) {
|
|
||||||
var content = fs.readFileSync(__dirname + '/../package.json', 'utf8');
|
|
||||||
var pkg = JSON.parse(content);
|
|
||||||
console.log(pkg.version);
|
|
||||||
process.exit(0);
|
|
||||||
} else if ((arg === '-h') || (arg === '--help')) {
|
|
||||||
console.log(usage);
|
|
||||||
process.exit(0);
|
|
||||||
} else {
|
|
||||||
files.push(arg);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// defaults to `test`
|
|
||||||
if (files.length === 0) {
|
|
||||||
files = ['test'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config_file) {
|
|
||||||
content = fs.readFileSync(config_file, 'utf8');
|
|
||||||
var custom_options = JSON.parse(content);
|
|
||||||
|
|
||||||
for (var option in custom_options) {
|
|
||||||
if (typeof option === 'string') {
|
|
||||||
options[option] = custom_options[option];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var builtin_reporters = require(__dirname + '/../lib/reporters');
|
|
||||||
if (reporter_file in builtin_reporters) {
|
|
||||||
testrunner = builtin_reporters[reporter_file];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
testrunner = require(reporter_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
testrunner.run(files, options, function(err) {
|
|
||||||
if (err) {
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
});
|
|
10
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/bin/nodeunit.json
generated
vendored
10
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/bin/nodeunit.json
generated
vendored
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"error_prefix": "\u001B[31m",
|
|
||||||
"error_suffix": "\u001B[39m",
|
|
||||||
"ok_prefix": "\u001B[32m",
|
|
||||||
"ok_suffix": "\u001B[39m",
|
|
||||||
"bold_prefix": "\u001B[1m",
|
|
||||||
"bold_suffix": "\u001B[22m",
|
|
||||||
"assertion_prefix": "\u001B[35m",
|
|
||||||
"assertion_suffix": "\u001B[39m"
|
|
||||||
}
|
|
628
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/async.js
generated
vendored
628
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/async.js
generated
vendored
|
@ -1,628 +0,0 @@
|
||||||
/*global setTimeout: false, console: false */
|
|
||||||
(function () {
|
|
||||||
|
|
||||||
var async = {};
|
|
||||||
|
|
||||||
// global on the server, window in the browser
|
|
||||||
var root = this,
|
|
||||||
previous_async = root.async;
|
|
||||||
|
|
||||||
if (typeof module !== 'undefined' && module.exports) {
|
|
||||||
module.exports = async;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
root.async = async;
|
|
||||||
}
|
|
||||||
|
|
||||||
async.noConflict = function () {
|
|
||||||
root.async = previous_async;
|
|
||||||
return async;
|
|
||||||
};
|
|
||||||
|
|
||||||
//// cross-browser compatiblity functions ////
|
|
||||||
|
|
||||||
var _forEach = function (arr, iterator) {
|
|
||||||
if (arr.forEach) {
|
|
||||||
return arr.forEach(iterator);
|
|
||||||
}
|
|
||||||
for (var i = 0; i < arr.length; i += 1) {
|
|
||||||
iterator(arr[i], i, arr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var _map = function (arr, iterator) {
|
|
||||||
if (arr.map) {
|
|
||||||
return arr.map(iterator);
|
|
||||||
}
|
|
||||||
var results = [];
|
|
||||||
_forEach(arr, function (x, i, a) {
|
|
||||||
results.push(iterator(x, i, a));
|
|
||||||
});
|
|
||||||
return results;
|
|
||||||
};
|
|
||||||
|
|
||||||
var _reduce = function (arr, iterator, memo) {
|
|
||||||
if (arr.reduce) {
|
|
||||||
return arr.reduce(iterator, memo);
|
|
||||||
}
|
|
||||||
_forEach(arr, function (x, i, a) {
|
|
||||||
memo = iterator(memo, x, i, a);
|
|
||||||
});
|
|
||||||
return memo;
|
|
||||||
};
|
|
||||||
|
|
||||||
var _keys = function (obj) {
|
|
||||||
if (Object.keys) {
|
|
||||||
return Object.keys(obj);
|
|
||||||
}
|
|
||||||
var keys = [];
|
|
||||||
for (var k in obj) {
|
|
||||||
if (obj.hasOwnProperty(k)) {
|
|
||||||
keys.push(k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
};
|
|
||||||
|
|
||||||
var _indexOf = function (arr, item) {
|
|
||||||
if (arr.indexOf) {
|
|
||||||
return arr.indexOf(item);
|
|
||||||
}
|
|
||||||
for (var i = 0; i < arr.length; i += 1) {
|
|
||||||
if (arr[i] === item) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
//// exported async module functions ////
|
|
||||||
|
|
||||||
//// nextTick implementation with browser-compatible fallback ////
|
|
||||||
if (typeof setImmediate === 'function') {
|
|
||||||
async.nextTick = function (fn) {
|
|
||||||
setImmediate(fn);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (typeof process !== 'undefined' && process.nextTick) {
|
|
||||||
async.nextTick = process.nextTick;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
async.nextTick = function (fn) {
|
|
||||||
setTimeout(fn, 0);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async.forEach = function (arr, iterator, callback) {
|
|
||||||
if (!arr.length) {
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
var completed = 0;
|
|
||||||
_forEach(arr, function (x) {
|
|
||||||
iterator(x, function (err) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
callback = function () {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
completed += 1;
|
|
||||||
if (completed === arr.length) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
async.forEachSeries = function (arr, iterator, callback) {
|
|
||||||
if (!arr.length) {
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
var completed = 0;
|
|
||||||
var iterate = function () {
|
|
||||||
iterator(arr[completed], function (err) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
callback = function () {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
completed += 1;
|
|
||||||
if (completed === arr.length) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
iterate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
iterate();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var doParallel = function (fn) {
|
|
||||||
return function () {
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
return fn.apply(null, [async.forEach].concat(args));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
var doSeries = function (fn) {
|
|
||||||
return function () {
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
return fn.apply(null, [async.forEachSeries].concat(args));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var _asyncMap = function (eachfn, arr, iterator, callback) {
|
|
||||||
var results = [];
|
|
||||||
arr = _map(arr, function (x, i) {
|
|
||||||
return {index: i, value: x};
|
|
||||||
});
|
|
||||||
eachfn(arr, function (x, callback) {
|
|
||||||
iterator(x.value, function (err, v) {
|
|
||||||
results[x.index] = v;
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, results);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.map = doParallel(_asyncMap);
|
|
||||||
async.mapSeries = doSeries(_asyncMap);
|
|
||||||
|
|
||||||
|
|
||||||
// reduce only has a series version, as doing reduce in parallel won't
|
|
||||||
// work in many situations.
|
|
||||||
async.reduce = function (arr, memo, iterator, callback) {
|
|
||||||
async.forEachSeries(arr, function (x, callback) {
|
|
||||||
iterator(memo, x, function (err, v) {
|
|
||||||
memo = v;
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, memo);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// inject alias
|
|
||||||
async.inject = async.reduce;
|
|
||||||
// foldl alias
|
|
||||||
async.foldl = async.reduce;
|
|
||||||
|
|
||||||
async.reduceRight = function (arr, memo, iterator, callback) {
|
|
||||||
var reversed = _map(arr, function (x) {
|
|
||||||
return x;
|
|
||||||
}).reverse();
|
|
||||||
async.reduce(reversed, memo, iterator, callback);
|
|
||||||
};
|
|
||||||
// foldr alias
|
|
||||||
async.foldr = async.reduceRight;
|
|
||||||
|
|
||||||
var _filter = function (eachfn, arr, iterator, callback) {
|
|
||||||
var results = [];
|
|
||||||
arr = _map(arr, function (x, i) {
|
|
||||||
return {index: i, value: x};
|
|
||||||
});
|
|
||||||
eachfn(arr, function (x, callback) {
|
|
||||||
iterator(x.value, function (v) {
|
|
||||||
if (v) {
|
|
||||||
results.push(x);
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(_map(results.sort(function (a, b) {
|
|
||||||
return a.index - b.index;
|
|
||||||
}), function (x) {
|
|
||||||
return x.value;
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.filter = doParallel(_filter);
|
|
||||||
async.filterSeries = doSeries(_filter);
|
|
||||||
// select alias
|
|
||||||
async.select = async.filter;
|
|
||||||
async.selectSeries = async.filterSeries;
|
|
||||||
|
|
||||||
var _reject = function (eachfn, arr, iterator, callback) {
|
|
||||||
var results = [];
|
|
||||||
arr = _map(arr, function (x, i) {
|
|
||||||
return {index: i, value: x};
|
|
||||||
});
|
|
||||||
eachfn(arr, function (x, callback) {
|
|
||||||
iterator(x.value, function (v) {
|
|
||||||
if (!v) {
|
|
||||||
results.push(x);
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(_map(results.sort(function (a, b) {
|
|
||||||
return a.index - b.index;
|
|
||||||
}), function (x) {
|
|
||||||
return x.value;
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.reject = doParallel(_reject);
|
|
||||||
async.rejectSeries = doSeries(_reject);
|
|
||||||
|
|
||||||
var _detect = function (eachfn, arr, iterator, main_callback) {
|
|
||||||
eachfn(arr, function (x, callback) {
|
|
||||||
iterator(x, function (result) {
|
|
||||||
if (result) {
|
|
||||||
main_callback(x);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
main_callback();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.detect = doParallel(_detect);
|
|
||||||
async.detectSeries = doSeries(_detect);
|
|
||||||
|
|
||||||
async.some = function (arr, iterator, main_callback) {
|
|
||||||
async.forEach(arr, function (x, callback) {
|
|
||||||
iterator(x, function (v) {
|
|
||||||
if (v) {
|
|
||||||
main_callback(true);
|
|
||||||
main_callback = function () {};
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
main_callback(false);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// any alias
|
|
||||||
async.any = async.some;
|
|
||||||
|
|
||||||
async.every = function (arr, iterator, main_callback) {
|
|
||||||
async.forEach(arr, function (x, callback) {
|
|
||||||
iterator(x, function (v) {
|
|
||||||
if (!v) {
|
|
||||||
main_callback(false);
|
|
||||||
main_callback = function () {};
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
main_callback(true);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// all alias
|
|
||||||
async.all = async.every;
|
|
||||||
|
|
||||||
async.sortBy = function (arr, iterator, callback) {
|
|
||||||
async.map(arr, function (x, callback) {
|
|
||||||
iterator(x, function (err, criteria) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback(null, {value: x, criteria: criteria});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, function (err, results) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var fn = function (left, right) {
|
|
||||||
var a = left.criteria, b = right.criteria;
|
|
||||||
return a < b ? -1 : a > b ? 1 : 0;
|
|
||||||
};
|
|
||||||
callback(null, _map(results.sort(fn), function (x) {
|
|
||||||
return x.value;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
async.auto = function (tasks, callback) {
|
|
||||||
callback = callback || function () {};
|
|
||||||
var keys = _keys(tasks);
|
|
||||||
if (!keys.length) {
|
|
||||||
return callback(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
var completed = [];
|
|
||||||
|
|
||||||
var listeners = [];
|
|
||||||
var addListener = function (fn) {
|
|
||||||
listeners.unshift(fn);
|
|
||||||
};
|
|
||||||
var removeListener = function (fn) {
|
|
||||||
for (var i = 0; i < listeners.length; i += 1) {
|
|
||||||
if (listeners[i] === fn) {
|
|
||||||
listeners.splice(i, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var taskComplete = function () {
|
|
||||||
_forEach(listeners, function (fn) {
|
|
||||||
fn();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
addListener(function () {
|
|
||||||
if (completed.length === keys.length) {
|
|
||||||
callback(null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
_forEach(keys, function (k) {
|
|
||||||
var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
|
|
||||||
var taskCallback = function (err) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
// stop subsequent errors hitting callback multiple times
|
|
||||||
callback = function () {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
completed.push(k);
|
|
||||||
taskComplete();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var requires = task.slice(0, Math.abs(task.length - 1)) || [];
|
|
||||||
var ready = function () {
|
|
||||||
return _reduce(requires, function (a, x) {
|
|
||||||
return (a && _indexOf(completed, x) !== -1);
|
|
||||||
}, true);
|
|
||||||
};
|
|
||||||
if (ready()) {
|
|
||||||
task[task.length - 1](taskCallback);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var listener = function () {
|
|
||||||
if (ready()) {
|
|
||||||
removeListener(listener);
|
|
||||||
task[task.length - 1](taskCallback);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
addListener(listener);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
async.waterfall = function (tasks, callback) {
|
|
||||||
if (!tasks.length) {
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
callback = callback || function () {};
|
|
||||||
var wrapIterator = function (iterator) {
|
|
||||||
return function (err) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
callback = function () {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
var next = iterator.next();
|
|
||||||
if (next) {
|
|
||||||
args.push(wrapIterator(next));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
args.push(callback);
|
|
||||||
}
|
|
||||||
async.nextTick(function () {
|
|
||||||
iterator.apply(null, args);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
wrapIterator(async.iterator(tasks))();
|
|
||||||
};
|
|
||||||
|
|
||||||
async.parallel = function (tasks, callback) {
|
|
||||||
callback = callback || function () {};
|
|
||||||
if (tasks.constructor === Array) {
|
|
||||||
async.map(tasks, function (fn, callback) {
|
|
||||||
if (fn) {
|
|
||||||
fn(function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (args.length <= 1) {
|
|
||||||
args = args[0];
|
|
||||||
}
|
|
||||||
callback.call(null, err, args || null);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, callback);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var results = {};
|
|
||||||
async.forEach(_keys(tasks), function (k, callback) {
|
|
||||||
tasks[k](function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (args.length <= 1) {
|
|
||||||
args = args[0];
|
|
||||||
}
|
|
||||||
results[k] = args;
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, results);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async.series = function (tasks, callback) {
|
|
||||||
callback = callback || function () {};
|
|
||||||
if (tasks.constructor === Array) {
|
|
||||||
async.mapSeries(tasks, function (fn, callback) {
|
|
||||||
if (fn) {
|
|
||||||
fn(function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (args.length <= 1) {
|
|
||||||
args = args[0];
|
|
||||||
}
|
|
||||||
callback.call(null, err, args || null);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, callback);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var results = {};
|
|
||||||
async.forEachSeries(_keys(tasks), function (k, callback) {
|
|
||||||
tasks[k](function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (args.length <= 1) {
|
|
||||||
args = args[0];
|
|
||||||
}
|
|
||||||
results[k] = args;
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, results);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async.iterator = function (tasks) {
|
|
||||||
var makeCallback = function (index) {
|
|
||||||
var fn = function () {
|
|
||||||
if (tasks.length) {
|
|
||||||
tasks[index].apply(null, arguments);
|
|
||||||
}
|
|
||||||
return fn.next();
|
|
||||||
};
|
|
||||||
fn.next = function () {
|
|
||||||
return (index < tasks.length - 1) ? makeCallback(index + 1): null;
|
|
||||||
};
|
|
||||||
return fn;
|
|
||||||
};
|
|
||||||
return makeCallback(0);
|
|
||||||
};
|
|
||||||
|
|
||||||
async.apply = function (fn) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
return function () {
|
|
||||||
return fn.apply(
|
|
||||||
null, args.concat(Array.prototype.slice.call(arguments))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var _concat = function (eachfn, arr, fn, callback) {
|
|
||||||
var r = [];
|
|
||||||
eachfn(arr, function (x, cb) {
|
|
||||||
fn(x, function (err, y) {
|
|
||||||
r = r.concat(y || []);
|
|
||||||
cb(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, r);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.concat = doParallel(_concat);
|
|
||||||
async.concatSeries = doSeries(_concat);
|
|
||||||
|
|
||||||
async.whilst = function (test, iterator, callback) {
|
|
||||||
if (test()) {
|
|
||||||
iterator(function (err) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
async.whilst(test, iterator, callback);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async.until = function (test, iterator, callback) {
|
|
||||||
if (!test()) {
|
|
||||||
iterator(function (err) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
async.until(test, iterator, callback);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async.queue = function (worker, concurrency) {
|
|
||||||
var workers = 0;
|
|
||||||
var tasks = [];
|
|
||||||
var q = {
|
|
||||||
concurrency: concurrency,
|
|
||||||
push: function (data, callback) {
|
|
||||||
tasks.push({data: data, callback: callback});
|
|
||||||
async.nextTick(q.process);
|
|
||||||
},
|
|
||||||
process: function () {
|
|
||||||
if (workers < q.concurrency && tasks.length) {
|
|
||||||
var task = tasks.splice(0, 1)[0];
|
|
||||||
workers += 1;
|
|
||||||
worker(task.data, function () {
|
|
||||||
workers -= 1;
|
|
||||||
if (task.callback) {
|
|
||||||
task.callback.apply(task, arguments);
|
|
||||||
}
|
|
||||||
q.process();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
length: function () {
|
|
||||||
return tasks.length;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return q;
|
|
||||||
};
|
|
||||||
|
|
||||||
var _console_fn = function (name) {
|
|
||||||
return function (fn) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
fn.apply(null, args.concat([function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (typeof console !== 'undefined') {
|
|
||||||
if (err) {
|
|
||||||
if (console.error) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (console[name]) {
|
|
||||||
_forEach(args, function (x) {
|
|
||||||
console[name](x);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}]));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
async.log = _console_fn('log');
|
|
||||||
async.dir = _console_fn('dir');
|
|
||||||
/*async.info = _console_fn('info');
|
|
||||||
async.warn = _console_fn('warn');
|
|
||||||
async.error = _console_fn('error');*/
|
|
||||||
|
|
||||||
async.memoize = function (fn, hasher) {
|
|
||||||
var memo = {};
|
|
||||||
hasher = hasher || function (x) {
|
|
||||||
return x;
|
|
||||||
};
|
|
||||||
return function () {
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
var callback = args.pop();
|
|
||||||
var key = hasher.apply(null, args);
|
|
||||||
if (key in memo) {
|
|
||||||
callback.apply(null, memo[key]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fn.apply(null, args.concat([function () {
|
|
||||||
memo[key] = arguments;
|
|
||||||
callback.apply(null, arguments);
|
|
||||||
}]));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}());
|
|
55
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/console.log.js
generated
vendored
55
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/console.log.js
generated
vendored
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
A console.log that won't leave you hanging when node exits
|
|
||||||
90% of this file was ripped from node.js
|
|
||||||
|
|
||||||
License: see: https://github.com/joyent/node/blob/master/lib/console.js
|
|
||||||
*/
|
|
||||||
|
|
||||||
// console object
|
|
||||||
var formatRegExp = /%[sdj]/g;
|
|
||||||
function format(f) {
|
|
||||||
var util = require('util');
|
|
||||||
|
|
||||||
if (typeof f !== 'string') {
|
|
||||||
var objects = [];
|
|
||||||
for (var i = 0; i < arguments.length; i++) {
|
|
||||||
objects.push(util.inspect(arguments[i]));
|
|
||||||
}
|
|
||||||
return objects.join(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var i = 1;
|
|
||||||
var args = arguments;
|
|
||||||
var str = String(f).replace(formatRegExp, function(x) {
|
|
||||||
switch (x) {
|
|
||||||
case '%s': return String(args[i++]);
|
|
||||||
case '%d': return Number(args[i++]);
|
|
||||||
case '%j': return JSON.stringify(args[i++]);
|
|
||||||
default:
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
for (var len = args.length, x = args[i]; i < len; x = args[++i]) {
|
|
||||||
if (x === null || typeof x !== 'object') {
|
|
||||||
str += ' ' + x;
|
|
||||||
} else {
|
|
||||||
str += ' ' + util.inspect(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log = function() {
|
|
||||||
var res = process.stdout.write(format.apply(this, arguments) + '\n');
|
|
||||||
|
|
||||||
// this is the first time stdout got backed up
|
|
||||||
if (!res && !process.stdout.pendingWrite) {
|
|
||||||
process.stdout.pendingWrite = true;
|
|
||||||
|
|
||||||
// magic sauce: keep node alive until stdout has flushed
|
|
||||||
process.stdout.once('drain', function () {
|
|
||||||
process.stdout.draining = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
70
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/History.md
generated
vendored
70
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/History.md
generated
vendored
|
@ -1,70 +0,0 @@
|
||||||
|
|
||||||
0.4.3 / 2011-06-20
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fixed stacktraces line number when used multiline js expressions [Octave]
|
|
||||||
|
|
||||||
0.4.2 / 2011-05-11
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Added client side support
|
|
||||||
|
|
||||||
0.4.1 / 2011-04-21
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fixed error context
|
|
||||||
|
|
||||||
0.4.0 / 2011-04-21
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Added; ported jade's error reporting to ejs. [slaskis]
|
|
||||||
|
|
||||||
0.3.1 / 2011-02-23
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fixed optional `compile()` options
|
|
||||||
|
|
||||||
0.3.0 / 2011-02-14
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Added 'json' filter [Yuriy Bogdanov]
|
|
||||||
* Use exported version of parse function to allow monkey-patching [Anatoliy Chakkaev]
|
|
||||||
|
|
||||||
0.2.1 / 2010-10-07
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Added filter support
|
|
||||||
* Fixed _cache_ option. ~4x performance increase
|
|
||||||
|
|
||||||
0.2.0 / 2010-08-05
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Added support for global tag config
|
|
||||||
* Added custom tag support. Closes #5
|
|
||||||
* Fixed whitespace bug. Closes #4
|
|
||||||
|
|
||||||
0.1.0 / 2010-08-04
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Faster implementation [ashleydev]
|
|
||||||
|
|
||||||
0.0.4 / 2010-08-02
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fixed single quotes for content outside of template tags. [aniero]
|
|
||||||
* Changed; `exports.compile()` now expects only "locals"
|
|
||||||
|
|
||||||
0.0.3 / 2010-07-15
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fixed single quotes
|
|
||||||
|
|
||||||
0.0.2 / 2010-07-09
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Fixed newline preservation
|
|
||||||
|
|
||||||
0.0.1 / 2010-07-09
|
|
||||||
==================
|
|
||||||
|
|
||||||
* Initial release
|
|
20
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/Makefile
generated
vendored
20
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/Makefile
generated
vendored
|
@ -1,20 +0,0 @@
|
||||||
|
|
||||||
SRC = $(shell find lib -name "*.js" -type f)
|
|
||||||
UGLIFY_FLAGS = --no-mangle
|
|
||||||
|
|
||||||
test:
|
|
||||||
@./node_modules/.bin/expresso test/*.test.js
|
|
||||||
|
|
||||||
ejs.js: $(SRC)
|
|
||||||
@node support/compile.js $^
|
|
||||||
|
|
||||||
ejs.min.js: ejs.js
|
|
||||||
@uglifyjs $(UGLIFY_FLAGS) $< > $@ \
|
|
||||||
&& du ejs.min.js \
|
|
||||||
&& du ejs.js
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f ejs.js
|
|
||||||
rm -f ejs.min.js
|
|
||||||
|
|
||||||
.PHONY: test
|
|
152
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/Readme.md
generated
vendored
152
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/Readme.md
generated
vendored
|
@ -1,152 +0,0 @@
|
||||||
|
|
||||||
# EJS
|
|
||||||
|
|
||||||
Embedded JavaScript templates.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
$ npm install ejs
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
* Complies with the [Express](http://expressjs.com) view system
|
|
||||||
* Static caching of intermediate JavaScript
|
|
||||||
* Unbuffered code for conditionals etc `<% code %>`
|
|
||||||
* Escapes html by default with `<%= code %>`
|
|
||||||
* Unescaped buffering with `<%- code %>`
|
|
||||||
* Supports tag customization
|
|
||||||
* Filter support for designer-friendly templates
|
|
||||||
* Client-side support
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
<% if (user) { %>
|
|
||||||
<h2><%= user.name %></h2>
|
|
||||||
<% } %>
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
ejs.compile(str, options);
|
|
||||||
// => Function
|
|
||||||
|
|
||||||
ejs.render(str, options);
|
|
||||||
// => str
|
|
||||||
|
|
||||||
## Options
|
|
||||||
|
|
||||||
- `locals` Local variables object
|
|
||||||
- `cache` Compiled functions are cached, requires `filename`
|
|
||||||
- `filename` Used by `cache` to key caches
|
|
||||||
- `scope` Function execution context
|
|
||||||
- `debug` Output generated function body
|
|
||||||
- `open` Open tag, defaulting to "<%"
|
|
||||||
- `close` Closing tag, defaulting to "%>"
|
|
||||||
|
|
||||||
## Custom tags
|
|
||||||
|
|
||||||
Custom tags can also be applied globally:
|
|
||||||
|
|
||||||
var ejs = require('ejs');
|
|
||||||
ejs.open = '{{';
|
|
||||||
ejs.close = '}}';
|
|
||||||
|
|
||||||
Which would make the following a valid template:
|
|
||||||
|
|
||||||
<h1>{{= title }}</h1>
|
|
||||||
|
|
||||||
## Filters
|
|
||||||
|
|
||||||
EJS conditionally supports the concept of "filters". A "filter chain"
|
|
||||||
is a designer friendly api for manipulating data, without writing JavaScript.
|
|
||||||
|
|
||||||
Filters can be applied by supplying the _:_ modifier, so for example if we wish to take the array `[{ name: 'tj' }, { name: 'mape' }, { name: 'guillermo' }]` and output a list of names we can do this simply with filters:
|
|
||||||
|
|
||||||
Template:
|
|
||||||
|
|
||||||
<p><%=: users | map:'name' | join %></p>
|
|
||||||
|
|
||||||
Output:
|
|
||||||
|
|
||||||
<p>Tj, Mape, Guillermo</p>
|
|
||||||
|
|
||||||
Render call:
|
|
||||||
|
|
||||||
ejs.render(str, {
|
|
||||||
locals: {
|
|
||||||
users: [
|
|
||||||
{ name: 'tj' },
|
|
||||||
{ name: 'mape' },
|
|
||||||
{ name: 'guillermo' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Or perhaps capitalize the first user's name for display:
|
|
||||||
|
|
||||||
<p><%=: users | first | capitalize %></p>
|
|
||||||
|
|
||||||
## Filter list
|
|
||||||
|
|
||||||
Currently these filters are available:
|
|
||||||
|
|
||||||
- first
|
|
||||||
- last
|
|
||||||
- capitalize
|
|
||||||
- downcase
|
|
||||||
- upcase
|
|
||||||
- sort
|
|
||||||
- sort_by:'prop'
|
|
||||||
- size
|
|
||||||
- length
|
|
||||||
- plus:n
|
|
||||||
- minus:n
|
|
||||||
- times:n
|
|
||||||
- divided_by:n
|
|
||||||
- join:'val'
|
|
||||||
- truncate:n
|
|
||||||
- truncate_words:n
|
|
||||||
- replace:pattern,substitution
|
|
||||||
- prepend:val
|
|
||||||
- append:val
|
|
||||||
- map:'prop'
|
|
||||||
- reverse
|
|
||||||
- get:'prop'
|
|
||||||
|
|
||||||
## Adding filters
|
|
||||||
|
|
||||||
To add a filter simply add a method to the `.filters` object:
|
|
||||||
|
|
||||||
```js
|
|
||||||
ejs.filters.last = function(obj) {
|
|
||||||
return obj[obj.length - 1];
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## client-side support
|
|
||||||
|
|
||||||
include `./ejs.js` or `./ejs.min.js` and `require("ejs").compile(str)`.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
(The MIT License)
|
|
||||||
|
|
||||||
Copyright (c) 2009-2010 TJ Holowaychuk <tj@vision-media.ca>
|
|
||||||
|
|
||||||
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.
|
|
14
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/benchmark.js
generated
vendored
14
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/benchmark.js
generated
vendored
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
var ejs = require('./lib/ejs'),
|
|
||||||
str = '<% if (foo) { %><p><%= foo %></p><% } %>',
|
|
||||||
times = 50000;
|
|
||||||
|
|
||||||
console.log('rendering ' + times + ' times');
|
|
||||||
|
|
||||||
var start = new Date;
|
|
||||||
while (times--) {
|
|
||||||
ejs.render(str, { cache: true, filename: 'test', locals: { foo: 'bar' }});
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('took ' + (new Date - start) + 'ms');
|
|
531
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/ejs.js
generated
vendored
531
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/ejs.js
generated
vendored
|
@ -1,531 +0,0 @@
|
||||||
|
|
||||||
// CommonJS require()
|
|
||||||
|
|
||||||
function require(p){
|
|
||||||
var path = require.resolve(p)
|
|
||||||
, mod = require.modules[path];
|
|
||||||
if (!mod) throw new Error('failed to require "' + p + '"');
|
|
||||||
if (!mod.exports) {
|
|
||||||
mod.exports = {};
|
|
||||||
mod.call(mod.exports, mod, mod.exports, require.relative(path));
|
|
||||||
}
|
|
||||||
return mod.exports;
|
|
||||||
}
|
|
||||||
|
|
||||||
require.modules = {};
|
|
||||||
|
|
||||||
require.resolve = function (path){
|
|
||||||
var orig = path
|
|
||||||
, reg = path + '.js'
|
|
||||||
, index = path + '/index.js';
|
|
||||||
return require.modules[reg] && reg
|
|
||||||
|| require.modules[index] && index
|
|
||||||
|| orig;
|
|
||||||
};
|
|
||||||
|
|
||||||
require.register = function (path, fn){
|
|
||||||
require.modules[path] = fn;
|
|
||||||
};
|
|
||||||
|
|
||||||
require.relative = function (parent) {
|
|
||||||
return function(p){
|
|
||||||
if ('.' != p[0]) return require(p);
|
|
||||||
|
|
||||||
var path = parent.split('/')
|
|
||||||
, segs = p.split('/');
|
|
||||||
path.pop();
|
|
||||||
|
|
||||||
for (var i = 0; i < segs.length; i++) {
|
|
||||||
var seg = segs[i];
|
|
||||||
if ('..' == seg) path.pop();
|
|
||||||
else if ('.' != seg) path.push(seg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return require(path.join('/'));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
require.register("ejs.js", function(module, exports, require){
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* EJS
|
|
||||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var utils = require('./utils');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Library version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.version = '0.4.2';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filters.
|
|
||||||
*
|
|
||||||
* @type Object
|
|
||||||
*/
|
|
||||||
|
|
||||||
var filters = exports.filters = require('./filters');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Intermediate js cache.
|
|
||||||
*
|
|
||||||
* @type Object
|
|
||||||
*/
|
|
||||||
|
|
||||||
var cache = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear intermediate js cache.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.clearCache = function(){
|
|
||||||
cache = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translate filtered code into function calls.
|
|
||||||
*
|
|
||||||
* @param {String} js
|
|
||||||
* @return {String}
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
function filtered(js) {
|
|
||||||
return js.substr(1).split('|').reduce(function(js, filter){
|
|
||||||
var parts = filter.split(':')
|
|
||||||
, name = parts.shift()
|
|
||||||
, args = parts.shift() || '';
|
|
||||||
if (args) args = ', ' + args;
|
|
||||||
return 'filters.' + name + '(' + js + args + ')';
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Re-throw the given `err` in context to the
|
|
||||||
* `str` of ejs, `filename`, and `lineno`.
|
|
||||||
*
|
|
||||||
* @param {Error} err
|
|
||||||
* @param {String} str
|
|
||||||
* @param {String} filename
|
|
||||||
* @param {String} lineno
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
function rethrow(err, str, filename, lineno){
|
|
||||||
var lines = str.split('\n')
|
|
||||||
, start = Math.max(lineno - 3, 0)
|
|
||||||
, end = Math.min(lines.length, lineno + 3);
|
|
||||||
|
|
||||||
// Error context
|
|
||||||
var context = lines.slice(start, end).map(function(line, i){
|
|
||||||
var curr = i + start + 1;
|
|
||||||
return (curr == lineno ? ' >> ' : ' ')
|
|
||||||
+ curr
|
|
||||||
+ '| '
|
|
||||||
+ line;
|
|
||||||
}).join('\n');
|
|
||||||
|
|
||||||
// Alter exception message
|
|
||||||
err.path = filename;
|
|
||||||
err.message = (filename || 'ejs') + ':'
|
|
||||||
+ lineno + '\n'
|
|
||||||
+ context + '\n\n'
|
|
||||||
+ err.message;
|
|
||||||
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the given `str` of ejs, returning the function body.
|
|
||||||
*
|
|
||||||
* @param {String} str
|
|
||||||
* @return {String}
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
var parse = exports.parse = function(str, options){
|
|
||||||
var options = options || {}
|
|
||||||
, open = options.open || exports.open || '<%'
|
|
||||||
, close = options.close || exports.close || '%>';
|
|
||||||
|
|
||||||
var buf = [
|
|
||||||
"var buf = [];"
|
|
||||||
, "\nwith (locals) {"
|
|
||||||
, "\n buf.push('"
|
|
||||||
];
|
|
||||||
|
|
||||||
var lineno = 1;
|
|
||||||
|
|
||||||
for (var i = 0, len = str.length; i < len; ++i) {
|
|
||||||
if (str.slice(i, open.length + i) == open) {
|
|
||||||
i += open.length
|
|
||||||
|
|
||||||
var prefix, postfix, line = '__stack.lineno=' + lineno;
|
|
||||||
switch (str[i]) {
|
|
||||||
case '=':
|
|
||||||
prefix = "', escape((" + line + ', ';
|
|
||||||
postfix = ")), '";
|
|
||||||
++i;
|
|
||||||
break;
|
|
||||||
case '-':
|
|
||||||
prefix = "', (" + line + ', ';
|
|
||||||
postfix = "), '";
|
|
||||||
++i;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
prefix = "');" + line + ';';
|
|
||||||
postfix = "; buf.push('";
|
|
||||||
}
|
|
||||||
|
|
||||||
var start = i;
|
|
||||||
var end = str.indexOf(close, i);
|
|
||||||
var js = str.substring(i, end);
|
|
||||||
var n = 0;
|
|
||||||
while ((n = js.indexOf("\n", n)) > -1) {
|
|
||||||
n++;
|
|
||||||
lineno++;
|
|
||||||
}
|
|
||||||
if (js[0] == ':') js = filtered(js);
|
|
||||||
buf.push(prefix, js, postfix);
|
|
||||||
i += end - start + close.length - 1;
|
|
||||||
|
|
||||||
} else if (str[i] == "\\") {
|
|
||||||
buf.push("\\\\");
|
|
||||||
} else if (str[i] == "'") {
|
|
||||||
buf.push("\\'");
|
|
||||||
} else if (str[i] == "\r") {
|
|
||||||
buf.push(" ");
|
|
||||||
} else if (str[i] == "\n") {
|
|
||||||
buf.push("\\n");
|
|
||||||
lineno++;
|
|
||||||
} else {
|
|
||||||
buf.push(str[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.push("');\n}\nreturn buf.join('');");
|
|
||||||
return buf.join('');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compile the given `str` of ejs into a `Function`.
|
|
||||||
*
|
|
||||||
* @param {String} str
|
|
||||||
* @param {Object} options
|
|
||||||
* @return {Function}
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
var compile = exports.compile = function(str, options){
|
|
||||||
options = options || {};
|
|
||||||
|
|
||||||
var input = JSON.stringify(str)
|
|
||||||
, filename = options.filename
|
|
||||||
? JSON.stringify(options.filename)
|
|
||||||
: 'undefined';
|
|
||||||
|
|
||||||
// Adds the fancy stack trace meta info
|
|
||||||
str = [
|
|
||||||
'var __stack = { lineno: 1, input: ' + input + ', filename: ' + filename + ' };',
|
|
||||||
rethrow.toString(),
|
|
||||||
'try {',
|
|
||||||
exports.parse(str, options),
|
|
||||||
'} catch (err) {',
|
|
||||||
' rethrow(err, __stack.input, __stack.filename, __stack.lineno);',
|
|
||||||
'}'
|
|
||||||
].join("\n");
|
|
||||||
|
|
||||||
if (options.debug) console.log(str);
|
|
||||||
var fn = new Function('locals, filters, escape', str);
|
|
||||||
return function(locals){
|
|
||||||
return fn.call(this, locals, filters, utils.escape);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render the given `str` of ejs.
|
|
||||||
*
|
|
||||||
* Options:
|
|
||||||
*
|
|
||||||
* - `locals` Local variables object
|
|
||||||
* - `cache` Compiled functions are cached, requires `filename`
|
|
||||||
* - `filename` Used by `cache` to key caches
|
|
||||||
* - `scope` Function execution context
|
|
||||||
* - `debug` Output generated function body
|
|
||||||
* - `open` Open tag, defaulting to "<%"
|
|
||||||
* - `close` Closing tag, defaulting to "%>"
|
|
||||||
*
|
|
||||||
* @param {String} str
|
|
||||||
* @param {Object} options
|
|
||||||
* @return {String}
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.render = function(str, options){
|
|
||||||
var fn
|
|
||||||
, options = options || {};
|
|
||||||
if (options.cache) {
|
|
||||||
if (options.filename) {
|
|
||||||
fn = cache[options.filename] || (cache[options.filename] = compile(str, options));
|
|
||||||
} else {
|
|
||||||
throw new Error('"cache" option requires "filename".');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fn = compile(str, options);
|
|
||||||
}
|
|
||||||
return fn.call(options.scope, options.locals || {});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expose to require().
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (require.extensions) {
|
|
||||||
require.extensions['.ejs'] = function(module, filename) {
|
|
||||||
source = require('fs').readFileSync(filename, 'utf-8');
|
|
||||||
module._compile(compile(source, {}), filename);
|
|
||||||
};
|
|
||||||
} else if (require.registerExtension) {
|
|
||||||
require.registerExtension('.ejs', function(src) {
|
|
||||||
return compile(src, {});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}); // module: ejs.js
|
|
||||||
|
|
||||||
require.register("filters.js", function(module, exports, require){
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* EJS - Filters
|
|
||||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* First element of the target `obj`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.first = function(obj) {
|
|
||||||
return obj[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Last element of the target `obj`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.last = function(obj) {
|
|
||||||
return obj[obj.length - 1];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Capitalize the first letter of the target `str`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.capitalize = function(str){
|
|
||||||
str = String(str);
|
|
||||||
return str[0].toUpperCase() + str.substr(1, str.length);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Downcase the target `str`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.downcase = function(str){
|
|
||||||
return String(str).toLowerCase();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uppercase the target `str`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.upcase = function(str){
|
|
||||||
return String(str).toUpperCase();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort the target `obj`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.sort = function(obj){
|
|
||||||
return Object.create(obj).sort();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort the target `obj` by the given `prop` ascending.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.sort_by = function(obj, prop){
|
|
||||||
return Object.create(obj).sort(function(a, b){
|
|
||||||
a = a[prop], b = b[prop];
|
|
||||||
if (a > b) return 1;
|
|
||||||
if (a < b) return -1;
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Size or length of the target `obj`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.size = exports.length = function(obj) {
|
|
||||||
return obj.length;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add `a` and `b`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.plus = function(a, b){
|
|
||||||
return Number(a) + Number(b);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subtract `b` from `a`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.minus = function(a, b){
|
|
||||||
return Number(a) - Number(b);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Multiply `a` by `b`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.times = function(a, b){
|
|
||||||
return Number(a) * Number(b);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Divide `a` by `b`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.divided_by = function(a, b){
|
|
||||||
return Number(a) / Number(b);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Join `obj` with the given `str`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.join = function(obj, str){
|
|
||||||
return obj.join(str || ', ');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Truncate `str` to `len`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.truncate = function(str, len){
|
|
||||||
str = String(str);
|
|
||||||
return str.substr(0, len);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Truncate `str` to `n` words.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.truncate_words = function(str, n){
|
|
||||||
var str = String(str)
|
|
||||||
, words = str.split(/ +/);
|
|
||||||
return words.slice(0, n).join(' ');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replace `pattern` with `substitution` in `str`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.replace = function(str, pattern, substitution){
|
|
||||||
return String(str).replace(pattern, substitution || '');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepend `val` to `obj`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.prepend = function(obj, val){
|
|
||||||
return Array.isArray(obj)
|
|
||||||
? [val].concat(obj)
|
|
||||||
: val + obj;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append `val` to `obj`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.append = function(obj, val){
|
|
||||||
return Array.isArray(obj)
|
|
||||||
? obj.concat(val)
|
|
||||||
: obj + val;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map the given `prop`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.map = function(arr, prop){
|
|
||||||
return arr.map(function(obj){
|
|
||||||
return obj[prop];
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the given `obj`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.reverse = function(obj){
|
|
||||||
return Array.isArray(obj)
|
|
||||||
? obj.reverse()
|
|
||||||
: String(obj).split('').reverse().join('');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get `prop` of the given `obj`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.get = function(obj, prop){
|
|
||||||
return obj[prop];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Packs the given `obj` into json string
|
|
||||||
*/
|
|
||||||
exports.json = function(obj){
|
|
||||||
return JSON.stringify(obj);
|
|
||||||
};
|
|
||||||
}); // module: filters.js
|
|
||||||
|
|
||||||
require.register("utils.js", function(module, exports, require){
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* EJS
|
|
||||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Escape the given string of `html`.
|
|
||||||
*
|
|
||||||
* @param {String} html
|
|
||||||
* @return {String}
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.escape = function(html){
|
|
||||||
return String(html)
|
|
||||||
.replace(/&(?!\w+;)/g, '&')
|
|
||||||
.replace(/</g, '<')
|
|
||||||
.replace(/>/g, '>')
|
|
||||||
.replace(/"/g, '"');
|
|
||||||
};
|
|
||||||
|
|
||||||
}); // module: utils.js
|
|
2
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/ejs.min.js
generated
vendored
2
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/ejs.min.js
generated
vendored
File diff suppressed because one or more lines are too long
|
@ -1,5 +0,0 @@
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<script src="../ejs.js"></script>
|
|
||||||
</head>
|
|
||||||
</html>
|
|
|
@ -1,7 +0,0 @@
|
||||||
<% if (names.length) { %>
|
|
||||||
<ul>
|
|
||||||
<% names.forEach(function(name){ %>
|
|
||||||
<li><%= name %></li>
|
|
||||||
<% }) %>
|
|
||||||
</ul>
|
|
||||||
<% } %>
|
|
|
@ -1,16 +0,0 @@
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var ejs = require('../')
|
|
||||||
, fs = require('fs')
|
|
||||||
, str = fs.readFileSync(__dirname + '/list.ejs', 'utf8');
|
|
||||||
|
|
||||||
var ret = ejs.render(str, {
|
|
||||||
locals: {
|
|
||||||
names: ['foo', 'bar', 'baz']
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(ret);
|
|
2
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/index.js
generated
vendored
2
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/index.js
generated
vendored
|
@ -1,2 +0,0 @@
|
||||||
|
|
||||||
module.exports = require('./lib/ejs');
|
|
251
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/lib/ejs.js
generated
vendored
251
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/lib/ejs.js
generated
vendored
|
@ -1,251 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* EJS
|
|
||||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var utils = require('./utils');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Library version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.version = '0.4.3';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filters.
|
|
||||||
*
|
|
||||||
* @type Object
|
|
||||||
*/
|
|
||||||
|
|
||||||
var filters = exports.filters = require('./filters');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Intermediate js cache.
|
|
||||||
*
|
|
||||||
* @type Object
|
|
||||||
*/
|
|
||||||
|
|
||||||
var cache = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear intermediate js cache.
|
|
||||||
*
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.clearCache = function(){
|
|
||||||
cache = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translate filtered code into function calls.
|
|
||||||
*
|
|
||||||
* @param {String} js
|
|
||||||
* @return {String}
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
function filtered(js) {
|
|
||||||
return js.substr(1).split('|').reduce(function(js, filter){
|
|
||||||
var parts = filter.split(':')
|
|
||||||
, name = parts.shift()
|
|
||||||
, args = parts.shift() || '';
|
|
||||||
if (args) args = ', ' + args;
|
|
||||||
return 'filters.' + name + '(' + js + args + ')';
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Re-throw the given `err` in context to the
|
|
||||||
* `str` of ejs, `filename`, and `lineno`.
|
|
||||||
*
|
|
||||||
* @param {Error} err
|
|
||||||
* @param {String} str
|
|
||||||
* @param {String} filename
|
|
||||||
* @param {String} lineno
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
function rethrow(err, str, filename, lineno){
|
|
||||||
var lines = str.split('\n')
|
|
||||||
, start = Math.max(lineno - 3, 0)
|
|
||||||
, end = Math.min(lines.length, lineno + 3);
|
|
||||||
|
|
||||||
// Error context
|
|
||||||
var context = lines.slice(start, end).map(function(line, i){
|
|
||||||
var curr = i + start + 1;
|
|
||||||
return (curr == lineno ? ' >> ' : ' ')
|
|
||||||
+ curr
|
|
||||||
+ '| '
|
|
||||||
+ line;
|
|
||||||
}).join('\n');
|
|
||||||
|
|
||||||
// Alter exception message
|
|
||||||
err.path = filename;
|
|
||||||
err.message = (filename || 'ejs') + ':'
|
|
||||||
+ lineno + '\n'
|
|
||||||
+ context + '\n\n'
|
|
||||||
+ err.message;
|
|
||||||
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the given `str` of ejs, returning the function body.
|
|
||||||
*
|
|
||||||
* @param {String} str
|
|
||||||
* @return {String}
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
var parse = exports.parse = function(str, options){
|
|
||||||
var options = options || {}
|
|
||||||
, open = options.open || exports.open || '<%'
|
|
||||||
, close = options.close || exports.close || '%>';
|
|
||||||
|
|
||||||
var buf = [
|
|
||||||
"var buf = [];"
|
|
||||||
, "\nwith (locals) {"
|
|
||||||
, "\n buf.push('"
|
|
||||||
];
|
|
||||||
|
|
||||||
var lineno = 1;
|
|
||||||
|
|
||||||
for (var i = 0, len = str.length; i < len; ++i) {
|
|
||||||
if (str.slice(i, open.length + i) == open) {
|
|
||||||
i += open.length
|
|
||||||
|
|
||||||
var prefix, postfix, line = '__stack.lineno=' + lineno;
|
|
||||||
switch (str.substr(i, 1)) {
|
|
||||||
case '=':
|
|
||||||
prefix = "', escape((" + line + ', ';
|
|
||||||
postfix = ")), '";
|
|
||||||
++i;
|
|
||||||
break;
|
|
||||||
case '-':
|
|
||||||
prefix = "', (" + line + ', ';
|
|
||||||
postfix = "), '";
|
|
||||||
++i;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
prefix = "');" + line + ';';
|
|
||||||
postfix = "; buf.push('";
|
|
||||||
}
|
|
||||||
|
|
||||||
var end = str.indexOf(close, i)
|
|
||||||
, js = str.substring(i, end)
|
|
||||||
, start = i
|
|
||||||
, n = 0;
|
|
||||||
|
|
||||||
while (~(n = js.indexOf("\n", n))) n++, lineno++;
|
|
||||||
if (js.substr(0, 1) == ':') js = filtered(js);
|
|
||||||
buf.push(prefix, js, postfix);
|
|
||||||
i += end - start + close.length - 1;
|
|
||||||
|
|
||||||
} else if (str.substr(i, 1) == "\\") {
|
|
||||||
buf.push("\\\\");
|
|
||||||
} else if (str.substr(i, 1) == "'") {
|
|
||||||
buf.push("\\'");
|
|
||||||
} else if (str.substr(i, 1) == "\r") {
|
|
||||||
buf.push(" ");
|
|
||||||
} else if (str.substr(i, 1) == "\n") {
|
|
||||||
buf.push("\\n");
|
|
||||||
lineno++;
|
|
||||||
} else {
|
|
||||||
buf.push(str.substr(i, 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.push("');\n}\nreturn buf.join('');");
|
|
||||||
return buf.join('');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compile the given `str` of ejs into a `Function`.
|
|
||||||
*
|
|
||||||
* @param {String} str
|
|
||||||
* @param {Object} options
|
|
||||||
* @return {Function}
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
var compile = exports.compile = function(str, options){
|
|
||||||
options = options || {};
|
|
||||||
|
|
||||||
var input = JSON.stringify(str)
|
|
||||||
, filename = options.filename
|
|
||||||
? JSON.stringify(options.filename)
|
|
||||||
: 'undefined';
|
|
||||||
|
|
||||||
// Adds the fancy stack trace meta info
|
|
||||||
str = [
|
|
||||||
'var __stack = { lineno: 1, input: ' + input + ', filename: ' + filename + ' };',
|
|
||||||
rethrow.toString(),
|
|
||||||
'try {',
|
|
||||||
exports.parse(str, options),
|
|
||||||
'} catch (err) {',
|
|
||||||
' rethrow(err, __stack.input, __stack.filename, __stack.lineno);',
|
|
||||||
'}'
|
|
||||||
].join("\n");
|
|
||||||
|
|
||||||
if (options.debug) console.log(str);
|
|
||||||
var fn = new Function('locals, filters, escape', str);
|
|
||||||
return function(locals){
|
|
||||||
return fn.call(this, locals, filters, utils.escape);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render the given `str` of ejs.
|
|
||||||
*
|
|
||||||
* Options:
|
|
||||||
*
|
|
||||||
* - `locals` Local variables object
|
|
||||||
* - `cache` Compiled functions are cached, requires `filename`
|
|
||||||
* - `filename` Used by `cache` to key caches
|
|
||||||
* - `scope` Function execution context
|
|
||||||
* - `debug` Output generated function body
|
|
||||||
* - `open` Open tag, defaulting to "<%"
|
|
||||||
* - `close` Closing tag, defaulting to "%>"
|
|
||||||
*
|
|
||||||
* @param {String} str
|
|
||||||
* @param {Object} options
|
|
||||||
* @return {String}
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.render = function(str, options){
|
|
||||||
var fn
|
|
||||||
, options = options || {};
|
|
||||||
if (options.cache) {
|
|
||||||
if (options.filename) {
|
|
||||||
fn = cache[options.filename] || (cache[options.filename] = compile(str, options));
|
|
||||||
} else {
|
|
||||||
throw new Error('"cache" option requires "filename".');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fn = compile(str, options);
|
|
||||||
}
|
|
||||||
return fn.call(options.scope, options.locals || {});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expose to require().
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (require.extensions) {
|
|
||||||
require.extensions['.ejs'] = function(module, filename) {
|
|
||||||
source = require('fs').readFileSync(filename, 'utf-8');
|
|
||||||
module._compile(compile(source, {}), filename);
|
|
||||||
};
|
|
||||||
} else if (require.registerExtension) {
|
|
||||||
require.registerExtension('.ejs', function(src) {
|
|
||||||
return compile(src, {});
|
|
||||||
});
|
|
||||||
}
|
|
198
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/lib/filters.js
generated
vendored
198
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/lib/filters.js
generated
vendored
|
@ -1,198 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* EJS - Filters
|
|
||||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* First element of the target `obj`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.first = function(obj) {
|
|
||||||
return obj[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Last element of the target `obj`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.last = function(obj) {
|
|
||||||
return obj[obj.length - 1];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Capitalize the first letter of the target `str`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.capitalize = function(str){
|
|
||||||
str = String(str);
|
|
||||||
return str[0].toUpperCase() + str.substr(1, str.length);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Downcase the target `str`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.downcase = function(str){
|
|
||||||
return String(str).toLowerCase();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uppercase the target `str`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.upcase = function(str){
|
|
||||||
return String(str).toUpperCase();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort the target `obj`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.sort = function(obj){
|
|
||||||
return Object.create(obj).sort();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort the target `obj` by the given `prop` ascending.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.sort_by = function(obj, prop){
|
|
||||||
return Object.create(obj).sort(function(a, b){
|
|
||||||
a = a[prop], b = b[prop];
|
|
||||||
if (a > b) return 1;
|
|
||||||
if (a < b) return -1;
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Size or length of the target `obj`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.size = exports.length = function(obj) {
|
|
||||||
return obj.length;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add `a` and `b`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.plus = function(a, b){
|
|
||||||
return Number(a) + Number(b);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subtract `b` from `a`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.minus = function(a, b){
|
|
||||||
return Number(a) - Number(b);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Multiply `a` by `b`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.times = function(a, b){
|
|
||||||
return Number(a) * Number(b);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Divide `a` by `b`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.divided_by = function(a, b){
|
|
||||||
return Number(a) / Number(b);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Join `obj` with the given `str`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.join = function(obj, str){
|
|
||||||
return obj.join(str || ', ');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Truncate `str` to `len`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.truncate = function(str, len){
|
|
||||||
str = String(str);
|
|
||||||
return str.substr(0, len);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Truncate `str` to `n` words.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.truncate_words = function(str, n){
|
|
||||||
var str = String(str)
|
|
||||||
, words = str.split(/ +/);
|
|
||||||
return words.slice(0, n).join(' ');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replace `pattern` with `substitution` in `str`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.replace = function(str, pattern, substitution){
|
|
||||||
return String(str).replace(pattern, substitution || '');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepend `val` to `obj`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.prepend = function(obj, val){
|
|
||||||
return Array.isArray(obj)
|
|
||||||
? [val].concat(obj)
|
|
||||||
: val + obj;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append `val` to `obj`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.append = function(obj, val){
|
|
||||||
return Array.isArray(obj)
|
|
||||||
? obj.concat(val)
|
|
||||||
: obj + val;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map the given `prop`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.map = function(arr, prop){
|
|
||||||
return arr.map(function(obj){
|
|
||||||
return obj[prop];
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the given `obj`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.reverse = function(obj){
|
|
||||||
return Array.isArray(obj)
|
|
||||||
? obj.reverse()
|
|
||||||
: String(obj).split('').reverse().join('');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get `prop` of the given `obj`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.get = function(obj, prop){
|
|
||||||
return obj[prop];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Packs the given `obj` into json string
|
|
||||||
*/
|
|
||||||
exports.json = function(obj){
|
|
||||||
return JSON.stringify(obj);
|
|
||||||
};
|
|
23
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/lib/utils.js
generated
vendored
23
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/lib/utils.js
generated
vendored
|
@ -1,23 +0,0 @@
|
||||||
|
|
||||||
/*!
|
|
||||||
* EJS
|
|
||||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Escape the given string of `html`.
|
|
||||||
*
|
|
||||||
* @param {String} html
|
|
||||||
* @return {String}
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.escape = function(html){
|
|
||||||
return String(html)
|
|
||||||
.replace(/&(?!\w+;)/g, '&')
|
|
||||||
.replace(/</g, '<')
|
|
||||||
.replace(/>/g, '>')
|
|
||||||
.replace(/"/g, '"');
|
|
||||||
};
|
|
||||||
|
|
11
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/package.json
generated
vendored
11
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/package.json
generated
vendored
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"name": "ejs",
|
|
||||||
"description": "Embedded JavaScript templates",
|
|
||||||
"version": "0.4.3",
|
|
||||||
"author": "TJ Holowaychuk <tj@vision-media.ca>",
|
|
||||||
"keywords": ["template", "engine", "ejs"],
|
|
||||||
"devDependencies": {
|
|
||||||
"expresso": "0.9.2"
|
|
||||||
},
|
|
||||||
"main": "./lib/ejs.js"
|
|
||||||
}
|
|
173
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/support/compile.js
generated
vendored
173
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/support/compile.js
generated
vendored
|
@ -1,173 +0,0 @@
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Arguments.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var args = process.argv.slice(2)
|
|
||||||
, pending = args.length
|
|
||||||
, files = {};
|
|
||||||
|
|
||||||
console.log('');
|
|
||||||
|
|
||||||
// parse arguments
|
|
||||||
|
|
||||||
args.forEach(function(file){
|
|
||||||
var mod = file.replace('lib/', '');
|
|
||||||
fs.readFile(file, 'utf8', function(err, js){
|
|
||||||
if (err) throw err;
|
|
||||||
console.log(' \033[90mcompile : \033[0m\033[36m%s\033[0m', file);
|
|
||||||
files[file] = parse(js);
|
|
||||||
--pending || compile();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the given `js`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function parse(js) {
|
|
||||||
return parseInheritance(parseConditionals(js));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse __proto__.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function parseInheritance(js) {
|
|
||||||
return js
|
|
||||||
.replace(/^ *(\w+)\.prototype\.__proto__ * = *(\w+)\.prototype *;?/gm, function(_, child, parent){
|
|
||||||
return child + '.prototype = new ' + parent + ';\n'
|
|
||||||
+ child + '.prototype.constructor = '+ child + ';\n';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the given `js`, currently supporting:
|
|
||||||
*
|
|
||||||
* 'if' ['node' | 'browser']
|
|
||||||
* 'end'
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
function parseConditionals(js) {
|
|
||||||
var lines = js.split('\n')
|
|
||||||
, len = lines.length
|
|
||||||
, buffer = true
|
|
||||||
, browser = false
|
|
||||||
, buf = []
|
|
||||||
, line
|
|
||||||
, cond;
|
|
||||||
|
|
||||||
for (var i = 0; i < len; ++i) {
|
|
||||||
line = lines[i];
|
|
||||||
if (/^ *\/\/ *if *(node|browser)/gm.exec(line)) {
|
|
||||||
cond = RegExp.$1;
|
|
||||||
buffer = browser = 'browser' == cond;
|
|
||||||
} else if (/^ *\/\/ *end/.test(line)) {
|
|
||||||
buffer = true;
|
|
||||||
browser = false;
|
|
||||||
} else if (browser) {
|
|
||||||
buf.push(line.replace(/^( *)\/\//, '$1'));
|
|
||||||
} else if (buffer) {
|
|
||||||
buf.push(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf.join('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compile the files.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function compile() {
|
|
||||||
var buf = '';
|
|
||||||
buf += '\n// CommonJS require()\n\n';
|
|
||||||
buf += browser.require + '\n\n';
|
|
||||||
buf += 'require.modules = {};\n\n';
|
|
||||||
buf += 'require.resolve = ' + browser.resolve + ';\n\n';
|
|
||||||
buf += 'require.register = ' + browser.register + ';\n\n';
|
|
||||||
buf += 'require.relative = ' + browser.relative + ';\n\n';
|
|
||||||
args.forEach(function(file){
|
|
||||||
var js = files[file];
|
|
||||||
file = file.replace('lib/', '');
|
|
||||||
buf += '\nrequire.register("' + file + '", function(module, exports, require){\n';
|
|
||||||
buf += js;
|
|
||||||
buf += '\n}); // module: ' + file + '\n';
|
|
||||||
});
|
|
||||||
fs.writeFile('ejs.js', buf, function(err){
|
|
||||||
if (err) throw err;
|
|
||||||
console.log(' \033[90m create : \033[0m\033[36m%s\033[0m', 'ejs.js');
|
|
||||||
console.log();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// refactored version of weepy's
|
|
||||||
// https://github.com/weepy/brequire/blob/master/browser/brequire.js
|
|
||||||
|
|
||||||
var browser = {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Require a module.
|
|
||||||
*/
|
|
||||||
|
|
||||||
require: function require(p){
|
|
||||||
var path = require.resolve(p)
|
|
||||||
, mod = require.modules[path];
|
|
||||||
if (!mod) throw new Error('failed to require "' + p + '"');
|
|
||||||
if (!mod.exports) {
|
|
||||||
mod.exports = {};
|
|
||||||
mod.call(mod.exports, mod, mod.exports, require.relative(path));
|
|
||||||
}
|
|
||||||
return mod.exports;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolve module path.
|
|
||||||
*/
|
|
||||||
|
|
||||||
resolve: function(path){
|
|
||||||
var orig = path
|
|
||||||
, reg = path + '.js'
|
|
||||||
, index = path + '/index.js';
|
|
||||||
return require.modules[reg] && reg
|
|
||||||
|| require.modules[index] && index
|
|
||||||
|| orig;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return relative require().
|
|
||||||
*/
|
|
||||||
|
|
||||||
relative: function(parent) {
|
|
||||||
return function(p){
|
|
||||||
if ('.' != p.substr(0, 1)) return require(p);
|
|
||||||
|
|
||||||
var path = parent.split('/')
|
|
||||||
, segs = p.split('/');
|
|
||||||
path.pop();
|
|
||||||
|
|
||||||
for (var i = 0; i < segs.length; i++) {
|
|
||||||
var seg = segs[i];
|
|
||||||
if ('..' == seg) path.pop();
|
|
||||||
else if ('.' != seg) path.push(seg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return require(path.join('/'));
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a module.
|
|
||||||
*/
|
|
||||||
|
|
||||||
register: function(path, fn){
|
|
||||||
require.modules[path] = fn;
|
|
||||||
}
|
|
||||||
};
|
|
269
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/test/ejs.test.js
generated
vendored
269
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/ejs/test/ejs.test.js
generated
vendored
|
@ -1,269 +0,0 @@
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var ejs = require('../')
|
|
||||||
, assert = require('assert');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
'test .version': function(){
|
|
||||||
assert.ok(/^\d+\.\d+\.\d+$/.test(ejs.version), 'Test .version format');
|
|
||||||
},
|
|
||||||
|
|
||||||
'test html': function(){
|
|
||||||
assert.equal('<p>yay</p>', ejs.render('<p>yay</p>'));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test buffered code': function(){
|
|
||||||
var html = '<p>tj</p>',
|
|
||||||
str = '<p><%= name %></p>',
|
|
||||||
locals = { name: 'tj' };
|
|
||||||
assert.equal(html, ejs.render(str, { locals: locals }));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test unbuffered code': function(){
|
|
||||||
var html = '<p>tj</p>',
|
|
||||||
str = '<% if (name) { %><p><%= name %></p><% } %>',
|
|
||||||
locals = { name: 'tj' };
|
|
||||||
assert.equal(html, ejs.render(str, { locals: locals }));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test `scope` option': function(){
|
|
||||||
var html = '<p>tj</p>',
|
|
||||||
str = '<p><%= this %></p>';
|
|
||||||
assert.equal(html, ejs.render(str, { scope: 'tj' }));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test escaping': function(){
|
|
||||||
assert.equal('<script>', ejs.render('<%= "<script>" %>'));
|
|
||||||
assert.equal('<script>', ejs.render('<%- "<script>" %>'));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test newlines': function(){
|
|
||||||
var html = '\n<p>tj</p>\n<p>tj@sencha.com</p>',
|
|
||||||
str = '<% if (name) { %>\n<p><%= name %></p>\n<p><%= email %></p><% } %>',
|
|
||||||
locals = { name: 'tj', email: 'tj@sencha.com' };
|
|
||||||
assert.equal(html, ejs.render(str, { locals: locals }));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test single quotes': function(){
|
|
||||||
var html = '<p>WAHOO</p>',
|
|
||||||
str = "<p><%= up('wahoo') %></p>",
|
|
||||||
locals = { up: function(str){ return str.toUpperCase(); }};
|
|
||||||
assert.equal(html, ejs.render(str, { locals: locals }));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test single quotes in the html': function(){
|
|
||||||
var html = '<p>WAHOO that\'s cool</p>',
|
|
||||||
str = '<p><%= up(\'wahoo\') %> that\'s cool</p>',
|
|
||||||
locals = { up: function(str){ return str.toUpperCase(); }};
|
|
||||||
assert.equal(html, ejs.render(str, { locals: locals }));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test multiple single quotes': function() {
|
|
||||||
var html = "<p>couldn't shouldn't can't</p>",
|
|
||||||
str = "<p>couldn't shouldn't can't</p>";
|
|
||||||
assert.equal(html, ejs.render(str));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test single quotes inside tags': function() {
|
|
||||||
var html = '<p>string</p>',
|
|
||||||
str = "<p><%= 'string' %></p>";
|
|
||||||
assert.equal(html, ejs.render(str));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test back-slashes in the document': function() {
|
|
||||||
var html = "<p>backslash: '\\'</p>",
|
|
||||||
str = "<p>backslash: '\\'</p>";
|
|
||||||
assert.equal(html, ejs.render(str));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test double quotes': function(){
|
|
||||||
var html = '<p>WAHOO</p>',
|
|
||||||
str = '<p><%= up("wahoo") %></p>',
|
|
||||||
locals = { up: function(str){ return str.toUpperCase(); }};
|
|
||||||
assert.equal(html, ejs.render(str, { locals: locals }));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test multiple double quotes': function() {
|
|
||||||
var html = '<p>just a "test" wahoo</p>',
|
|
||||||
str = '<p>just a "test" wahoo</p>';
|
|
||||||
assert.equal(html, ejs.render(str));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test whitespace': function(){
|
|
||||||
var html = '<p>foo</p>',
|
|
||||||
str = '<p><%="foo"%></p>';
|
|
||||||
assert.equal(html, ejs.render(str));
|
|
||||||
|
|
||||||
var html = '<p>foo</p>',
|
|
||||||
str = '<p><%=bar%></p>';
|
|
||||||
assert.equal(html, ejs.render(str, { locals: { bar: 'foo' }}));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test custom tags': function(){
|
|
||||||
var html = '<p>foo</p>',
|
|
||||||
str = '<p>{{= "foo" }}</p>';
|
|
||||||
|
|
||||||
assert.equal(html, ejs.render(str, {
|
|
||||||
open: '{{',
|
|
||||||
close: '}}'
|
|
||||||
}));
|
|
||||||
|
|
||||||
var html = '<p>foo</p>',
|
|
||||||
str = '<p><?= "foo" ?></p>';
|
|
||||||
|
|
||||||
assert.equal(html, ejs.render(str, {
|
|
||||||
open: '<?',
|
|
||||||
close: '?>'
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test custom tags over 2 chars': function(){
|
|
||||||
var html = '<p>foo</p>',
|
|
||||||
str = '<p>{{{{= "foo" }>>}</p>';
|
|
||||||
|
|
||||||
assert.equal(html, ejs.render(str, {
|
|
||||||
open: '{{{{',
|
|
||||||
close: '}>>}'
|
|
||||||
}));
|
|
||||||
|
|
||||||
var html = '<p>foo</p>',
|
|
||||||
str = '<p><??= "foo" ??></p>';
|
|
||||||
|
|
||||||
assert.equal(html, ejs.render(str, {
|
|
||||||
open: '<??',
|
|
||||||
close: '??>'
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test global custom tags': function(){
|
|
||||||
var html = '<p>foo</p>',
|
|
||||||
str = '<p>{{= "foo" }}</p>';
|
|
||||||
ejs.open = '{{';
|
|
||||||
ejs.close = '}}';
|
|
||||||
assert.equal(html, ejs.render(str));
|
|
||||||
delete ejs.open;
|
|
||||||
delete ejs.close;
|
|
||||||
},
|
|
||||||
|
|
||||||
'test iteration': function(){
|
|
||||||
var html = '<p>foo</p>',
|
|
||||||
str = '<% for (var key in items) { %>'
|
|
||||||
+ '<p><%= items[key] %></p>'
|
|
||||||
+ '<% } %>';
|
|
||||||
assert.equal(html, ejs.render(str, {
|
|
||||||
locals: {
|
|
||||||
items: ['foo']
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
var html = '<p>foo</p>',
|
|
||||||
str = '<% items.forEach(function(item){ %>'
|
|
||||||
+ '<p><%= item %></p>'
|
|
||||||
+ '<% }) %>';
|
|
||||||
assert.equal(html, ejs.render(str, {
|
|
||||||
locals: {
|
|
||||||
items: ['foo']
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test filter support': function(){
|
|
||||||
var html = 'Zab',
|
|
||||||
str = '<%=: items | reverse | first | reverse | capitalize %>';
|
|
||||||
assert.equal(html, ejs.render(str, {
|
|
||||||
locals: {
|
|
||||||
items: ['foo', 'bar', 'baz']
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test filter argument support': function(){
|
|
||||||
var html = 'tj, guillermo',
|
|
||||||
str = '<%=: users | map:"name" | join:", " %>';
|
|
||||||
assert.equal(html, ejs.render(str, {
|
|
||||||
locals: {
|
|
||||||
users: [
|
|
||||||
{ name: 'tj' },
|
|
||||||
{ name: 'guillermo' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test sort_by filter': function(){
|
|
||||||
var html = 'tj',
|
|
||||||
str = '<%=: users | sort_by:"name" | last | get:"name" %>';
|
|
||||||
assert.equal(html, ejs.render(str, {
|
|
||||||
locals: {
|
|
||||||
users: [
|
|
||||||
{ name: 'guillermo' },
|
|
||||||
{ name: 'tj' },
|
|
||||||
{ name: 'mape' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test custom filters': function(){
|
|
||||||
var html = 'Welcome Tj Holowaychuk',
|
|
||||||
str = '<%=: users | first | greeting %>';
|
|
||||||
|
|
||||||
ejs.filters.greeting = function(user){
|
|
||||||
return 'Welcome ' + user.first + ' ' + user.last + '';
|
|
||||||
};
|
|
||||||
|
|
||||||
assert.equal(html, ejs.render(str, {
|
|
||||||
locals: {
|
|
||||||
users: [
|
|
||||||
{ first: 'Tj', last: 'Holowaychuk' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
'test useful stack traces': function(){
|
|
||||||
var str = [
|
|
||||||
"A little somethin'",
|
|
||||||
"somethin'",
|
|
||||||
"<% if (name) { %>", // Failing line
|
|
||||||
" <p><%= name %></p>",
|
|
||||||
" <p><%= email %></p>",
|
|
||||||
"<% } %>"
|
|
||||||
].join("\n");
|
|
||||||
|
|
||||||
try {
|
|
||||||
ejs.render(str)
|
|
||||||
} catch( err ){
|
|
||||||
assert.includes(err.message,"name is not defined");
|
|
||||||
assert.eql(err.name,"ReferenceError");
|
|
||||||
var lineno = parseInt(err.toString().match(/ejs:(\d+)\n/)[1]);
|
|
||||||
assert.eql(lineno,3,"Error should been thrown on line 3, was thrown on line "+lineno);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
'test useful stack traces multiline': function(){
|
|
||||||
var str = [
|
|
||||||
"A little somethin'",
|
|
||||||
"somethin'",
|
|
||||||
"<% var some = 'pretty';",
|
|
||||||
" var multiline = 'javascript';",
|
|
||||||
"%>",
|
|
||||||
"<% if (name) { %>", // Failing line
|
|
||||||
" <p><%= name %></p>",
|
|
||||||
" <p><%= email %></p>",
|
|
||||||
"<% } %>"
|
|
||||||
].join("\n");
|
|
||||||
|
|
||||||
try {
|
|
||||||
ejs.render(str)
|
|
||||||
} catch( err ){
|
|
||||||
assert.includes(err.message,"name is not defined");
|
|
||||||
assert.eql(err.name,"ReferenceError");
|
|
||||||
var lineno = parseInt(err.toString().match(/ejs:(\d+)\n/)[1]);
|
|
||||||
assert.eql(lineno,6,"Error should been thrown on line 3, was thrown on line "+lineno);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
481
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/json2.js
generated
vendored
481
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/deps/json2.js
generated
vendored
|
@ -1,481 +0,0 @@
|
||||||
/*
|
|
||||||
http://www.JSON.org/json2.js
|
|
||||||
2010-11-17
|
|
||||||
|
|
||||||
Public Domain.
|
|
||||||
|
|
||||||
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
|
||||||
|
|
||||||
See http://www.JSON.org/js.html
|
|
||||||
|
|
||||||
|
|
||||||
This code should be minified before deployment.
|
|
||||||
See http://javascript.crockford.com/jsmin.html
|
|
||||||
|
|
||||||
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
|
|
||||||
NOT CONTROL.
|
|
||||||
|
|
||||||
|
|
||||||
This file creates a global JSON object containing two methods: stringify
|
|
||||||
and parse.
|
|
||||||
|
|
||||||
JSON.stringify(value, replacer, space)
|
|
||||||
value any JavaScript value, usually an object or array.
|
|
||||||
|
|
||||||
replacer an optional parameter that determines how object
|
|
||||||
values are stringified for objects. It can be a
|
|
||||||
function or an array of strings.
|
|
||||||
|
|
||||||
space an optional parameter that specifies the indentation
|
|
||||||
of nested structures. If it is omitted, the text will
|
|
||||||
be packed without extra whitespace. If it is a number,
|
|
||||||
it will specify the number of spaces to indent at each
|
|
||||||
level. If it is a string (such as '\t' or ' '),
|
|
||||||
it contains the characters used to indent at each level.
|
|
||||||
|
|
||||||
This method produces a JSON text from a JavaScript value.
|
|
||||||
|
|
||||||
When an object value is found, if the object contains a toJSON
|
|
||||||
method, its toJSON method will be called and the result will be
|
|
||||||
stringified. A toJSON method does not serialize: it returns the
|
|
||||||
value represented by the name/value pair that should be serialized,
|
|
||||||
or undefined if nothing should be serialized. The toJSON method
|
|
||||||
will be passed the key associated with the value, and this will be
|
|
||||||
bound to the value
|
|
||||||
|
|
||||||
For example, this would serialize Dates as ISO strings.
|
|
||||||
|
|
||||||
Date.prototype.toJSON = function (key) {
|
|
||||||
function f(n) {
|
|
||||||
// Format integers to have at least two digits.
|
|
||||||
return n < 10 ? '0' + n : n;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.getUTCFullYear() + '-' +
|
|
||||||
f(this.getUTCMonth() + 1) + '-' +
|
|
||||||
f(this.getUTCDate()) + 'T' +
|
|
||||||
f(this.getUTCHours()) + ':' +
|
|
||||||
f(this.getUTCMinutes()) + ':' +
|
|
||||||
f(this.getUTCSeconds()) + 'Z';
|
|
||||||
};
|
|
||||||
|
|
||||||
You can provide an optional replacer method. It will be passed the
|
|
||||||
key and value of each member, with this bound to the containing
|
|
||||||
object. The value that is returned from your method will be
|
|
||||||
serialized. If your method returns undefined, then the member will
|
|
||||||
be excluded from the serialization.
|
|
||||||
|
|
||||||
If the replacer parameter is an array of strings, then it will be
|
|
||||||
used to select the members to be serialized. It filters the results
|
|
||||||
such that only members with keys listed in the replacer array are
|
|
||||||
stringified.
|
|
||||||
|
|
||||||
Values that do not have JSON representations, such as undefined or
|
|
||||||
functions, will not be serialized. Such values in objects will be
|
|
||||||
dropped; in arrays they will be replaced with null. You can use
|
|
||||||
a replacer function to replace those with JSON values.
|
|
||||||
JSON.stringify(undefined) returns undefined.
|
|
||||||
|
|
||||||
The optional space parameter produces a stringification of the
|
|
||||||
value that is filled with line breaks and indentation to make it
|
|
||||||
easier to read.
|
|
||||||
|
|
||||||
If the space parameter is a non-empty string, then that string will
|
|
||||||
be used for indentation. If the space parameter is a number, then
|
|
||||||
the indentation will be that many spaces.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
text = JSON.stringify(['e', {pluribus: 'unum'}]);
|
|
||||||
// text is '["e",{"pluribus":"unum"}]'
|
|
||||||
|
|
||||||
|
|
||||||
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
|
|
||||||
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
|
|
||||||
|
|
||||||
text = JSON.stringify([new Date()], function (key, value) {
|
|
||||||
return this[key] instanceof Date ?
|
|
||||||
'Date(' + this[key] + ')' : value;
|
|
||||||
});
|
|
||||||
// text is '["Date(---current time---)"]'
|
|
||||||
|
|
||||||
|
|
||||||
JSON.parse(text, reviver)
|
|
||||||
This method parses a JSON text to produce an object or array.
|
|
||||||
It can throw a SyntaxError exception.
|
|
||||||
|
|
||||||
The optional reviver parameter is a function that can filter and
|
|
||||||
transform the results. It receives each of the keys and values,
|
|
||||||
and its return value is used instead of the original value.
|
|
||||||
If it returns what it received, then the structure is not modified.
|
|
||||||
If it returns undefined then the member is deleted.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
// Parse the text. Values that look like ISO date strings will
|
|
||||||
// be converted to Date objects.
|
|
||||||
|
|
||||||
myData = JSON.parse(text, function (key, value) {
|
|
||||||
var a;
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
a =
|
|
||||||
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
|
|
||||||
if (a) {
|
|
||||||
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
|
|
||||||
+a[5], +a[6]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
});
|
|
||||||
|
|
||||||
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
|
|
||||||
var d;
|
|
||||||
if (typeof value === 'string' &&
|
|
||||||
value.slice(0, 5) === 'Date(' &&
|
|
||||||
value.slice(-1) === ')') {
|
|
||||||
d = new Date(value.slice(5, -1));
|
|
||||||
if (d) {
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
This is a reference implementation. You are free to copy, modify, or
|
|
||||||
redistribute.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*jslint evil: true, strict: false, regexp: false */
|
|
||||||
|
|
||||||
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
|
|
||||||
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
|
|
||||||
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
|
|
||||||
lastIndex, length, parse, prototype, push, replace, slice, stringify,
|
|
||||||
test, toJSON, toString, valueOf
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// Create a JSON object only if one does not already exist. We create the
|
|
||||||
// methods in a closure to avoid creating global variables.
|
|
||||||
|
|
||||||
var JSON = {};
|
|
||||||
|
|
||||||
(function () {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
function f(n) {
|
|
||||||
// Format integers to have at least two digits.
|
|
||||||
return n < 10 ? '0' + n : n;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof Date.prototype.toJSON !== 'function') {
|
|
||||||
|
|
||||||
Date.prototype.toJSON = function (key) {
|
|
||||||
|
|
||||||
return isFinite(this.valueOf()) ?
|
|
||||||
this.getUTCFullYear() + '-' +
|
|
||||||
f(this.getUTCMonth() + 1) + '-' +
|
|
||||||
f(this.getUTCDate()) + 'T' +
|
|
||||||
f(this.getUTCHours()) + ':' +
|
|
||||||
f(this.getUTCMinutes()) + ':' +
|
|
||||||
f(this.getUTCSeconds()) + 'Z' : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
String.prototype.toJSON =
|
|
||||||
Number.prototype.toJSON =
|
|
||||||
Boolean.prototype.toJSON = function (key) {
|
|
||||||
return this.valueOf();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
|
||||||
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
|
||||||
gap,
|
|
||||||
indent,
|
|
||||||
meta = { // table of character substitutions
|
|
||||||
'\b': '\\b',
|
|
||||||
'\t': '\\t',
|
|
||||||
'\n': '\\n',
|
|
||||||
'\f': '\\f',
|
|
||||||
'\r': '\\r',
|
|
||||||
'"' : '\\"',
|
|
||||||
'\\': '\\\\'
|
|
||||||
},
|
|
||||||
rep;
|
|
||||||
|
|
||||||
|
|
||||||
function quote(string) {
|
|
||||||
|
|
||||||
// If the string contains no control characters, no quote characters, and no
|
|
||||||
// backslash characters, then we can safely slap some quotes around it.
|
|
||||||
// Otherwise we must also replace the offending characters with safe escape
|
|
||||||
// sequences.
|
|
||||||
|
|
||||||
escapable.lastIndex = 0;
|
|
||||||
return escapable.test(string) ?
|
|
||||||
'"' + string.replace(escapable, function (a) {
|
|
||||||
var c = meta[a];
|
|
||||||
return typeof c === 'string' ? c :
|
|
||||||
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
|
||||||
}) + '"' :
|
|
||||||
'"' + string + '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function str(key, holder) {
|
|
||||||
|
|
||||||
// Produce a string from holder[key].
|
|
||||||
|
|
||||||
var i, // The loop counter.
|
|
||||||
k, // The member key.
|
|
||||||
v, // The member value.
|
|
||||||
length,
|
|
||||||
mind = gap,
|
|
||||||
partial,
|
|
||||||
value = holder[key];
|
|
||||||
|
|
||||||
// If the value has a toJSON method, call it to obtain a replacement value.
|
|
||||||
|
|
||||||
if (value && typeof value === 'object' &&
|
|
||||||
typeof value.toJSON === 'function') {
|
|
||||||
value = value.toJSON(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we were called with a replacer function, then call the replacer to
|
|
||||||
// obtain a replacement value.
|
|
||||||
|
|
||||||
if (typeof rep === 'function') {
|
|
||||||
value = rep.call(holder, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// What happens next depends on the value's type.
|
|
||||||
|
|
||||||
switch (typeof value) {
|
|
||||||
case 'string':
|
|
||||||
return quote(value);
|
|
||||||
|
|
||||||
case 'number':
|
|
||||||
|
|
||||||
// JSON numbers must be finite. Encode non-finite numbers as null.
|
|
||||||
|
|
||||||
return isFinite(value) ? String(value) : 'null';
|
|
||||||
|
|
||||||
case 'boolean':
|
|
||||||
case 'null':
|
|
||||||
|
|
||||||
// If the value is a boolean or null, convert it to a string. Note:
|
|
||||||
// typeof null does not produce 'null'. The case is included here in
|
|
||||||
// the remote chance that this gets fixed someday.
|
|
||||||
|
|
||||||
return String(value);
|
|
||||||
|
|
||||||
// If the type is 'object', we might be dealing with an object or an array or
|
|
||||||
// null.
|
|
||||||
|
|
||||||
case 'object':
|
|
||||||
|
|
||||||
// Due to a specification blunder in ECMAScript, typeof null is 'object',
|
|
||||||
// so watch out for that case.
|
|
||||||
|
|
||||||
if (!value) {
|
|
||||||
return 'null';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make an array to hold the partial results of stringifying this object value.
|
|
||||||
|
|
||||||
gap += indent;
|
|
||||||
partial = [];
|
|
||||||
|
|
||||||
// Is the value an array?
|
|
||||||
|
|
||||||
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
|
||||||
|
|
||||||
// The value is an array. Stringify every element. Use null as a placeholder
|
|
||||||
// for non-JSON values.
|
|
||||||
|
|
||||||
length = value.length;
|
|
||||||
for (i = 0; i < length; i += 1) {
|
|
||||||
partial[i] = str(i, value) || 'null';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join all of the elements together, separated with commas, and wrap them in
|
|
||||||
// brackets.
|
|
||||||
|
|
||||||
v = partial.length === 0 ? '[]' :
|
|
||||||
gap ? '[\n' + gap +
|
|
||||||
partial.join(',\n' + gap) + '\n' +
|
|
||||||
mind + ']' :
|
|
||||||
'[' + partial.join(',') + ']';
|
|
||||||
gap = mind;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the replacer is an array, use it to select the members to be stringified.
|
|
||||||
|
|
||||||
if (rep && typeof rep === 'object') {
|
|
||||||
length = rep.length;
|
|
||||||
for (i = 0; i < length; i += 1) {
|
|
||||||
k = rep[i];
|
|
||||||
if (typeof k === 'string') {
|
|
||||||
v = str(k, value);
|
|
||||||
if (v) {
|
|
||||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Otherwise, iterate through all of the keys in the object.
|
|
||||||
|
|
||||||
for (k in value) {
|
|
||||||
if (Object.hasOwnProperty.call(value, k)) {
|
|
||||||
v = str(k, value);
|
|
||||||
if (v) {
|
|
||||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join all of the member texts together, separated with commas,
|
|
||||||
// and wrap them in braces.
|
|
||||||
|
|
||||||
v = partial.length === 0 ? '{}' :
|
|
||||||
gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
|
|
||||||
mind + '}' : '{' + partial.join(',') + '}';
|
|
||||||
gap = mind;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the JSON object does not yet have a stringify method, give it one.
|
|
||||||
|
|
||||||
if (typeof JSON.stringify !== 'function') {
|
|
||||||
JSON.stringify = function (value, replacer, space) {
|
|
||||||
|
|
||||||
// The stringify method takes a value and an optional replacer, and an optional
|
|
||||||
// space parameter, and returns a JSON text. The replacer can be a function
|
|
||||||
// that can replace values, or an array of strings that will select the keys.
|
|
||||||
// A default replacer method can be provided. Use of the space parameter can
|
|
||||||
// produce text that is more easily readable.
|
|
||||||
|
|
||||||
var i;
|
|
||||||
gap = '';
|
|
||||||
indent = '';
|
|
||||||
|
|
||||||
// If the space parameter is a number, make an indent string containing that
|
|
||||||
// many spaces.
|
|
||||||
|
|
||||||
if (typeof space === 'number') {
|
|
||||||
for (i = 0; i < space; i += 1) {
|
|
||||||
indent += ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the space parameter is a string, it will be used as the indent string.
|
|
||||||
|
|
||||||
} else if (typeof space === 'string') {
|
|
||||||
indent = space;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is a replacer, it must be a function or an array.
|
|
||||||
// Otherwise, throw an error.
|
|
||||||
|
|
||||||
rep = replacer;
|
|
||||||
if (replacer && typeof replacer !== 'function' &&
|
|
||||||
(typeof replacer !== 'object' ||
|
|
||||||
typeof replacer.length !== 'number')) {
|
|
||||||
throw new Error('JSON.stringify');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a fake root object containing our value under the key of ''.
|
|
||||||
// Return the result of stringifying the value.
|
|
||||||
|
|
||||||
return str('', {'': value});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// If the JSON object does not yet have a parse method, give it one.
|
|
||||||
|
|
||||||
if (typeof JSON.parse !== 'function') {
|
|
||||||
JSON.parse = function (text, reviver) {
|
|
||||||
|
|
||||||
// The parse method takes a text and an optional reviver function, and returns
|
|
||||||
// a JavaScript value if the text is a valid JSON text.
|
|
||||||
|
|
||||||
var j;
|
|
||||||
|
|
||||||
function walk(holder, key) {
|
|
||||||
|
|
||||||
// The walk method is used to recursively walk the resulting structure so
|
|
||||||
// that modifications can be made.
|
|
||||||
|
|
||||||
var k, v, value = holder[key];
|
|
||||||
if (value && typeof value === 'object') {
|
|
||||||
for (k in value) {
|
|
||||||
if (Object.hasOwnProperty.call(value, k)) {
|
|
||||||
v = walk(value, k);
|
|
||||||
if (v !== undefined) {
|
|
||||||
value[k] = v;
|
|
||||||
} else {
|
|
||||||
delete value[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return reviver.call(holder, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Parsing happens in four stages. In the first stage, we replace certain
|
|
||||||
// Unicode characters with escape sequences. JavaScript handles many characters
|
|
||||||
// incorrectly, either silently deleting them, or treating them as line endings.
|
|
||||||
|
|
||||||
text = String(text);
|
|
||||||
cx.lastIndex = 0;
|
|
||||||
if (cx.test(text)) {
|
|
||||||
text = text.replace(cx, function (a) {
|
|
||||||
return '\\u' +
|
|
||||||
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// In the second stage, we run the text against regular expressions that look
|
|
||||||
// for non-JSON patterns. We are especially concerned with '()' and 'new'
|
|
||||||
// because they can cause invocation, and '=' because it can cause mutation.
|
|
||||||
// But just to be safe, we want to reject all unexpected forms.
|
|
||||||
|
|
||||||
// We split the second stage into 4 regexp operations in order to work around
|
|
||||||
// crippling inefficiencies in IE's and Safari's regexp engines. First we
|
|
||||||
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
|
|
||||||
// replace all simple value tokens with ']' characters. Third, we delete all
|
|
||||||
// open brackets that follow a colon or comma or that begin the text. Finally,
|
|
||||||
// we look to see that the remaining characters are only whitespace or ']' or
|
|
||||||
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
|
|
||||||
|
|
||||||
if (/^[\],:{}\s]*$/
|
|
||||||
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
|
|
||||||
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
|
|
||||||
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
|
||||||
|
|
||||||
// In the third stage we use the eval function to compile the text into a
|
|
||||||
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
|
||||||
// in JavaScript: it can begin a block or an object literal. We wrap the text
|
|
||||||
// in parens to eliminate the ambiguity.
|
|
||||||
|
|
||||||
j = eval('(' + text + ')');
|
|
||||||
|
|
||||||
// In the optional fourth stage, we recursively walk the new structure, passing
|
|
||||||
// each name/value pair to a reviver function for possible transformation.
|
|
||||||
|
|
||||||
return typeof reviver === 'function' ?
|
|
||||||
walk({'': j}, '') : j;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the text is not JSON parseable, then a SyntaxError is thrown.
|
|
||||||
|
|
||||||
throw new SyntaxError('JSON.parse');
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}());
|
|
|
@ -1,70 +0,0 @@
|
||||||
/*!
|
|
||||||
* Styles taken from qunit.css
|
|
||||||
*/
|
|
||||||
|
|
||||||
h1#nodeunit-header, h1.nodeunit-header {
|
|
||||||
padding: 15px;
|
|
||||||
font-size: large;
|
|
||||||
background-color: #06b;
|
|
||||||
color: white;
|
|
||||||
font-family: 'trebuchet ms', verdana, arial;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1#nodeunit-header a {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2#nodeunit-banner {
|
|
||||||
height: 2em;
|
|
||||||
border-bottom: 1px solid white;
|
|
||||||
background-color: #eee;
|
|
||||||
margin: 0;
|
|
||||||
font-family: 'trebuchet ms', verdana, arial;
|
|
||||||
}
|
|
||||||
h2#nodeunit-banner.pass {
|
|
||||||
background-color: green;
|
|
||||||
}
|
|
||||||
h2#nodeunit-banner.fail {
|
|
||||||
background-color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2#nodeunit-userAgent, h2.nodeunit-userAgent {
|
|
||||||
padding: 10px;
|
|
||||||
background-color: #eee;
|
|
||||||
color: black;
|
|
||||||
margin: 0;
|
|
||||||
font-size: small;
|
|
||||||
font-weight: normal;
|
|
||||||
font-family: 'trebuchet ms', verdana, arial;
|
|
||||||
font-size: 10pt;
|
|
||||||
}
|
|
||||||
|
|
||||||
div#nodeunit-testrunner-toolbar {
|
|
||||||
background: #eee;
|
|
||||||
border-top: 1px solid black;
|
|
||||||
padding: 10px;
|
|
||||||
font-family: 'trebuchet ms', verdana, arial;
|
|
||||||
margin: 0;
|
|
||||||
font-size: 10pt;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol#nodeunit-tests {
|
|
||||||
font-family: 'trebuchet ms', verdana, arial;
|
|
||||||
font-size: 10pt;
|
|
||||||
}
|
|
||||||
ol#nodeunit-tests li strong {
|
|
||||||
cursor:pointer;
|
|
||||||
}
|
|
||||||
ol#nodeunit-tests .pass {
|
|
||||||
color: green;
|
|
||||||
}
|
|
||||||
ol#nodeunit-tests .fail {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
p#nodeunit-testresult {
|
|
||||||
margin-left: 1em;
|
|
||||||
font-size: 10pt;
|
|
||||||
font-family: 'trebuchet ms', verdana, arial;
|
|
||||||
}
|
|
2117
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/dist/browser/nodeunit.js
generated
vendored
2117
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/dist/browser/nodeunit.js
generated
vendored
|
@ -1,2117 +0,0 @@
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* https://github.com/caolan/nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*
|
|
||||||
* json2.js
|
|
||||||
* http://www.JSON.org/json2.js
|
|
||||||
* Public Domain.
|
|
||||||
* NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
|
||||||
*/
|
|
||||||
nodeunit = (function(){
|
|
||||||
/*
|
|
||||||
http://www.JSON.org/json2.js
|
|
||||||
2010-11-17
|
|
||||||
|
|
||||||
Public Domain.
|
|
||||||
|
|
||||||
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
|
||||||
|
|
||||||
See http://www.JSON.org/js.html
|
|
||||||
|
|
||||||
|
|
||||||
This code should be minified before deployment.
|
|
||||||
See http://javascript.crockford.com/jsmin.html
|
|
||||||
|
|
||||||
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
|
|
||||||
NOT CONTROL.
|
|
||||||
|
|
||||||
|
|
||||||
This file creates a global JSON object containing two methods: stringify
|
|
||||||
and parse.
|
|
||||||
|
|
||||||
JSON.stringify(value, replacer, space)
|
|
||||||
value any JavaScript value, usually an object or array.
|
|
||||||
|
|
||||||
replacer an optional parameter that determines how object
|
|
||||||
values are stringified for objects. It can be a
|
|
||||||
function or an array of strings.
|
|
||||||
|
|
||||||
space an optional parameter that specifies the indentation
|
|
||||||
of nested structures. If it is omitted, the text will
|
|
||||||
be packed without extra whitespace. If it is a number,
|
|
||||||
it will specify the number of spaces to indent at each
|
|
||||||
level. If it is a string (such as '\t' or ' '),
|
|
||||||
it contains the characters used to indent at each level.
|
|
||||||
|
|
||||||
This method produces a JSON text from a JavaScript value.
|
|
||||||
|
|
||||||
When an object value is found, if the object contains a toJSON
|
|
||||||
method, its toJSON method will be called and the result will be
|
|
||||||
stringified. A toJSON method does not serialize: it returns the
|
|
||||||
value represented by the name/value pair that should be serialized,
|
|
||||||
or undefined if nothing should be serialized. The toJSON method
|
|
||||||
will be passed the key associated with the value, and this will be
|
|
||||||
bound to the value
|
|
||||||
|
|
||||||
For example, this would serialize Dates as ISO strings.
|
|
||||||
|
|
||||||
Date.prototype.toJSON = function (key) {
|
|
||||||
function f(n) {
|
|
||||||
// Format integers to have at least two digits.
|
|
||||||
return n < 10 ? '0' + n : n;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.getUTCFullYear() + '-' +
|
|
||||||
f(this.getUTCMonth() + 1) + '-' +
|
|
||||||
f(this.getUTCDate()) + 'T' +
|
|
||||||
f(this.getUTCHours()) + ':' +
|
|
||||||
f(this.getUTCMinutes()) + ':' +
|
|
||||||
f(this.getUTCSeconds()) + 'Z';
|
|
||||||
};
|
|
||||||
|
|
||||||
You can provide an optional replacer method. It will be passed the
|
|
||||||
key and value of each member, with this bound to the containing
|
|
||||||
object. The value that is returned from your method will be
|
|
||||||
serialized. If your method returns undefined, then the member will
|
|
||||||
be excluded from the serialization.
|
|
||||||
|
|
||||||
If the replacer parameter is an array of strings, then it will be
|
|
||||||
used to select the members to be serialized. It filters the results
|
|
||||||
such that only members with keys listed in the replacer array are
|
|
||||||
stringified.
|
|
||||||
|
|
||||||
Values that do not have JSON representations, such as undefined or
|
|
||||||
functions, will not be serialized. Such values in objects will be
|
|
||||||
dropped; in arrays they will be replaced with null. You can use
|
|
||||||
a replacer function to replace those with JSON values.
|
|
||||||
JSON.stringify(undefined) returns undefined.
|
|
||||||
|
|
||||||
The optional space parameter produces a stringification of the
|
|
||||||
value that is filled with line breaks and indentation to make it
|
|
||||||
easier to read.
|
|
||||||
|
|
||||||
If the space parameter is a non-empty string, then that string will
|
|
||||||
be used for indentation. If the space parameter is a number, then
|
|
||||||
the indentation will be that many spaces.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
text = JSON.stringify(['e', {pluribus: 'unum'}]);
|
|
||||||
// text is '["e",{"pluribus":"unum"}]'
|
|
||||||
|
|
||||||
|
|
||||||
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
|
|
||||||
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
|
|
||||||
|
|
||||||
text = JSON.stringify([new Date()], function (key, value) {
|
|
||||||
return this[key] instanceof Date ?
|
|
||||||
'Date(' + this[key] + ')' : value;
|
|
||||||
});
|
|
||||||
// text is '["Date(---current time---)"]'
|
|
||||||
|
|
||||||
|
|
||||||
JSON.parse(text, reviver)
|
|
||||||
This method parses a JSON text to produce an object or array.
|
|
||||||
It can throw a SyntaxError exception.
|
|
||||||
|
|
||||||
The optional reviver parameter is a function that can filter and
|
|
||||||
transform the results. It receives each of the keys and values,
|
|
||||||
and its return value is used instead of the original value.
|
|
||||||
If it returns what it received, then the structure is not modified.
|
|
||||||
If it returns undefined then the member is deleted.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
// Parse the text. Values that look like ISO date strings will
|
|
||||||
// be converted to Date objects.
|
|
||||||
|
|
||||||
myData = JSON.parse(text, function (key, value) {
|
|
||||||
var a;
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
a =
|
|
||||||
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
|
|
||||||
if (a) {
|
|
||||||
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
|
|
||||||
+a[5], +a[6]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
});
|
|
||||||
|
|
||||||
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
|
|
||||||
var d;
|
|
||||||
if (typeof value === 'string' &&
|
|
||||||
value.slice(0, 5) === 'Date(' &&
|
|
||||||
value.slice(-1) === ')') {
|
|
||||||
d = new Date(value.slice(5, -1));
|
|
||||||
if (d) {
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
This is a reference implementation. You are free to copy, modify, or
|
|
||||||
redistribute.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*jslint evil: true, strict: false, regexp: false */
|
|
||||||
|
|
||||||
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
|
|
||||||
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
|
|
||||||
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
|
|
||||||
lastIndex, length, parse, prototype, push, replace, slice, stringify,
|
|
||||||
test, toJSON, toString, valueOf
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// Create a JSON object only if one does not already exist. We create the
|
|
||||||
// methods in a closure to avoid creating global variables.
|
|
||||||
|
|
||||||
var JSON = {};
|
|
||||||
|
|
||||||
(function () {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
function f(n) {
|
|
||||||
// Format integers to have at least two digits.
|
|
||||||
return n < 10 ? '0' + n : n;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof Date.prototype.toJSON !== 'function') {
|
|
||||||
|
|
||||||
Date.prototype.toJSON = function (key) {
|
|
||||||
|
|
||||||
return isFinite(this.valueOf()) ?
|
|
||||||
this.getUTCFullYear() + '-' +
|
|
||||||
f(this.getUTCMonth() + 1) + '-' +
|
|
||||||
f(this.getUTCDate()) + 'T' +
|
|
||||||
f(this.getUTCHours()) + ':' +
|
|
||||||
f(this.getUTCMinutes()) + ':' +
|
|
||||||
f(this.getUTCSeconds()) + 'Z' : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
String.prototype.toJSON =
|
|
||||||
Number.prototype.toJSON =
|
|
||||||
Boolean.prototype.toJSON = function (key) {
|
|
||||||
return this.valueOf();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
|
||||||
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
|
||||||
gap,
|
|
||||||
indent,
|
|
||||||
meta = { // table of character substitutions
|
|
||||||
'\b': '\\b',
|
|
||||||
'\t': '\\t',
|
|
||||||
'\n': '\\n',
|
|
||||||
'\f': '\\f',
|
|
||||||
'\r': '\\r',
|
|
||||||
'"' : '\\"',
|
|
||||||
'\\': '\\\\'
|
|
||||||
},
|
|
||||||
rep;
|
|
||||||
|
|
||||||
|
|
||||||
function quote(string) {
|
|
||||||
|
|
||||||
// If the string contains no control characters, no quote characters, and no
|
|
||||||
// backslash characters, then we can safely slap some quotes around it.
|
|
||||||
// Otherwise we must also replace the offending characters with safe escape
|
|
||||||
// sequences.
|
|
||||||
|
|
||||||
escapable.lastIndex = 0;
|
|
||||||
return escapable.test(string) ?
|
|
||||||
'"' + string.replace(escapable, function (a) {
|
|
||||||
var c = meta[a];
|
|
||||||
return typeof c === 'string' ? c :
|
|
||||||
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
|
||||||
}) + '"' :
|
|
||||||
'"' + string + '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function str(key, holder) {
|
|
||||||
|
|
||||||
// Produce a string from holder[key].
|
|
||||||
|
|
||||||
var i, // The loop counter.
|
|
||||||
k, // The member key.
|
|
||||||
v, // The member value.
|
|
||||||
length,
|
|
||||||
mind = gap,
|
|
||||||
partial,
|
|
||||||
value = holder[key];
|
|
||||||
|
|
||||||
// If the value has a toJSON method, call it to obtain a replacement value.
|
|
||||||
|
|
||||||
if (value && typeof value === 'object' &&
|
|
||||||
typeof value.toJSON === 'function') {
|
|
||||||
value = value.toJSON(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we were called with a replacer function, then call the replacer to
|
|
||||||
// obtain a replacement value.
|
|
||||||
|
|
||||||
if (typeof rep === 'function') {
|
|
||||||
value = rep.call(holder, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// What happens next depends on the value's type.
|
|
||||||
|
|
||||||
switch (typeof value) {
|
|
||||||
case 'string':
|
|
||||||
return quote(value);
|
|
||||||
|
|
||||||
case 'number':
|
|
||||||
|
|
||||||
// JSON numbers must be finite. Encode non-finite numbers as null.
|
|
||||||
|
|
||||||
return isFinite(value) ? String(value) : 'null';
|
|
||||||
|
|
||||||
case 'boolean':
|
|
||||||
case 'null':
|
|
||||||
|
|
||||||
// If the value is a boolean or null, convert it to a string. Note:
|
|
||||||
// typeof null does not produce 'null'. The case is included here in
|
|
||||||
// the remote chance that this gets fixed someday.
|
|
||||||
|
|
||||||
return String(value);
|
|
||||||
|
|
||||||
// If the type is 'object', we might be dealing with an object or an array or
|
|
||||||
// null.
|
|
||||||
|
|
||||||
case 'object':
|
|
||||||
|
|
||||||
// Due to a specification blunder in ECMAScript, typeof null is 'object',
|
|
||||||
// so watch out for that case.
|
|
||||||
|
|
||||||
if (!value) {
|
|
||||||
return 'null';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make an array to hold the partial results of stringifying this object value.
|
|
||||||
|
|
||||||
gap += indent;
|
|
||||||
partial = [];
|
|
||||||
|
|
||||||
// Is the value an array?
|
|
||||||
|
|
||||||
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
|
||||||
|
|
||||||
// The value is an array. Stringify every element. Use null as a placeholder
|
|
||||||
// for non-JSON values.
|
|
||||||
|
|
||||||
length = value.length;
|
|
||||||
for (i = 0; i < length; i += 1) {
|
|
||||||
partial[i] = str(i, value) || 'null';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join all of the elements together, separated with commas, and wrap them in
|
|
||||||
// brackets.
|
|
||||||
|
|
||||||
v = partial.length === 0 ? '[]' :
|
|
||||||
gap ? '[\n' + gap +
|
|
||||||
partial.join(',\n' + gap) + '\n' +
|
|
||||||
mind + ']' :
|
|
||||||
'[' + partial.join(',') + ']';
|
|
||||||
gap = mind;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the replacer is an array, use it to select the members to be stringified.
|
|
||||||
|
|
||||||
if (rep && typeof rep === 'object') {
|
|
||||||
length = rep.length;
|
|
||||||
for (i = 0; i < length; i += 1) {
|
|
||||||
k = rep[i];
|
|
||||||
if (typeof k === 'string') {
|
|
||||||
v = str(k, value);
|
|
||||||
if (v) {
|
|
||||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Otherwise, iterate through all of the keys in the object.
|
|
||||||
|
|
||||||
for (k in value) {
|
|
||||||
if (Object.hasOwnProperty.call(value, k)) {
|
|
||||||
v = str(k, value);
|
|
||||||
if (v) {
|
|
||||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join all of the member texts together, separated with commas,
|
|
||||||
// and wrap them in braces.
|
|
||||||
|
|
||||||
v = partial.length === 0 ? '{}' :
|
|
||||||
gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
|
|
||||||
mind + '}' : '{' + partial.join(',') + '}';
|
|
||||||
gap = mind;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the JSON object does not yet have a stringify method, give it one.
|
|
||||||
|
|
||||||
if (typeof JSON.stringify !== 'function') {
|
|
||||||
JSON.stringify = function (value, replacer, space) {
|
|
||||||
|
|
||||||
// The stringify method takes a value and an optional replacer, and an optional
|
|
||||||
// space parameter, and returns a JSON text. The replacer can be a function
|
|
||||||
// that can replace values, or an array of strings that will select the keys.
|
|
||||||
// A default replacer method can be provided. Use of the space parameter can
|
|
||||||
// produce text that is more easily readable.
|
|
||||||
|
|
||||||
var i;
|
|
||||||
gap = '';
|
|
||||||
indent = '';
|
|
||||||
|
|
||||||
// If the space parameter is a number, make an indent string containing that
|
|
||||||
// many spaces.
|
|
||||||
|
|
||||||
if (typeof space === 'number') {
|
|
||||||
for (i = 0; i < space; i += 1) {
|
|
||||||
indent += ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the space parameter is a string, it will be used as the indent string.
|
|
||||||
|
|
||||||
} else if (typeof space === 'string') {
|
|
||||||
indent = space;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is a replacer, it must be a function or an array.
|
|
||||||
// Otherwise, throw an error.
|
|
||||||
|
|
||||||
rep = replacer;
|
|
||||||
if (replacer && typeof replacer !== 'function' &&
|
|
||||||
(typeof replacer !== 'object' ||
|
|
||||||
typeof replacer.length !== 'number')) {
|
|
||||||
throw new Error('JSON.stringify');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a fake root object containing our value under the key of ''.
|
|
||||||
// Return the result of stringifying the value.
|
|
||||||
|
|
||||||
return str('', {'': value});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// If the JSON object does not yet have a parse method, give it one.
|
|
||||||
|
|
||||||
if (typeof JSON.parse !== 'function') {
|
|
||||||
JSON.parse = function (text, reviver) {
|
|
||||||
|
|
||||||
// The parse method takes a text and an optional reviver function, and returns
|
|
||||||
// a JavaScript value if the text is a valid JSON text.
|
|
||||||
|
|
||||||
var j;
|
|
||||||
|
|
||||||
function walk(holder, key) {
|
|
||||||
|
|
||||||
// The walk method is used to recursively walk the resulting structure so
|
|
||||||
// that modifications can be made.
|
|
||||||
|
|
||||||
var k, v, value = holder[key];
|
|
||||||
if (value && typeof value === 'object') {
|
|
||||||
for (k in value) {
|
|
||||||
if (Object.hasOwnProperty.call(value, k)) {
|
|
||||||
v = walk(value, k);
|
|
||||||
if (v !== undefined) {
|
|
||||||
value[k] = v;
|
|
||||||
} else {
|
|
||||||
delete value[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return reviver.call(holder, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Parsing happens in four stages. In the first stage, we replace certain
|
|
||||||
// Unicode characters with escape sequences. JavaScript handles many characters
|
|
||||||
// incorrectly, either silently deleting them, or treating them as line endings.
|
|
||||||
|
|
||||||
text = String(text);
|
|
||||||
cx.lastIndex = 0;
|
|
||||||
if (cx.test(text)) {
|
|
||||||
text = text.replace(cx, function (a) {
|
|
||||||
return '\\u' +
|
|
||||||
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// In the second stage, we run the text against regular expressions that look
|
|
||||||
// for non-JSON patterns. We are especially concerned with '()' and 'new'
|
|
||||||
// because they can cause invocation, and '=' because it can cause mutation.
|
|
||||||
// But just to be safe, we want to reject all unexpected forms.
|
|
||||||
|
|
||||||
// We split the second stage into 4 regexp operations in order to work around
|
|
||||||
// crippling inefficiencies in IE's and Safari's regexp engines. First we
|
|
||||||
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
|
|
||||||
// replace all simple value tokens with ']' characters. Third, we delete all
|
|
||||||
// open brackets that follow a colon or comma or that begin the text. Finally,
|
|
||||||
// we look to see that the remaining characters are only whitespace or ']' or
|
|
||||||
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
|
|
||||||
|
|
||||||
if (/^[\],:{}\s]*$/
|
|
||||||
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
|
|
||||||
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
|
|
||||||
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
|
||||||
|
|
||||||
// In the third stage we use the eval function to compile the text into a
|
|
||||||
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
|
||||||
// in JavaScript: it can begin a block or an object literal. We wrap the text
|
|
||||||
// in parens to eliminate the ambiguity.
|
|
||||||
|
|
||||||
j = eval('(' + text + ')');
|
|
||||||
|
|
||||||
// In the optional fourth stage, we recursively walk the new structure, passing
|
|
||||||
// each name/value pair to a reviver function for possible transformation.
|
|
||||||
|
|
||||||
return typeof reviver === 'function' ?
|
|
||||||
walk({'': j}, '') : j;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the text is not JSON parseable, then a SyntaxError is thrown.
|
|
||||||
|
|
||||||
throw new SyntaxError('JSON.parse');
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}());
|
|
||||||
var assert = this.assert = {};
|
|
||||||
var types = {};
|
|
||||||
var core = {};
|
|
||||||
var nodeunit = {};
|
|
||||||
var reporter = {};
|
|
||||||
/*global setTimeout: false, console: false */
|
|
||||||
(function () {
|
|
||||||
|
|
||||||
var async = {};
|
|
||||||
|
|
||||||
// global on the server, window in the browser
|
|
||||||
var root = this,
|
|
||||||
previous_async = root.async;
|
|
||||||
|
|
||||||
if (typeof module !== 'undefined' && module.exports) {
|
|
||||||
module.exports = async;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
root.async = async;
|
|
||||||
}
|
|
||||||
|
|
||||||
async.noConflict = function () {
|
|
||||||
root.async = previous_async;
|
|
||||||
return async;
|
|
||||||
};
|
|
||||||
|
|
||||||
//// cross-browser compatiblity functions ////
|
|
||||||
|
|
||||||
var _forEach = function (arr, iterator) {
|
|
||||||
if (arr.forEach) {
|
|
||||||
return arr.forEach(iterator);
|
|
||||||
}
|
|
||||||
for (var i = 0; i < arr.length; i += 1) {
|
|
||||||
iterator(arr[i], i, arr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var _map = function (arr, iterator) {
|
|
||||||
if (arr.map) {
|
|
||||||
return arr.map(iterator);
|
|
||||||
}
|
|
||||||
var results = [];
|
|
||||||
_forEach(arr, function (x, i, a) {
|
|
||||||
results.push(iterator(x, i, a));
|
|
||||||
});
|
|
||||||
return results;
|
|
||||||
};
|
|
||||||
|
|
||||||
var _reduce = function (arr, iterator, memo) {
|
|
||||||
if (arr.reduce) {
|
|
||||||
return arr.reduce(iterator, memo);
|
|
||||||
}
|
|
||||||
_forEach(arr, function (x, i, a) {
|
|
||||||
memo = iterator(memo, x, i, a);
|
|
||||||
});
|
|
||||||
return memo;
|
|
||||||
};
|
|
||||||
|
|
||||||
var _keys = function (obj) {
|
|
||||||
if (Object.keys) {
|
|
||||||
return Object.keys(obj);
|
|
||||||
}
|
|
||||||
var keys = [];
|
|
||||||
for (var k in obj) {
|
|
||||||
if (obj.hasOwnProperty(k)) {
|
|
||||||
keys.push(k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
};
|
|
||||||
|
|
||||||
var _indexOf = function (arr, item) {
|
|
||||||
if (arr.indexOf) {
|
|
||||||
return arr.indexOf(item);
|
|
||||||
}
|
|
||||||
for (var i = 0; i < arr.length; i += 1) {
|
|
||||||
if (arr[i] === item) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
//// exported async module functions ////
|
|
||||||
|
|
||||||
//// nextTick implementation with browser-compatible fallback ////
|
|
||||||
if (typeof setImmediate === 'function') {
|
|
||||||
async.nextTick = function (fn) {
|
|
||||||
setImmediate(fn);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (typeof process !== 'undefined' && process.nextTick) {
|
|
||||||
async.nextTick = process.nextTick;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
async.nextTick = function (fn) {
|
|
||||||
setTimeout(fn, 0);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async.forEach = function (arr, iterator, callback) {
|
|
||||||
if (!arr.length) {
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
var completed = 0;
|
|
||||||
_forEach(arr, function (x) {
|
|
||||||
iterator(x, function (err) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
callback = function () {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
completed += 1;
|
|
||||||
if (completed === arr.length) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
async.forEachSeries = function (arr, iterator, callback) {
|
|
||||||
if (!arr.length) {
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
var completed = 0;
|
|
||||||
var iterate = function () {
|
|
||||||
iterator(arr[completed], function (err) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
callback = function () {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
completed += 1;
|
|
||||||
if (completed === arr.length) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
iterate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
iterate();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var doParallel = function (fn) {
|
|
||||||
return function () {
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
return fn.apply(null, [async.forEach].concat(args));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
var doSeries = function (fn) {
|
|
||||||
return function () {
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
return fn.apply(null, [async.forEachSeries].concat(args));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var _asyncMap = function (eachfn, arr, iterator, callback) {
|
|
||||||
var results = [];
|
|
||||||
arr = _map(arr, function (x, i) {
|
|
||||||
return {index: i, value: x};
|
|
||||||
});
|
|
||||||
eachfn(arr, function (x, callback) {
|
|
||||||
iterator(x.value, function (err, v) {
|
|
||||||
results[x.index] = v;
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, results);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.map = doParallel(_asyncMap);
|
|
||||||
async.mapSeries = doSeries(_asyncMap);
|
|
||||||
|
|
||||||
|
|
||||||
// reduce only has a series version, as doing reduce in parallel won't
|
|
||||||
// work in many situations.
|
|
||||||
async.reduce = function (arr, memo, iterator, callback) {
|
|
||||||
async.forEachSeries(arr, function (x, callback) {
|
|
||||||
iterator(memo, x, function (err, v) {
|
|
||||||
memo = v;
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, memo);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// inject alias
|
|
||||||
async.inject = async.reduce;
|
|
||||||
// foldl alias
|
|
||||||
async.foldl = async.reduce;
|
|
||||||
|
|
||||||
async.reduceRight = function (arr, memo, iterator, callback) {
|
|
||||||
var reversed = _map(arr, function (x) {
|
|
||||||
return x;
|
|
||||||
}).reverse();
|
|
||||||
async.reduce(reversed, memo, iterator, callback);
|
|
||||||
};
|
|
||||||
// foldr alias
|
|
||||||
async.foldr = async.reduceRight;
|
|
||||||
|
|
||||||
var _filter = function (eachfn, arr, iterator, callback) {
|
|
||||||
var results = [];
|
|
||||||
arr = _map(arr, function (x, i) {
|
|
||||||
return {index: i, value: x};
|
|
||||||
});
|
|
||||||
eachfn(arr, function (x, callback) {
|
|
||||||
iterator(x.value, function (v) {
|
|
||||||
if (v) {
|
|
||||||
results.push(x);
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(_map(results.sort(function (a, b) {
|
|
||||||
return a.index - b.index;
|
|
||||||
}), function (x) {
|
|
||||||
return x.value;
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.filter = doParallel(_filter);
|
|
||||||
async.filterSeries = doSeries(_filter);
|
|
||||||
// select alias
|
|
||||||
async.select = async.filter;
|
|
||||||
async.selectSeries = async.filterSeries;
|
|
||||||
|
|
||||||
var _reject = function (eachfn, arr, iterator, callback) {
|
|
||||||
var results = [];
|
|
||||||
arr = _map(arr, function (x, i) {
|
|
||||||
return {index: i, value: x};
|
|
||||||
});
|
|
||||||
eachfn(arr, function (x, callback) {
|
|
||||||
iterator(x.value, function (v) {
|
|
||||||
if (!v) {
|
|
||||||
results.push(x);
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(_map(results.sort(function (a, b) {
|
|
||||||
return a.index - b.index;
|
|
||||||
}), function (x) {
|
|
||||||
return x.value;
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.reject = doParallel(_reject);
|
|
||||||
async.rejectSeries = doSeries(_reject);
|
|
||||||
|
|
||||||
var _detect = function (eachfn, arr, iterator, main_callback) {
|
|
||||||
eachfn(arr, function (x, callback) {
|
|
||||||
iterator(x, function (result) {
|
|
||||||
if (result) {
|
|
||||||
main_callback(x);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
main_callback();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.detect = doParallel(_detect);
|
|
||||||
async.detectSeries = doSeries(_detect);
|
|
||||||
|
|
||||||
async.some = function (arr, iterator, main_callback) {
|
|
||||||
async.forEach(arr, function (x, callback) {
|
|
||||||
iterator(x, function (v) {
|
|
||||||
if (v) {
|
|
||||||
main_callback(true);
|
|
||||||
main_callback = function () {};
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
main_callback(false);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// any alias
|
|
||||||
async.any = async.some;
|
|
||||||
|
|
||||||
async.every = function (arr, iterator, main_callback) {
|
|
||||||
async.forEach(arr, function (x, callback) {
|
|
||||||
iterator(x, function (v) {
|
|
||||||
if (!v) {
|
|
||||||
main_callback(false);
|
|
||||||
main_callback = function () {};
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
main_callback(true);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// all alias
|
|
||||||
async.all = async.every;
|
|
||||||
|
|
||||||
async.sortBy = function (arr, iterator, callback) {
|
|
||||||
async.map(arr, function (x, callback) {
|
|
||||||
iterator(x, function (err, criteria) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback(null, {value: x, criteria: criteria});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, function (err, results) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var fn = function (left, right) {
|
|
||||||
var a = left.criteria, b = right.criteria;
|
|
||||||
return a < b ? -1 : a > b ? 1 : 0;
|
|
||||||
};
|
|
||||||
callback(null, _map(results.sort(fn), function (x) {
|
|
||||||
return x.value;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
async.auto = function (tasks, callback) {
|
|
||||||
callback = callback || function () {};
|
|
||||||
var keys = _keys(tasks);
|
|
||||||
if (!keys.length) {
|
|
||||||
return callback(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
var completed = [];
|
|
||||||
|
|
||||||
var listeners = [];
|
|
||||||
var addListener = function (fn) {
|
|
||||||
listeners.unshift(fn);
|
|
||||||
};
|
|
||||||
var removeListener = function (fn) {
|
|
||||||
for (var i = 0; i < listeners.length; i += 1) {
|
|
||||||
if (listeners[i] === fn) {
|
|
||||||
listeners.splice(i, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var taskComplete = function () {
|
|
||||||
_forEach(listeners, function (fn) {
|
|
||||||
fn();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
addListener(function () {
|
|
||||||
if (completed.length === keys.length) {
|
|
||||||
callback(null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
_forEach(keys, function (k) {
|
|
||||||
var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
|
|
||||||
var taskCallback = function (err) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
// stop subsequent errors hitting callback multiple times
|
|
||||||
callback = function () {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
completed.push(k);
|
|
||||||
taskComplete();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var requires = task.slice(0, Math.abs(task.length - 1)) || [];
|
|
||||||
var ready = function () {
|
|
||||||
return _reduce(requires, function (a, x) {
|
|
||||||
return (a && _indexOf(completed, x) !== -1);
|
|
||||||
}, true);
|
|
||||||
};
|
|
||||||
if (ready()) {
|
|
||||||
task[task.length - 1](taskCallback);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var listener = function () {
|
|
||||||
if (ready()) {
|
|
||||||
removeListener(listener);
|
|
||||||
task[task.length - 1](taskCallback);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
addListener(listener);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
async.waterfall = function (tasks, callback) {
|
|
||||||
if (!tasks.length) {
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
callback = callback || function () {};
|
|
||||||
var wrapIterator = function (iterator) {
|
|
||||||
return function (err) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
callback = function () {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
var next = iterator.next();
|
|
||||||
if (next) {
|
|
||||||
args.push(wrapIterator(next));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
args.push(callback);
|
|
||||||
}
|
|
||||||
async.nextTick(function () {
|
|
||||||
iterator.apply(null, args);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
wrapIterator(async.iterator(tasks))();
|
|
||||||
};
|
|
||||||
|
|
||||||
async.parallel = function (tasks, callback) {
|
|
||||||
callback = callback || function () {};
|
|
||||||
if (tasks.constructor === Array) {
|
|
||||||
async.map(tasks, function (fn, callback) {
|
|
||||||
if (fn) {
|
|
||||||
fn(function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (args.length <= 1) {
|
|
||||||
args = args[0];
|
|
||||||
}
|
|
||||||
callback.call(null, err, args || null);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, callback);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var results = {};
|
|
||||||
async.forEach(_keys(tasks), function (k, callback) {
|
|
||||||
tasks[k](function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (args.length <= 1) {
|
|
||||||
args = args[0];
|
|
||||||
}
|
|
||||||
results[k] = args;
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, results);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async.series = function (tasks, callback) {
|
|
||||||
callback = callback || function () {};
|
|
||||||
if (tasks.constructor === Array) {
|
|
||||||
async.mapSeries(tasks, function (fn, callback) {
|
|
||||||
if (fn) {
|
|
||||||
fn(function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (args.length <= 1) {
|
|
||||||
args = args[0];
|
|
||||||
}
|
|
||||||
callback.call(null, err, args || null);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, callback);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var results = {};
|
|
||||||
async.forEachSeries(_keys(tasks), function (k, callback) {
|
|
||||||
tasks[k](function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (args.length <= 1) {
|
|
||||||
args = args[0];
|
|
||||||
}
|
|
||||||
results[k] = args;
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, results);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async.iterator = function (tasks) {
|
|
||||||
var makeCallback = function (index) {
|
|
||||||
var fn = function () {
|
|
||||||
if (tasks.length) {
|
|
||||||
tasks[index].apply(null, arguments);
|
|
||||||
}
|
|
||||||
return fn.next();
|
|
||||||
};
|
|
||||||
fn.next = function () {
|
|
||||||
return (index < tasks.length - 1) ? makeCallback(index + 1): null;
|
|
||||||
};
|
|
||||||
return fn;
|
|
||||||
};
|
|
||||||
return makeCallback(0);
|
|
||||||
};
|
|
||||||
|
|
||||||
async.apply = function (fn) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
return function () {
|
|
||||||
return fn.apply(
|
|
||||||
null, args.concat(Array.prototype.slice.call(arguments))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var _concat = function (eachfn, arr, fn, callback) {
|
|
||||||
var r = [];
|
|
||||||
eachfn(arr, function (x, cb) {
|
|
||||||
fn(x, function (err, y) {
|
|
||||||
r = r.concat(y || []);
|
|
||||||
cb(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, r);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.concat = doParallel(_concat);
|
|
||||||
async.concatSeries = doSeries(_concat);
|
|
||||||
|
|
||||||
async.whilst = function (test, iterator, callback) {
|
|
||||||
if (test()) {
|
|
||||||
iterator(function (err) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
async.whilst(test, iterator, callback);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async.until = function (test, iterator, callback) {
|
|
||||||
if (!test()) {
|
|
||||||
iterator(function (err) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
async.until(test, iterator, callback);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async.queue = function (worker, concurrency) {
|
|
||||||
var workers = 0;
|
|
||||||
var tasks = [];
|
|
||||||
var q = {
|
|
||||||
concurrency: concurrency,
|
|
||||||
push: function (data, callback) {
|
|
||||||
tasks.push({data: data, callback: callback});
|
|
||||||
async.nextTick(q.process);
|
|
||||||
},
|
|
||||||
process: function () {
|
|
||||||
if (workers < q.concurrency && tasks.length) {
|
|
||||||
var task = tasks.splice(0, 1)[0];
|
|
||||||
workers += 1;
|
|
||||||
worker(task.data, function () {
|
|
||||||
workers -= 1;
|
|
||||||
if (task.callback) {
|
|
||||||
task.callback.apply(task, arguments);
|
|
||||||
}
|
|
||||||
q.process();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
length: function () {
|
|
||||||
return tasks.length;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return q;
|
|
||||||
};
|
|
||||||
|
|
||||||
var _console_fn = function (name) {
|
|
||||||
return function (fn) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
fn.apply(null, args.concat([function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (typeof console !== 'undefined') {
|
|
||||||
if (err) {
|
|
||||||
if (console.error) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (console[name]) {
|
|
||||||
_forEach(args, function (x) {
|
|
||||||
console[name](x);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}]));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
async.log = _console_fn('log');
|
|
||||||
async.dir = _console_fn('dir');
|
|
||||||
/*async.info = _console_fn('info');
|
|
||||||
async.warn = _console_fn('warn');
|
|
||||||
async.error = _console_fn('error');*/
|
|
||||||
|
|
||||||
async.memoize = function (fn, hasher) {
|
|
||||||
var memo = {};
|
|
||||||
hasher = hasher || function (x) {
|
|
||||||
return x;
|
|
||||||
};
|
|
||||||
return function () {
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
var callback = args.pop();
|
|
||||||
var key = hasher.apply(null, args);
|
|
||||||
if (key in memo) {
|
|
||||||
callback.apply(null, memo[key]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fn.apply(null, args.concat([function () {
|
|
||||||
memo[key] = arguments;
|
|
||||||
callback.apply(null, arguments);
|
|
||||||
}]));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}());
|
|
||||||
(function(exports){
|
|
||||||
/**
|
|
||||||
* This file is based on the node.js assert module, but with some small
|
|
||||||
* changes for browser-compatibility
|
|
||||||
* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Added for browser compatibility
|
|
||||||
*/
|
|
||||||
|
|
||||||
var _keys = function(obj){
|
|
||||||
if(Object.keys) return Object.keys(obj);
|
|
||||||
if (typeof obj != 'object' && typeof obj != 'function') {
|
|
||||||
throw new TypeError('-');
|
|
||||||
}
|
|
||||||
var keys = [];
|
|
||||||
for(var k in obj){
|
|
||||||
if(obj.hasOwnProperty(k)) keys.push(k);
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
|
|
||||||
//
|
|
||||||
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
|
|
||||||
//
|
|
||||||
// Originally from narwhal.js (http://narwhaljs.org)
|
|
||||||
// Copyright (c) 2009 Thomas Robinson <280north.com>
|
|
||||||
//
|
|
||||||
// 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 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.
|
|
||||||
|
|
||||||
|
|
||||||
var pSlice = Array.prototype.slice;
|
|
||||||
|
|
||||||
// 1. The assert module provides functions that throw
|
|
||||||
// AssertionError's when particular conditions are not met. The
|
|
||||||
// assert module must conform to the following interface.
|
|
||||||
|
|
||||||
var assert = exports;
|
|
||||||
|
|
||||||
// 2. The AssertionError is defined in assert.
|
|
||||||
// new assert.AssertionError({message: message, actual: actual, expected: expected})
|
|
||||||
|
|
||||||
assert.AssertionError = function AssertionError (options) {
|
|
||||||
this.name = "AssertionError";
|
|
||||||
this.message = options.message;
|
|
||||||
this.actual = options.actual;
|
|
||||||
this.expected = options.expected;
|
|
||||||
this.operator = options.operator;
|
|
||||||
var stackStartFunction = options.stackStartFunction || fail;
|
|
||||||
|
|
||||||
if (Error.captureStackTrace) {
|
|
||||||
Error.captureStackTrace(this, stackStartFunction);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// code from util.inherits in node
|
|
||||||
assert.AssertionError.super_ = Error;
|
|
||||||
|
|
||||||
|
|
||||||
// EDITED FOR BROWSER COMPATIBILITY: replaced Object.create call
|
|
||||||
// TODO: test what effect this may have
|
|
||||||
var ctor = function () { this.constructor = assert.AssertionError; };
|
|
||||||
ctor.prototype = Error.prototype;
|
|
||||||
assert.AssertionError.prototype = new ctor();
|
|
||||||
|
|
||||||
|
|
||||||
assert.AssertionError.prototype.toString = function() {
|
|
||||||
if (this.message) {
|
|
||||||
return [this.name+":", this.message].join(' ');
|
|
||||||
} else {
|
|
||||||
return [ this.name+":"
|
|
||||||
, typeof this.expected !== 'undefined' ? JSON.stringify(this.expected) : 'undefined'
|
|
||||||
, this.operator
|
|
||||||
, typeof this.actual !== 'undefined' ? JSON.stringify(this.actual) : 'undefined'
|
|
||||||
].join(" ");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// assert.AssertionError instanceof Error
|
|
||||||
|
|
||||||
assert.AssertionError.__proto__ = Error.prototype;
|
|
||||||
|
|
||||||
// At present only the three keys mentioned above are used and
|
|
||||||
// understood by the spec. Implementations or sub modules can pass
|
|
||||||
// other keys to the AssertionError's constructor - they will be
|
|
||||||
// ignored.
|
|
||||||
|
|
||||||
// 3. All of the following functions must throw an AssertionError
|
|
||||||
// when a corresponding condition is not met, with a message that
|
|
||||||
// may be undefined if not provided. All assertion methods provide
|
|
||||||
// both the actual and expected values to the assertion error for
|
|
||||||
// display purposes.
|
|
||||||
|
|
||||||
function fail(actual, expected, message, operator, stackStartFunction) {
|
|
||||||
throw new assert.AssertionError({
|
|
||||||
message: message,
|
|
||||||
actual: actual,
|
|
||||||
expected: expected,
|
|
||||||
operator: operator,
|
|
||||||
stackStartFunction: stackStartFunction
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// EXTENSION! allows for well behaved errors defined elsewhere.
|
|
||||||
assert.fail = fail;
|
|
||||||
|
|
||||||
// 4. Pure assertion tests whether a value is truthy, as determined
|
|
||||||
// by !!guard.
|
|
||||||
// assert.ok(guard, message_opt);
|
|
||||||
// This statement is equivalent to assert.equal(true, guard,
|
|
||||||
// message_opt);. To test strictly for the value true, use
|
|
||||||
// assert.strictEqual(true, guard, message_opt);.
|
|
||||||
|
|
||||||
assert.ok = function ok(value, message) {
|
|
||||||
if (!!!value) fail(value, true, message, "==", assert.ok);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 5. The equality assertion tests shallow, coercive equality with
|
|
||||||
// ==.
|
|
||||||
// assert.equal(actual, expected, message_opt);
|
|
||||||
|
|
||||||
assert.equal = function equal(actual, expected, message) {
|
|
||||||
if (actual != expected) fail(actual, expected, message, "==", assert.equal);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 6. The non-equality assertion tests for whether two objects are not equal
|
|
||||||
// with != assert.notEqual(actual, expected, message_opt);
|
|
||||||
|
|
||||||
assert.notEqual = function notEqual(actual, expected, message) {
|
|
||||||
if (actual == expected) {
|
|
||||||
fail(actual, expected, message, "!=", assert.notEqual);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 7. The equivalence assertion tests a deep equality relation.
|
|
||||||
// assert.deepEqual(actual, expected, message_opt);
|
|
||||||
|
|
||||||
assert.deepEqual = function deepEqual(actual, expected, message) {
|
|
||||||
if (!_deepEqual(actual, expected)) {
|
|
||||||
fail(actual, expected, message, "deepEqual", assert.deepEqual);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var Buffer = null;
|
|
||||||
if (typeof require !== 'undefined' && typeof process !== 'undefined') {
|
|
||||||
try {
|
|
||||||
Buffer = require('buffer').Buffer;
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
// May be a CommonJS environment other than Node.js
|
|
||||||
Buffer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function _deepEqual(actual, expected) {
|
|
||||||
// 7.1. All identical values are equivalent, as determined by ===.
|
|
||||||
if (actual === expected) {
|
|
||||||
return true;
|
|
||||||
// 7.2. If the expected value is a Date object, the actual value is
|
|
||||||
// equivalent if it is also a Date object that refers to the same time.
|
|
||||||
} else if (actual instanceof Date && expected instanceof Date) {
|
|
||||||
return actual.getTime() === expected.getTime();
|
|
||||||
|
|
||||||
// 7.2.1 If the expcted value is a RegExp object, the actual value is
|
|
||||||
// equivalent if it is also a RegExp object that refers to the same source and options
|
|
||||||
} else if (actual instanceof RegExp && expected instanceof RegExp) {
|
|
||||||
return actual.source === expected.source &&
|
|
||||||
actual.global === expected.global &&
|
|
||||||
actual.ignoreCase === expected.ignoreCase &&
|
|
||||||
actual.multiline === expected.multiline;
|
|
||||||
|
|
||||||
} else if (Buffer && actual instanceof Buffer && expected instanceof Buffer) {
|
|
||||||
return (function() {
|
|
||||||
var i, len;
|
|
||||||
|
|
||||||
for (i = 0, len = expected.length; i < len; i++) {
|
|
||||||
if (actual[i] !== expected[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return actual.length === expected.length;
|
|
||||||
})();
|
|
||||||
// 7.3. Other pairs that do not both pass typeof value == "object",
|
|
||||||
// equivalence is determined by ==.
|
|
||||||
} else if (typeof actual != 'object' && typeof expected != 'object') {
|
|
||||||
return actual == expected;
|
|
||||||
|
|
||||||
// 7.4. For all other Object pairs, including Array objects, equivalence is
|
|
||||||
// determined by having the same number of owned properties (as verified
|
|
||||||
// with Object.prototype.hasOwnProperty.call), the same set of keys
|
|
||||||
// (although not necessarily the same order), equivalent values for every
|
|
||||||
// corresponding key, and an identical "prototype" property. Note: this
|
|
||||||
// accounts for both named and indexed properties on Arrays.
|
|
||||||
} else {
|
|
||||||
return objEquiv(actual, expected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isUndefinedOrNull (value) {
|
|
||||||
return value === null || value === undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isArguments (object) {
|
|
||||||
return Object.prototype.toString.call(object) == '[object Arguments]';
|
|
||||||
}
|
|
||||||
|
|
||||||
function objEquiv (a, b) {
|
|
||||||
if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
|
|
||||||
return false;
|
|
||||||
// an identical "prototype" property.
|
|
||||||
if (a.prototype !== b.prototype) return false;
|
|
||||||
//~~~I've managed to break Object.keys through screwy arguments passing.
|
|
||||||
// Converting to array solves the problem.
|
|
||||||
if (isArguments(a)) {
|
|
||||||
if (!isArguments(b)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
a = pSlice.call(a);
|
|
||||||
b = pSlice.call(b);
|
|
||||||
return _deepEqual(a, b);
|
|
||||||
}
|
|
||||||
try{
|
|
||||||
var ka = _keys(a),
|
|
||||||
kb = _keys(b),
|
|
||||||
key, i;
|
|
||||||
} catch (e) {//happens when one is a string literal and the other isn't
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// having the same number of owned properties (keys incorporates hasOwnProperty)
|
|
||||||
if (ka.length != kb.length)
|
|
||||||
return false;
|
|
||||||
//the same set of keys (although not necessarily the same order),
|
|
||||||
ka.sort();
|
|
||||||
kb.sort();
|
|
||||||
//~~~cheap key test
|
|
||||||
for (i = ka.length - 1; i >= 0; i--) {
|
|
||||||
if (ka[i] != kb[i])
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
//equivalent values for every corresponding key, and
|
|
||||||
//~~~possibly expensive deep test
|
|
||||||
for (i = ka.length - 1; i >= 0; i--) {
|
|
||||||
key = ka[i];
|
|
||||||
if (!_deepEqual(a[key], b[key] ))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 8. The non-equivalence assertion tests for any deep inequality.
|
|
||||||
// assert.notDeepEqual(actual, expected, message_opt);
|
|
||||||
|
|
||||||
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
|
|
||||||
if (_deepEqual(actual, expected)) {
|
|
||||||
fail(actual, expected, message, "notDeepEqual", assert.notDeepEqual);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 9. The strict equality assertion tests strict equality, as determined by ===.
|
|
||||||
// assert.strictEqual(actual, expected, message_opt);
|
|
||||||
|
|
||||||
assert.strictEqual = function strictEqual(actual, expected, message) {
|
|
||||||
if (actual !== expected) {
|
|
||||||
fail(actual, expected, message, "===", assert.strictEqual);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 10. The strict non-equality assertion tests for strict inequality, as determined by !==.
|
|
||||||
// assert.notStrictEqual(actual, expected, message_opt);
|
|
||||||
|
|
||||||
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
|
|
||||||
if (actual === expected) {
|
|
||||||
fail(actual, expected, message, "!==", assert.notStrictEqual);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function expectedException(actual, expected) {
|
|
||||||
if (!actual || !expected) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expected instanceof RegExp) {
|
|
||||||
return expected.test(actual.message || actual);
|
|
||||||
} else if (actual instanceof expected) {
|
|
||||||
return true;
|
|
||||||
} else if (expected.call({}, actual) === true) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _throws(shouldThrow, block, expected, message) {
|
|
||||||
var actual;
|
|
||||||
|
|
||||||
if (typeof expected === 'string') {
|
|
||||||
message = expected;
|
|
||||||
expected = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
block();
|
|
||||||
} catch (e) {
|
|
||||||
actual = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
|
|
||||||
(message ? ' ' + message : '.');
|
|
||||||
|
|
||||||
if (shouldThrow && !actual) {
|
|
||||||
fail('Missing expected exception' + message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!shouldThrow && expectedException(actual, expected)) {
|
|
||||||
fail('Got unwanted exception' + message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((shouldThrow && actual && expected &&
|
|
||||||
!expectedException(actual, expected)) || (!shouldThrow && actual)) {
|
|
||||||
throw actual;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 11. Expected to throw an error:
|
|
||||||
// assert.throws(block, Error_opt, message_opt);
|
|
||||||
|
|
||||||
assert.throws = function(block, /*optional*/error, /*optional*/message) {
|
|
||||||
_throws.apply(this, [true].concat(pSlice.call(arguments)));
|
|
||||||
};
|
|
||||||
|
|
||||||
// EXTENSION! This is annoying to write outside this module.
|
|
||||||
assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
|
|
||||||
_throws.apply(this, [false].concat(pSlice.call(arguments)));
|
|
||||||
};
|
|
||||||
|
|
||||||
assert.ifError = function (err) { if (err) {throw err;}};
|
|
||||||
})(assert);
|
|
||||||
(function(exports){
|
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*
|
|
||||||
* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
|
|
||||||
* Only code on that line will be removed, it's mostly to avoid requiring code
|
|
||||||
* that is node specific
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates assertion objects representing the result of an assert call.
|
|
||||||
* Accepts an object or AssertionError as its argument.
|
|
||||||
*
|
|
||||||
* @param {object} obj
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.assertion = function (obj) {
|
|
||||||
return {
|
|
||||||
method: obj.method || '',
|
|
||||||
message: obj.message || (obj.error && obj.error.message) || '',
|
|
||||||
error: obj.error,
|
|
||||||
passed: function () {
|
|
||||||
return !this.error;
|
|
||||||
},
|
|
||||||
failed: function () {
|
|
||||||
return Boolean(this.error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an assertion list object representing a group of assertions.
|
|
||||||
* Accepts an array of assertion objects.
|
|
||||||
*
|
|
||||||
* @param {Array} arr
|
|
||||||
* @param {Number} duration
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.assertionList = function (arr, duration) {
|
|
||||||
var that = arr || [];
|
|
||||||
that.failures = function () {
|
|
||||||
var failures = 0;
|
|
||||||
for (var i = 0; i < this.length; i += 1) {
|
|
||||||
if (this[i].failed()) {
|
|
||||||
failures += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return failures;
|
|
||||||
};
|
|
||||||
that.passes = function () {
|
|
||||||
return that.length - that.failures();
|
|
||||||
};
|
|
||||||
that.duration = duration || 0;
|
|
||||||
return that;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a wrapper function for assert module methods. Executes a callback
|
|
||||||
* after it's complete with an assertion object representing the result.
|
|
||||||
*
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
var assertWrapper = function (callback) {
|
|
||||||
return function (new_method, assert_method, arity) {
|
|
||||||
return function () {
|
|
||||||
var message = arguments[arity - 1];
|
|
||||||
var a = exports.assertion({method: new_method, message: message});
|
|
||||||
try {
|
|
||||||
assert[assert_method].apply(null, arguments);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
a.error = e;
|
|
||||||
}
|
|
||||||
callback(a);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the 'test' object that gets passed to every test function.
|
|
||||||
* Accepts the name of the test function as its first argument, followed by
|
|
||||||
* the start time in ms, the options object and a callback function.
|
|
||||||
*
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Number} start
|
|
||||||
* @param {Object} options
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.test = function (name, start, options, callback) {
|
|
||||||
var expecting;
|
|
||||||
var a_list = [];
|
|
||||||
|
|
||||||
var wrapAssert = assertWrapper(function (a) {
|
|
||||||
a_list.push(a);
|
|
||||||
if (options.log) {
|
|
||||||
async.nextTick(function () {
|
|
||||||
options.log(a);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var test = {
|
|
||||||
done: function (err) {
|
|
||||||
if (expecting !== undefined && expecting !== a_list.length) {
|
|
||||||
var e = new Error(
|
|
||||||
'Expected ' + expecting + ' assertions, ' +
|
|
||||||
a_list.length + ' ran'
|
|
||||||
);
|
|
||||||
var a1 = exports.assertion({method: 'expect', error: e});
|
|
||||||
a_list.push(a1);
|
|
||||||
if (options.log) {
|
|
||||||
async.nextTick(function () {
|
|
||||||
options.log(a1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (err) {
|
|
||||||
var a2 = exports.assertion({error: err});
|
|
||||||
a_list.push(a2);
|
|
||||||
if (options.log) {
|
|
||||||
async.nextTick(function () {
|
|
||||||
options.log(a2);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var end = new Date().getTime();
|
|
||||||
async.nextTick(function () {
|
|
||||||
var assertion_list = exports.assertionList(a_list, end - start);
|
|
||||||
options.testDone(name, assertion_list);
|
|
||||||
callback(null, a_list);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
ok: wrapAssert('ok', 'ok', 2),
|
|
||||||
same: wrapAssert('same', 'deepEqual', 3),
|
|
||||||
equals: wrapAssert('equals', 'equal', 3),
|
|
||||||
expect: function (num) {
|
|
||||||
expecting = num;
|
|
||||||
},
|
|
||||||
_assertion_list: a_list
|
|
||||||
};
|
|
||||||
// add all functions from the assert module
|
|
||||||
for (var k in assert) {
|
|
||||||
if (assert.hasOwnProperty(k)) {
|
|
||||||
test[k] = wrapAssert(k, k, assert[k].length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return test;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensures an options object has all callbacks, adding empty callback functions
|
|
||||||
* if any are missing.
|
|
||||||
*
|
|
||||||
* @param {Object} opt
|
|
||||||
* @return {Object}
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.options = function (opt) {
|
|
||||||
var optionalCallback = function (name) {
|
|
||||||
opt[name] = opt[name] || function () {};
|
|
||||||
};
|
|
||||||
|
|
||||||
optionalCallback('moduleStart');
|
|
||||||
optionalCallback('moduleDone');
|
|
||||||
optionalCallback('testStart');
|
|
||||||
optionalCallback('testReady');
|
|
||||||
optionalCallback('testDone');
|
|
||||||
//optionalCallback('log');
|
|
||||||
|
|
||||||
// 'done' callback is not optional.
|
|
||||||
|
|
||||||
return opt;
|
|
||||||
};
|
|
||||||
})(types);
|
|
||||||
(function(exports){
|
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*
|
|
||||||
* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
|
|
||||||
* Only code on that line will be removed, it's mostly to avoid requiring code
|
|
||||||
* that is node specific
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Added for browser compatibility
|
|
||||||
*/
|
|
||||||
|
|
||||||
var _keys = function (obj) {
|
|
||||||
if (Object.keys) {
|
|
||||||
return Object.keys(obj);
|
|
||||||
}
|
|
||||||
var keys = [];
|
|
||||||
for (var k in obj) {
|
|
||||||
if (obj.hasOwnProperty(k)) {
|
|
||||||
keys.push(k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var _copy = function (obj) {
|
|
||||||
var nobj = {};
|
|
||||||
var keys = _keys(obj);
|
|
||||||
for (var i = 0; i < keys.length; i += 1) {
|
|
||||||
nobj[keys[i]] = obj[keys[i]];
|
|
||||||
}
|
|
||||||
return nobj;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs a test function (fn) from a loaded module. After the test function
|
|
||||||
* calls test.done(), the callback is executed with an assertionList as its
|
|
||||||
* second argument.
|
|
||||||
*
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Function} fn
|
|
||||||
* @param {Object} opt
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.runTest = function (name, fn, opt, callback) {
|
|
||||||
var options = types.options(opt);
|
|
||||||
|
|
||||||
options.testStart(name);
|
|
||||||
var start = new Date().getTime();
|
|
||||||
var test = types.test(name, start, options, callback);
|
|
||||||
|
|
||||||
options.testReady(test);
|
|
||||||
try {
|
|
||||||
fn(test);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
test.done(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes an object containing test functions or other test suites as properties
|
|
||||||
* and runs each in series. After all tests have completed, the callback is
|
|
||||||
* called with a list of all assertions as the second argument.
|
|
||||||
*
|
|
||||||
* If a name is passed to this function it is prepended to all test and suite
|
|
||||||
* names that run within it.
|
|
||||||
*
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Object} suite
|
|
||||||
* @param {Object} opt
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.runSuite = function (name, suite, opt, callback) {
|
|
||||||
suite = wrapGroup(suite);
|
|
||||||
var keys = _keys(suite);
|
|
||||||
|
|
||||||
async.concatSeries(keys, function (k, cb) {
|
|
||||||
var prop = suite[k], _name;
|
|
||||||
|
|
||||||
_name = name ? [].concat(name, k) : [k];
|
|
||||||
_name.toString = function () {
|
|
||||||
// fallback for old one
|
|
||||||
return this.join(' - ');
|
|
||||||
};
|
|
||||||
|
|
||||||
if (typeof prop === 'function') {
|
|
||||||
var in_name = false,
|
|
||||||
in_specific_test = (_name.toString() === opt.testFullSpec) ? true : false;
|
|
||||||
for (var i = 0; i < _name.length; i += 1) {
|
|
||||||
if (_name[i] === opt.testspec) {
|
|
||||||
in_name = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((!opt.testFullSpec || in_specific_test) && (!opt.testspec || in_name)) {
|
|
||||||
if (opt.moduleStart) {
|
|
||||||
opt.moduleStart();
|
|
||||||
}
|
|
||||||
exports.runTest(_name, suite[k], opt, cb);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return cb();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
exports.runSuite(_name, suite[k], opt, cb);
|
|
||||||
}
|
|
||||||
}, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run each exported test function or test suite from a loaded module.
|
|
||||||
*
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Object} mod
|
|
||||||
* @param {Object} opt
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.runModule = function (name, mod, opt, callback) {
|
|
||||||
var options = _copy(types.options(opt));
|
|
||||||
|
|
||||||
var _run = false;
|
|
||||||
var _moduleStart = options.moduleStart;
|
|
||||||
|
|
||||||
mod = wrapGroup(mod);
|
|
||||||
|
|
||||||
function run_once() {
|
|
||||||
if (!_run) {
|
|
||||||
_run = true;
|
|
||||||
_moduleStart(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
options.moduleStart = run_once;
|
|
||||||
|
|
||||||
var start = new Date().getTime();
|
|
||||||
|
|
||||||
exports.runSuite(null, mod, options, function (err, a_list) {
|
|
||||||
var end = new Date().getTime();
|
|
||||||
var assertion_list = types.assertionList(a_list, end - start);
|
|
||||||
options.moduleDone(name, assertion_list);
|
|
||||||
if (nodeunit.complete) {
|
|
||||||
nodeunit.complete(name, assertion_list);
|
|
||||||
}
|
|
||||||
callback(null, a_list);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Treats an object literal as a list of modules keyed by name. Runs each
|
|
||||||
* module and finished with calling 'done'. You can think of this as a browser
|
|
||||||
* safe alternative to runFiles in the nodeunit module.
|
|
||||||
*
|
|
||||||
* @param {Object} modules
|
|
||||||
* @param {Object} opt
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO: add proper unit tests for this function
|
|
||||||
exports.runModules = function (modules, opt) {
|
|
||||||
var all_assertions = [];
|
|
||||||
var options = types.options(opt);
|
|
||||||
var start = new Date().getTime();
|
|
||||||
|
|
||||||
async.concatSeries(_keys(modules), function (k, cb) {
|
|
||||||
exports.runModule(k, modules[k], options, cb);
|
|
||||||
},
|
|
||||||
function (err, all_assertions) {
|
|
||||||
var end = new Date().getTime();
|
|
||||||
options.done(types.assertionList(all_assertions, end - start));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps a test function with setUp and tearDown functions.
|
|
||||||
* Used by testCase.
|
|
||||||
*
|
|
||||||
* @param {Function} setUp
|
|
||||||
* @param {Function} tearDown
|
|
||||||
* @param {Function} fn
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
var wrapTest = function (setUp, tearDown, fn) {
|
|
||||||
return function (test) {
|
|
||||||
var context = {};
|
|
||||||
if (tearDown) {
|
|
||||||
var done = test.done;
|
|
||||||
test.done = function (err) {
|
|
||||||
try {
|
|
||||||
tearDown.call(context, function (err2) {
|
|
||||||
if (err && err2) {
|
|
||||||
test._assertion_list.push(
|
|
||||||
types.assertion({error: err})
|
|
||||||
);
|
|
||||||
return done(err2);
|
|
||||||
}
|
|
||||||
done(err || err2);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
done(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (setUp) {
|
|
||||||
setUp.call(context, function (err) {
|
|
||||||
if (err) {
|
|
||||||
return test.done(err);
|
|
||||||
}
|
|
||||||
fn.call(context, test);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fn.call(context, test);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a serial callback from two functions.
|
|
||||||
*
|
|
||||||
* @param {Function} funcFirst
|
|
||||||
* @param {Function} funcSecond
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
var getSerialCallback = function (fns) {
|
|
||||||
if (!fns.length) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return function (callback) {
|
|
||||||
var that = this;
|
|
||||||
var bound_fns = [];
|
|
||||||
for (var i = 0, len = fns.length; i < len; i++) {
|
|
||||||
(function (j) {
|
|
||||||
bound_fns.push(function () {
|
|
||||||
return fns[j].apply(that, arguments);
|
|
||||||
});
|
|
||||||
})(i);
|
|
||||||
}
|
|
||||||
return async.series(bound_fns, callback);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps a group of tests with setUp and tearDown functions.
|
|
||||||
* Used by testCase.
|
|
||||||
*
|
|
||||||
* @param {Object} group
|
|
||||||
* @param {Array} setUps - parent setUp functions
|
|
||||||
* @param {Array} tearDowns - parent tearDown functions
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
var wrapGroup = function (group, setUps, tearDowns) {
|
|
||||||
var tests = {};
|
|
||||||
|
|
||||||
var setUps = setUps ? setUps.slice(): [];
|
|
||||||
var tearDowns = tearDowns ? tearDowns.slice(): [];
|
|
||||||
|
|
||||||
if (group.setUp) {
|
|
||||||
setUps.push(group.setUp);
|
|
||||||
delete group.setUp;
|
|
||||||
}
|
|
||||||
if (group.tearDown) {
|
|
||||||
tearDowns.unshift(group.tearDown);
|
|
||||||
delete group.tearDown;
|
|
||||||
}
|
|
||||||
|
|
||||||
var keys = _keys(group);
|
|
||||||
|
|
||||||
for (var i = 0; i < keys.length; i += 1) {
|
|
||||||
var k = keys[i];
|
|
||||||
if (typeof group[k] === 'function') {
|
|
||||||
tests[k] = wrapTest(
|
|
||||||
getSerialCallback(setUps),
|
|
||||||
getSerialCallback(tearDowns),
|
|
||||||
group[k]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (typeof group[k] === 'object') {
|
|
||||||
tests[k] = wrapGroup(group[k], setUps, tearDowns);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tests;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Backwards compatibility for test suites using old testCase API
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.testCase = function (suite) {
|
|
||||||
return suite;
|
|
||||||
};
|
|
||||||
})(core);
|
|
||||||
(function(exports){
|
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*
|
|
||||||
* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
|
|
||||||
* Only code on that line will be removed, its mostly to avoid requiring code
|
|
||||||
* that is node specific
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* NOTE: this test runner is not listed in index.js because it cannot be
|
|
||||||
* used with the command-line tool, only inside the browser.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reporter info string
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.info = "Browser-based test reporter";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run all tests within each module, reporting the results
|
|
||||||
*
|
|
||||||
* @param {Array} files
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.run = function (modules, options, callback) {
|
|
||||||
var start = new Date().getTime(), div;
|
|
||||||
options = options || {};
|
|
||||||
div = options.div || document.body;
|
|
||||||
|
|
||||||
function setText(el, txt) {
|
|
||||||
if ('innerText' in el) {
|
|
||||||
el.innerText = txt;
|
|
||||||
}
|
|
||||||
else if ('textContent' in el){
|
|
||||||
el.textContent = txt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getOrCreate(tag, id) {
|
|
||||||
var el = document.getElementById(id);
|
|
||||||
if (!el) {
|
|
||||||
el = document.createElement(tag);
|
|
||||||
el.id = id;
|
|
||||||
div.appendChild(el);
|
|
||||||
}
|
|
||||||
return el;
|
|
||||||
};
|
|
||||||
|
|
||||||
var header = getOrCreate('h1', 'nodeunit-header');
|
|
||||||
var banner = getOrCreate('h2', 'nodeunit-banner');
|
|
||||||
var userAgent = getOrCreate('h2', 'nodeunit-userAgent');
|
|
||||||
var tests = getOrCreate('ol', 'nodeunit-tests');
|
|
||||||
var result = getOrCreate('p', 'nodeunit-testresult');
|
|
||||||
|
|
||||||
setText(userAgent, navigator.userAgent);
|
|
||||||
|
|
||||||
nodeunit.runModules(modules, {
|
|
||||||
moduleStart: function (name) {
|
|
||||||
/*var mheading = document.createElement('h2');
|
|
||||||
mheading.innerText = name;
|
|
||||||
results.appendChild(mheading);
|
|
||||||
module = document.createElement('ol');
|
|
||||||
results.appendChild(module);*/
|
|
||||||
},
|
|
||||||
testDone: function (name, assertions) {
|
|
||||||
var test = document.createElement('li');
|
|
||||||
var strong = document.createElement('strong');
|
|
||||||
strong.innerHTML = name + ' <b style="color: black;">(' +
|
|
||||||
'<b class="fail">' + assertions.failures() + '</b>, ' +
|
|
||||||
'<b class="pass">' + assertions.passes() + '</b>, ' +
|
|
||||||
assertions.length +
|
|
||||||
')</b>';
|
|
||||||
test.className = assertions.failures() ? 'fail': 'pass';
|
|
||||||
test.appendChild(strong);
|
|
||||||
|
|
||||||
var aList = document.createElement('ol');
|
|
||||||
aList.style.display = 'none';
|
|
||||||
test.onclick = function () {
|
|
||||||
var d = aList.style.display;
|
|
||||||
aList.style.display = (d == 'none') ? 'block': 'none';
|
|
||||||
};
|
|
||||||
for (var i=0; i<assertions.length; i++) {
|
|
||||||
var li = document.createElement('li');
|
|
||||||
var a = assertions[i];
|
|
||||||
if (a.failed()) {
|
|
||||||
li.innerHTML = (a.message || a.method || 'no message') +
|
|
||||||
'<pre>' + (a.error.stack || a.error) + '</pre>';
|
|
||||||
li.className = 'fail';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
li.innerHTML = a.message || a.method || 'no message';
|
|
||||||
li.className = 'pass';
|
|
||||||
}
|
|
||||||
aList.appendChild(li);
|
|
||||||
}
|
|
||||||
test.appendChild(aList);
|
|
||||||
tests.appendChild(test);
|
|
||||||
},
|
|
||||||
done: function (assertions) {
|
|
||||||
var end = new Date().getTime();
|
|
||||||
var duration = end - start;
|
|
||||||
|
|
||||||
var failures = assertions.failures();
|
|
||||||
banner.className = failures ? 'fail': 'pass';
|
|
||||||
|
|
||||||
result.innerHTML = 'Tests completed in ' + duration +
|
|
||||||
' milliseconds.<br/><span class="passed">' +
|
|
||||||
assertions.passes() + '</span> assertions of ' +
|
|
||||||
'<span class="all">' + assertions.length + '<span> passed, ' +
|
|
||||||
assertions.failures() + ' failed.';
|
|
||||||
|
|
||||||
if (callback) callback(assertions.failures() ? new Error('We have got test failures.') : undefined);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
})(reporter);
|
|
||||||
nodeunit = core;
|
|
||||||
nodeunit.assert = assert;
|
|
||||||
nodeunit.reporter = reporter;
|
|
||||||
nodeunit.run = reporter.run;
|
|
||||||
return nodeunit; })();
|
|
66
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/doc/nodeunit.md
generated
vendored
66
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/doc/nodeunit.md
generated
vendored
|
@ -1,66 +0,0 @@
|
||||||
nodeunit(1) -- simple node.js unit testing tool
|
|
||||||
===============================================
|
|
||||||
|
|
||||||
## SYNOPSIS
|
|
||||||
|
|
||||||
nodeunit [options] <file-or-directory> [<file-or-directory> ...]
|
|
||||||
|
|
||||||
## DESCRIPTION
|
|
||||||
|
|
||||||
Nodeunit is a simple unit testing tool based on the node.js assert module.
|
|
||||||
|
|
||||||
* Simple to use
|
|
||||||
* Just export the tests from a module
|
|
||||||
* Helps you avoid common pitfalls when testing asynchronous code
|
|
||||||
* Easy to add test cases with setUp and tearDown functions if you wish
|
|
||||||
* Allows the use of mocks and stubs
|
|
||||||
|
|
||||||
## OPTIONS
|
|
||||||
|
|
||||||
__--config FILE__:
|
|
||||||
Load config options from a JSON file, allows the customisation
|
|
||||||
of color schemes for the default test reporter etc.
|
|
||||||
See bin/nodeunit.json for current available options.
|
|
||||||
|
|
||||||
__--reporter FILE__:
|
|
||||||
You can set the test reporter to a custom module or on of the modules
|
|
||||||
in nodeunit/lib/reporters, when omitted, the default test runner is used.
|
|
||||||
|
|
||||||
__--list-reporters__:
|
|
||||||
List available build-in reporters.
|
|
||||||
|
|
||||||
__-t testName__:
|
|
||||||
Run specifc test only.
|
|
||||||
|
|
||||||
__-f fullTestName__:
|
|
||||||
Run specific test only. fullTestName is built so: "outerGroup - .. - innerGroup - testName".
|
|
||||||
|
|
||||||
__-h__, __--help__:
|
|
||||||
Display the help and exit.
|
|
||||||
|
|
||||||
__-v__, __--version__:
|
|
||||||
Output version information and exit.
|
|
||||||
|
|
||||||
__<file-or-directory>__:
|
|
||||||
You can run nodeunit on specific files or on all *\*.js* files inside
|
|
||||||
a directory.
|
|
||||||
|
|
||||||
## AUTHORS
|
|
||||||
|
|
||||||
Written by Caolan McMahon and other nodeunit contributors.
|
|
||||||
Contributors list: <http://github.com/caolan/nodeunit/contributors>.
|
|
||||||
|
|
||||||
## REPORTING BUGS
|
|
||||||
|
|
||||||
Report nodeunit bugs to <http://github.com/caolan/nodeunit/issues>.
|
|
||||||
|
|
||||||
## COPYRIGHT
|
|
||||||
|
|
||||||
Copyright © 2010 Caolan McMahon.
|
|
||||||
Nodeunit has been released under the MIT license:
|
|
||||||
<http://github.com/caolan/nodeunit/raw/master/LICENSE>.
|
|
||||||
|
|
||||||
## SEE ALSO
|
|
||||||
|
|
||||||
node(1)
|
|
||||||
|
|
2034
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/examples/browser/nodeunit.js
generated
vendored
2034
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/examples/browser/nodeunit.js
generated
vendored
|
@ -1,2034 +0,0 @@
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* https://github.com/caolan/nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*
|
|
||||||
* json2.js
|
|
||||||
* http://www.JSON.org/json2.js
|
|
||||||
* Public Domain.
|
|
||||||
* NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
|
||||||
*/
|
|
||||||
nodeunit = (function(){
|
|
||||||
/*
|
|
||||||
http://www.JSON.org/json2.js
|
|
||||||
2010-11-17
|
|
||||||
|
|
||||||
Public Domain.
|
|
||||||
|
|
||||||
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
|
||||||
|
|
||||||
See http://www.JSON.org/js.html
|
|
||||||
|
|
||||||
|
|
||||||
This code should be minified before deployment.
|
|
||||||
See http://javascript.crockford.com/jsmin.html
|
|
||||||
|
|
||||||
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
|
|
||||||
NOT CONTROL.
|
|
||||||
|
|
||||||
|
|
||||||
This file creates a global JSON object containing two methods: stringify
|
|
||||||
and parse.
|
|
||||||
|
|
||||||
JSON.stringify(value, replacer, space)
|
|
||||||
value any JavaScript value, usually an object or array.
|
|
||||||
|
|
||||||
replacer an optional parameter that determines how object
|
|
||||||
values are stringified for objects. It can be a
|
|
||||||
function or an array of strings.
|
|
||||||
|
|
||||||
space an optional parameter that specifies the indentation
|
|
||||||
of nested structures. If it is omitted, the text will
|
|
||||||
be packed without extra whitespace. If it is a number,
|
|
||||||
it will specify the number of spaces to indent at each
|
|
||||||
level. If it is a string (such as '\t' or ' '),
|
|
||||||
it contains the characters used to indent at each level.
|
|
||||||
|
|
||||||
This method produces a JSON text from a JavaScript value.
|
|
||||||
|
|
||||||
When an object value is found, if the object contains a toJSON
|
|
||||||
method, its toJSON method will be called and the result will be
|
|
||||||
stringified. A toJSON method does not serialize: it returns the
|
|
||||||
value represented by the name/value pair that should be serialized,
|
|
||||||
or undefined if nothing should be serialized. The toJSON method
|
|
||||||
will be passed the key associated with the value, and this will be
|
|
||||||
bound to the value
|
|
||||||
|
|
||||||
For example, this would serialize Dates as ISO strings.
|
|
||||||
|
|
||||||
Date.prototype.toJSON = function (key) {
|
|
||||||
function f(n) {
|
|
||||||
// Format integers to have at least two digits.
|
|
||||||
return n < 10 ? '0' + n : n;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.getUTCFullYear() + '-' +
|
|
||||||
f(this.getUTCMonth() + 1) + '-' +
|
|
||||||
f(this.getUTCDate()) + 'T' +
|
|
||||||
f(this.getUTCHours()) + ':' +
|
|
||||||
f(this.getUTCMinutes()) + ':' +
|
|
||||||
f(this.getUTCSeconds()) + 'Z';
|
|
||||||
};
|
|
||||||
|
|
||||||
You can provide an optional replacer method. It will be passed the
|
|
||||||
key and value of each member, with this bound to the containing
|
|
||||||
object. The value that is returned from your method will be
|
|
||||||
serialized. If your method returns undefined, then the member will
|
|
||||||
be excluded from the serialization.
|
|
||||||
|
|
||||||
If the replacer parameter is an array of strings, then it will be
|
|
||||||
used to select the members to be serialized. It filters the results
|
|
||||||
such that only members with keys listed in the replacer array are
|
|
||||||
stringified.
|
|
||||||
|
|
||||||
Values that do not have JSON representations, such as undefined or
|
|
||||||
functions, will not be serialized. Such values in objects will be
|
|
||||||
dropped; in arrays they will be replaced with null. You can use
|
|
||||||
a replacer function to replace those with JSON values.
|
|
||||||
JSON.stringify(undefined) returns undefined.
|
|
||||||
|
|
||||||
The optional space parameter produces a stringification of the
|
|
||||||
value that is filled with line breaks and indentation to make it
|
|
||||||
easier to read.
|
|
||||||
|
|
||||||
If the space parameter is a non-empty string, then that string will
|
|
||||||
be used for indentation. If the space parameter is a number, then
|
|
||||||
the indentation will be that many spaces.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
text = JSON.stringify(['e', {pluribus: 'unum'}]);
|
|
||||||
// text is '["e",{"pluribus":"unum"}]'
|
|
||||||
|
|
||||||
|
|
||||||
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
|
|
||||||
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
|
|
||||||
|
|
||||||
text = JSON.stringify([new Date()], function (key, value) {
|
|
||||||
return this[key] instanceof Date ?
|
|
||||||
'Date(' + this[key] + ')' : value;
|
|
||||||
});
|
|
||||||
// text is '["Date(---current time---)"]'
|
|
||||||
|
|
||||||
|
|
||||||
JSON.parse(text, reviver)
|
|
||||||
This method parses a JSON text to produce an object or array.
|
|
||||||
It can throw a SyntaxError exception.
|
|
||||||
|
|
||||||
The optional reviver parameter is a function that can filter and
|
|
||||||
transform the results. It receives each of the keys and values,
|
|
||||||
and its return value is used instead of the original value.
|
|
||||||
If it returns what it received, then the structure is not modified.
|
|
||||||
If it returns undefined then the member is deleted.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
// Parse the text. Values that look like ISO date strings will
|
|
||||||
// be converted to Date objects.
|
|
||||||
|
|
||||||
myData = JSON.parse(text, function (key, value) {
|
|
||||||
var a;
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
a =
|
|
||||||
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
|
|
||||||
if (a) {
|
|
||||||
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
|
|
||||||
+a[5], +a[6]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
});
|
|
||||||
|
|
||||||
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
|
|
||||||
var d;
|
|
||||||
if (typeof value === 'string' &&
|
|
||||||
value.slice(0, 5) === 'Date(' &&
|
|
||||||
value.slice(-1) === ')') {
|
|
||||||
d = new Date(value.slice(5, -1));
|
|
||||||
if (d) {
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
This is a reference implementation. You are free to copy, modify, or
|
|
||||||
redistribute.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*jslint evil: true, strict: false, regexp: false */
|
|
||||||
|
|
||||||
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
|
|
||||||
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
|
|
||||||
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
|
|
||||||
lastIndex, length, parse, prototype, push, replace, slice, stringify,
|
|
||||||
test, toJSON, toString, valueOf
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// Create a JSON object only if one does not already exist. We create the
|
|
||||||
// methods in a closure to avoid creating global variables.
|
|
||||||
|
|
||||||
var JSON = {};
|
|
||||||
|
|
||||||
(function () {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
function f(n) {
|
|
||||||
// Format integers to have at least two digits.
|
|
||||||
return n < 10 ? '0' + n : n;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof Date.prototype.toJSON !== 'function') {
|
|
||||||
|
|
||||||
Date.prototype.toJSON = function (key) {
|
|
||||||
|
|
||||||
return isFinite(this.valueOf()) ?
|
|
||||||
this.getUTCFullYear() + '-' +
|
|
||||||
f(this.getUTCMonth() + 1) + '-' +
|
|
||||||
f(this.getUTCDate()) + 'T' +
|
|
||||||
f(this.getUTCHours()) + ':' +
|
|
||||||
f(this.getUTCMinutes()) + ':' +
|
|
||||||
f(this.getUTCSeconds()) + 'Z' : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
String.prototype.toJSON =
|
|
||||||
Number.prototype.toJSON =
|
|
||||||
Boolean.prototype.toJSON = function (key) {
|
|
||||||
return this.valueOf();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
|
||||||
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
|
||||||
gap,
|
|
||||||
indent,
|
|
||||||
meta = { // table of character substitutions
|
|
||||||
'\b': '\\b',
|
|
||||||
'\t': '\\t',
|
|
||||||
'\n': '\\n',
|
|
||||||
'\f': '\\f',
|
|
||||||
'\r': '\\r',
|
|
||||||
'"' : '\\"',
|
|
||||||
'\\': '\\\\'
|
|
||||||
},
|
|
||||||
rep;
|
|
||||||
|
|
||||||
|
|
||||||
function quote(string) {
|
|
||||||
|
|
||||||
// If the string contains no control characters, no quote characters, and no
|
|
||||||
// backslash characters, then we can safely slap some quotes around it.
|
|
||||||
// Otherwise we must also replace the offending characters with safe escape
|
|
||||||
// sequences.
|
|
||||||
|
|
||||||
escapable.lastIndex = 0;
|
|
||||||
return escapable.test(string) ?
|
|
||||||
'"' + string.replace(escapable, function (a) {
|
|
||||||
var c = meta[a];
|
|
||||||
return typeof c === 'string' ? c :
|
|
||||||
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
|
||||||
}) + '"' :
|
|
||||||
'"' + string + '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function str(key, holder) {
|
|
||||||
|
|
||||||
// Produce a string from holder[key].
|
|
||||||
|
|
||||||
var i, // The loop counter.
|
|
||||||
k, // The member key.
|
|
||||||
v, // The member value.
|
|
||||||
length,
|
|
||||||
mind = gap,
|
|
||||||
partial,
|
|
||||||
value = holder[key];
|
|
||||||
|
|
||||||
// If the value has a toJSON method, call it to obtain a replacement value.
|
|
||||||
|
|
||||||
if (value && typeof value === 'object' &&
|
|
||||||
typeof value.toJSON === 'function') {
|
|
||||||
value = value.toJSON(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we were called with a replacer function, then call the replacer to
|
|
||||||
// obtain a replacement value.
|
|
||||||
|
|
||||||
if (typeof rep === 'function') {
|
|
||||||
value = rep.call(holder, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// What happens next depends on the value's type.
|
|
||||||
|
|
||||||
switch (typeof value) {
|
|
||||||
case 'string':
|
|
||||||
return quote(value);
|
|
||||||
|
|
||||||
case 'number':
|
|
||||||
|
|
||||||
// JSON numbers must be finite. Encode non-finite numbers as null.
|
|
||||||
|
|
||||||
return isFinite(value) ? String(value) : 'null';
|
|
||||||
|
|
||||||
case 'boolean':
|
|
||||||
case 'null':
|
|
||||||
|
|
||||||
// If the value is a boolean or null, convert it to a string. Note:
|
|
||||||
// typeof null does not produce 'null'. The case is included here in
|
|
||||||
// the remote chance that this gets fixed someday.
|
|
||||||
|
|
||||||
return String(value);
|
|
||||||
|
|
||||||
// If the type is 'object', we might be dealing with an object or an array or
|
|
||||||
// null.
|
|
||||||
|
|
||||||
case 'object':
|
|
||||||
|
|
||||||
// Due to a specification blunder in ECMAScript, typeof null is 'object',
|
|
||||||
// so watch out for that case.
|
|
||||||
|
|
||||||
if (!value) {
|
|
||||||
return 'null';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make an array to hold the partial results of stringifying this object value.
|
|
||||||
|
|
||||||
gap += indent;
|
|
||||||
partial = [];
|
|
||||||
|
|
||||||
// Is the value an array?
|
|
||||||
|
|
||||||
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
|
||||||
|
|
||||||
// The value is an array. Stringify every element. Use null as a placeholder
|
|
||||||
// for non-JSON values.
|
|
||||||
|
|
||||||
length = value.length;
|
|
||||||
for (i = 0; i < length; i += 1) {
|
|
||||||
partial[i] = str(i, value) || 'null';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join all of the elements together, separated with commas, and wrap them in
|
|
||||||
// brackets.
|
|
||||||
|
|
||||||
v = partial.length === 0 ? '[]' :
|
|
||||||
gap ? '[\n' + gap +
|
|
||||||
partial.join(',\n' + gap) + '\n' +
|
|
||||||
mind + ']' :
|
|
||||||
'[' + partial.join(',') + ']';
|
|
||||||
gap = mind;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the replacer is an array, use it to select the members to be stringified.
|
|
||||||
|
|
||||||
if (rep && typeof rep === 'object') {
|
|
||||||
length = rep.length;
|
|
||||||
for (i = 0; i < length; i += 1) {
|
|
||||||
k = rep[i];
|
|
||||||
if (typeof k === 'string') {
|
|
||||||
v = str(k, value);
|
|
||||||
if (v) {
|
|
||||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Otherwise, iterate through all of the keys in the object.
|
|
||||||
|
|
||||||
for (k in value) {
|
|
||||||
if (Object.hasOwnProperty.call(value, k)) {
|
|
||||||
v = str(k, value);
|
|
||||||
if (v) {
|
|
||||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join all of the member texts together, separated with commas,
|
|
||||||
// and wrap them in braces.
|
|
||||||
|
|
||||||
v = partial.length === 0 ? '{}' :
|
|
||||||
gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
|
|
||||||
mind + '}' : '{' + partial.join(',') + '}';
|
|
||||||
gap = mind;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the JSON object does not yet have a stringify method, give it one.
|
|
||||||
|
|
||||||
if (typeof JSON.stringify !== 'function') {
|
|
||||||
JSON.stringify = function (value, replacer, space) {
|
|
||||||
|
|
||||||
// The stringify method takes a value and an optional replacer, and an optional
|
|
||||||
// space parameter, and returns a JSON text. The replacer can be a function
|
|
||||||
// that can replace values, or an array of strings that will select the keys.
|
|
||||||
// A default replacer method can be provided. Use of the space parameter can
|
|
||||||
// produce text that is more easily readable.
|
|
||||||
|
|
||||||
var i;
|
|
||||||
gap = '';
|
|
||||||
indent = '';
|
|
||||||
|
|
||||||
// If the space parameter is a number, make an indent string containing that
|
|
||||||
// many spaces.
|
|
||||||
|
|
||||||
if (typeof space === 'number') {
|
|
||||||
for (i = 0; i < space; i += 1) {
|
|
||||||
indent += ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the space parameter is a string, it will be used as the indent string.
|
|
||||||
|
|
||||||
} else if (typeof space === 'string') {
|
|
||||||
indent = space;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is a replacer, it must be a function or an array.
|
|
||||||
// Otherwise, throw an error.
|
|
||||||
|
|
||||||
rep = replacer;
|
|
||||||
if (replacer && typeof replacer !== 'function' &&
|
|
||||||
(typeof replacer !== 'object' ||
|
|
||||||
typeof replacer.length !== 'number')) {
|
|
||||||
throw new Error('JSON.stringify');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a fake root object containing our value under the key of ''.
|
|
||||||
// Return the result of stringifying the value.
|
|
||||||
|
|
||||||
return str('', {'': value});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// If the JSON object does not yet have a parse method, give it one.
|
|
||||||
|
|
||||||
if (typeof JSON.parse !== 'function') {
|
|
||||||
JSON.parse = function (text, reviver) {
|
|
||||||
|
|
||||||
// The parse method takes a text and an optional reviver function, and returns
|
|
||||||
// a JavaScript value if the text is a valid JSON text.
|
|
||||||
|
|
||||||
var j;
|
|
||||||
|
|
||||||
function walk(holder, key) {
|
|
||||||
|
|
||||||
// The walk method is used to recursively walk the resulting structure so
|
|
||||||
// that modifications can be made.
|
|
||||||
|
|
||||||
var k, v, value = holder[key];
|
|
||||||
if (value && typeof value === 'object') {
|
|
||||||
for (k in value) {
|
|
||||||
if (Object.hasOwnProperty.call(value, k)) {
|
|
||||||
v = walk(value, k);
|
|
||||||
if (v !== undefined) {
|
|
||||||
value[k] = v;
|
|
||||||
} else {
|
|
||||||
delete value[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return reviver.call(holder, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Parsing happens in four stages. In the first stage, we replace certain
|
|
||||||
// Unicode characters with escape sequences. JavaScript handles many characters
|
|
||||||
// incorrectly, either silently deleting them, or treating them as line endings.
|
|
||||||
|
|
||||||
text = String(text);
|
|
||||||
cx.lastIndex = 0;
|
|
||||||
if (cx.test(text)) {
|
|
||||||
text = text.replace(cx, function (a) {
|
|
||||||
return '\\u' +
|
|
||||||
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// In the second stage, we run the text against regular expressions that look
|
|
||||||
// for non-JSON patterns. We are especially concerned with '()' and 'new'
|
|
||||||
// because they can cause invocation, and '=' because it can cause mutation.
|
|
||||||
// But just to be safe, we want to reject all unexpected forms.
|
|
||||||
|
|
||||||
// We split the second stage into 4 regexp operations in order to work around
|
|
||||||
// crippling inefficiencies in IE's and Safari's regexp engines. First we
|
|
||||||
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
|
|
||||||
// replace all simple value tokens with ']' characters. Third, we delete all
|
|
||||||
// open brackets that follow a colon or comma or that begin the text. Finally,
|
|
||||||
// we look to see that the remaining characters are only whitespace or ']' or
|
|
||||||
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
|
|
||||||
|
|
||||||
if (/^[\],:{}\s]*$/
|
|
||||||
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
|
|
||||||
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
|
|
||||||
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
|
||||||
|
|
||||||
// In the third stage we use the eval function to compile the text into a
|
|
||||||
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
|
||||||
// in JavaScript: it can begin a block or an object literal. We wrap the text
|
|
||||||
// in parens to eliminate the ambiguity.
|
|
||||||
|
|
||||||
j = eval('(' + text + ')');
|
|
||||||
|
|
||||||
// In the optional fourth stage, we recursively walk the new structure, passing
|
|
||||||
// each name/value pair to a reviver function for possible transformation.
|
|
||||||
|
|
||||||
return typeof reviver === 'function' ?
|
|
||||||
walk({'': j}, '') : j;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the text is not JSON parseable, then a SyntaxError is thrown.
|
|
||||||
|
|
||||||
throw new SyntaxError('JSON.parse');
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}());
|
|
||||||
var assert = this.assert = {};
|
|
||||||
var types = {};
|
|
||||||
var core = {};
|
|
||||||
var nodeunit = {};
|
|
||||||
var reporter = {};
|
|
||||||
/*global setTimeout: false, console: false */
|
|
||||||
(function () {
|
|
||||||
|
|
||||||
var async = {};
|
|
||||||
|
|
||||||
// global on the server, window in the browser
|
|
||||||
var root = this,
|
|
||||||
previous_async = root.async;
|
|
||||||
|
|
||||||
if (typeof module !== 'undefined' && module.exports) {
|
|
||||||
module.exports = async;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
root.async = async;
|
|
||||||
}
|
|
||||||
|
|
||||||
async.noConflict = function () {
|
|
||||||
root.async = previous_async;
|
|
||||||
return async;
|
|
||||||
};
|
|
||||||
|
|
||||||
//// cross-browser compatiblity functions ////
|
|
||||||
|
|
||||||
var _forEach = function (arr, iterator) {
|
|
||||||
if (arr.forEach) {
|
|
||||||
return arr.forEach(iterator);
|
|
||||||
}
|
|
||||||
for (var i = 0; i < arr.length; i += 1) {
|
|
||||||
iterator(arr[i], i, arr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var _map = function (arr, iterator) {
|
|
||||||
if (arr.map) {
|
|
||||||
return arr.map(iterator);
|
|
||||||
}
|
|
||||||
var results = [];
|
|
||||||
_forEach(arr, function (x, i, a) {
|
|
||||||
results.push(iterator(x, i, a));
|
|
||||||
});
|
|
||||||
return results;
|
|
||||||
};
|
|
||||||
|
|
||||||
var _reduce = function (arr, iterator, memo) {
|
|
||||||
if (arr.reduce) {
|
|
||||||
return arr.reduce(iterator, memo);
|
|
||||||
}
|
|
||||||
_forEach(arr, function (x, i, a) {
|
|
||||||
memo = iterator(memo, x, i, a);
|
|
||||||
});
|
|
||||||
return memo;
|
|
||||||
};
|
|
||||||
|
|
||||||
var _keys = function (obj) {
|
|
||||||
if (Object.keys) {
|
|
||||||
return Object.keys(obj);
|
|
||||||
}
|
|
||||||
var keys = [];
|
|
||||||
for (var k in obj) {
|
|
||||||
if (obj.hasOwnProperty(k)) {
|
|
||||||
keys.push(k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
};
|
|
||||||
|
|
||||||
var _indexOf = function (arr, item) {
|
|
||||||
if (arr.indexOf) {
|
|
||||||
return arr.indexOf(item);
|
|
||||||
}
|
|
||||||
for (var i = 0; i < arr.length; i += 1) {
|
|
||||||
if (arr[i] === item) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
//// exported async module functions ////
|
|
||||||
|
|
||||||
//// nextTick implementation with browser-compatible fallback ////
|
|
||||||
if (typeof process === 'undefined' || !(process.nextTick)) {
|
|
||||||
async.nextTick = function (fn) {
|
|
||||||
setTimeout(fn, 0);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
async.nextTick = process.nextTick;
|
|
||||||
}
|
|
||||||
|
|
||||||
async.forEach = function (arr, iterator, callback) {
|
|
||||||
if (!arr.length) {
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
var completed = 0;
|
|
||||||
_forEach(arr, function (x) {
|
|
||||||
iterator(x, function (err) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
callback = function () {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
completed += 1;
|
|
||||||
if (completed === arr.length) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
async.forEachSeries = function (arr, iterator, callback) {
|
|
||||||
if (!arr.length) {
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
var completed = 0;
|
|
||||||
var iterate = function () {
|
|
||||||
iterator(arr[completed], function (err) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
callback = function () {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
completed += 1;
|
|
||||||
if (completed === arr.length) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
iterate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
iterate();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var doParallel = function (fn) {
|
|
||||||
return function () {
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
return fn.apply(null, [async.forEach].concat(args));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
var doSeries = function (fn) {
|
|
||||||
return function () {
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
return fn.apply(null, [async.forEachSeries].concat(args));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var _asyncMap = function (eachfn, arr, iterator, callback) {
|
|
||||||
var results = [];
|
|
||||||
arr = _map(arr, function (x, i) {
|
|
||||||
return {index: i, value: x};
|
|
||||||
});
|
|
||||||
eachfn(arr, function (x, callback) {
|
|
||||||
iterator(x.value, function (err, v) {
|
|
||||||
results[x.index] = v;
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, results);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.map = doParallel(_asyncMap);
|
|
||||||
async.mapSeries = doSeries(_asyncMap);
|
|
||||||
|
|
||||||
|
|
||||||
// reduce only has a series version, as doing reduce in parallel won't
|
|
||||||
// work in many situations.
|
|
||||||
async.reduce = function (arr, memo, iterator, callback) {
|
|
||||||
async.forEachSeries(arr, function (x, callback) {
|
|
||||||
iterator(memo, x, function (err, v) {
|
|
||||||
memo = v;
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, memo);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// inject alias
|
|
||||||
async.inject = async.reduce;
|
|
||||||
// foldl alias
|
|
||||||
async.foldl = async.reduce;
|
|
||||||
|
|
||||||
async.reduceRight = function (arr, memo, iterator, callback) {
|
|
||||||
var reversed = _map(arr, function (x) {
|
|
||||||
return x;
|
|
||||||
}).reverse();
|
|
||||||
async.reduce(reversed, memo, iterator, callback);
|
|
||||||
};
|
|
||||||
// foldr alias
|
|
||||||
async.foldr = async.reduceRight;
|
|
||||||
|
|
||||||
var _filter = function (eachfn, arr, iterator, callback) {
|
|
||||||
var results = [];
|
|
||||||
arr = _map(arr, function (x, i) {
|
|
||||||
return {index: i, value: x};
|
|
||||||
});
|
|
||||||
eachfn(arr, function (x, callback) {
|
|
||||||
iterator(x.value, function (v) {
|
|
||||||
if (v) {
|
|
||||||
results.push(x);
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(_map(results.sort(function (a, b) {
|
|
||||||
return a.index - b.index;
|
|
||||||
}), function (x) {
|
|
||||||
return x.value;
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.filter = doParallel(_filter);
|
|
||||||
async.filterSeries = doSeries(_filter);
|
|
||||||
// select alias
|
|
||||||
async.select = async.filter;
|
|
||||||
async.selectSeries = async.filterSeries;
|
|
||||||
|
|
||||||
var _reject = function (eachfn, arr, iterator, callback) {
|
|
||||||
var results = [];
|
|
||||||
arr = _map(arr, function (x, i) {
|
|
||||||
return {index: i, value: x};
|
|
||||||
});
|
|
||||||
eachfn(arr, function (x, callback) {
|
|
||||||
iterator(x.value, function (v) {
|
|
||||||
if (!v) {
|
|
||||||
results.push(x);
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(_map(results.sort(function (a, b) {
|
|
||||||
return a.index - b.index;
|
|
||||||
}), function (x) {
|
|
||||||
return x.value;
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.reject = doParallel(_reject);
|
|
||||||
async.rejectSeries = doSeries(_reject);
|
|
||||||
|
|
||||||
var _detect = function (eachfn, arr, iterator, main_callback) {
|
|
||||||
eachfn(arr, function (x, callback) {
|
|
||||||
iterator(x, function (result) {
|
|
||||||
if (result) {
|
|
||||||
main_callback(x);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
main_callback();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.detect = doParallel(_detect);
|
|
||||||
async.detectSeries = doSeries(_detect);
|
|
||||||
|
|
||||||
async.some = function (arr, iterator, main_callback) {
|
|
||||||
async.forEach(arr, function (x, callback) {
|
|
||||||
iterator(x, function (v) {
|
|
||||||
if (v) {
|
|
||||||
main_callback(true);
|
|
||||||
main_callback = function () {};
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
main_callback(false);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// any alias
|
|
||||||
async.any = async.some;
|
|
||||||
|
|
||||||
async.every = function (arr, iterator, main_callback) {
|
|
||||||
async.forEach(arr, function (x, callback) {
|
|
||||||
iterator(x, function (v) {
|
|
||||||
if (!v) {
|
|
||||||
main_callback(false);
|
|
||||||
main_callback = function () {};
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
main_callback(true);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// all alias
|
|
||||||
async.all = async.every;
|
|
||||||
|
|
||||||
async.sortBy = function (arr, iterator, callback) {
|
|
||||||
async.map(arr, function (x, callback) {
|
|
||||||
iterator(x, function (err, criteria) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback(null, {value: x, criteria: criteria});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, function (err, results) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var fn = function (left, right) {
|
|
||||||
var a = left.criteria, b = right.criteria;
|
|
||||||
return a < b ? -1 : a > b ? 1 : 0;
|
|
||||||
};
|
|
||||||
callback(null, _map(results.sort(fn), function (x) {
|
|
||||||
return x.value;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
async.auto = function (tasks, callback) {
|
|
||||||
callback = callback || function () {};
|
|
||||||
var keys = _keys(tasks);
|
|
||||||
if (!keys.length) {
|
|
||||||
return callback(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
var completed = [];
|
|
||||||
|
|
||||||
var listeners = [];
|
|
||||||
var addListener = function (fn) {
|
|
||||||
listeners.unshift(fn);
|
|
||||||
};
|
|
||||||
var removeListener = function (fn) {
|
|
||||||
for (var i = 0; i < listeners.length; i += 1) {
|
|
||||||
if (listeners[i] === fn) {
|
|
||||||
listeners.splice(i, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var taskComplete = function () {
|
|
||||||
_forEach(listeners, function (fn) {
|
|
||||||
fn();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
addListener(function () {
|
|
||||||
if (completed.length === keys.length) {
|
|
||||||
callback(null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
_forEach(keys, function (k) {
|
|
||||||
var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
|
|
||||||
var taskCallback = function (err) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
// stop subsequent errors hitting callback multiple times
|
|
||||||
callback = function () {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
completed.push(k);
|
|
||||||
taskComplete();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var requires = task.slice(0, Math.abs(task.length - 1)) || [];
|
|
||||||
var ready = function () {
|
|
||||||
return _reduce(requires, function (a, x) {
|
|
||||||
return (a && _indexOf(completed, x) !== -1);
|
|
||||||
}, true);
|
|
||||||
};
|
|
||||||
if (ready()) {
|
|
||||||
task[task.length - 1](taskCallback);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var listener = function () {
|
|
||||||
if (ready()) {
|
|
||||||
removeListener(listener);
|
|
||||||
task[task.length - 1](taskCallback);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
addListener(listener);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
async.waterfall = function (tasks, callback) {
|
|
||||||
if (!tasks.length) {
|
|
||||||
return callback();
|
|
||||||
}
|
|
||||||
callback = callback || function () {};
|
|
||||||
var wrapIterator = function (iterator) {
|
|
||||||
return function (err) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
callback = function () {};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
var next = iterator.next();
|
|
||||||
if (next) {
|
|
||||||
args.push(wrapIterator(next));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
args.push(callback);
|
|
||||||
}
|
|
||||||
async.nextTick(function () {
|
|
||||||
iterator.apply(null, args);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
wrapIterator(async.iterator(tasks))();
|
|
||||||
};
|
|
||||||
|
|
||||||
async.parallel = function (tasks, callback) {
|
|
||||||
callback = callback || function () {};
|
|
||||||
if (tasks.constructor === Array) {
|
|
||||||
async.map(tasks, function (fn, callback) {
|
|
||||||
if (fn) {
|
|
||||||
fn(function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (args.length <= 1) {
|
|
||||||
args = args[0];
|
|
||||||
}
|
|
||||||
callback.call(null, err, args || null);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, callback);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var results = {};
|
|
||||||
async.forEach(_keys(tasks), function (k, callback) {
|
|
||||||
tasks[k](function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (args.length <= 1) {
|
|
||||||
args = args[0];
|
|
||||||
}
|
|
||||||
results[k] = args;
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, results);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async.series = function (tasks, callback) {
|
|
||||||
callback = callback || function () {};
|
|
||||||
if (tasks.constructor === Array) {
|
|
||||||
async.mapSeries(tasks, function (fn, callback) {
|
|
||||||
if (fn) {
|
|
||||||
fn(function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (args.length <= 1) {
|
|
||||||
args = args[0];
|
|
||||||
}
|
|
||||||
callback.call(null, err, args || null);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, callback);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var results = {};
|
|
||||||
async.forEachSeries(_keys(tasks), function (k, callback) {
|
|
||||||
tasks[k](function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (args.length <= 1) {
|
|
||||||
args = args[0];
|
|
||||||
}
|
|
||||||
results[k] = args;
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, results);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async.iterator = function (tasks) {
|
|
||||||
var makeCallback = function (index) {
|
|
||||||
var fn = function () {
|
|
||||||
if (tasks.length) {
|
|
||||||
tasks[index].apply(null, arguments);
|
|
||||||
}
|
|
||||||
return fn.next();
|
|
||||||
};
|
|
||||||
fn.next = function () {
|
|
||||||
return (index < tasks.length - 1) ? makeCallback(index + 1): null;
|
|
||||||
};
|
|
||||||
return fn;
|
|
||||||
};
|
|
||||||
return makeCallback(0);
|
|
||||||
};
|
|
||||||
|
|
||||||
async.apply = function (fn) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
return function () {
|
|
||||||
return fn.apply(
|
|
||||||
null, args.concat(Array.prototype.slice.call(arguments))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var _concat = function (eachfn, arr, fn, callback) {
|
|
||||||
var r = [];
|
|
||||||
eachfn(arr, function (x, cb) {
|
|
||||||
fn(x, function (err, y) {
|
|
||||||
r = r.concat(y || []);
|
|
||||||
cb(err);
|
|
||||||
});
|
|
||||||
}, function (err) {
|
|
||||||
callback(err, r);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
async.concat = doParallel(_concat);
|
|
||||||
async.concatSeries = doSeries(_concat);
|
|
||||||
|
|
||||||
async.whilst = function (test, iterator, callback) {
|
|
||||||
if (test()) {
|
|
||||||
iterator(function (err) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
async.whilst(test, iterator, callback);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async.until = function (test, iterator, callback) {
|
|
||||||
if (!test()) {
|
|
||||||
iterator(function (err) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
async.until(test, iterator, callback);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async.queue = function (worker, concurrency) {
|
|
||||||
var workers = 0;
|
|
||||||
var tasks = [];
|
|
||||||
var q = {
|
|
||||||
concurrency: concurrency,
|
|
||||||
push: function (data, callback) {
|
|
||||||
tasks.push({data: data, callback: callback});
|
|
||||||
async.nextTick(q.process);
|
|
||||||
},
|
|
||||||
process: function () {
|
|
||||||
if (workers < q.concurrency && tasks.length) {
|
|
||||||
var task = tasks.splice(0, 1)[0];
|
|
||||||
workers += 1;
|
|
||||||
worker(task.data, function () {
|
|
||||||
workers -= 1;
|
|
||||||
if (task.callback) {
|
|
||||||
task.callback.apply(task, arguments);
|
|
||||||
}
|
|
||||||
q.process();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
length: function () {
|
|
||||||
return tasks.length;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return q;
|
|
||||||
};
|
|
||||||
|
|
||||||
var _console_fn = function (name) {
|
|
||||||
return function (fn) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
fn.apply(null, args.concat([function (err) {
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
if (typeof console !== 'undefined') {
|
|
||||||
if (err) {
|
|
||||||
if (console.error) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (console[name]) {
|
|
||||||
_forEach(args, function (x) {
|
|
||||||
console[name](x);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}]));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
async.log = _console_fn('log');
|
|
||||||
async.dir = _console_fn('dir');
|
|
||||||
/*async.info = _console_fn('info');
|
|
||||||
async.warn = _console_fn('warn');
|
|
||||||
async.error = _console_fn('error');*/
|
|
||||||
|
|
||||||
async.memoize = function (fn, hasher) {
|
|
||||||
var memo = {};
|
|
||||||
hasher = hasher || function (x) {
|
|
||||||
return x;
|
|
||||||
};
|
|
||||||
return function () {
|
|
||||||
var args = Array.prototype.slice.call(arguments);
|
|
||||||
var callback = args.pop();
|
|
||||||
var key = hasher.apply(null, args);
|
|
||||||
if (key in memo) {
|
|
||||||
callback.apply(null, memo[key]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fn.apply(null, args.concat([function () {
|
|
||||||
memo[key] = arguments;
|
|
||||||
callback.apply(null, arguments);
|
|
||||||
}]));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}());
|
|
||||||
(function(exports){
|
|
||||||
/**
|
|
||||||
* This file is based on the node.js assert module, but with some small
|
|
||||||
* changes for browser-compatibility
|
|
||||||
* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Added for browser compatibility
|
|
||||||
*/
|
|
||||||
|
|
||||||
var _keys = function(obj){
|
|
||||||
if(Object.keys) return Object.keys(obj);
|
|
||||||
if (typeof obj != 'object' && typeof obj != 'function') {
|
|
||||||
throw new TypeError('-');
|
|
||||||
}
|
|
||||||
var keys = [];
|
|
||||||
for(var k in obj){
|
|
||||||
if(obj.hasOwnProperty(k)) keys.push(k);
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
|
|
||||||
//
|
|
||||||
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
|
|
||||||
//
|
|
||||||
// Originally from narwhal.js (http://narwhaljs.org)
|
|
||||||
// Copyright (c) 2009 Thomas Robinson <280north.com>
|
|
||||||
//
|
|
||||||
// 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 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.
|
|
||||||
|
|
||||||
|
|
||||||
var pSlice = Array.prototype.slice;
|
|
||||||
|
|
||||||
// 1. The assert module provides functions that throw
|
|
||||||
// AssertionError's when particular conditions are not met. The
|
|
||||||
// assert module must conform to the following interface.
|
|
||||||
|
|
||||||
var assert = exports;
|
|
||||||
|
|
||||||
// 2. The AssertionError is defined in assert.
|
|
||||||
// new assert.AssertionError({message: message, actual: actual, expected: expected})
|
|
||||||
|
|
||||||
assert.AssertionError = function AssertionError (options) {
|
|
||||||
this.name = "AssertionError";
|
|
||||||
this.message = options.message;
|
|
||||||
this.actual = options.actual;
|
|
||||||
this.expected = options.expected;
|
|
||||||
this.operator = options.operator;
|
|
||||||
var stackStartFunction = options.stackStartFunction || fail;
|
|
||||||
|
|
||||||
if (Error.captureStackTrace) {
|
|
||||||
Error.captureStackTrace(this, stackStartFunction);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// code from util.inherits in node
|
|
||||||
assert.AssertionError.super_ = Error;
|
|
||||||
|
|
||||||
|
|
||||||
// EDITED FOR BROWSER COMPATIBILITY: replaced Object.create call
|
|
||||||
// TODO: test what effect this may have
|
|
||||||
var ctor = function () { this.constructor = assert.AssertionError; };
|
|
||||||
ctor.prototype = Error.prototype;
|
|
||||||
assert.AssertionError.prototype = new ctor();
|
|
||||||
|
|
||||||
|
|
||||||
assert.AssertionError.prototype.toString = function() {
|
|
||||||
if (this.message) {
|
|
||||||
return [this.name+":", this.message].join(' ');
|
|
||||||
} else {
|
|
||||||
return [ this.name+":"
|
|
||||||
, JSON.stringify(this.expected )
|
|
||||||
, this.operator
|
|
||||||
, JSON.stringify(this.actual)
|
|
||||||
].join(" ");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// assert.AssertionError instanceof Error
|
|
||||||
|
|
||||||
assert.AssertionError.__proto__ = Error.prototype;
|
|
||||||
|
|
||||||
// At present only the three keys mentioned above are used and
|
|
||||||
// understood by the spec. Implementations or sub modules can pass
|
|
||||||
// other keys to the AssertionError's constructor - they will be
|
|
||||||
// ignored.
|
|
||||||
|
|
||||||
// 3. All of the following functions must throw an AssertionError
|
|
||||||
// when a corresponding condition is not met, with a message that
|
|
||||||
// may be undefined if not provided. All assertion methods provide
|
|
||||||
// both the actual and expected values to the assertion error for
|
|
||||||
// display purposes.
|
|
||||||
|
|
||||||
function fail(actual, expected, message, operator, stackStartFunction) {
|
|
||||||
throw new assert.AssertionError({
|
|
||||||
message: message,
|
|
||||||
actual: actual,
|
|
||||||
expected: expected,
|
|
||||||
operator: operator,
|
|
||||||
stackStartFunction: stackStartFunction
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// EXTENSION! allows for well behaved errors defined elsewhere.
|
|
||||||
assert.fail = fail;
|
|
||||||
|
|
||||||
// 4. Pure assertion tests whether a value is truthy, as determined
|
|
||||||
// by !!guard.
|
|
||||||
// assert.ok(guard, message_opt);
|
|
||||||
// This statement is equivalent to assert.equal(true, guard,
|
|
||||||
// message_opt);. To test strictly for the value true, use
|
|
||||||
// assert.strictEqual(true, guard, message_opt);.
|
|
||||||
|
|
||||||
assert.ok = function ok(value, message) {
|
|
||||||
if (!!!value) fail(value, true, message, "==", assert.ok);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 5. The equality assertion tests shallow, coercive equality with
|
|
||||||
// ==.
|
|
||||||
// assert.equal(actual, expected, message_opt);
|
|
||||||
|
|
||||||
assert.equal = function equal(actual, expected, message) {
|
|
||||||
if (actual != expected) fail(actual, expected, message, "==", assert.equal);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 6. The non-equality assertion tests for whether two objects are not equal
|
|
||||||
// with != assert.notEqual(actual, expected, message_opt);
|
|
||||||
|
|
||||||
assert.notEqual = function notEqual(actual, expected, message) {
|
|
||||||
if (actual == expected) {
|
|
||||||
fail(actual, expected, message, "!=", assert.notEqual);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 7. The equivalence assertion tests a deep equality relation.
|
|
||||||
// assert.deepEqual(actual, expected, message_opt);
|
|
||||||
|
|
||||||
assert.deepEqual = function deepEqual(actual, expected, message) {
|
|
||||||
if (!_deepEqual(actual, expected)) {
|
|
||||||
fail(actual, expected, message, "deepEqual", assert.deepEqual);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function _deepEqual(actual, expected) {
|
|
||||||
// 7.1. All identical values are equivalent, as determined by ===.
|
|
||||||
if (actual === expected) {
|
|
||||||
return true;
|
|
||||||
// 7.2. If the expected value is a Date object, the actual value is
|
|
||||||
// equivalent if it is also a Date object that refers to the same time.
|
|
||||||
} else if (actual instanceof Date && expected instanceof Date) {
|
|
||||||
return actual.getTime() === expected.getTime();
|
|
||||||
|
|
||||||
// 7.3. Other pairs that do not both pass typeof value == "object",
|
|
||||||
// equivalence is determined by ==.
|
|
||||||
} else if (typeof actual != 'object' && typeof expected != 'object') {
|
|
||||||
return actual == expected;
|
|
||||||
|
|
||||||
// 7.4. For all other Object pairs, including Array objects, equivalence is
|
|
||||||
// determined by having the same number of owned properties (as verified
|
|
||||||
// with Object.prototype.hasOwnProperty.call), the same set of keys
|
|
||||||
// (although not necessarily the same order), equivalent values for every
|
|
||||||
// corresponding key, and an identical "prototype" property. Note: this
|
|
||||||
// accounts for both named and indexed properties on Arrays.
|
|
||||||
} else {
|
|
||||||
return objEquiv(actual, expected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isUndefinedOrNull (value) {
|
|
||||||
return value === null || value === undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isArguments (object) {
|
|
||||||
return Object.prototype.toString.call(object) == '[object Arguments]';
|
|
||||||
}
|
|
||||||
|
|
||||||
function objEquiv (a, b) {
|
|
||||||
if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
|
|
||||||
return false;
|
|
||||||
// an identical "prototype" property.
|
|
||||||
if (a.prototype !== b.prototype) return false;
|
|
||||||
//~~~I've managed to break Object.keys through screwy arguments passing.
|
|
||||||
// Converting to array solves the problem.
|
|
||||||
if (isArguments(a)) {
|
|
||||||
if (!isArguments(b)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
a = pSlice.call(a);
|
|
||||||
b = pSlice.call(b);
|
|
||||||
return _deepEqual(a, b);
|
|
||||||
}
|
|
||||||
try{
|
|
||||||
var ka = _keys(a),
|
|
||||||
kb = _keys(b),
|
|
||||||
key, i;
|
|
||||||
} catch (e) {//happens when one is a string literal and the other isn't
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// having the same number of owned properties (keys incorporates hasOwnProperty)
|
|
||||||
if (ka.length != kb.length)
|
|
||||||
return false;
|
|
||||||
//the same set of keys (although not necessarily the same order),
|
|
||||||
ka.sort();
|
|
||||||
kb.sort();
|
|
||||||
//~~~cheap key test
|
|
||||||
for (i = ka.length - 1; i >= 0; i--) {
|
|
||||||
if (ka[i] != kb[i])
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
//equivalent values for every corresponding key, and
|
|
||||||
//~~~possibly expensive deep test
|
|
||||||
for (i = ka.length - 1; i >= 0; i--) {
|
|
||||||
key = ka[i];
|
|
||||||
if (!_deepEqual(a[key], b[key] ))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 8. The non-equivalence assertion tests for any deep inequality.
|
|
||||||
// assert.notDeepEqual(actual, expected, message_opt);
|
|
||||||
|
|
||||||
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
|
|
||||||
if (_deepEqual(actual, expected)) {
|
|
||||||
fail(actual, expected, message, "notDeepEqual", assert.notDeepEqual);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 9. The strict equality assertion tests strict equality, as determined by ===.
|
|
||||||
// assert.strictEqual(actual, expected, message_opt);
|
|
||||||
|
|
||||||
assert.strictEqual = function strictEqual(actual, expected, message) {
|
|
||||||
if (actual !== expected) {
|
|
||||||
fail(actual, expected, message, "===", assert.strictEqual);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 10. The strict non-equality assertion tests for strict inequality, as determined by !==.
|
|
||||||
// assert.notStrictEqual(actual, expected, message_opt);
|
|
||||||
|
|
||||||
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
|
|
||||||
if (actual === expected) {
|
|
||||||
fail(actual, expected, message, "!==", assert.notStrictEqual);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function _throws (shouldThrow, block, err, message) {
|
|
||||||
var exception = null,
|
|
||||||
threw = false,
|
|
||||||
typematters = true;
|
|
||||||
|
|
||||||
message = message || "";
|
|
||||||
|
|
||||||
//handle optional arguments
|
|
||||||
if (arguments.length == 3) {
|
|
||||||
if (typeof(err) == "string") {
|
|
||||||
message = err;
|
|
||||||
typematters = false;
|
|
||||||
}
|
|
||||||
} else if (arguments.length == 2) {
|
|
||||||
typematters = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
block();
|
|
||||||
} catch (e) {
|
|
||||||
threw = true;
|
|
||||||
exception = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldThrow && !threw) {
|
|
||||||
fail( "Missing expected exception"
|
|
||||||
+ (err && err.name ? " ("+err.name+")." : '.')
|
|
||||||
+ (message ? " " + message : "")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!shouldThrow && threw && typematters && exception instanceof err) {
|
|
||||||
fail( "Got unwanted exception"
|
|
||||||
+ (err && err.name ? " ("+err.name+")." : '.')
|
|
||||||
+ (message ? " " + message : "")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ((shouldThrow && threw && typematters && !(exception instanceof err)) ||
|
|
||||||
(!shouldThrow && threw)) {
|
|
||||||
throw exception;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 11. Expected to throw an error:
|
|
||||||
// assert.throws(block, Error_opt, message_opt);
|
|
||||||
|
|
||||||
assert.throws = function(block, /*optional*/error, /*optional*/message) {
|
|
||||||
_throws.apply(this, [true].concat(pSlice.call(arguments)));
|
|
||||||
};
|
|
||||||
|
|
||||||
// EXTENSION! This is annoying to write outside this module.
|
|
||||||
assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
|
|
||||||
_throws.apply(this, [false].concat(pSlice.call(arguments)));
|
|
||||||
};
|
|
||||||
|
|
||||||
assert.ifError = function (err) { if (err) {throw err;}};
|
|
||||||
})(assert);
|
|
||||||
(function(exports){
|
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*
|
|
||||||
* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
|
|
||||||
* You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build.
|
|
||||||
* Only code on that line will be removed, its mostly to avoid requiring code
|
|
||||||
* that is node specific
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
//var assert = require('./assert'), //@REMOVE_LINE_FOR_BROWSER
|
|
||||||
// async = require('../deps/async'); //@REMOVE_LINE_FOR_BROWSER
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates assertion objects representing the result of an assert call.
|
|
||||||
* Accepts an object or AssertionError as its argument.
|
|
||||||
*
|
|
||||||
* @param {object} obj
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.assertion = function (obj) {
|
|
||||||
return {
|
|
||||||
method: obj.method || '',
|
|
||||||
message: obj.message || (obj.error && obj.error.message) || '',
|
|
||||||
error: obj.error,
|
|
||||||
passed: function () {
|
|
||||||
return !this.error;
|
|
||||||
},
|
|
||||||
failed: function () {
|
|
||||||
return Boolean(this.error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an assertion list object representing a group of assertions.
|
|
||||||
* Accepts an array of assertion objects.
|
|
||||||
*
|
|
||||||
* @param {Array} arr
|
|
||||||
* @param {Number} duration
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.assertionList = function (arr, duration) {
|
|
||||||
var that = arr || [];
|
|
||||||
that.failures = function () {
|
|
||||||
var failures = 0;
|
|
||||||
for (var i = 0; i < this.length; i += 1) {
|
|
||||||
if (this[i].failed()) {
|
|
||||||
failures += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return failures;
|
|
||||||
};
|
|
||||||
that.passes = function () {
|
|
||||||
return that.length - that.failures();
|
|
||||||
};
|
|
||||||
that.duration = duration || 0;
|
|
||||||
return that;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a wrapper function for assert module methods. Executes a callback
|
|
||||||
* after the it's complete with an assertion object representing the result.
|
|
||||||
*
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
var assertWrapper = function (callback) {
|
|
||||||
return function (new_method, assert_method, arity) {
|
|
||||||
return function () {
|
|
||||||
var message = arguments[arity - 1];
|
|
||||||
var a = exports.assertion({method: new_method, message: message});
|
|
||||||
try {
|
|
||||||
assert[assert_method].apply(null, arguments);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
a.error = e;
|
|
||||||
}
|
|
||||||
callback(a);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the 'test' object that gets passed to every test function.
|
|
||||||
* Accepts the name of the test function as its first argument, followed by
|
|
||||||
* the start time in ms, the options object and a callback function.
|
|
||||||
*
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Number} start
|
|
||||||
* @param {Object} options
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.test = function (name, start, options, callback) {
|
|
||||||
var expecting;
|
|
||||||
var a_list = [];
|
|
||||||
|
|
||||||
var wrapAssert = assertWrapper(function (a) {
|
|
||||||
a_list.push(a);
|
|
||||||
if (options.log) {
|
|
||||||
async.nextTick(function () {
|
|
||||||
options.log(a);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var test = {
|
|
||||||
done: function (err) {
|
|
||||||
if (expecting !== undefined && expecting !== a_list.length) {
|
|
||||||
var e = new Error(
|
|
||||||
'Expected ' + expecting + ' assertions, ' +
|
|
||||||
a_list.length + ' ran'
|
|
||||||
);
|
|
||||||
var a1 = exports.assertion({method: 'expect', error: e});
|
|
||||||
a_list.push(a1);
|
|
||||||
if (options.log) {
|
|
||||||
async.nextTick(function () {
|
|
||||||
options.log(a1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (err) {
|
|
||||||
var a2 = exports.assertion({error: err});
|
|
||||||
a_list.push(a2);
|
|
||||||
if (options.log) {
|
|
||||||
async.nextTick(function () {
|
|
||||||
options.log(a2);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var end = new Date().getTime();
|
|
||||||
async.nextTick(function () {
|
|
||||||
var assertion_list = exports.assertionList(a_list, end - start);
|
|
||||||
options.testDone(name, assertion_list);
|
|
||||||
callback(null, a_list);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
ok: wrapAssert('ok', 'ok', 2),
|
|
||||||
same: wrapAssert('same', 'deepEqual', 3),
|
|
||||||
equals: wrapAssert('equals', 'equal', 3),
|
|
||||||
expect: function (num) {
|
|
||||||
expecting = num;
|
|
||||||
},
|
|
||||||
_assertion_list: a_list
|
|
||||||
};
|
|
||||||
// add all functions from the assert module
|
|
||||||
for (var k in assert) {
|
|
||||||
if (assert.hasOwnProperty(k)) {
|
|
||||||
test[k] = wrapAssert(k, k, assert[k].length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return test;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensures an options object has all callbacks, adding empty callback functions
|
|
||||||
* if any are missing.
|
|
||||||
*
|
|
||||||
* @param {Object} opt
|
|
||||||
* @return {Object}
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.options = function (opt) {
|
|
||||||
var optionalCallback = function (name) {
|
|
||||||
opt[name] = opt[name] || function () {};
|
|
||||||
};
|
|
||||||
|
|
||||||
optionalCallback('moduleStart');
|
|
||||||
optionalCallback('moduleDone');
|
|
||||||
optionalCallback('testStart');
|
|
||||||
optionalCallback('testDone');
|
|
||||||
//optionalCallback('log');
|
|
||||||
|
|
||||||
// 'done' callback is not optional.
|
|
||||||
|
|
||||||
return opt;
|
|
||||||
};
|
|
||||||
})(types);
|
|
||||||
(function(exports){
|
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*
|
|
||||||
* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
|
|
||||||
* You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build.
|
|
||||||
* Only code on that line will be removed, its mostly to avoid requiring code
|
|
||||||
* that is node specific
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
//var async = require('../deps/async'), //@REMOVE_LINE_FOR_BROWSER
|
|
||||||
// types = require('./types'); //@REMOVE_LINE_FOR_BROWSER
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Added for browser compatibility
|
|
||||||
*/
|
|
||||||
|
|
||||||
var _keys = function (obj) {
|
|
||||||
if (Object.keys) {
|
|
||||||
return Object.keys(obj);
|
|
||||||
}
|
|
||||||
var keys = [];
|
|
||||||
for (var k in obj) {
|
|
||||||
if (obj.hasOwnProperty(k)) {
|
|
||||||
keys.push(k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var _copy = function (obj) {
|
|
||||||
var nobj = {};
|
|
||||||
var keys = _keys(obj);
|
|
||||||
for (var i = 0; i < keys.length; i += 1) {
|
|
||||||
nobj[keys[i]] = obj[keys[i]];
|
|
||||||
}
|
|
||||||
return nobj;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs a test function (fn) from a loaded module. After the test function
|
|
||||||
* calls test.done(), the callback is executed with an assertionList as its
|
|
||||||
* second argument.
|
|
||||||
*
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Function} fn
|
|
||||||
* @param {Object} opt
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.runTest = function (name, fn, opt, callback) {
|
|
||||||
var options = types.options(opt);
|
|
||||||
|
|
||||||
options.testStart(name);
|
|
||||||
var start = new Date().getTime();
|
|
||||||
var test = types.test(name, start, options, callback);
|
|
||||||
|
|
||||||
try {
|
|
||||||
fn(test);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
test.done(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes an object containing test functions or other test suites as properties
|
|
||||||
* and runs each in series. After all tests have completed, the callback is
|
|
||||||
* called with a list of all assertions as the second argument.
|
|
||||||
*
|
|
||||||
* If a name is passed to this function it is prepended to all test and suite
|
|
||||||
* names that run within it.
|
|
||||||
*
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Object} suite
|
|
||||||
* @param {Object} opt
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.runSuite = function (name, suite, opt, callback) {
|
|
||||||
var keys = _keys(suite);
|
|
||||||
|
|
||||||
async.concatSeries(keys, function (k, cb) {
|
|
||||||
var prop = suite[k], _name;
|
|
||||||
|
|
||||||
_name = name ? [].concat(name, k) : [k];
|
|
||||||
|
|
||||||
_name.toString = function () {
|
|
||||||
// fallback for old one
|
|
||||||
return this.join(' - ');
|
|
||||||
};
|
|
||||||
|
|
||||||
if (typeof prop === 'function') {
|
|
||||||
var in_name = false;
|
|
||||||
for (var i = 0; i < _name.length; i += 1) {
|
|
||||||
if (_name[i] === opt.testspec) {
|
|
||||||
in_name = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!opt.testspec || in_name) {
|
|
||||||
if (opt.moduleStart) {
|
|
||||||
opt.moduleStart();
|
|
||||||
}
|
|
||||||
exports.runTest(_name, suite[k], opt, cb);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return cb();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
exports.runSuite(_name, suite[k], opt, cb);
|
|
||||||
}
|
|
||||||
}, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run each exported test function or test suite from a loaded module.
|
|
||||||
*
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Object} mod
|
|
||||||
* @param {Object} opt
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.runModule = function (name, mod, opt, callback) {
|
|
||||||
var options = _copy(types.options(opt));
|
|
||||||
|
|
||||||
var _run = false;
|
|
||||||
var _moduleStart = options.moduleStart;
|
|
||||||
function run_once() {
|
|
||||||
if (!_run) {
|
|
||||||
_run = true;
|
|
||||||
_moduleStart(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
options.moduleStart = run_once;
|
|
||||||
|
|
||||||
var start = new Date().getTime();
|
|
||||||
|
|
||||||
exports.runSuite(null, mod, options, function (err, a_list) {
|
|
||||||
var end = new Date().getTime();
|
|
||||||
var assertion_list = types.assertionList(a_list, end - start);
|
|
||||||
options.moduleDone(name, assertion_list);
|
|
||||||
callback(null, a_list);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Treats an object literal as a list of modules keyed by name. Runs each
|
|
||||||
* module and finished with calling 'done'. You can think of this as a browser
|
|
||||||
* safe alternative to runFiles in the nodeunit module.
|
|
||||||
*
|
|
||||||
* @param {Object} modules
|
|
||||||
* @param {Object} opt
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO: add proper unit tests for this function
|
|
||||||
exports.runModules = function (modules, opt) {
|
|
||||||
var all_assertions = [];
|
|
||||||
var options = types.options(opt);
|
|
||||||
var start = new Date().getTime();
|
|
||||||
|
|
||||||
async.concatSeries(_keys(modules), function (k, cb) {
|
|
||||||
exports.runModule(k, modules[k], options, cb);
|
|
||||||
},
|
|
||||||
function (err, all_assertions) {
|
|
||||||
var end = new Date().getTime();
|
|
||||||
options.done(types.assertionList(all_assertions, end - start));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps a test function with setUp and tearDown functions.
|
|
||||||
* Used by testCase.
|
|
||||||
*
|
|
||||||
* @param {Function} setUp
|
|
||||||
* @param {Function} tearDown
|
|
||||||
* @param {Function} fn
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
var wrapTest = function (setUp, tearDown, fn) {
|
|
||||||
return function (test) {
|
|
||||||
var context = {};
|
|
||||||
if (tearDown) {
|
|
||||||
var done = test.done;
|
|
||||||
test.done = function (err) {
|
|
||||||
try {
|
|
||||||
tearDown.call(context, function (err2) {
|
|
||||||
if (err && err2) {
|
|
||||||
test._assertion_list.push(
|
|
||||||
types.assertion({error: err})
|
|
||||||
);
|
|
||||||
return done(err2);
|
|
||||||
}
|
|
||||||
done(err || err2);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
done(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (setUp) {
|
|
||||||
setUp.call(context, function (err) {
|
|
||||||
if (err) {
|
|
||||||
return test.done(err);
|
|
||||||
}
|
|
||||||
fn.call(context, test);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fn.call(context, test);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps a group of tests with setUp and tearDown functions.
|
|
||||||
* Used by testCase.
|
|
||||||
*
|
|
||||||
* @param {Function} setUp
|
|
||||||
* @param {Function} tearDown
|
|
||||||
* @param {Object} group
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
var wrapGroup = function (setUp, tearDown, group) {
|
|
||||||
var tests = {};
|
|
||||||
var keys = _keys(group);
|
|
||||||
for (var i = 0; i < keys.length; i += 1) {
|
|
||||||
var k = keys[i];
|
|
||||||
if (typeof group[k] === 'function') {
|
|
||||||
tests[k] = wrapTest(setUp, tearDown, group[k]);
|
|
||||||
}
|
|
||||||
else if (typeof group[k] === 'object') {
|
|
||||||
tests[k] = wrapGroup(setUp, tearDown, group[k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tests;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility for wrapping a suite of test functions with setUp and tearDown
|
|
||||||
* functions.
|
|
||||||
*
|
|
||||||
* @param {Object} suite
|
|
||||||
* @return {Object}
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.testCase = function (suite) {
|
|
||||||
var setUp = suite.setUp;
|
|
||||||
var tearDown = suite.tearDown;
|
|
||||||
delete suite.setUp;
|
|
||||||
delete suite.tearDown;
|
|
||||||
return wrapGroup(setUp, tearDown, suite);
|
|
||||||
};
|
|
||||||
})(core);
|
|
||||||
(function(exports){
|
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*
|
|
||||||
* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
|
|
||||||
* You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build.
|
|
||||||
* Only code on that line will be removed, its mostly to avoid requiring code
|
|
||||||
* that is node specific
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* NOTE: this test runner is not listed in index.js because it cannot be
|
|
||||||
* used with the command-line tool, only inside the browser.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reporter info string
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.info = "Browser-based test reporter";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run all tests within each module, reporting the results
|
|
||||||
*
|
|
||||||
* @param {Array} files
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.run = function (modules, options) {
|
|
||||||
var start = new Date().getTime();
|
|
||||||
|
|
||||||
function setText(el, txt) {
|
|
||||||
if ('innerText' in el) {
|
|
||||||
el.innerText = txt;
|
|
||||||
}
|
|
||||||
else if ('textContent' in el){
|
|
||||||
el.textContent = txt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getOrCreate(tag, id) {
|
|
||||||
var el = document.getElementById(id);
|
|
||||||
if (!el) {
|
|
||||||
el = document.createElement(tag);
|
|
||||||
el.id = id;
|
|
||||||
document.body.appendChild(el);
|
|
||||||
}
|
|
||||||
return el;
|
|
||||||
};
|
|
||||||
|
|
||||||
var header = getOrCreate('h1', 'nodeunit-header');
|
|
||||||
var banner = getOrCreate('h2', 'nodeunit-banner');
|
|
||||||
var userAgent = getOrCreate('h2', 'nodeunit-userAgent');
|
|
||||||
var tests = getOrCreate('ol', 'nodeunit-tests');
|
|
||||||
var result = getOrCreate('p', 'nodeunit-testresult');
|
|
||||||
|
|
||||||
setText(userAgent, navigator.userAgent);
|
|
||||||
|
|
||||||
nodeunit.runModules(modules, {
|
|
||||||
moduleStart: function (name) {
|
|
||||||
/*var mheading = document.createElement('h2');
|
|
||||||
mheading.innerText = name;
|
|
||||||
results.appendChild(mheading);
|
|
||||||
module = document.createElement('ol');
|
|
||||||
results.appendChild(module);*/
|
|
||||||
},
|
|
||||||
testDone: function (name, assertions) {
|
|
||||||
var test = document.createElement('li');
|
|
||||||
var strong = document.createElement('strong');
|
|
||||||
strong.innerHTML = name + ' <b style="color: black;">(' +
|
|
||||||
'<b class="fail">' + assertions.failures() + '</b>, ' +
|
|
||||||
'<b class="pass">' + assertions.passes() + '</b>, ' +
|
|
||||||
assertions.length +
|
|
||||||
')</b>';
|
|
||||||
test.className = assertions.failures() ? 'fail': 'pass';
|
|
||||||
test.appendChild(strong);
|
|
||||||
|
|
||||||
var aList = document.createElement('ol');
|
|
||||||
aList.style.display = 'none';
|
|
||||||
test.onclick = function () {
|
|
||||||
var d = aList.style.display;
|
|
||||||
aList.style.display = (d == 'none') ? 'block': 'none';
|
|
||||||
};
|
|
||||||
for (var i=0; i<assertions.length; i++) {
|
|
||||||
var li = document.createElement('li');
|
|
||||||
var a = assertions[i];
|
|
||||||
if (a.failed()) {
|
|
||||||
li.innerHTML = (a.message || a.method || 'no message') +
|
|
||||||
'<pre>' + (a.error.stack || a.error) + '</pre>';
|
|
||||||
li.className = 'fail';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
li.innerHTML = a.message || a.method || 'no message';
|
|
||||||
li.className = 'pass';
|
|
||||||
}
|
|
||||||
aList.appendChild(li);
|
|
||||||
}
|
|
||||||
test.appendChild(aList);
|
|
||||||
tests.appendChild(test);
|
|
||||||
},
|
|
||||||
done: function (assertions) {
|
|
||||||
var end = new Date().getTime();
|
|
||||||
var duration = end - start;
|
|
||||||
|
|
||||||
var failures = assertions.failures();
|
|
||||||
banner.className = failures ? 'fail': 'pass';
|
|
||||||
|
|
||||||
result.innerHTML = 'Tests completed in ' + duration +
|
|
||||||
' milliseconds.<br/><span class="passed">' +
|
|
||||||
assertions.passes() + '</span> assertions of ' +
|
|
||||||
'<span class="all">' + assertions.length + '<span> passed, ' +
|
|
||||||
assertions.failures() + ' failed.';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
})(reporter);
|
|
||||||
nodeunit = core;
|
|
||||||
nodeunit.assert = assert;
|
|
||||||
nodeunit.reporter = reporter;
|
|
||||||
nodeunit.run = reporter.run;
|
|
||||||
return nodeunit; })();
|
|
|
@ -1,12 +0,0 @@
|
||||||
this.suite1 = {
|
|
||||||
'test one': function (test) {
|
|
||||||
test.ok(true, 'everythings ok');
|
|
||||||
setTimeout(function () {
|
|
||||||
test.done();
|
|
||||||
}, 10);
|
|
||||||
},
|
|
||||||
'apples and oranges': function (test) {
|
|
||||||
test.equal('apples', 'oranges', 'comparing apples and oranges');
|
|
||||||
test.done();
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,13 +0,0 @@
|
||||||
this.suite2 = {
|
|
||||||
'another test': function (test) {
|
|
||||||
setTimeout(function () {
|
|
||||||
// lots of assertions
|
|
||||||
test.ok(true, 'everythings ok');
|
|
||||||
test.ok(true, 'everythings ok');
|
|
||||||
test.ok(true, 'everythings ok');
|
|
||||||
test.ok(true, 'everythings ok');
|
|
||||||
test.ok(true, 'everythings ok');
|
|
||||||
test.done();
|
|
||||||
}, 10);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,7 +0,0 @@
|
||||||
this.suite3 = {
|
|
||||||
'test for ie6,7,8': function (test) {
|
|
||||||
test.deepEqual(["test"], ["test"]);
|
|
||||||
test.notDeepEqual(["a"], ["b"]);
|
|
||||||
test.done();
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,18 +0,0 @@
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Example tests</title>
|
|
||||||
<script src="nodeunit.js"></script>
|
|
||||||
<script src="suite1.js"></script>
|
|
||||||
<script src="suite2.js"></script>
|
|
||||||
<script src="suite3.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<script>
|
|
||||||
nodeunit.run({
|
|
||||||
'suite1': suite1,
|
|
||||||
'suite2': suite2,
|
|
||||||
'suite3': suite3
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,94 +0,0 @@
|
||||||
var testCase = require('nodeunit').testCase;
|
|
||||||
/*
|
|
||||||
This is an example test suite to demonstrate the nested test reporter.
|
|
||||||
Run with --reporter nested, e.g.,
|
|
||||||
nodeunit --reporter nested nested_reporter_test.unit.js
|
|
||||||
|
|
||||||
The test output should be something like:
|
|
||||||
|
|
||||||
nested_reporter_test.unit.js
|
|
||||||
Test 0.1 (pass)
|
|
||||||
TC 1
|
|
||||||
TC 1.1
|
|
||||||
Test 1.1.1 (pass)
|
|
||||||
TC 2
|
|
||||||
TC 2.1
|
|
||||||
TC 2.1.1
|
|
||||||
Test 2.1.1.1 (pass)
|
|
||||||
Test 2.1.1.2 (pass)
|
|
||||||
TC 2.2.1
|
|
||||||
Test 2.2.1.1 (pass)
|
|
||||||
TC 2.2.1.1
|
|
||||||
Test 2.2.1.1.1 (pass)
|
|
||||||
Test 2.2.1.2 (pass)
|
|
||||||
TC 3
|
|
||||||
TC 3.1
|
|
||||||
TC 3.1.1
|
|
||||||
Test 3.1.1.1 (should fail) (fail) ✖
|
|
||||||
AssertionError: false == true
|
|
||||||
// stack trace here.
|
|
||||||
|
|
||||||
FAILURES: 1/8 assertions failed (6ms)
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = testCase({
|
|
||||||
"Test 0.1": function(test) {
|
|
||||||
test.ok(true);
|
|
||||||
test.done();
|
|
||||||
},
|
|
||||||
|
|
||||||
"TC 1": testCase({
|
|
||||||
"TC 1.1": testCase({
|
|
||||||
"Test 1.1.1": function(test) {
|
|
||||||
test.ok(true);
|
|
||||||
test.done();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
|
|
||||||
"TC 2": testCase({
|
|
||||||
"TC 2.1": testCase({
|
|
||||||
"TC 2.1.1": testCase({
|
|
||||||
"Test 2.1.1.1": function(test) {
|
|
||||||
test.ok(true);
|
|
||||||
test.done();
|
|
||||||
},
|
|
||||||
|
|
||||||
"Test 2.1.1.2": function(test) {
|
|
||||||
test.ok(true);
|
|
||||||
test.done();
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
|
|
||||||
"TC 2.2.1": testCase({
|
|
||||||
"Test 2.2.1.1": function(test) {
|
|
||||||
test.ok(true);
|
|
||||||
test.done();
|
|
||||||
},
|
|
||||||
|
|
||||||
"TC 2.2.1.1": testCase({
|
|
||||||
"Test 2.2.1.1.1": function(test) {
|
|
||||||
test.ok(true);
|
|
||||||
test.done();
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
"Test 2.2.1.2": function(test) {
|
|
||||||
test.ok(true);
|
|
||||||
test.done();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
|
|
||||||
"TC 3": testCase({
|
|
||||||
"TC 3.1": testCase({
|
|
||||||
"TC 3.1.1": testCase({
|
|
||||||
"Test 3.1.1.1 (should fail)": function(test) {
|
|
||||||
test.ok(false);
|
|
||||||
test.done();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
});
|
|
BIN
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/img/example_fail.png
generated
vendored
BIN
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/img/example_fail.png
generated
vendored
Binary file not shown.
Before Width: | Height: | Size: 38 KiB |
BIN
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/img/example_machineout.png
generated
vendored
BIN
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/img/example_machineout.png
generated
vendored
Binary file not shown.
Before Width: | Height: | Size: 412 KiB |
BIN
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/img/example_pass.png
generated
vendored
BIN
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/img/example_pass.png
generated
vendored
Binary file not shown.
Before Width: | Height: | Size: 14 KiB |
|
@ -1,3 +0,0 @@
|
||||||
// This file is just added for convenience so this repository can be
|
|
||||||
// directly checked out into a project's deps folder
|
|
||||||
module.exports = require('./lib/nodeunit');
|
|
354
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/assert.js
generated
vendored
354
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/assert.js
generated
vendored
|
@ -1,354 +0,0 @@
|
||||||
/**
|
|
||||||
* This file is based on the node.js assert module, but with some small
|
|
||||||
* changes for browser-compatibility
|
|
||||||
* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Added for browser compatibility
|
|
||||||
*/
|
|
||||||
|
|
||||||
var _keys = function(obj){
|
|
||||||
if(Object.keys) return Object.keys(obj);
|
|
||||||
if (typeof obj != 'object' && typeof obj != 'function') {
|
|
||||||
throw new TypeError('-');
|
|
||||||
}
|
|
||||||
var keys = [];
|
|
||||||
for(var k in obj){
|
|
||||||
if(obj.hasOwnProperty(k)) keys.push(k);
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
|
|
||||||
//
|
|
||||||
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
|
|
||||||
//
|
|
||||||
// Originally from narwhal.js (http://narwhaljs.org)
|
|
||||||
// Copyright (c) 2009 Thomas Robinson <280north.com>
|
|
||||||
//
|
|
||||||
// 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 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.
|
|
||||||
|
|
||||||
|
|
||||||
var pSlice = Array.prototype.slice;
|
|
||||||
|
|
||||||
// 1. The assert module provides functions that throw
|
|
||||||
// AssertionError's when particular conditions are not met. The
|
|
||||||
// assert module must conform to the following interface.
|
|
||||||
|
|
||||||
var assert = exports;
|
|
||||||
|
|
||||||
// 2. The AssertionError is defined in assert.
|
|
||||||
// new assert.AssertionError({message: message, actual: actual, expected: expected})
|
|
||||||
|
|
||||||
assert.AssertionError = function AssertionError (options) {
|
|
||||||
this.name = "AssertionError";
|
|
||||||
this.message = options.message;
|
|
||||||
this.actual = options.actual;
|
|
||||||
this.expected = options.expected;
|
|
||||||
this.operator = options.operator;
|
|
||||||
var stackStartFunction = options.stackStartFunction || fail;
|
|
||||||
|
|
||||||
if (Error.captureStackTrace) {
|
|
||||||
Error.captureStackTrace(this, stackStartFunction);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// code from util.inherits in node
|
|
||||||
assert.AssertionError.super_ = Error;
|
|
||||||
|
|
||||||
|
|
||||||
// EDITED FOR BROWSER COMPATIBILITY: replaced Object.create call
|
|
||||||
// TODO: test what effect this may have
|
|
||||||
var ctor = function () { this.constructor = assert.AssertionError; };
|
|
||||||
ctor.prototype = Error.prototype;
|
|
||||||
assert.AssertionError.prototype = new ctor();
|
|
||||||
|
|
||||||
|
|
||||||
assert.AssertionError.prototype.toString = function() {
|
|
||||||
if (this.message) {
|
|
||||||
return [this.name+":", this.message].join(' ');
|
|
||||||
} else {
|
|
||||||
return [ this.name+":"
|
|
||||||
, typeof this.expected !== 'undefined' ? JSON.stringify(this.expected) : 'undefined'
|
|
||||||
, this.operator
|
|
||||||
, typeof this.actual !== 'undefined' ? JSON.stringify(this.actual) : 'undefined'
|
|
||||||
].join(" ");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// assert.AssertionError instanceof Error
|
|
||||||
|
|
||||||
assert.AssertionError.__proto__ = Error.prototype;
|
|
||||||
|
|
||||||
// At present only the three keys mentioned above are used and
|
|
||||||
// understood by the spec. Implementations or sub modules can pass
|
|
||||||
// other keys to the AssertionError's constructor - they will be
|
|
||||||
// ignored.
|
|
||||||
|
|
||||||
// 3. All of the following functions must throw an AssertionError
|
|
||||||
// when a corresponding condition is not met, with a message that
|
|
||||||
// may be undefined if not provided. All assertion methods provide
|
|
||||||
// both the actual and expected values to the assertion error for
|
|
||||||
// display purposes.
|
|
||||||
|
|
||||||
function fail(actual, expected, message, operator, stackStartFunction) {
|
|
||||||
throw new assert.AssertionError({
|
|
||||||
message: message,
|
|
||||||
actual: actual,
|
|
||||||
expected: expected,
|
|
||||||
operator: operator,
|
|
||||||
stackStartFunction: stackStartFunction
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// EXTENSION! allows for well behaved errors defined elsewhere.
|
|
||||||
assert.fail = fail;
|
|
||||||
|
|
||||||
// 4. Pure assertion tests whether a value is truthy, as determined
|
|
||||||
// by !!guard.
|
|
||||||
// assert.ok(guard, message_opt);
|
|
||||||
// This statement is equivalent to assert.equal(true, guard,
|
|
||||||
// message_opt);. To test strictly for the value true, use
|
|
||||||
// assert.strictEqual(true, guard, message_opt);.
|
|
||||||
|
|
||||||
assert.ok = function ok(value, message) {
|
|
||||||
if (!!!value) fail(value, true, message, "==", assert.ok);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 5. The equality assertion tests shallow, coercive equality with
|
|
||||||
// ==.
|
|
||||||
// assert.equal(actual, expected, message_opt);
|
|
||||||
|
|
||||||
assert.equal = function equal(actual, expected, message) {
|
|
||||||
if (actual != expected) fail(actual, expected, message, "==", assert.equal);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 6. The non-equality assertion tests for whether two objects are not equal
|
|
||||||
// with != assert.notEqual(actual, expected, message_opt);
|
|
||||||
|
|
||||||
assert.notEqual = function notEqual(actual, expected, message) {
|
|
||||||
if (actual == expected) {
|
|
||||||
fail(actual, expected, message, "!=", assert.notEqual);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 7. The equivalence assertion tests a deep equality relation.
|
|
||||||
// assert.deepEqual(actual, expected, message_opt);
|
|
||||||
|
|
||||||
assert.deepEqual = function deepEqual(actual, expected, message) {
|
|
||||||
if (!_deepEqual(actual, expected)) {
|
|
||||||
fail(actual, expected, message, "deepEqual", assert.deepEqual);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var Buffer = null;
|
|
||||||
if (typeof require !== 'undefined' && typeof process !== 'undefined') {
|
|
||||||
try {
|
|
||||||
Buffer = require('buffer').Buffer;
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
// May be a CommonJS environment other than Node.js
|
|
||||||
Buffer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function _deepEqual(actual, expected) {
|
|
||||||
// 7.1. All identical values are equivalent, as determined by ===.
|
|
||||||
if (actual === expected) {
|
|
||||||
return true;
|
|
||||||
// 7.2. If the expected value is a Date object, the actual value is
|
|
||||||
// equivalent if it is also a Date object that refers to the same time.
|
|
||||||
} else if (actual instanceof Date && expected instanceof Date) {
|
|
||||||
return actual.getTime() === expected.getTime();
|
|
||||||
|
|
||||||
// 7.2.1 If the expcted value is a RegExp object, the actual value is
|
|
||||||
// equivalent if it is also a RegExp object that refers to the same source and options
|
|
||||||
} else if (actual instanceof RegExp && expected instanceof RegExp) {
|
|
||||||
return actual.source === expected.source &&
|
|
||||||
actual.global === expected.global &&
|
|
||||||
actual.ignoreCase === expected.ignoreCase &&
|
|
||||||
actual.multiline === expected.multiline;
|
|
||||||
|
|
||||||
} else if (Buffer && actual instanceof Buffer && expected instanceof Buffer) {
|
|
||||||
return (function() {
|
|
||||||
var i, len;
|
|
||||||
|
|
||||||
for (i = 0, len = expected.length; i < len; i++) {
|
|
||||||
if (actual[i] !== expected[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return actual.length === expected.length;
|
|
||||||
})();
|
|
||||||
// 7.3. Other pairs that do not both pass typeof value == "object",
|
|
||||||
// equivalence is determined by ==.
|
|
||||||
} else if (typeof actual != 'object' && typeof expected != 'object') {
|
|
||||||
return actual == expected;
|
|
||||||
|
|
||||||
// 7.4. For all other Object pairs, including Array objects, equivalence is
|
|
||||||
// determined by having the same number of owned properties (as verified
|
|
||||||
// with Object.prototype.hasOwnProperty.call), the same set of keys
|
|
||||||
// (although not necessarily the same order), equivalent values for every
|
|
||||||
// corresponding key, and an identical "prototype" property. Note: this
|
|
||||||
// accounts for both named and indexed properties on Arrays.
|
|
||||||
} else {
|
|
||||||
return objEquiv(actual, expected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isUndefinedOrNull (value) {
|
|
||||||
return value === null || value === undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isArguments (object) {
|
|
||||||
return Object.prototype.toString.call(object) == '[object Arguments]';
|
|
||||||
}
|
|
||||||
|
|
||||||
function objEquiv (a, b) {
|
|
||||||
if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
|
|
||||||
return false;
|
|
||||||
// an identical "prototype" property.
|
|
||||||
if (a.prototype !== b.prototype) return false;
|
|
||||||
//~~~I've managed to break Object.keys through screwy arguments passing.
|
|
||||||
// Converting to array solves the problem.
|
|
||||||
if (isArguments(a)) {
|
|
||||||
if (!isArguments(b)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
a = pSlice.call(a);
|
|
||||||
b = pSlice.call(b);
|
|
||||||
return _deepEqual(a, b);
|
|
||||||
}
|
|
||||||
try{
|
|
||||||
var ka = _keys(a),
|
|
||||||
kb = _keys(b),
|
|
||||||
key, i;
|
|
||||||
} catch (e) {//happens when one is a string literal and the other isn't
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// having the same number of owned properties (keys incorporates hasOwnProperty)
|
|
||||||
if (ka.length != kb.length)
|
|
||||||
return false;
|
|
||||||
//the same set of keys (although not necessarily the same order),
|
|
||||||
ka.sort();
|
|
||||||
kb.sort();
|
|
||||||
//~~~cheap key test
|
|
||||||
for (i = ka.length - 1; i >= 0; i--) {
|
|
||||||
if (ka[i] != kb[i])
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
//equivalent values for every corresponding key, and
|
|
||||||
//~~~possibly expensive deep test
|
|
||||||
for (i = ka.length - 1; i >= 0; i--) {
|
|
||||||
key = ka[i];
|
|
||||||
if (!_deepEqual(a[key], b[key] ))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 8. The non-equivalence assertion tests for any deep inequality.
|
|
||||||
// assert.notDeepEqual(actual, expected, message_opt);
|
|
||||||
|
|
||||||
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
|
|
||||||
if (_deepEqual(actual, expected)) {
|
|
||||||
fail(actual, expected, message, "notDeepEqual", assert.notDeepEqual);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 9. The strict equality assertion tests strict equality, as determined by ===.
|
|
||||||
// assert.strictEqual(actual, expected, message_opt);
|
|
||||||
|
|
||||||
assert.strictEqual = function strictEqual(actual, expected, message) {
|
|
||||||
if (actual !== expected) {
|
|
||||||
fail(actual, expected, message, "===", assert.strictEqual);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 10. The strict non-equality assertion tests for strict inequality, as determined by !==.
|
|
||||||
// assert.notStrictEqual(actual, expected, message_opt);
|
|
||||||
|
|
||||||
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
|
|
||||||
if (actual === expected) {
|
|
||||||
fail(actual, expected, message, "!==", assert.notStrictEqual);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function expectedException(actual, expected) {
|
|
||||||
if (!actual || !expected) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expected instanceof RegExp) {
|
|
||||||
return expected.test(actual.message || actual);
|
|
||||||
} else if (actual instanceof expected) {
|
|
||||||
return true;
|
|
||||||
} else if (expected.call({}, actual) === true) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _throws(shouldThrow, block, expected, message) {
|
|
||||||
var actual;
|
|
||||||
|
|
||||||
if (typeof expected === 'string') {
|
|
||||||
message = expected;
|
|
||||||
expected = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
block();
|
|
||||||
} catch (e) {
|
|
||||||
actual = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
|
|
||||||
(message ? ' ' + message : '.');
|
|
||||||
|
|
||||||
if (shouldThrow && !actual) {
|
|
||||||
fail('Missing expected exception' + message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!shouldThrow && expectedException(actual, expected)) {
|
|
||||||
fail('Got unwanted exception' + message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((shouldThrow && actual && expected &&
|
|
||||||
!expectedException(actual, expected)) || (!shouldThrow && actual)) {
|
|
||||||
throw actual;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 11. Expected to throw an error:
|
|
||||||
// assert.throws(block, Error_opt, message_opt);
|
|
||||||
|
|
||||||
assert.throws = function(block, /*optional*/error, /*optional*/message) {
|
|
||||||
_throws.apply(this, [true].concat(pSlice.call(arguments)));
|
|
||||||
};
|
|
||||||
|
|
||||||
// EXTENSION! This is annoying to write outside this module.
|
|
||||||
assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
|
|
||||||
_throws.apply(this, [false].concat(pSlice.call(arguments)));
|
|
||||||
};
|
|
||||||
|
|
||||||
assert.ifError = function (err) { if (err) {throw err;}};
|
|
|
@ -1,319 +0,0 @@
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*
|
|
||||||
* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
|
|
||||||
* You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build.
|
|
||||||
* Only code on that line will be removed, it's mostly to avoid requiring code
|
|
||||||
* that is node specific
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
var async = require('../deps/async'), //@REMOVE_LINE_FOR_BROWSER
|
|
||||||
nodeunit = require('./nodeunit'), //@REMOVE_LINE_FOR_BROWSER
|
|
||||||
types = require('./types'); //@REMOVE_LINE_FOR_BROWSER
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Added for browser compatibility
|
|
||||||
*/
|
|
||||||
|
|
||||||
var _keys = function (obj) {
|
|
||||||
if (Object.keys) {
|
|
||||||
return Object.keys(obj);
|
|
||||||
}
|
|
||||||
var keys = [];
|
|
||||||
for (var k in obj) {
|
|
||||||
if (obj.hasOwnProperty(k)) {
|
|
||||||
keys.push(k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var _copy = function (obj) {
|
|
||||||
var nobj = {};
|
|
||||||
var keys = _keys(obj);
|
|
||||||
for (var i = 0; i < keys.length; i += 1) {
|
|
||||||
nobj[keys[i]] = obj[keys[i]];
|
|
||||||
}
|
|
||||||
return nobj;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs a test function (fn) from a loaded module. After the test function
|
|
||||||
* calls test.done(), the callback is executed with an assertionList as its
|
|
||||||
* second argument.
|
|
||||||
*
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Function} fn
|
|
||||||
* @param {Object} opt
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.runTest = function (name, fn, opt, callback) {
|
|
||||||
var options = types.options(opt);
|
|
||||||
|
|
||||||
options.testStart(name);
|
|
||||||
var start = new Date().getTime();
|
|
||||||
var test = types.test(name, start, options, callback);
|
|
||||||
|
|
||||||
options.testReady(test);
|
|
||||||
try {
|
|
||||||
fn(test);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
test.done(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes an object containing test functions or other test suites as properties
|
|
||||||
* and runs each in series. After all tests have completed, the callback is
|
|
||||||
* called with a list of all assertions as the second argument.
|
|
||||||
*
|
|
||||||
* If a name is passed to this function it is prepended to all test and suite
|
|
||||||
* names that run within it.
|
|
||||||
*
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Object} suite
|
|
||||||
* @param {Object} opt
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.runSuite = function (name, suite, opt, callback) {
|
|
||||||
suite = wrapGroup(suite);
|
|
||||||
var keys = _keys(suite);
|
|
||||||
|
|
||||||
async.concatSeries(keys, function (k, cb) {
|
|
||||||
var prop = suite[k], _name;
|
|
||||||
|
|
||||||
_name = name ? [].concat(name, k) : [k];
|
|
||||||
_name.toString = function () {
|
|
||||||
// fallback for old one
|
|
||||||
return this.join(' - ');
|
|
||||||
};
|
|
||||||
|
|
||||||
if (typeof prop === 'function') {
|
|
||||||
var in_name = false,
|
|
||||||
in_specific_test = (_name.toString() === opt.testFullSpec) ? true : false;
|
|
||||||
for (var i = 0; i < _name.length; i += 1) {
|
|
||||||
if (_name[i] === opt.testspec) {
|
|
||||||
in_name = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((!opt.testFullSpec || in_specific_test) && (!opt.testspec || in_name)) {
|
|
||||||
if (opt.moduleStart) {
|
|
||||||
opt.moduleStart();
|
|
||||||
}
|
|
||||||
exports.runTest(_name, suite[k], opt, cb);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return cb();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
exports.runSuite(_name, suite[k], opt, cb);
|
|
||||||
}
|
|
||||||
}, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run each exported test function or test suite from a loaded module.
|
|
||||||
*
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Object} mod
|
|
||||||
* @param {Object} opt
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.runModule = function (name, mod, opt, callback) {
|
|
||||||
var options = _copy(types.options(opt));
|
|
||||||
|
|
||||||
var _run = false;
|
|
||||||
var _moduleStart = options.moduleStart;
|
|
||||||
|
|
||||||
mod = wrapGroup(mod);
|
|
||||||
|
|
||||||
function run_once() {
|
|
||||||
if (!_run) {
|
|
||||||
_run = true;
|
|
||||||
_moduleStart(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
options.moduleStart = run_once;
|
|
||||||
|
|
||||||
var start = new Date().getTime();
|
|
||||||
|
|
||||||
exports.runSuite(null, mod, options, function (err, a_list) {
|
|
||||||
var end = new Date().getTime();
|
|
||||||
var assertion_list = types.assertionList(a_list, end - start);
|
|
||||||
options.moduleDone(name, assertion_list);
|
|
||||||
if (nodeunit.complete) {
|
|
||||||
nodeunit.complete(name, assertion_list);
|
|
||||||
}
|
|
||||||
callback(null, a_list);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Treats an object literal as a list of modules keyed by name. Runs each
|
|
||||||
* module and finished with calling 'done'. You can think of this as a browser
|
|
||||||
* safe alternative to runFiles in the nodeunit module.
|
|
||||||
*
|
|
||||||
* @param {Object} modules
|
|
||||||
* @param {Object} opt
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO: add proper unit tests for this function
|
|
||||||
exports.runModules = function (modules, opt) {
|
|
||||||
var all_assertions = [];
|
|
||||||
var options = types.options(opt);
|
|
||||||
var start = new Date().getTime();
|
|
||||||
|
|
||||||
async.concatSeries(_keys(modules), function (k, cb) {
|
|
||||||
exports.runModule(k, modules[k], options, cb);
|
|
||||||
},
|
|
||||||
function (err, all_assertions) {
|
|
||||||
var end = new Date().getTime();
|
|
||||||
options.done(types.assertionList(all_assertions, end - start));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps a test function with setUp and tearDown functions.
|
|
||||||
* Used by testCase.
|
|
||||||
*
|
|
||||||
* @param {Function} setUp
|
|
||||||
* @param {Function} tearDown
|
|
||||||
* @param {Function} fn
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
var wrapTest = function (setUp, tearDown, fn) {
|
|
||||||
return function (test) {
|
|
||||||
var context = {};
|
|
||||||
if (tearDown) {
|
|
||||||
var done = test.done;
|
|
||||||
test.done = function (err) {
|
|
||||||
try {
|
|
||||||
tearDown.call(context, function (err2) {
|
|
||||||
if (err && err2) {
|
|
||||||
test._assertion_list.push(
|
|
||||||
types.assertion({error: err})
|
|
||||||
);
|
|
||||||
return done(err2);
|
|
||||||
}
|
|
||||||
done(err || err2);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
done(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (setUp) {
|
|
||||||
setUp.call(context, function (err) {
|
|
||||||
if (err) {
|
|
||||||
return test.done(err);
|
|
||||||
}
|
|
||||||
fn.call(context, test);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fn.call(context, test);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a serial callback from two functions.
|
|
||||||
*
|
|
||||||
* @param {Function} funcFirst
|
|
||||||
* @param {Function} funcSecond
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
var getSerialCallback = function (fns) {
|
|
||||||
if (!fns.length) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return function (callback) {
|
|
||||||
var that = this;
|
|
||||||
var bound_fns = [];
|
|
||||||
for (var i = 0, len = fns.length; i < len; i++) {
|
|
||||||
(function (j) {
|
|
||||||
bound_fns.push(function () {
|
|
||||||
return fns[j].apply(that, arguments);
|
|
||||||
});
|
|
||||||
})(i);
|
|
||||||
}
|
|
||||||
return async.series(bound_fns, callback);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps a group of tests with setUp and tearDown functions.
|
|
||||||
* Used by testCase.
|
|
||||||
*
|
|
||||||
* @param {Object} group
|
|
||||||
* @param {Array} setUps - parent setUp functions
|
|
||||||
* @param {Array} tearDowns - parent tearDown functions
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
var wrapGroup = function (group, setUps, tearDowns) {
|
|
||||||
var tests = {};
|
|
||||||
|
|
||||||
var setUps = setUps ? setUps.slice(): [];
|
|
||||||
var tearDowns = tearDowns ? tearDowns.slice(): [];
|
|
||||||
|
|
||||||
if (group.setUp) {
|
|
||||||
setUps.push(group.setUp);
|
|
||||||
delete group.setUp;
|
|
||||||
}
|
|
||||||
if (group.tearDown) {
|
|
||||||
tearDowns.unshift(group.tearDown);
|
|
||||||
delete group.tearDown;
|
|
||||||
}
|
|
||||||
|
|
||||||
var keys = _keys(group);
|
|
||||||
|
|
||||||
for (var i = 0; i < keys.length; i += 1) {
|
|
||||||
var k = keys[i];
|
|
||||||
if (typeof group[k] === 'function') {
|
|
||||||
tests[k] = wrapTest(
|
|
||||||
getSerialCallback(setUps),
|
|
||||||
getSerialCallback(tearDowns),
|
|
||||||
group[k]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (typeof group[k] === 'object') {
|
|
||||||
tests[k] = wrapGroup(group[k], setUps, tearDowns);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tests;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Backwards compatibility for test suites using old testCase API
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.testCase = function (suite) {
|
|
||||||
return suite;
|
|
||||||
};
|
|
104
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/nodeunit.js
generated
vendored
104
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/nodeunit.js
generated
vendored
|
@ -1,104 +0,0 @@
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
var async = require('../deps/async'),
|
|
||||||
types = require('./types'),
|
|
||||||
utils = require('./utils'),
|
|
||||||
core = require('./core'),
|
|
||||||
reporters = require('./reporters'),
|
|
||||||
assert = require('./assert'),
|
|
||||||
path = require('path'),
|
|
||||||
events = require('events');
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export sub-modules.
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.types = types;
|
|
||||||
exports.utils = utils;
|
|
||||||
exports.reporters = reporters;
|
|
||||||
exports.assert = assert;
|
|
||||||
|
|
||||||
// backwards compatibility
|
|
||||||
exports.testrunner = {
|
|
||||||
run: function () {
|
|
||||||
console.log(
|
|
||||||
'WARNING: nodeunit.testrunner is going to be deprecated, please ' +
|
|
||||||
'use nodeunit.reporters.default instead!'
|
|
||||||
);
|
|
||||||
return reporters['default'].run.apply(this, arguments);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Export all core functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
for (var k in core) {
|
|
||||||
exports[k] = core[k];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load modules from paths array and run all exported tests in series. If a path
|
|
||||||
* is a directory, load all supported file types inside it as modules. This only
|
|
||||||
* reads 1 level deep in the directory and does not recurse through
|
|
||||||
* sub-directories.
|
|
||||||
*
|
|
||||||
* @param {Array} paths
|
|
||||||
* @param {Object} opt
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.runFiles = function (paths, opt) {
|
|
||||||
var all_assertions = [];
|
|
||||||
var options = types.options(opt);
|
|
||||||
var start = new Date().getTime();
|
|
||||||
|
|
||||||
if (!paths.length) {
|
|
||||||
return options.done(types.assertionList(all_assertions));
|
|
||||||
}
|
|
||||||
|
|
||||||
utils.modulePaths(paths, function (err, files) {
|
|
||||||
if (err) throw err;
|
|
||||||
async.concatSeries(files, function (file, cb) {
|
|
||||||
var name = path.basename(file);
|
|
||||||
exports.runModule(name, require(file), options, cb);
|
|
||||||
},
|
|
||||||
function (err, all_assertions) {
|
|
||||||
var end = new Date().getTime();
|
|
||||||
exports.done()
|
|
||||||
options.done(types.assertionList(all_assertions, end - start));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Export all prototypes from events.EventEmitter */
|
|
||||||
var label;
|
|
||||||
for (label in events.EventEmitter.prototype) {
|
|
||||||
exports[label] = events.EventEmitter.prototype[label];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Emit event 'complete' on completion of a test suite. */
|
|
||||||
exports.complete = function(name, assertions)
|
|
||||||
{
|
|
||||||
exports.emit('complete', name, assertions);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Emit event 'complete' on completion of all tests. */
|
|
||||||
exports.done = function()
|
|
||||||
{
|
|
||||||
exports.emit('done');
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = exports;
|
|
123
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/browser.js
generated
vendored
123
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/browser.js
generated
vendored
|
@ -1,123 +0,0 @@
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*
|
|
||||||
* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
|
|
||||||
* You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build.
|
|
||||||
* Only code on that line will be removed, its mostly to avoid requiring code
|
|
||||||
* that is node specific
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* NOTE: this test runner is not listed in index.js because it cannot be
|
|
||||||
* used with the command-line tool, only inside the browser.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reporter info string
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.info = "Browser-based test reporter";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run all tests within each module, reporting the results
|
|
||||||
*
|
|
||||||
* @param {Array} files
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.run = function (modules, options, callback) {
|
|
||||||
var start = new Date().getTime(), div;
|
|
||||||
options = options || {};
|
|
||||||
div = options.div || document.body;
|
|
||||||
|
|
||||||
function setText(el, txt) {
|
|
||||||
if ('innerText' in el) {
|
|
||||||
el.innerText = txt;
|
|
||||||
}
|
|
||||||
else if ('textContent' in el){
|
|
||||||
el.textContent = txt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getOrCreate(tag, id) {
|
|
||||||
var el = document.getElementById(id);
|
|
||||||
if (!el) {
|
|
||||||
el = document.createElement(tag);
|
|
||||||
el.id = id;
|
|
||||||
div.appendChild(el);
|
|
||||||
}
|
|
||||||
return el;
|
|
||||||
};
|
|
||||||
|
|
||||||
var header = getOrCreate('h1', 'nodeunit-header');
|
|
||||||
var banner = getOrCreate('h2', 'nodeunit-banner');
|
|
||||||
var userAgent = getOrCreate('h2', 'nodeunit-userAgent');
|
|
||||||
var tests = getOrCreate('ol', 'nodeunit-tests');
|
|
||||||
var result = getOrCreate('p', 'nodeunit-testresult');
|
|
||||||
|
|
||||||
setText(userAgent, navigator.userAgent);
|
|
||||||
|
|
||||||
nodeunit.runModules(modules, {
|
|
||||||
moduleStart: function (name) {
|
|
||||||
/*var mheading = document.createElement('h2');
|
|
||||||
mheading.innerText = name;
|
|
||||||
results.appendChild(mheading);
|
|
||||||
module = document.createElement('ol');
|
|
||||||
results.appendChild(module);*/
|
|
||||||
},
|
|
||||||
testDone: function (name, assertions) {
|
|
||||||
var test = document.createElement('li');
|
|
||||||
var strong = document.createElement('strong');
|
|
||||||
strong.innerHTML = name + ' <b style="color: black;">(' +
|
|
||||||
'<b class="fail">' + assertions.failures() + '</b>, ' +
|
|
||||||
'<b class="pass">' + assertions.passes() + '</b>, ' +
|
|
||||||
assertions.length +
|
|
||||||
')</b>';
|
|
||||||
test.className = assertions.failures() ? 'fail': 'pass';
|
|
||||||
test.appendChild(strong);
|
|
||||||
|
|
||||||
var aList = document.createElement('ol');
|
|
||||||
aList.style.display = 'none';
|
|
||||||
test.onclick = function () {
|
|
||||||
var d = aList.style.display;
|
|
||||||
aList.style.display = (d == 'none') ? 'block': 'none';
|
|
||||||
};
|
|
||||||
for (var i=0; i<assertions.length; i++) {
|
|
||||||
var li = document.createElement('li');
|
|
||||||
var a = assertions[i];
|
|
||||||
if (a.failed()) {
|
|
||||||
li.innerHTML = (a.message || a.method || 'no message') +
|
|
||||||
'<pre>' + (a.error.stack || a.error) + '</pre>';
|
|
||||||
li.className = 'fail';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
li.innerHTML = a.message || a.method || 'no message';
|
|
||||||
li.className = 'pass';
|
|
||||||
}
|
|
||||||
aList.appendChild(li);
|
|
||||||
}
|
|
||||||
test.appendChild(aList);
|
|
||||||
tests.appendChild(test);
|
|
||||||
},
|
|
||||||
done: function (assertions) {
|
|
||||||
var end = new Date().getTime();
|
|
||||||
var duration = end - start;
|
|
||||||
|
|
||||||
var failures = assertions.failures();
|
|
||||||
banner.className = failures ? 'fail': 'pass';
|
|
||||||
|
|
||||||
result.innerHTML = 'Tests completed in ' + duration +
|
|
||||||
' milliseconds.<br/><span class="passed">' +
|
|
||||||
assertions.passes() + '</span> assertions of ' +
|
|
||||||
'<span class="all">' + assertions.length + '<span> passed, ' +
|
|
||||||
assertions.failures() + ' failed.';
|
|
||||||
|
|
||||||
if (callback) callback(assertions.failures() ? new Error('We have got test failures.') : undefined);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
131
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/default.js
generated
vendored
131
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/default.js
generated
vendored
|
@ -1,131 +0,0 @@
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
var nodeunit = require('../nodeunit'),
|
|
||||||
utils = require('../utils'),
|
|
||||||
fs = require('fs'),
|
|
||||||
track = require('../track'),
|
|
||||||
path = require('path'),
|
|
||||||
AssertionError = require('../assert').AssertionError;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reporter info string
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.info = "Default tests reporter";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run all tests within each module, reporting the results to the command-line.
|
|
||||||
*
|
|
||||||
* @param {Array} files
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.run = function (files, options, callback) {
|
|
||||||
|
|
||||||
if (!options) {
|
|
||||||
// load default options
|
|
||||||
var content = fs.readFileSync(
|
|
||||||
__dirname + '/../../bin/nodeunit.json', 'utf8'
|
|
||||||
);
|
|
||||||
options = JSON.parse(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
var error = function (str) {
|
|
||||||
return options.error_prefix + str + options.error_suffix;
|
|
||||||
};
|
|
||||||
var ok = function (str) {
|
|
||||||
return options.ok_prefix + str + options.ok_suffix;
|
|
||||||
};
|
|
||||||
var bold = function (str) {
|
|
||||||
return options.bold_prefix + str + options.bold_suffix;
|
|
||||||
};
|
|
||||||
var assertion_message = function (str) {
|
|
||||||
return options.assertion_prefix + str + options.assertion_suffix;
|
|
||||||
};
|
|
||||||
|
|
||||||
var start = new Date().getTime();
|
|
||||||
var tracker = track.createTracker(function (tracker) {
|
|
||||||
if (tracker.unfinished()) {
|
|
||||||
console.log('');
|
|
||||||
console.log(error(bold(
|
|
||||||
'FAILURES: Undone tests (or their setups/teardowns): '
|
|
||||||
)));
|
|
||||||
var names = tracker.names();
|
|
||||||
for (var i = 0; i < names.length; i += 1) {
|
|
||||||
console.log('- ' + names[i]);
|
|
||||||
}
|
|
||||||
console.log('');
|
|
||||||
console.log('To fix this, make sure all tests call test.done()');
|
|
||||||
process.reallyExit(tracker.unfinished());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var opts = {
|
|
||||||
testspec: options.testspec,
|
|
||||||
testFullSpec: options.testFullSpec,
|
|
||||||
moduleStart: function (name) {
|
|
||||||
console.log('\n' + bold(name));
|
|
||||||
},
|
|
||||||
testDone: function (name, assertions) {
|
|
||||||
tracker.remove(name);
|
|
||||||
|
|
||||||
if (!assertions.failures()) {
|
|
||||||
console.log('✔ ' + name);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(error('✖ ' + name) + '\n');
|
|
||||||
assertions.forEach(function (a) {
|
|
||||||
if (a.failed()) {
|
|
||||||
a = utils.betterErrors(a);
|
|
||||||
if (a.error instanceof AssertionError && a.message) {
|
|
||||||
console.log(
|
|
||||||
'Assertion Message: ' +
|
|
||||||
assertion_message(a.message)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
console.log(a.error.stack + '\n');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
done: function (assertions, end) {
|
|
||||||
var end = end || new Date().getTime();
|
|
||||||
var duration = end - start;
|
|
||||||
if (assertions.failures()) {
|
|
||||||
console.log(
|
|
||||||
'\n' + bold(error('FAILURES: ')) + assertions.failures() +
|
|
||||||
'/' + assertions.length + ' assertions failed (' +
|
|
||||||
assertions.duration + 'ms)'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(
|
|
||||||
'\n' + bold(ok('OK: ')) + assertions.length +
|
|
||||||
' assertions (' + assertions.duration + 'ms)'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback) callback(assertions.failures() ? new Error('We have got test failures.') : undefined);
|
|
||||||
},
|
|
||||||
testStart: function(name) {
|
|
||||||
tracker.put(name);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (files && files.length) {
|
|
||||||
var paths = files.map(function (p) {
|
|
||||||
return path.resolve(p);
|
|
||||||
});
|
|
||||||
nodeunit.runFiles(paths, opts);
|
|
||||||
} else {
|
|
||||||
nodeunit.runModules(files,opts);
|
|
||||||
}
|
|
||||||
};
|
|
104
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/eclipse.js
generated
vendored
104
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/eclipse.js
generated
vendored
|
@ -1,104 +0,0 @@
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
var nodeunit = require('../nodeunit'),
|
|
||||||
utils = require('../utils'),
|
|
||||||
fs = require('fs'),
|
|
||||||
track = require('../track'),
|
|
||||||
path = require('path'),
|
|
||||||
AssertionError = require('../assert').AssertionError;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reporter info string
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.info = "Reporter for eclipse plugin";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run all tests within each module, reporting the results to the command-line.
|
|
||||||
*
|
|
||||||
* @param {Array} files
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.run = function (files, options, callback) {
|
|
||||||
|
|
||||||
var start = new Date().getTime();
|
|
||||||
var paths = files.map(function (p) {
|
|
||||||
if (p.indexOf('/') === 0) {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
return path.resolve(p);
|
|
||||||
});
|
|
||||||
var tracker = track.createTracker(function (tracker) {
|
|
||||||
if (tracker.unfinished()) {
|
|
||||||
console.log('');
|
|
||||||
console.log('FAILURES: Undone tests (or their setups/teardowns): ');
|
|
||||||
var names = tracker.names();
|
|
||||||
for (var i = 0; i < names.length; i += 1) {
|
|
||||||
console.log('- ' + names[i]);
|
|
||||||
}
|
|
||||||
console.log('');
|
|
||||||
console.log('To fix this, make sure all tests call test.done()');
|
|
||||||
process.reallyExit(tracker.unfinished());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
nodeunit.runFiles(paths, {
|
|
||||||
testspec: undefined,
|
|
||||||
moduleStart: function (name) {
|
|
||||||
console.log('\n' + name);
|
|
||||||
},
|
|
||||||
testDone: function (name, assertions) {
|
|
||||||
tracker.remove(name);
|
|
||||||
|
|
||||||
if (!assertions.failures()) {
|
|
||||||
console.log('✔ ' + name);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log('✖ ' + name + '\n');
|
|
||||||
assertions.forEach(function (a) {
|
|
||||||
if (a.failed()) {
|
|
||||||
a = utils.betterErrors(a);
|
|
||||||
if (a.error instanceof AssertionError && a.message) {
|
|
||||||
console.log(
|
|
||||||
'Assertion Message: ' + a.message
|
|
||||||
);
|
|
||||||
}
|
|
||||||
console.log(a.error.stack + '\n');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
done: function (assertions, end) {
|
|
||||||
var end = end || new Date().getTime();
|
|
||||||
var duration = end - start;
|
|
||||||
if (assertions.failures()) {
|
|
||||||
console.log(
|
|
||||||
'\n' + 'FAILURES: ' + assertions.failures() +
|
|
||||||
'/' + assertions.length + ' assertions failed (' +
|
|
||||||
assertions.duration + 'ms)'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(
|
|
||||||
'\n' + 'OK: ' + assertions.length +
|
|
||||||
' assertions (' + assertions.duration + 'ms)'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback) callback(assertions.failures() ? new Error('We have got test failures.') : undefined);
|
|
||||||
},
|
|
||||||
testStart: function (name) {
|
|
||||||
tracker.put(name);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
110
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/html.js
generated
vendored
110
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/html.js
generated
vendored
|
@ -1,110 +0,0 @@
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
var nodeunit = require('../nodeunit'),
|
|
||||||
utils = require('../utils'),
|
|
||||||
fs = require('fs'),
|
|
||||||
path = require('path'),
|
|
||||||
AssertionError = require('assert').AssertionError;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reporter info string
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.info = "Report tests result as HTML";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run all tests within each module, reporting the results to the command-line.
|
|
||||||
*
|
|
||||||
* @param {Array} files
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.run = function (files, options, callback) {
|
|
||||||
|
|
||||||
var start = new Date().getTime();
|
|
||||||
var paths = files.map(function (p) {
|
|
||||||
return path.resolve(p);
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('<html>');
|
|
||||||
console.log('<head>');
|
|
||||||
console.log('<title></title>');
|
|
||||||
console.log('<style type="text/css">');
|
|
||||||
console.log('body { font: 12px Helvetica Neue }');
|
|
||||||
console.log('h2 { margin:0 ; padding:0 }');
|
|
||||||
console.log('pre { font: 11px Andale Mono; margin-left: 1em; padding-left: 1em; margin-top:0; font-size:smaller;}');
|
|
||||||
console.log('.assertion_message { margin-left: 1em; }');
|
|
||||||
console.log(' ol {' +
|
|
||||||
' list-style: none;' +
|
|
||||||
' margin-left: 1em;' +
|
|
||||||
' padding-left: 1em;' +
|
|
||||||
' text-indent: -1em;' +
|
|
||||||
'}');
|
|
||||||
console.log(' ol li.pass:before { content: "\\2714 \\0020"; }');
|
|
||||||
console.log(' ol li.fail:before { content: "\\2716 \\0020"; }');
|
|
||||||
console.log('</style>');
|
|
||||||
console.log('</head>');
|
|
||||||
console.log('<body>');
|
|
||||||
nodeunit.runFiles(paths, {
|
|
||||||
testspec: options.testspec,
|
|
||||||
testFullSpec: options.testFullSpec,
|
|
||||||
moduleStart: function (name) {
|
|
||||||
console.log('<h2>' + name + '</h2>');
|
|
||||||
console.log('<ol>');
|
|
||||||
},
|
|
||||||
testDone: function (name, assertions) {
|
|
||||||
if (!assertions.failures()) {
|
|
||||||
console.log('<li class="pass">' + name + '</li>');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log('<li class="fail">' + name);
|
|
||||||
assertions.forEach(function (a) {
|
|
||||||
if (a.failed()) {
|
|
||||||
a = utils.betterErrors(a);
|
|
||||||
if (a.error instanceof AssertionError && a.message) {
|
|
||||||
console.log('<div class="assertion_message">' +
|
|
||||||
'Assertion Message: ' + a.message +
|
|
||||||
'</div>');
|
|
||||||
}
|
|
||||||
console.log('<pre>');
|
|
||||||
console.log(a.error.stack);
|
|
||||||
console.log('</pre>');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
console.log('</li>');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
moduleDone: function () {
|
|
||||||
console.log('</ol>');
|
|
||||||
},
|
|
||||||
done: function (assertions) {
|
|
||||||
var end = new Date().getTime();
|
|
||||||
var duration = end - start;
|
|
||||||
if (assertions.failures()) {
|
|
||||||
console.log(
|
|
||||||
'<h3>FAILURES: ' + assertions.failures() +
|
|
||||||
'/' + assertions.length + ' assertions failed (' +
|
|
||||||
assertions.duration + 'ms)</h3>'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(
|
|
||||||
'<h3>OK: ' + assertions.length +
|
|
||||||
' assertions (' + assertions.duration + 'ms)</h3>'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
console.log('</body>');
|
|
||||||
console.log('</html>');
|
|
||||||
|
|
||||||
if (callback) callback(assertions.failures() ? new Error('We have got test failures.') : undefined);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
27
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/index.js
generated
vendored
27
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/index.js
generated
vendored
|
@ -1,27 +0,0 @@
|
||||||
// This is a hack to make browserify skip tap
|
|
||||||
var tap;
|
|
||||||
try {
|
|
||||||
tap = require('./' + 'tap');
|
|
||||||
} catch (ex) {
|
|
||||||
tap = {
|
|
||||||
run: function() {
|
|
||||||
throw new Error('Sorry, tap reporter not available');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
'junit': require('./junit'),
|
|
||||||
'default': require('./default'),
|
|
||||||
'skip_passed': require('./skip_passed'),
|
|
||||||
'minimal': require('./minimal'),
|
|
||||||
'html': require('./html'),
|
|
||||||
'eclipse': require('./eclipse'),
|
|
||||||
'machineout': require('./machineout'),
|
|
||||||
'tap': tap,
|
|
||||||
'nested': require('./nested'),
|
|
||||||
'verbose' : require('./verbose'),
|
|
||||||
'lcov' : require('./lcov')
|
|
||||||
// browser test reporter is not listed because it cannot be used
|
|
||||||
// with the command line tool, only inside a browser.
|
|
||||||
};
|
|
180
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/junit.js
generated
vendored
180
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/junit.js
generated
vendored
|
@ -1,180 +0,0 @@
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
var nodeunit = require('../nodeunit'),
|
|
||||||
utils = require('../utils'),
|
|
||||||
fs = require('fs'),
|
|
||||||
path = require('path'),
|
|
||||||
async = require('../../deps/async'),
|
|
||||||
AssertionError = require('assert').AssertionError,
|
|
||||||
child_process = require('child_process'),
|
|
||||||
ejs = require('../../deps/ejs');
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reporter info string
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.info = "jUnit XML test reports";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensures a directory exists using mkdir -p.
|
|
||||||
*
|
|
||||||
* @param {String} path
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
var ensureDir = function (path, callback) {
|
|
||||||
var mkdir = child_process.spawn('mkdir', ['-p', path]);
|
|
||||||
mkdir.on('error', function (err) {
|
|
||||||
callback(err);
|
|
||||||
callback = function(){};
|
|
||||||
});
|
|
||||||
mkdir.on('exit', function (code) {
|
|
||||||
if (code === 0) callback();
|
|
||||||
else callback(new Error('mkdir exited with code: ' + code));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns absolute version of a path. Relative paths are interpreted
|
|
||||||
* relative to process.cwd() or the cwd parameter. Paths that are already
|
|
||||||
* absolute are returned unaltered.
|
|
||||||
*
|
|
||||||
* @param {String} p
|
|
||||||
* @param {String} cwd
|
|
||||||
* @return {String}
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
var abspath = function (p, /*optional*/cwd) {
|
|
||||||
if (p[0] === '/') return p;
|
|
||||||
cwd = cwd || process.cwd();
|
|
||||||
return path.normalize(path.resolve(p));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run all tests within each module, reporting the results to the command-line,
|
|
||||||
* then writes out junit-compatible xml documents.
|
|
||||||
*
|
|
||||||
* @param {Array} files
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.run = function (files, opts, callback) {
|
|
||||||
if (!opts.output) {
|
|
||||||
console.error(
|
|
||||||
'Error: No output directory defined.\n' +
|
|
||||||
'\tEither add an "output" property to your nodeunit.json config ' +
|
|
||||||
'file, or\n\tuse the --output command line option.'
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
opts.output = abspath(opts.output);
|
|
||||||
var error = function (str) {
|
|
||||||
return opts.error_prefix + str + opts.error_suffix;
|
|
||||||
};
|
|
||||||
var ok = function (str) {
|
|
||||||
return opts.ok_prefix + str + opts.ok_suffix;
|
|
||||||
};
|
|
||||||
var bold = function (str) {
|
|
||||||
return opts.bold_prefix + str + opts.bold_suffix;
|
|
||||||
};
|
|
||||||
|
|
||||||
var start = new Date().getTime();
|
|
||||||
var paths = files.map(function (p) {
|
|
||||||
return path.resolve(p);
|
|
||||||
});
|
|
||||||
|
|
||||||
var modules = {}
|
|
||||||
var curModule;
|
|
||||||
|
|
||||||
nodeunit.runFiles(paths, {
|
|
||||||
testspec: opts.testspec,
|
|
||||||
testFullSpec: opts.testFullSpec,
|
|
||||||
moduleStart: function (name) {
|
|
||||||
curModule = {
|
|
||||||
errorCount: 0,
|
|
||||||
failureCount: 0,
|
|
||||||
tests: 0,
|
|
||||||
testcases: [],
|
|
||||||
name: name
|
|
||||||
};
|
|
||||||
modules[name] = curModule;
|
|
||||||
},
|
|
||||||
testDone: function (name, assertions) {
|
|
||||||
var testcase = {name: name};
|
|
||||||
for (var i=0; i<assertions.length; i++) {
|
|
||||||
var a = assertions[i];
|
|
||||||
if (a.failed()) {
|
|
||||||
a = utils.betterErrors(a);
|
|
||||||
testcase.failure = {
|
|
||||||
message: a.message,
|
|
||||||
backtrace: a.error.stack
|
|
||||||
};
|
|
||||||
|
|
||||||
if (a.error instanceof AssertionError) {
|
|
||||||
curModule.failureCount++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
curModule.errorCount++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
curModule.tests++;
|
|
||||||
curModule.testcases.push(testcase);
|
|
||||||
},
|
|
||||||
done: function (assertions) {
|
|
||||||
var end = new Date().getTime();
|
|
||||||
var duration = end - start;
|
|
||||||
|
|
||||||
ensureDir(opts.output, function (err) {
|
|
||||||
var tmpl = __dirname + "/../../share/junit.xml.ejs";
|
|
||||||
fs.readFile(tmpl, function (err, data) {
|
|
||||||
if (err) throw err;
|
|
||||||
var tmpl = data.toString();
|
|
||||||
for(var k in modules) {
|
|
||||||
var module = modules[k];
|
|
||||||
var rendered = ejs.render(tmpl, {
|
|
||||||
locals: {suites: [module]}
|
|
||||||
});
|
|
||||||
var filename = path.resolve(
|
|
||||||
opts.output,
|
|
||||||
module.name + '.xml'
|
|
||||||
);
|
|
||||||
console.log('Writing ' + filename);
|
|
||||||
fs.writeFileSync(filename, rendered, 'utf8');
|
|
||||||
}
|
|
||||||
if (assertions.failures()) {
|
|
||||||
console.log(
|
|
||||||
'\n' + bold(error('FAILURES: ')) +
|
|
||||||
assertions.failures() + '/' +
|
|
||||||
assertions.length + ' assertions failed (' +
|
|
||||||
assertions.duration + 'ms)'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(
|
|
||||||
'\n' + bold(ok('OK: ')) + assertions.length +
|
|
||||||
' assertions (' + assertions.duration + 'ms)'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback) callback(assertions.failures() ? new Error('We have got test failures.') : undefined);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
54
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/lcov.js
generated
vendored
54
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/lcov.js
generated
vendored
|
@ -1,54 +0,0 @@
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
var nodeunit = require('../nodeunit'),
|
|
||||||
path = require('path');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reporter info string
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.info = 'The LCOV reporter reads JS files instrumented by JSCoverage (http://siliconforks.com/jscoverage/) and outputs coverage data in the LCOV format (http://ltp.sourceforge.net/coverage/lcov/geninfo.1.php)';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run all tests within each module, reporting the results to the command-line.
|
|
||||||
*
|
|
||||||
* @param {Array} files
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.run = function (files, options, callback) {
|
|
||||||
|
|
||||||
var paths = files.map(function (p) {
|
|
||||||
return path.resolve(p);
|
|
||||||
});
|
|
||||||
|
|
||||||
nodeunit.runFiles(paths, {
|
|
||||||
done: function (assertions) {
|
|
||||||
var cov = (global || window)._$jscoverage || {};
|
|
||||||
|
|
||||||
Object.keys(cov).forEach(function (filename) {
|
|
||||||
var data = cov[filename];
|
|
||||||
reportFile(filename, data);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (callback) callback(assertions.failures() ? new Error('We have got test failures.') : undefined);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
function reportFile(filename, data) {
|
|
||||||
console.log('SF:' + filename);
|
|
||||||
|
|
||||||
data.source.forEach(function(line, num) {
|
|
||||||
// increase the line number, as JS arrays are zero-based
|
|
||||||
num++;
|
|
||||||
|
|
||||||
if (data[num] !== undefined) {
|
|
||||||
console.log('DA:' + num + ',' + data[num]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('end_of_record');
|
|
||||||
}
|
|
112
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/machineout.js
generated
vendored
112
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/machineout.js
generated
vendored
|
@ -1,112 +0,0 @@
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
*
|
|
||||||
* @author Alisue (lambdalisue@hashnote.net)
|
|
||||||
* @url http://hashnote.net/
|
|
||||||
*
|
|
||||||
* Copyright (c) 2011 Alisue
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
var nodeunit = require('../nodeunit'),
|
|
||||||
utils = require('../utils'),
|
|
||||||
fs = require('fs'),
|
|
||||||
track = require('../track'),
|
|
||||||
path = require('path'),
|
|
||||||
AssertionError = require('../assert').AssertionError;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reporter info string
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.info = "Tests reporter for machinally analysis";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run all tests within each module, reporting the results to the command-line.
|
|
||||||
*
|
|
||||||
* @param {Array} files
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.run = function (files, options, callback) {
|
|
||||||
// options doesn't effect
|
|
||||||
|
|
||||||
var parseStack = function (stack, delimiter) {
|
|
||||||
var parseTrace = function (trace) {
|
|
||||||
var filename, row, column;
|
|
||||||
pattern1 = /\s{4}at\s\S+\s\(([^:]+):(\d+):(\d+)\)/;
|
|
||||||
pattern2 = /\s{4}at\s([^:]+):(\d+):(\d+)/;
|
|
||||||
|
|
||||||
if (trace.match(pattern1) !== null) {
|
|
||||||
filename = RegExp.$1;
|
|
||||||
row = RegExp.$2;
|
|
||||||
column = RegExp.$3;
|
|
||||||
} else if (trace.match(pattern2) !== null) {
|
|
||||||
filename = RegExp.$1;
|
|
||||||
row = RegExp.$2;
|
|
||||||
column = RegExp.$3;
|
|
||||||
} else {
|
|
||||||
throw new Error("Could not parse a line of stack trace: " + trace);
|
|
||||||
}
|
|
||||||
return {filename: filename, row: row, column: column};
|
|
||||||
};
|
|
||||||
if (delimiter === undefined) {
|
|
||||||
delimiter = ':';
|
|
||||||
}
|
|
||||||
traceback = stack.split('\n');
|
|
||||||
firstline = traceback.shift();
|
|
||||||
trace = parseTrace(traceback[0]);
|
|
||||||
return {filename: trace.filename, row: trace.row, column: trace.column, message: firstline};
|
|
||||||
};
|
|
||||||
var createErrorMessage = function(type, name, filename, row, column, message){
|
|
||||||
return [type, name, filename, row, column, message].join(":");
|
|
||||||
};
|
|
||||||
var paths = files.map(function (p) {
|
|
||||||
return path.resolve(p);
|
|
||||||
});
|
|
||||||
var tracker = track.createTracker(function (tracker) {
|
|
||||||
if (tracker.unfinished()) {
|
|
||||||
var names = tracker.names();
|
|
||||||
for (var i = 0; i < names.length; i += 1) {
|
|
||||||
console.log(createErrorMessage(
|
|
||||||
'Error', names[i],
|
|
||||||
'', '', '',
|
|
||||||
'Undone tests - To fix this, make sure all tests call test.done()'
|
|
||||||
));
|
|
||||||
}
|
|
||||||
process.reallyExit(tracker.unfinished());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
nodeunit.runFiles(paths, {
|
|
||||||
testspec: options.testspec,
|
|
||||||
testFullSpec: options.testFullSpec,
|
|
||||||
moduleStart: function (name) {},
|
|
||||||
testDone: function (name, assertions) {
|
|
||||||
tracker.remove(name);
|
|
||||||
if (assertions.failures()) {
|
|
||||||
assertions.forEach(function (a) {
|
|
||||||
var stacks, message, filename, row, column;
|
|
||||||
if (a.failed()) {
|
|
||||||
stackinfo = parseStack(a.error.stack, ':');
|
|
||||||
console.log(createErrorMessage(
|
|
||||||
'Fail', name, stackinfo.filename,
|
|
||||||
stackinfo.row, stackinfo.column, stackinfo.message));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
done: function (assertions, end) {
|
|
||||||
if (callback) callback(assertions.failures() ? new Error('We have got test failures.') : undefined);
|
|
||||||
},
|
|
||||||
testStart: function(name) {
|
|
||||||
tracker.put(name);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
142
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/minimal.js
generated
vendored
142
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/minimal.js
generated
vendored
|
@ -1,142 +0,0 @@
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
var nodeunit = require('../nodeunit'),
|
|
||||||
utils = require('../utils'),
|
|
||||||
fs = require('fs'),
|
|
||||||
path = require('path'),
|
|
||||||
track = require('../track'),
|
|
||||||
AssertionError = require('assert').AssertionError;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reporter info string
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.info = "Pretty minimal output";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run all tests within each module, reporting the results to the command-line.
|
|
||||||
*
|
|
||||||
* @param {Array} files
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.run = function (files, options, callback) {
|
|
||||||
|
|
||||||
if (!options) {
|
|
||||||
// load default options
|
|
||||||
var content = fs.readFileSync(
|
|
||||||
__dirname + '/../../bin/nodeunit.json', 'utf8'
|
|
||||||
);
|
|
||||||
options = JSON.parse(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
var red = function (str) {
|
|
||||||
return options.error_prefix + str + options.error_suffix;
|
|
||||||
};
|
|
||||||
var green = function (str) {
|
|
||||||
return options.ok_prefix + str + options.ok_suffix;
|
|
||||||
};
|
|
||||||
var magenta = function (str) {
|
|
||||||
return options.assertion_prefix + str + options.assertion_suffix;
|
|
||||||
};
|
|
||||||
var bold = function (str) {
|
|
||||||
return options.bold_prefix + str + options.bold_suffix;
|
|
||||||
};
|
|
||||||
|
|
||||||
var start = new Date().getTime();
|
|
||||||
|
|
||||||
var tracker = track.createTracker(function (tracker) {
|
|
||||||
if (tracker.unfinished()) {
|
|
||||||
console.log('');
|
|
||||||
console.log(bold(red(
|
|
||||||
'FAILURES: Undone tests (or their setups/teardowns): '
|
|
||||||
)));
|
|
||||||
var names = tracker.names();
|
|
||||||
for (var i = 0; i < names.length; i += 1) {
|
|
||||||
console.log('- ' + names[i]);
|
|
||||||
}
|
|
||||||
console.log('');
|
|
||||||
console.log('To fix this, make sure all tests call test.done()');
|
|
||||||
process.reallyExit(tracker.unfinished());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
var opts = {
|
|
||||||
testspec: options.testspec,
|
|
||||||
testFullSpec: options.testFullSpec,
|
|
||||||
moduleStart: function (name) {
|
|
||||||
process.stdout.write(bold(name) + ': ');
|
|
||||||
},
|
|
||||||
moduleDone: function (name, assertions) {
|
|
||||||
console.log('');
|
|
||||||
if (assertions.failures()) {
|
|
||||||
assertions.forEach(function (a) {
|
|
||||||
if (a.failed()) {
|
|
||||||
a = utils.betterErrors(a);
|
|
||||||
if (a.error instanceof AssertionError && a.message) {
|
|
||||||
console.log(
|
|
||||||
'Assertion in test ' + bold(a.testname) + ': ' +
|
|
||||||
magenta(a.message)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
console.log(a.error.stack + '\n');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
testStart: function (name) {
|
|
||||||
tracker.put(name);
|
|
||||||
},
|
|
||||||
testDone: function (name, assertions) {
|
|
||||||
tracker.remove(name);
|
|
||||||
|
|
||||||
if (!assertions.failures()) {
|
|
||||||
process.stdout.write('.');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
process.stdout.write(red('F'));
|
|
||||||
assertions.forEach(function (assertion) {
|
|
||||||
assertion.testname = name;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
done: function (assertions) {
|
|
||||||
var end = new Date().getTime();
|
|
||||||
var duration = end - start;
|
|
||||||
if (assertions.failures()) {
|
|
||||||
console.log(
|
|
||||||
'\n' + bold(red('FAILURES: ')) + assertions.failures() +
|
|
||||||
'/' + assertions.length + ' assertions failed (' +
|
|
||||||
assertions.duration + 'ms)'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(
|
|
||||||
'\n' + bold(green('OK: ')) + assertions.length +
|
|
||||||
' assertions (' + assertions.duration + 'ms)'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback) callback(assertions.failures() ? new Error('We have got test failures.') : undefined);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (files && files.length) {
|
|
||||||
var paths = files.map(function (p) {
|
|
||||||
return path.resolve(p);
|
|
||||||
});
|
|
||||||
nodeunit.runFiles(paths, opts);
|
|
||||||
} else {
|
|
||||||
nodeunit.runModules(files,opts);
|
|
||||||
}
|
|
||||||
};
|
|
216
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/nested.js
generated
vendored
216
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/nested.js
generated
vendored
|
@ -1,216 +0,0 @@
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
var nodeunit = require('../nodeunit'),
|
|
||||||
utils = require('../utils'),
|
|
||||||
fs = require('fs'),
|
|
||||||
track = require('../track'),
|
|
||||||
path = require('path'),
|
|
||||||
AssertionError = require('../assert').AssertionError;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reporter info string
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.info = "Nested test reporter";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run all tests within each module, reporting the results to the command-line.
|
|
||||||
*
|
|
||||||
* @param {Array} files
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.run = function (files, options, callback) {
|
|
||||||
|
|
||||||
if (!options) {
|
|
||||||
// load default options
|
|
||||||
var content = fs.readFileSync(
|
|
||||||
__dirname + '/../../bin/nodeunit.json',
|
|
||||||
'utf8'
|
|
||||||
);
|
|
||||||
options = JSON.parse(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
var error = function (str) {
|
|
||||||
return options.error_prefix + str + options.error_suffix;
|
|
||||||
};
|
|
||||||
var ok = function (str) {
|
|
||||||
return options.ok_prefix + str + options.ok_suffix;
|
|
||||||
};
|
|
||||||
var bold = function (str) {
|
|
||||||
return options.bold_prefix + str + options.bold_suffix;
|
|
||||||
};
|
|
||||||
var assertion_message = function (str) {
|
|
||||||
return options.assertion_prefix + str + options.assertion_suffix;
|
|
||||||
};
|
|
||||||
|
|
||||||
var spaces_per_indent = options.spaces_per_indent || 4;
|
|
||||||
|
|
||||||
var start = new Date().getTime();
|
|
||||||
var paths = files.map(function (p) {
|
|
||||||
return path.resolve(p);
|
|
||||||
});
|
|
||||||
var tracker = track.createTracker(function (tracker) {
|
|
||||||
var i, names;
|
|
||||||
if (tracker.unfinished()) {
|
|
||||||
console.log('');
|
|
||||||
console.log(error(bold(
|
|
||||||
'FAILURES: Undone tests (or their setups/teardowns): '
|
|
||||||
)));
|
|
||||||
names = tracker.names();
|
|
||||||
for (i = 0; i < names.length; i += 1) {
|
|
||||||
console.log('- ' + names[i]);
|
|
||||||
}
|
|
||||||
console.log('');
|
|
||||||
console.log('To fix this, make sure all tests call test.done()');
|
|
||||||
process.reallyExit(tracker.unfinished());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Object to hold status of each 'part' of the testCase/name array,
|
|
||||||
// i.e., whether this part has been printed yet.
|
|
||||||
tracker.already_printed = {};
|
|
||||||
|
|
||||||
var pass_text = function (txt) {
|
|
||||||
// Print in bold green.
|
|
||||||
return bold(ok(txt + " (pass)"));
|
|
||||||
};
|
|
||||||
|
|
||||||
var fail_text = function (txt) {
|
|
||||||
return bold(error(txt + " (fail) ✖ "));
|
|
||||||
};
|
|
||||||
|
|
||||||
var status_text = function (txt, status) {
|
|
||||||
if (status === 'pass') {
|
|
||||||
return pass_text(txt);
|
|
||||||
} else {
|
|
||||||
return fail_text(txt);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Slices an array, returns a string by joining the sliced elements.
|
|
||||||
* @example
|
|
||||||
* > name_slice(['TC1', 'TC1.1', 'mytest'], 1);
|
|
||||||
* "TC1,TC1.1"
|
|
||||||
*/
|
|
||||||
var name_slice = function (name_arr, end_index) {
|
|
||||||
return name_arr.slice(0, end_index + 1).join(",");
|
|
||||||
};
|
|
||||||
|
|
||||||
var indent = (function () {
|
|
||||||
var txt = '';
|
|
||||||
var i;
|
|
||||||
for (i = 0; i < spaces_per_indent; i++) {
|
|
||||||
txt += ' ';
|
|
||||||
}
|
|
||||||
return txt;
|
|
||||||
}());
|
|
||||||
|
|
||||||
// Indent once for each indent_level
|
|
||||||
var add_indent = function (txt, indent_level) {
|
|
||||||
var k;
|
|
||||||
for (k = 0; k < indent_level; k++) {
|
|
||||||
txt += indent;
|
|
||||||
}
|
|
||||||
return txt;
|
|
||||||
};
|
|
||||||
|
|
||||||
// If it's not the last element of the name_arr, it's a testCase.
|
|
||||||
var is_testCase = function (name_arr, index) {
|
|
||||||
return index === name_arr.length - 1 ? false : true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var testCase_line = function (txt) {
|
|
||||||
return txt + "\n";
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints (console.log) the nested test status line(s).
|
|
||||||
*
|
|
||||||
* @param {Array} name_arr - Array of name elements.
|
|
||||||
* @param {String} status - either 'pass' or 'fail'.
|
|
||||||
* @example
|
|
||||||
* > print_status(['TC1', 'TC1.1', 'mytest'], 'pass');
|
|
||||||
* TC1
|
|
||||||
* TC1.1
|
|
||||||
* mytest (pass)
|
|
||||||
*/
|
|
||||||
var print_status = function (name_arr, status) {
|
|
||||||
var txt = '';
|
|
||||||
var _name_slice, part, i;
|
|
||||||
for (i = 0; i < name_arr.length; i++) {
|
|
||||||
_name_slice = name_slice(name_arr, i);
|
|
||||||
part = name_arr[i];
|
|
||||||
if (!tracker.already_printed[_name_slice]) {
|
|
||||||
txt = add_indent(txt, i);
|
|
||||||
if (is_testCase(name_arr, i)) {
|
|
||||||
txt += testCase_line(part);
|
|
||||||
} else {
|
|
||||||
txt += status_text(part, status);
|
|
||||||
}
|
|
||||||
tracker.already_printed[_name_slice] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log(txt);
|
|
||||||
};
|
|
||||||
|
|
||||||
nodeunit.runFiles(paths, {
|
|
||||||
testspec: options.testspec,
|
|
||||||
testFullSpec: options.testFullSpec,
|
|
||||||
moduleStart: function (name) {
|
|
||||||
console.log('\n' + bold(name));
|
|
||||||
},
|
|
||||||
testDone: function (name, assertions) {
|
|
||||||
tracker.remove(name);
|
|
||||||
|
|
||||||
if (!assertions.failures()) {
|
|
||||||
print_status(name, 'pass');
|
|
||||||
} else {
|
|
||||||
print_status(name, 'fail');
|
|
||||||
assertions.forEach(function (a) {
|
|
||||||
if (a.failed()) {
|
|
||||||
a = utils.betterErrors(a);
|
|
||||||
if (a.error instanceof AssertionError && a.message) {
|
|
||||||
console.log(
|
|
||||||
'Assertion Message: ' +
|
|
||||||
assertion_message(a.message)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
console.log(a.error.stack + '\n');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
done: function (assertions, end) {
|
|
||||||
end = end || new Date().getTime();
|
|
||||||
var duration = end - start;
|
|
||||||
if (assertions.failures()) {
|
|
||||||
console.log(
|
|
||||||
'\n' + bold(error('FAILURES: ')) + assertions.failures() +
|
|
||||||
'/' + assertions.length + ' assertions failed (' +
|
|
||||||
assertions.duration + 'ms)'
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
console.log(
|
|
||||||
'\n' + bold(ok('OK: ')) + assertions.length +
|
|
||||||
' assertions (' + assertions.duration + 'ms)'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback) callback(assertions.failures() ? new Error('We have got test failures.') : undefined);
|
|
||||||
},
|
|
||||||
testStart: function (name) {
|
|
||||||
tracker.put(name);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
108
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/skip_passed.js
generated
vendored
108
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/skip_passed.js
generated
vendored
|
@ -1,108 +0,0 @@
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
var nodeunit = require('../nodeunit'),
|
|
||||||
utils = require('../utils'),
|
|
||||||
fs = require('fs'),
|
|
||||||
path = require('path'),
|
|
||||||
AssertionError = require('assert').AssertionError;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reporter info string
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.info = "Skip passed tests output";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run all tests within each module, reporting the results to the command-line.
|
|
||||||
*
|
|
||||||
* @param {Array} files
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.run = function (files, options, callback) {
|
|
||||||
|
|
||||||
if (!options) {
|
|
||||||
// load default options
|
|
||||||
var content = fs.readFileSync(
|
|
||||||
__dirname + '/../../bin/nodeunit.json', 'utf8'
|
|
||||||
);
|
|
||||||
options = JSON.parse(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
var error = function (str) {
|
|
||||||
return options.error_prefix + str + options.error_suffix;
|
|
||||||
};
|
|
||||||
var ok = function (str) {
|
|
||||||
return options.ok_prefix + str + options.ok_suffix;
|
|
||||||
};
|
|
||||||
var bold = function (str) {
|
|
||||||
return options.bold_prefix + str + options.bold_suffix;
|
|
||||||
};
|
|
||||||
var assertion_message = function (str) {
|
|
||||||
return options.assertion_prefix + str + options.assertion_suffix;
|
|
||||||
};
|
|
||||||
|
|
||||||
var start = new Date().getTime();
|
|
||||||
var paths = files.map(function (p) {
|
|
||||||
return path.resolve(p);
|
|
||||||
});
|
|
||||||
|
|
||||||
nodeunit.runFiles(paths, {
|
|
||||||
testspec: options.testspec,
|
|
||||||
testFullSpec: options.testFullSpec,
|
|
||||||
moduleStart: function (name) {
|
|
||||||
console.log('\n' + bold(name));
|
|
||||||
},
|
|
||||||
testDone: function (name, assertions) {
|
|
||||||
if (assertions.failures()) {
|
|
||||||
console.log(error('✖ ' + name) + '\n');
|
|
||||||
assertions.forEach(function (a) {
|
|
||||||
if (a.failed()) {
|
|
||||||
a = utils.betterErrors(a);
|
|
||||||
if (a.error instanceof AssertionError && a.message) {
|
|
||||||
console.log(
|
|
||||||
'Assertion Message: ' + assertion_message(a.message)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
console.log(a.error.stack + '\n');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
moduleDone: function (name, assertions) {
|
|
||||||
if (!assertions.failures()) {
|
|
||||||
console.log('✔ all tests passed');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(error('✖ some tests failed'));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
done: function (assertions) {
|
|
||||||
var end = new Date().getTime();
|
|
||||||
var duration = end - start;
|
|
||||||
if (assertions.failures()) {
|
|
||||||
console.log(
|
|
||||||
'\n' + bold(error('FAILURES: ')) + assertions.failures() +
|
|
||||||
'/' + assertions.length + ' assertions failed (' +
|
|
||||||
assertions.duration + 'ms)'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(
|
|
||||||
'\n' + bold(ok('OK: ')) + assertions.length +
|
|
||||||
' assertions (' + assertions.duration + 'ms)'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback) callback(assertions.failures() ? new Error('We have got test failures.') : undefined);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
67
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/tap.js
generated
vendored
67
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/tap.js
generated
vendored
|
@ -1,67 +0,0 @@
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
var nodeunit = require('../nodeunit'),
|
|
||||||
path = require('path'),
|
|
||||||
assert = require('tap').assert,
|
|
||||||
TapProducer = require('tap').Producer,
|
|
||||||
fs = require('fs');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reporter info string
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.info = "TAP output";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run all tests within each module, reporting the results to the command-line.
|
|
||||||
*
|
|
||||||
* @param {Array} files
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.run = function (files, options, callback) {
|
|
||||||
|
|
||||||
if (!options) {
|
|
||||||
// load default options
|
|
||||||
var content = fs.readFileSync(
|
|
||||||
__dirname + '/../../bin/nodeunit.json', 'utf8'
|
|
||||||
);
|
|
||||||
options = JSON.parse(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
var paths = files.map(function (p) {
|
|
||||||
return path.resolve(p);
|
|
||||||
});
|
|
||||||
var output = new TapProducer();
|
|
||||||
output.pipe(process.stdout);
|
|
||||||
|
|
||||||
nodeunit.runFiles(paths, {
|
|
||||||
testStart: function (name) {
|
|
||||||
output.write(name.toString());
|
|
||||||
},
|
|
||||||
testDone: function (name, assertions) {
|
|
||||||
assertions.forEach(function (e) {
|
|
||||||
var extra = {};
|
|
||||||
if (e.error) {
|
|
||||||
extra.error = {
|
|
||||||
name: e.error.name,
|
|
||||||
message: e.error.message,
|
|
||||||
stack: e.error.stack.split(/\n/).filter(function (line) {
|
|
||||||
// exclude line of "types.js"
|
|
||||||
return ! RegExp(/types.js:83:39/).test(line);
|
|
||||||
}).join('\n')
|
|
||||||
};
|
|
||||||
extra.wanted = e.error.expected;
|
|
||||||
extra.found = e.error.actual;
|
|
||||||
}
|
|
||||||
output.write(assert(e.passed(), e.message, extra));
|
|
||||||
});
|
|
||||||
},
|
|
||||||
done: function (assertions) {
|
|
||||||
output.end();
|
|
||||||
if (callback) callback(assertions.failures() ? new Error('We have got test failures.') : undefined);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
125
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/verbose.js
generated
vendored
125
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/lib/reporters/verbose.js
generated
vendored
|
@ -1,125 +0,0 @@
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
var nodeunit = require('../nodeunit'),
|
|
||||||
utils = require('../utils'),
|
|
||||||
fs = require('fs'),
|
|
||||||
track = require('../track'),
|
|
||||||
path = require('path');
|
|
||||||
AssertionError = require('../assert').AssertionError;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reporter info string
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.info = "Verbose tests reporter"
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run all tests within each module, reporting the results to the command-line.
|
|
||||||
*
|
|
||||||
* @param {Array} files
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.run = function (files, options, callback) {
|
|
||||||
|
|
||||||
if (!options) {
|
|
||||||
// load default options
|
|
||||||
var content = fs.readFileSync(
|
|
||||||
__dirname + '/../../bin/nodeunit.json', 'utf8'
|
|
||||||
);
|
|
||||||
options = JSON.parse(content);
|
|
||||||
}
|
|
||||||
|
|
||||||
var error = function (str) {
|
|
||||||
return options.error_prefix + str + options.error_suffix;
|
|
||||||
};
|
|
||||||
var ok = function (str) {
|
|
||||||
return options.ok_prefix + str + options.ok_suffix;
|
|
||||||
};
|
|
||||||
var bold = function (str) {
|
|
||||||
return options.bold_prefix + str + options.bold_suffix;
|
|
||||||
};
|
|
||||||
var assertion_message = function (str) {
|
|
||||||
return options.assertion_prefix + str + options.assertion_suffix;
|
|
||||||
};
|
|
||||||
|
|
||||||
var start = new Date().getTime();
|
|
||||||
var paths = files.map(function (p) {
|
|
||||||
return path.resolve(p);
|
|
||||||
});
|
|
||||||
var tracker = track.createTracker(function (tracker) {
|
|
||||||
if (tracker.unfinished()) {
|
|
||||||
console.log('');
|
|
||||||
console.log(error(bold(
|
|
||||||
'FAILURES: Undone tests (or their setups/teardowns): '
|
|
||||||
)));
|
|
||||||
var names = tracker.names();
|
|
||||||
for (var i = 0; i < names.length; i += 1) {
|
|
||||||
console.log('- ' + names[i]);
|
|
||||||
}
|
|
||||||
console.log('');
|
|
||||||
console.log('To fix this, make sure all tests call test.done()');
|
|
||||||
process.reallyExit(tracker.unfinished());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
nodeunit.runFiles(paths, {
|
|
||||||
testspec: options.testspec,
|
|
||||||
testFullSpec: options.testFullSpec,
|
|
||||||
moduleStart: function (name) {
|
|
||||||
console.log('\n' + bold(name));
|
|
||||||
},
|
|
||||||
testDone: function (name, assertions) {
|
|
||||||
tracker.remove(name);
|
|
||||||
|
|
||||||
if (!assertions.failures()) {
|
|
||||||
console.log('✔ ' + name);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(error('✖ ' + name));
|
|
||||||
}
|
|
||||||
// verbose so print everything
|
|
||||||
assertions.forEach(function (a) {
|
|
||||||
if (a.failed()) {
|
|
||||||
console.log(error(' ✖ ' + a.message));
|
|
||||||
a = utils.betterErrors(a);
|
|
||||||
console.log(' ' + a.error.stack);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(' ✔ ' + a.message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
done: function (assertions, end) {
|
|
||||||
var end = end || new Date().getTime();
|
|
||||||
var duration = end - start;
|
|
||||||
if (assertions.failures()) {
|
|
||||||
console.log(
|
|
||||||
'\n' + bold(error('FAILURES: ')) + assertions.failures() +
|
|
||||||
'/' + assertions.length + ' assertions failed (' +
|
|
||||||
assertions.duration + 'ms)'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(
|
|
||||||
'\n' + bold(ok('OK: ')) + assertions.length +
|
|
||||||
' assertions (' + assertions.duration + 'ms)'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback) callback(assertions.failures() ? new Error('We have got test failures.') : undefined);
|
|
||||||
},
|
|
||||||
testStart: function(name) {
|
|
||||||
tracker.put(name);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,48 +0,0 @@
|
||||||
/*!
|
|
||||||
* Simple util module to track tests. Adds a process.exit hook to print
|
|
||||||
* the undone tests.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
exports.createTracker = function (on_exit) {
|
|
||||||
var names = {};
|
|
||||||
var tracker = {
|
|
||||||
names: function () {
|
|
||||||
var arr = [];
|
|
||||||
for (var k in names) {
|
|
||||||
if (names.hasOwnProperty(k)) {
|
|
||||||
arr.push(k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return arr;
|
|
||||||
},
|
|
||||||
unfinished: function () {
|
|
||||||
return tracker.names().length;
|
|
||||||
},
|
|
||||||
put: function (testname) {
|
|
||||||
names[testname] = testname;
|
|
||||||
},
|
|
||||||
remove: function (testname) {
|
|
||||||
delete names[testname];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
process.on('exit', function() {
|
|
||||||
on_exit = on_exit || exports.default_on_exit;
|
|
||||||
on_exit(tracker);
|
|
||||||
});
|
|
||||||
|
|
||||||
return tracker;
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.default_on_exit = function (tracker) {
|
|
||||||
if (tracker.unfinished()) {
|
|
||||||
console.log('');
|
|
||||||
console.log('Undone tests (or their setups/teardowns): ');
|
|
||||||
var names = tracker.names();
|
|
||||||
for (var i = 0; i < names.length; i += 1) {
|
|
||||||
console.log(names[i]);
|
|
||||||
}
|
|
||||||
process.reallyExit(tracker.unfinished());
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,190 +0,0 @@
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*
|
|
||||||
* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
|
|
||||||
* You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build.
|
|
||||||
* Only code on that line will be removed, it's mostly to avoid requiring code
|
|
||||||
* that is node specific
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
var assert = require('./assert'), //@REMOVE_LINE_FOR_BROWSER
|
|
||||||
async = require('../deps/async'); //@REMOVE_LINE_FOR_BROWSER
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates assertion objects representing the result of an assert call.
|
|
||||||
* Accepts an object or AssertionError as its argument.
|
|
||||||
*
|
|
||||||
* @param {object} obj
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.assertion = function (obj) {
|
|
||||||
return {
|
|
||||||
method: obj.method || '',
|
|
||||||
message: obj.message || (obj.error && obj.error.message) || '',
|
|
||||||
error: obj.error,
|
|
||||||
passed: function () {
|
|
||||||
return !this.error;
|
|
||||||
},
|
|
||||||
failed: function () {
|
|
||||||
return Boolean(this.error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an assertion list object representing a group of assertions.
|
|
||||||
* Accepts an array of assertion objects.
|
|
||||||
*
|
|
||||||
* @param {Array} arr
|
|
||||||
* @param {Number} duration
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.assertionList = function (arr, duration) {
|
|
||||||
var that = arr || [];
|
|
||||||
that.failures = function () {
|
|
||||||
var failures = 0;
|
|
||||||
for (var i = 0; i < this.length; i += 1) {
|
|
||||||
if (this[i].failed()) {
|
|
||||||
failures += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return failures;
|
|
||||||
};
|
|
||||||
that.passes = function () {
|
|
||||||
return that.length - that.failures();
|
|
||||||
};
|
|
||||||
that.duration = duration || 0;
|
|
||||||
return that;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a wrapper function for assert module methods. Executes a callback
|
|
||||||
* after it's complete with an assertion object representing the result.
|
|
||||||
*
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api private
|
|
||||||
*/
|
|
||||||
|
|
||||||
var assertWrapper = function (callback) {
|
|
||||||
return function (new_method, assert_method, arity) {
|
|
||||||
return function () {
|
|
||||||
var message = arguments[arity - 1];
|
|
||||||
var a = exports.assertion({method: new_method, message: message});
|
|
||||||
try {
|
|
||||||
assert[assert_method].apply(null, arguments);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
a.error = e;
|
|
||||||
}
|
|
||||||
callback(a);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the 'test' object that gets passed to every test function.
|
|
||||||
* Accepts the name of the test function as its first argument, followed by
|
|
||||||
* the start time in ms, the options object and a callback function.
|
|
||||||
*
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Number} start
|
|
||||||
* @param {Object} options
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.test = function (name, start, options, callback) {
|
|
||||||
var expecting;
|
|
||||||
var a_list = [];
|
|
||||||
|
|
||||||
var wrapAssert = assertWrapper(function (a) {
|
|
||||||
a_list.push(a);
|
|
||||||
if (options.log) {
|
|
||||||
async.nextTick(function () {
|
|
||||||
options.log(a);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var test = {
|
|
||||||
done: function (err) {
|
|
||||||
if (expecting !== undefined && expecting !== a_list.length) {
|
|
||||||
var e = new Error(
|
|
||||||
'Expected ' + expecting + ' assertions, ' +
|
|
||||||
a_list.length + ' ran'
|
|
||||||
);
|
|
||||||
var a1 = exports.assertion({method: 'expect', error: e});
|
|
||||||
a_list.push(a1);
|
|
||||||
if (options.log) {
|
|
||||||
async.nextTick(function () {
|
|
||||||
options.log(a1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (err) {
|
|
||||||
var a2 = exports.assertion({error: err});
|
|
||||||
a_list.push(a2);
|
|
||||||
if (options.log) {
|
|
||||||
async.nextTick(function () {
|
|
||||||
options.log(a2);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var end = new Date().getTime();
|
|
||||||
async.nextTick(function () {
|
|
||||||
var assertion_list = exports.assertionList(a_list, end - start);
|
|
||||||
options.testDone(name, assertion_list);
|
|
||||||
callback(null, a_list);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
ok: wrapAssert('ok', 'ok', 2),
|
|
||||||
same: wrapAssert('same', 'deepEqual', 3),
|
|
||||||
equals: wrapAssert('equals', 'equal', 3),
|
|
||||||
expect: function (num) {
|
|
||||||
expecting = num;
|
|
||||||
},
|
|
||||||
_assertion_list: a_list
|
|
||||||
};
|
|
||||||
// add all functions from the assert module
|
|
||||||
for (var k in assert) {
|
|
||||||
if (assert.hasOwnProperty(k)) {
|
|
||||||
test[k] = wrapAssert(k, k, assert[k].length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return test;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensures an options object has all callbacks, adding empty callback functions
|
|
||||||
* if any are missing.
|
|
||||||
*
|
|
||||||
* @param {Object} opt
|
|
||||||
* @return {Object}
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.options = function (opt) {
|
|
||||||
var optionalCallback = function (name) {
|
|
||||||
opt[name] = opt[name] || function () {};
|
|
||||||
};
|
|
||||||
|
|
||||||
optionalCallback('moduleStart');
|
|
||||||
optionalCallback('moduleDone');
|
|
||||||
optionalCallback('testStart');
|
|
||||||
optionalCallback('testReady');
|
|
||||||
optionalCallback('testDone');
|
|
||||||
//optionalCallback('log');
|
|
||||||
|
|
||||||
// 'done' callback is not optional.
|
|
||||||
|
|
||||||
return opt;
|
|
||||||
};
|
|
|
@ -1,216 +0,0 @@
|
||||||
/*!
|
|
||||||
* Nodeunit
|
|
||||||
* Copyright (c) 2010 Caolan McMahon
|
|
||||||
* MIT Licensed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module dependencies
|
|
||||||
*/
|
|
||||||
|
|
||||||
var async = require('../deps/async'),
|
|
||||||
fs = require('fs'),
|
|
||||||
util = require('util'),
|
|
||||||
Script = require('vm').Script,
|
|
||||||
http = require('http');
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detect if coffee-script, iced-coffeescript, or streamline are available and
|
|
||||||
* the respective file extensions to the search filter in modulePaths if it is.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var extensions = [ 'js' ]; // js is always supported: add it unconditionally
|
|
||||||
var extensionPattern;
|
|
||||||
|
|
||||||
try {
|
|
||||||
require('coffee' + '-script/register');
|
|
||||||
extensions.push('coffee');
|
|
||||||
} catch (e) { }
|
|
||||||
|
|
||||||
try {
|
|
||||||
require('iced-coffee' + '-script/register');
|
|
||||||
extensions.push('iced');
|
|
||||||
} catch (e) { }
|
|
||||||
|
|
||||||
try {
|
|
||||||
require('stream' + 'line').register();
|
|
||||||
extensions.push('_coffee');
|
|
||||||
extensions.push('_js');
|
|
||||||
} catch (e) { }
|
|
||||||
|
|
||||||
extensionPattern = new RegExp('\\.(?:' + extensions.join('|') + ')$');
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds all modules at each path in an array, If a path is a directory, it
|
|
||||||
* returns all supported file types inside it. This only reads 1 level deep in
|
|
||||||
* the directory and does not recurse through sub-directories.
|
|
||||||
*
|
|
||||||
* The extension (.js, .coffee etc) is stripped from the filenames so they can
|
|
||||||
* simply be require()'ed.
|
|
||||||
*
|
|
||||||
* @param {Array} paths
|
|
||||||
* @param {Function} callback
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.modulePaths = function (paths, callback) {
|
|
||||||
async.concat(paths, function (p, cb) {
|
|
||||||
fs.stat(p, function (err, stats) {
|
|
||||||
if (err) {
|
|
||||||
return cb(err);
|
|
||||||
}
|
|
||||||
if (stats.isFile()) {
|
|
||||||
return cb(null, [p]);
|
|
||||||
}
|
|
||||||
if (stats.isDirectory()) {
|
|
||||||
fs.readdir(p, function (err, files) {
|
|
||||||
if (err) {
|
|
||||||
return cb(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
// filter out any filenames with unsupported extensions
|
|
||||||
var modules = files.filter(function (filename) {
|
|
||||||
return extensionPattern.exec(filename);
|
|
||||||
});
|
|
||||||
|
|
||||||
// remove extension from module name and prepend the
|
|
||||||
// directory path
|
|
||||||
var fullpaths = modules.map(function (filename) {
|
|
||||||
var mod_name = filename.replace(extensionPattern, '');
|
|
||||||
return [p, mod_name].join('/');
|
|
||||||
});
|
|
||||||
|
|
||||||
// sort filenames here, because Array.map changes order
|
|
||||||
fullpaths.sort();
|
|
||||||
|
|
||||||
cb(null, fullpaths);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluates JavaScript files in a sandbox, returning the context. The first
|
|
||||||
* argument can either be a single filename or an array of filenames. If
|
|
||||||
* multiple filenames are given their contents are concatenated before
|
|
||||||
* evalution. The second argument is an optional context to use for the sandbox.
|
|
||||||
*
|
|
||||||
* @param files
|
|
||||||
* @param {Object} sandbox
|
|
||||||
* @return {Object}
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.sandbox = function (files, /*optional*/sandbox) {
|
|
||||||
var source, script, result;
|
|
||||||
if (!(files instanceof Array)) {
|
|
||||||
files = [files];
|
|
||||||
}
|
|
||||||
source = files.map(function (file) {
|
|
||||||
return fs.readFileSync(file, 'utf8');
|
|
||||||
}).join('');
|
|
||||||
|
|
||||||
if (!sandbox) {
|
|
||||||
sandbox = {};
|
|
||||||
}
|
|
||||||
script = new Script(source);
|
|
||||||
result = script.runInNewContext(sandbox);
|
|
||||||
return sandbox;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides a http request, response testing environment.
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
*
|
|
||||||
* var httputil = require('nodeunit').utils.httputil
|
|
||||||
* exports.testSomething = function(test) {
|
|
||||||
* httputil(function (req, resp) {
|
|
||||||
* resp.writeHead(200, {});
|
|
||||||
* resp.end('test data');
|
|
||||||
* },
|
|
||||||
* function(server, client) {
|
|
||||||
* client.fetch('GET', '/', {}, function(resp) {
|
|
||||||
* test.equal('test data', resp.body);
|
|
||||||
* server.close();
|
|
||||||
* test.done();
|
|
||||||
* })
|
|
||||||
* });
|
|
||||||
* };
|
|
||||||
*
|
|
||||||
* @param {Function} cgi
|
|
||||||
* @param {Function} envReady
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
exports.httputil = function (cgi, envReady) {
|
|
||||||
var hostname = process.env.HOSTNAME || 'localhost';
|
|
||||||
var port = process.env.PORT || 3000;
|
|
||||||
|
|
||||||
var server = http.createServer(cgi);
|
|
||||||
server.listen(port, hostname);
|
|
||||||
|
|
||||||
var client = http.createClient(port, hostname);
|
|
||||||
client.fetch = function (method, path, headers, respReady) {
|
|
||||||
var request = this.request(method, path, headers);
|
|
||||||
request.end();
|
|
||||||
request.on('response', function (response) {
|
|
||||||
response.setEncoding('utf8');
|
|
||||||
response.on('data', function (chunk) {
|
|
||||||
if (response.body) {
|
|
||||||
response.body += chunk;
|
|
||||||
} else {
|
|
||||||
response.body = chunk;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
response.on('end', function () {
|
|
||||||
if (response.headers['content-type'] === 'application/json') {
|
|
||||||
response.bodyAsObject = JSON.parse(response.body);
|
|
||||||
}
|
|
||||||
respReady(response);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
process.nextTick(function () {
|
|
||||||
if (envReady && typeof envReady === 'function') {
|
|
||||||
envReady(server, client);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Improves formatting of AssertionError messages to make deepEqual etc more
|
|
||||||
* readable.
|
|
||||||
*
|
|
||||||
* @param {Object} assertion
|
|
||||||
* @return {Object}
|
|
||||||
* @api public
|
|
||||||
*/
|
|
||||||
|
|
||||||
exports.betterErrors = function (assertion) {
|
|
||||||
if (!assertion.error) {
|
|
||||||
return assertion;
|
|
||||||
}
|
|
||||||
var e = assertion.error;
|
|
||||||
if (e.actual && e.expected) {
|
|
||||||
var actual = util.inspect(e.actual, false, 10).replace(/\n$/, '');
|
|
||||||
var expected = util.inspect(e.expected, false, 10).replace(/\n$/, '');
|
|
||||||
var multiline = (
|
|
||||||
actual.indexOf('\n') !== -1 ||
|
|
||||||
expected.indexOf('\n') !== -1
|
|
||||||
);
|
|
||||||
var spacing = (multiline ? '\n' : ' ');
|
|
||||||
e._message = e.message;
|
|
||||||
e.stack = (
|
|
||||||
e.name + ':' + spacing +
|
|
||||||
actual + spacing + e.operator + spacing +
|
|
||||||
expected + '\n' +
|
|
||||||
e.stack.split('\n').slice(1).join('\n')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return assertion;
|
|
||||||
};
|
|
95
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/man1/nodeunit.1
generated
vendored
95
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/man1/nodeunit.1
generated
vendored
|
@ -1,95 +0,0 @@
|
||||||
.\" Generated with Ronnjs/v0.1
|
|
||||||
.\" http://github.com/kapouer/ronnjs/
|
|
||||||
.
|
|
||||||
.TH "NODEUNIT" "1" "October 2010" "" ""
|
|
||||||
.
|
|
||||||
.SH "NAME"
|
|
||||||
\fBnodeunit\fR \-\- simple node\.js unit testing tool
|
|
||||||
.
|
|
||||||
.SH "SYNOPSIS"
|
|
||||||
.
|
|
||||||
.nf
|
|
||||||
nodeunit [options] <file\-or\-directory> [<file\-or\-directory> \.\.\.]
|
|
||||||
.
|
|
||||||
.fi
|
|
||||||
.
|
|
||||||
.SH "DESCRIPTION"
|
|
||||||
Nodeunit is a simple unit testing tool based on the node\.js assert module\.
|
|
||||||
.
|
|
||||||
.IP "\(bu" 4
|
|
||||||
Simple to use
|
|
||||||
.
|
|
||||||
.IP "\(bu" 4
|
|
||||||
Just export the tests from a module
|
|
||||||
.
|
|
||||||
.IP "\(bu" 4
|
|
||||||
Helps you avoid common pitfalls when testing asynchronous code
|
|
||||||
.
|
|
||||||
.IP "\(bu" 4
|
|
||||||
Easy to add test cases with setUp and tearDown functions if you wish
|
|
||||||
.
|
|
||||||
.IP "\(bu" 4
|
|
||||||
Allows the use of mocks and stubs
|
|
||||||
.
|
|
||||||
.IP "" 0
|
|
||||||
.
|
|
||||||
.SH "OPTIONS"
|
|
||||||
\fB\-\-config FILE\fR:
|
|
||||||
.
|
|
||||||
.br
|
|
||||||
Load config options from a JSON file, allows the customisation
|
|
||||||
of color schemes for the default test reporter etc\.
|
|
||||||
See bin/nodeunit\.json for current available options\.
|
|
||||||
.
|
|
||||||
.P
|
|
||||||
\fB\-\-reporter FILE\fR:
|
|
||||||
.
|
|
||||||
.br
|
|
||||||
You can set the test reporter to a custom module or on of the modules
|
|
||||||
in nodeunit/lib/reporters, when omitted, the default test runner is used\.
|
|
||||||
.
|
|
||||||
.P
|
|
||||||
\fB\-\-list\-reporters\fR:
|
|
||||||
.
|
|
||||||
.br
|
|
||||||
List available build\-in reporters\.
|
|
||||||
.
|
|
||||||
.P
|
|
||||||
\fB\-h\fR, \fB\-\-help\fR:
|
|
||||||
.
|
|
||||||
.br
|
|
||||||
Display the help and exit\.
|
|
||||||
.
|
|
||||||
.P
|
|
||||||
\fB\-v\fR, \fB\-\-version\fR:
|
|
||||||
.
|
|
||||||
.br
|
|
||||||
Output version information and exit\.
|
|
||||||
.
|
|
||||||
.P
|
|
||||||
\fB<file\-or\-directory>\fR:
|
|
||||||
You can run nodeunit on specific files or on all \fI*\.js\fR files inside
|
|
||||||
.
|
|
||||||
.br
|
|
||||||
a directory\.
|
|
||||||
.
|
|
||||||
.SH "AUTHORS"
|
|
||||||
Written by Caolan McMahon and other nodeunit contributors\.
|
|
||||||
.
|
|
||||||
.br
|
|
||||||
Contributors list: \fIhttp://github\.com/caolan/nodeunit/contributors\fR\|\.
|
|
||||||
.
|
|
||||||
.SH "REPORTING BUGS"
|
|
||||||
Report nodeunit bugs to \fIhttp://github\.com/caolan/nodeunit/issues\fR\|\.
|
|
||||||
.
|
|
||||||
.SH "COPYRIGHT"
|
|
||||||
Copyright © 2010 Caolan McMahon\.
|
|
||||||
.
|
|
||||||
.br
|
|
||||||
Nodeunit has been released under the MIT license:
|
|
||||||
.
|
|
||||||
.br
|
|
||||||
\fIhttp://github\.com/caolan/nodeunit/raw/master/LICENSE\fR\|\.
|
|
||||||
.
|
|
||||||
.SH "SEE ALSO"
|
|
||||||
node(1)
|
|
|
@ -1 +0,0 @@
|
||||||
../tap/bin/tap.js
|
|
11
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/node_modules/tap/AUTHORS
generated
vendored
11
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/node_modules/tap/AUTHORS
generated
vendored
|
@ -1,11 +0,0 @@
|
||||||
# contributors sorted by whether or not they're me
|
|
||||||
Isaac Z. Schlueter <i@izs.me>
|
|
||||||
baudehlo <helpme+github@gmail.com>
|
|
||||||
James Halliday <mail@substack.net>
|
|
||||||
Jason Smith (air) <jhs@iriscouch.com>
|
|
||||||
Pedro P. Candel <kusorbox@gmail.com>
|
|
||||||
Stein Martin Hustad <stein@hustad.com>
|
|
||||||
Trent Mick <trentm@gmail.com>
|
|
||||||
Corey Richardson <kb1pkl@aim.com>
|
|
||||||
Raynos <raynos2@gmail.com>
|
|
||||||
Siddharth Mahendraker <siddharth_mahen@me.com>
|
|
23
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/node_modules/tap/LICENSE
generated
vendored
23
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/node_modules/tap/LICENSE
generated
vendored
|
@ -1,23 +0,0 @@
|
||||||
Copyright 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.
|
|
|
@ -1,86 +0,0 @@
|
||||||
This 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.
|
|
|
@ -1,19 +0,0 @@
|
||||||
#!/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)
|
|
|
@ -1,33 +0,0 @@
|
||||||
#!/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)
|
|
||||||
})
|
|
147
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/node_modules/tap/bin/tap.js
generated
vendored
147
javascript/base/exercices/tests-unitaires/node_modules/nodeunit/node_modules/tap/bin/tap.js
generated
vendored
|
@ -1,147 +0,0 @@
|
||||||
#!/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 <options> <files>
|
|
||||||
|
|
||||||
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)
|
|
||||||
})
|
|
|
@ -1,15 +0,0 @@
|
||||||
var 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;
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
var 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;
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
var 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();
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
var 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();
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
var 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();
|
|
||||||
});
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
module.exports = Math
|
|
|
@ -1,237 +0,0 @@
|
||||||
var 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()
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,16 +0,0 @@
|
||||||
|
|
||||||
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")
|
|
|
@ -1,466 +0,0 @@
|
||||||
// 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 || "<root>")
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
// 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)
|
|
||||||
// })
|
|
||||||
}
|
|
|
@ -1,246 +0,0 @@
|
||||||
module.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)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,78 +0,0 @@
|
||||||
var 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 = '<!doctype html>\n<html lang="en">\n<head>\n ' +
|
|
||||||
'<meta charset="utf-8">\n <title>' +
|
|
||||||
|
|
||||||
f + ' (' + st.loc + ')</title>\n' +
|
|
||||||
'<style type="text/css">\n' +
|
|
||||||
'li {\n' +
|
|
||||||
' font-family: monospace;\n' +
|
|
||||||
' white-space: pre;\n' +
|
|
||||||
'}\n' +
|
|
||||||
'</style>\n' +
|
|
||||||
'</head>\n<body>\n' +
|
|
||||||
'<h1>' + f + ' (' + st.loc + ')' + '</h1>' +
|
|
||||||
'<h2>Run: ' + (st.missing.length ? st.loc - st.missing.length : st.loc) + ', Missing: ' +
|
|
||||||
st.missing.length + ', Percentage: ' + st.percentage + '</h2>' +
|
|
||||||
'<h2>Source:</h2>\n' +
|
|
||||||
'<ol>\n' +
|
|
||||||
st.lines.map(function(line) {
|
|
||||||
var number = line.number,
|
|
||||||
color = (missing_lines.indexOf(number) !== -1) ? '#fcc' : '#cfc';
|
|
||||||
return '<li id="L' + line.number + '" style="background-color: ' + color +
|
|
||||||
';">' + line.source.replace(/</g, "<") + '</li>';
|
|
||||||
}).join('\n') +
|
|
||||||
'</ol>\n' +
|
|
||||||
'<h2>Data</h2>\n'+
|
|
||||||
'<pre>' + util.inspect(st, true, Infinity, false).replace(/</g, "<") + '</pre></body>\n</html>';
|
|
||||||
|
|
||||||
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 = '<!doctype html>\n<html lang="en">\n<head>\n ' +
|
|
||||||
'<meta charset="utf-8">\n <title>Coverage Index</title>\n</head>\n' +
|
|
||||||
'<body>\n<h1>Code Coverage Information</h1>\n<ul>' +
|
|
||||||
index.map(function(fname) {
|
|
||||||
return '<li><a href="' +
|
|
||||||
fname.replace(process.cwd() + '/', '').replace(/\//g, '+') + '.html' +
|
|
||||||
'">' + fname + '</a></li>';
|
|
||||||
}).join('\n') + '</ul>\n</body>\n</html>';
|
|
||||||
|
|
||||||
fs.writeFile(cov_dir + '/index.html', out, 'utf8', function(err) {
|
|
||||||
if (err) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
// 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)
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,226 +0,0 @@
|
||||||
// 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)
|
|
||||||
}
|
|
|
@ -1,131 +0,0 @@
|
||||||
module.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
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
// 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)
|
|
||||||
}
|
|
|
@ -1,502 +0,0 @@
|
||||||
var 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()
|
|
||||||
}
|
|
|
@ -1,110 +0,0 @@
|
||||||
// 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)
|
|
|
@ -1 +0,0 @@
|
||||||
../mkdirp/bin/cmd.js
|
|
|
@ -1 +0,0 @@
|
||||||
../nopt/bin/nopt.js
|
|
|
@ -1,4 +0,0 @@
|
||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- 0.8
|
|
||||||
- "0.10"
|
|
|
@ -1,62 +0,0 @@
|
||||||
buffer-equal
|
|
||||||
============
|
|
||||||
|
|
||||||
Return whether two buffers are equal.
|
|
||||||
|
|
||||||
[![build status](https://secure.travis-ci.org/substack/node-buffer-equal.png)](http://travis-ci.org/substack/node-buffer-equal)
|
|
||||||
|
|
||||||
example
|
|
||||||
=======
|
|
||||||
|
|
||||||
``` js
|
|
||||||
var bufferEqual = require('buffer-equal');
|
|
||||||
|
|
||||||
console.dir(bufferEqual(
|
|
||||||
new Buffer([253,254,255]),
|
|
||||||
new Buffer([253,254,255])
|
|
||||||
));
|
|
||||||
console.dir(bufferEqual(
|
|
||||||
new Buffer('abc'),
|
|
||||||
new Buffer('abcd')
|
|
||||||
));
|
|
||||||
console.dir(bufferEqual(
|
|
||||||
new Buffer('abc'),
|
|
||||||
'abc'
|
|
||||||
));
|
|
||||||
```
|
|
||||||
|
|
||||||
output:
|
|
||||||
|
|
||||||
```
|
|
||||||
true
|
|
||||||
false
|
|
||||||
undefined
|
|
||||||
```
|
|
||||||
|
|
||||||
methods
|
|
||||||
=======
|
|
||||||
|
|
||||||
``` js
|
|
||||||
var bufferEqual = require('buffer-equal')
|
|
||||||
```
|
|
||||||
|
|
||||||
bufferEqual(a, b)
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
Return whether the two buffers `a` and `b` are equal.
|
|
||||||
|
|
||||||
If `a` or `b` is not a buffer, return `undefined`.
|
|
||||||
|
|
||||||
install
|
|
||||||
=======
|
|
||||||
|
|
||||||
With [npm](http://npmjs.org) do:
|
|
||||||
|
|
||||||
```
|
|
||||||
npm install buffer-equal
|
|
||||||
```
|
|
||||||
|
|
||||||
license
|
|
||||||
=======
|
|
||||||
|
|
||||||
MIT
|
|
|
@ -1,14 +0,0 @@
|
||||||
var bufferEqual = require('../');
|
|
||||||
|
|
||||||
console.dir(bufferEqual(
|
|
||||||
new Buffer([253,254,255]),
|
|
||||||
new Buffer([253,254,255])
|
|
||||||
));
|
|
||||||
console.dir(bufferEqual(
|
|
||||||
new Buffer('abc'),
|
|
||||||
new Buffer('abcd')
|
|
||||||
));
|
|
||||||
console.dir(bufferEqual(
|
|
||||||
new Buffer('abc'),
|
|
||||||
'abc'
|
|
||||||
));
|
|
|
@ -1,14 +0,0 @@
|
||||||
var Buffer = require('buffer').Buffer; // for use with browserify
|
|
||||||
|
|
||||||
module.exports = function (a, b) {
|
|
||||||
if (!Buffer.isBuffer(a)) return undefined;
|
|
||||||
if (!Buffer.isBuffer(b)) return undefined;
|
|
||||||
if (typeof a.equals === 'function') return a.equals(b);
|
|
||||||
if (a.length !== b.length) return false;
|
|
||||||
|
|
||||||
for (var i = 0; i < a.length; i++) {
|
|
||||||
if (a[i] !== b[i]) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
|
@ -1,56 +0,0 @@
|
||||||
{
|
|
||||||
"name": "buffer-equal",
|
|
||||||
"description": "return whether two buffers are equal",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git://github.com/substack/node-buffer-equal.git"
|
|
||||||
},
|
|
||||||
"main": "index.js",
|
|
||||||
"keywords": [
|
|
||||||
"buffer",
|
|
||||||
"equal"
|
|
||||||
],
|
|
||||||
"directories": {
|
|
||||||
"example": "example",
|
|
||||||
"test": "test"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "tap test/*.js"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"tap": "0.2.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.4.0"
|
|
||||||
},
|
|
||||||
"license": "MIT",
|
|
||||||
"author": {
|
|
||||||
"name": "James Halliday",
|
|
||||||
"email": "mail@substack.net",
|
|
||||||
"url": "http://substack.net"
|
|
||||||
},
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/substack/node-buffer-equal/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/substack/node-buffer-equal",
|
|
||||||
"_id": "buffer-equal@0.0.1",
|
|
||||||
"dist": {
|
|
||||||
"shasum": "91bc74b11ea405bc916bc6aa908faafa5b4aac4b",
|
|
||||||
"tarball": "http://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz"
|
|
||||||
},
|
|
||||||
"_from": "buffer-equal@~0.0.0",
|
|
||||||
"_npmVersion": "1.4.3",
|
|
||||||
"_npmUser": {
|
|
||||||
"name": "substack",
|
|
||||||
"email": "mail@substack.net"
|
|
||||||
},
|
|
||||||
"maintainers": [
|
|
||||||
{
|
|
||||||
"name": "substack",
|
|
||||||
"email": "mail@substack.net"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"_shasum": "91bc74b11ea405bc916bc6aa908faafa5b4aac4b",
|
|
||||||
"_resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz"
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
var bufferEqual = require('../');
|
|
||||||
var test = require('tap').test;
|
|
||||||
|
|
||||||
test('equal', function (t) {
|
|
||||||
var eq = bufferEqual(
|
|
||||||
new Buffer([253,254,255]),
|
|
||||||
new Buffer([253,254,255])
|
|
||||||
);
|
|
||||||
t.strictEqual(eq, true);
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('not equal', function (t) {
|
|
||||||
var eq = bufferEqual(
|
|
||||||
new Buffer('abc'),
|
|
||||||
new Buffer('abcd')
|
|
||||||
);
|
|
||||||
t.strictEqual(eq, false);
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('not equal not buffer', function (t) {
|
|
||||||
var eq = bufferEqual(
|
|
||||||
new Buffer('abc'),
|
|
||||||
'abc'
|
|
||||||
);
|
|
||||||
t.strictEqual(eq, undefined);
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('equal not buffer', function (t) {
|
|
||||||
var eq = bufferEqual('abc', 'abc');
|
|
||||||
t.strictEqual(eq, undefined);
|
|
||||||
t.end();
|
|
||||||
});
|
|
|
@ -1,4 +0,0 @@
|
||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- 0.4
|
|
||||||
- 0.6
|
|
|
@ -1,18 +0,0 @@
|
||||||
This software is released under the MIT license:
|
|
||||||
|
|
||||||
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.
|
|
|
@ -1,11 +0,0 @@
|
||||||
var equal = require('../');
|
|
||||||
console.dir([
|
|
||||||
equal(
|
|
||||||
{ a : [ 2, 3 ], b : [ 4 ] },
|
|
||||||
{ a : [ 2, 3 ], b : [ 4 ] }
|
|
||||||
),
|
|
||||||
equal(
|
|
||||||
{ x : 5, y : [6] },
|
|
||||||
{ x : 5, y : 6 }
|
|
||||||
)
|
|
||||||
]);
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue