vulcan 0.2.5 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +1 -80
- data/lib/vulcan/cli.rb +12 -33
- data/lib/vulcan/version.rb +1 -1
- data/server/bin/make +3 -1
- data/server/lib/spawner.js +4 -9
- data/server/node_modules/connect-form/node_modules/formidable/Readme.md +2 -13
- data/server/node_modules/connect-form/node_modules/formidable/lib/incoming_form.js +7 -19
- data/server/node_modules/connect-form/node_modules/formidable/lib/multipart_parser.js +1 -12
- data/server/node_modules/connect-form/node_modules/formidable/package.json +1 -1
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-chrome-13.http +10 -0
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-chrome-12.http +9 -0
- data/server/node_modules/connect-form/node_modules/formidable/test/legacy/simple/test-multipart-parser.js +1 -1
- data/server/node_modules/cradle/lib/cradle.js +1 -0
- data/server/node_modules/cradle/node_modules/vows/LICENSE +20 -0
- data/server/node_modules/cradle/node_modules/vows/Makefile +7 -0
- data/server/node_modules/cradle/node_modules/vows/README.md +39 -0
- data/server/node_modules/cradle/node_modules/vows/bin/vows +515 -0
- data/server/node_modules/cradle/node_modules/vows/lib/assert/error.js +27 -0
- data/server/node_modules/cradle/node_modules/vows/lib/assert/macros.js +215 -0
- data/server/node_modules/cradle/node_modules/vows/lib/assert/utils.js +77 -0
- data/server/node_modules/cradle/node_modules/vows/lib/vows.js +193 -0
- data/server/node_modules/cradle/node_modules/vows/lib/vows/console.js +131 -0
- data/server/node_modules/cradle/node_modules/vows/lib/vows/context.js +55 -0
- data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/file.js +29 -0
- data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/fragments/coverage-foot.html +2 -0
- data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/fragments/coverage-head.html +61 -0
- data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/report-html.js +54 -0
- data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/report-json.js +54 -0
- data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/report-plain.js +38 -0
- data/server/node_modules/cradle/node_modules/vows/lib/vows/extras.js +28 -0
- data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/dot-matrix.js +67 -0
- data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/json.js +16 -0
- data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/silent.js +8 -0
- data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/spec.js +44 -0
- data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/watch.js +39 -0
- data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/xunit.js +90 -0
- data/server/node_modules/cradle/node_modules/vows/lib/vows/suite.js +319 -0
- data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/LICENSE +20 -0
- data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/Makefile +4 -0
- data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/README.md +72 -0
- data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/lib/eyes.js +233 -0
- data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/package.json +14 -0
- data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/test/eyes-test.js +55 -0
- data/server/node_modules/cradle/node_modules/vows/package.json +14 -0
- data/server/node_modules/cradle/node_modules/vows/test/assert-test.js +135 -0
- data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/failing.js +18 -0
- data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/log.js +18 -0
- data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/passing.js +17 -0
- data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/stderr.js +18 -0
- data/server/node_modules/cradle/node_modules/vows/test/isolate-test.js +140 -0
- data/server/node_modules/cradle/node_modules/vows/test/testInherit.js +133 -0
- data/server/node_modules/cradle/node_modules/vows/test/vows-error-test.js +51 -0
- data/server/node_modules/cradle/node_modules/vows/test/vows-test.js +374 -0
- data/server/node_modules/cradle/package.json +3 -3
- data/server/node_modules/cradle/test/cache-test.js +7 -6
- data/server/node_modules/cradle/test/cradle-test.js +5 -4
- data/server/node_modules/cradle/test/response-test.js +6 -5
- data/server/node_modules/express/History.md +1 -53
- data/server/node_modules/express/Makefile +9 -3
- data/server/node_modules/express/Readme.md +1 -3
- data/server/node_modules/express/bin/express +66 -65
- data/server/node_modules/express/lib/express.js +1 -1
- data/server/node_modules/express/lib/request.js +9 -23
- data/server/node_modules/express/lib/response.js +2 -3
- data/server/node_modules/express/lib/utils.js +0 -13
- data/server/node_modules/express/lib/view.js +16 -19
- data/server/node_modules/express/lib/view/view.js +1 -2
- data/server/node_modules/express/node_modules/connect/lib/connect.js +1 -1
- data/server/node_modules/express/node_modules/connect/lib/http.js +0 -2
- data/server/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js +31 -135
- data/server/node_modules/express/node_modules/connect/lib/middleware/limit.js +1 -5
- data/server/node_modules/express/node_modules/connect/lib/middleware/session.js +2 -2
- data/server/node_modules/express/node_modules/connect/lib/middleware/static.js +21 -26
- data/server/node_modules/express/node_modules/connect/lib/middleware/staticCache.js +38 -91
- data/server/node_modules/express/node_modules/connect/lib/middleware/vhost.js +1 -1
- data/server/node_modules/express/node_modules/connect/lib/utils.js +4 -11
- data/server/node_modules/express/node_modules/connect/package.json +6 -7
- data/server/node_modules/express/node_modules/connect/test.js +31 -44
- data/server/node_modules/express/node_modules/mime/index.js +1 -0
- data/server/node_modules/express/node_modules/mime/mime.js +3 -3
- data/server/node_modules/express/node_modules/mime/{types/mime.types → mime.types} +0 -0
- data/server/node_modules/express/node_modules/mime/{types/node.types → node.types} +0 -17
- data/server/node_modules/express/node_modules/mime/package.json +10 -21
- data/server/node_modules/express/node_modules/mime/test.js +3 -2
- data/server/node_modules/express/node_modules/qs/History.md +0 -11
- data/server/node_modules/express/node_modules/qs/Makefile +3 -1
- data/server/node_modules/express/node_modules/qs/Readme.md +4 -2
- data/server/node_modules/express/node_modules/qs/lib/querystring.js +74 -100
- data/server/node_modules/express/node_modules/qs/package.json +2 -9
- data/server/node_modules/express/node_modules/qs/support/expresso/History.md +128 -0
- data/server/node_modules/express/node_modules/qs/support/expresso/Makefile +53 -0
- data/server/node_modules/express/node_modules/qs/support/expresso/Readme.md +61 -0
- data/server/node_modules/express/node_modules/qs/support/expresso/bin/expresso +856 -0
- data/server/node_modules/express/node_modules/qs/support/expresso/docs/api.html +1080 -0
- data/server/node_modules/express/node_modules/qs/support/expresso/docs/index.html +377 -0
- data/server/node_modules/express/node_modules/qs/support/expresso/docs/index.md +290 -0
- data/server/node_modules/express/node_modules/qs/support/expresso/docs/layout/foot.html +3 -0
- data/server/node_modules/express/node_modules/qs/support/expresso/docs/layout/head.html +42 -0
- data/server/node_modules/express/node_modules/qs/support/expresso/lib/bar.js +4 -0
- data/server/node_modules/express/node_modules/qs/support/expresso/lib/foo.js +16 -0
- data/server/node_modules/express/node_modules/qs/support/expresso/package.json +12 -0
- data/server/node_modules/express/node_modules/qs/support/expresso/test/assert.test.js +91 -0
- data/server/node_modules/express/node_modules/qs/support/expresso/test/async.test.js +12 -0
- data/server/node_modules/express/node_modules/qs/support/expresso/test/bar.test.js +13 -0
- data/server/node_modules/express/node_modules/qs/support/expresso/test/foo.test.js +14 -0
- data/server/node_modules/express/node_modules/qs/support/expresso/test/http.test.js +146 -0
- data/server/node_modules/express/node_modules/qs/support/expresso/test/serial/async.test.js +39 -0
- data/server/node_modules/express/node_modules/qs/support/expresso/test/serial/http.test.js +48 -0
- data/server/node_modules/express/node_modules/qs/support/should/History.md +22 -0
- data/server/node_modules/express/node_modules/qs/support/should/Makefile +6 -0
- data/server/node_modules/express/node_modules/qs/support/should/Readme.md +248 -0
- data/server/node_modules/express/node_modules/qs/support/should/examples/runner.js +53 -0
- data/server/node_modules/express/node_modules/qs/support/should/index.js +2 -0
- data/server/node_modules/express/node_modules/qs/support/should/lib/eql.js +91 -0
- data/server/node_modules/express/node_modules/qs/support/should/lib/should.js +548 -0
- data/server/node_modules/express/node_modules/qs/support/should/package.json +8 -0
- data/server/node_modules/express/node_modules/qs/support/should/test/should.test.js +358 -0
- data/server/node_modules/express/node_modules/qs/test/{parse.js → parse.test.js} +2 -1
- data/server/node_modules/express/node_modules/qs/test/{stringify.js → stringify.test.js} +0 -0
- data/server/node_modules/express/package.json +8 -9
- data/server/node_modules/node-uuid/README.md +67 -166
- data/server/node_modules/node-uuid/package.json +3 -5
- data/server/node_modules/node-uuid/{benchmark → test}/benchmark-native.c +0 -0
- data/server/node_modules/node-uuid/test/benchmark.js +27 -0
- data/server/node_modules/node-uuid/test/test.html +0 -3
- data/server/node_modules/node-uuid/test/test.js +57 -214
- data/server/node_modules/node-uuid/uuid.js +56 -225
- data/server/node_modules/restler/README.md +7 -20
- data/server/node_modules/restler/bin/restler +1 -1
- data/server/node_modules/restler/lib/multipartform.js +8 -9
- data/server/node_modules/restler/lib/restler.js +22 -64
- data/server/node_modules/restler/package.json +2 -2
- data/server/node_modules/restler/test/restler.js +2 -22
- data/server/node_modules/restler/test/test_helper.js +1 -20
- data/server/package.json +10 -10
- data/server/web.js +7 -30
- metadata +96 -89
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/file/plain.txt +0 -1
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/no-filename/generic.http +0 -13
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/js/no-filename.js +0 -3
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/Makefile +0 -14
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md +0 -286
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/TODO +0 -3
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js +0 -70
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js +0 -43
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js +0 -48
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/index.js +0 -1
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js +0 -61
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js +0 -377
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js +0 -3
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js +0 -312
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js +0 -25
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/util.js +0 -6
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/package.json +0 -22
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js +0 -19
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt +0 -1
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt +0 -1
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/no-filename/generic.http +0 -13
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md +0 -3
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-chrome-13.http +0 -26
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-firefox-3.6.http +0 -24
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-safari-5.http +0 -23
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-chrome-12.http +0 -24
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-7.http +0 -22
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-8.http +0 -22
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-safari-5.http +0 -22
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js +0 -3
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js +0 -21
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multi_video.upload +0 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js +0 -72
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js +0 -89
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js +0 -24
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js +0 -80
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js +0 -104
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js +0 -715
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js +0 -50
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js +0 -45
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js +0 -72
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js +0 -2
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js +0 -63
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js +0 -47
- data/server/node_modules/express/node_modules/mkdirp/LICENSE +0 -21
- data/server/node_modules/express/node_modules/mkdirp/README.markdown +0 -21
- data/server/node_modules/express/node_modules/mkdirp/examples/pow.js +0 -6
- data/server/node_modules/express/node_modules/mkdirp/examples/pow.js.orig +0 -6
- data/server/node_modules/express/node_modules/mkdirp/examples/pow.js.rej +0 -19
- data/server/node_modules/express/node_modules/mkdirp/index.js +0 -20
- data/server/node_modules/express/node_modules/mkdirp/package.json +0 -23
- data/server/node_modules/express/node_modules/mkdirp/test/mkdirp.js +0 -28
- data/server/node_modules/express/node_modules/mkdirp/test/race.js +0 -41
- data/server/node_modules/express/node_modules/mkdirp/test/rel.js +0 -32
- data/server/node_modules/express/node_modules/qs/test/mocha.opts +0 -2
- data/server/node_modules/express/testing/foo/app.js +0 -35
- data/server/node_modules/express/testing/foo/package.json +0 -9
- data/server/node_modules/express/testing/foo/public/stylesheets/style.css +0 -8
- data/server/node_modules/express/testing/foo/routes/index.js +0 -10
- data/server/node_modules/express/testing/foo/views/index.jade +0 -2
- data/server/node_modules/express/testing/foo/views/layout.jade +0 -6
- data/server/node_modules/express/testing/index.js +0 -43
- data/server/node_modules/express/testing/public/test.txt +0 -2971
- data/server/node_modules/express/testing/views/page.html +0 -1
- data/server/node_modules/express/testing/views/page.jade +0 -3
- data/server/node_modules/express/testing/views/test.md +0 -1
- data/server/node_modules/express/testing/views/user/index.jade +0 -1
- data/server/node_modules/express/testing/views/user/list.jade +0 -1
- data/server/node_modules/node-uuid/benchmark/README.md +0 -53
- data/server/node_modules/node-uuid/benchmark/bench.gnu +0 -174
- data/server/node_modules/node-uuid/benchmark/bench.sh +0 -34
- data/server/node_modules/node-uuid/benchmark/benchmark.js +0 -84
- data/server/node_modules/node-uuid/test/benchmark-native +0 -0
- data/server/node_modules/node-uuid/test/compare_v1.js +0 -63
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
|
|
2
|
+
PREFIX ?= /usr/local
|
|
3
|
+
BIN = bin/expresso
|
|
4
|
+
JSCOV = deps/jscoverage/node-jscoverage
|
|
5
|
+
DOCS = docs/index.md
|
|
6
|
+
HTMLDOCS = $(DOCS:.md=.html)
|
|
7
|
+
|
|
8
|
+
test: $(BIN)
|
|
9
|
+
@./$(BIN) -I lib --growl $(TEST_FLAGS) test/*.test.js
|
|
10
|
+
|
|
11
|
+
test-cov:
|
|
12
|
+
@./$(BIN) -I lib --cov $(TEST_FLAGS) test/*.test.js
|
|
13
|
+
|
|
14
|
+
test-serial:
|
|
15
|
+
@./$(BIN) --serial -I lib $(TEST_FLAGS) test/serial/*.test.js
|
|
16
|
+
|
|
17
|
+
install: install-jscov install-expresso
|
|
18
|
+
|
|
19
|
+
uninstall:
|
|
20
|
+
rm -f $(PREFIX)/bin/expresso
|
|
21
|
+
rm -f $(PREFIX)/bin/node-jscoverage
|
|
22
|
+
|
|
23
|
+
install-jscov: $(JSCOV)
|
|
24
|
+
install $(JSCOV) $(PREFIX)/bin
|
|
25
|
+
|
|
26
|
+
install-expresso:
|
|
27
|
+
install $(BIN) $(PREFIX)/bin
|
|
28
|
+
|
|
29
|
+
$(JSCOV):
|
|
30
|
+
cd deps/jscoverage && ./configure && make && mv jscoverage node-jscoverage
|
|
31
|
+
|
|
32
|
+
clean:
|
|
33
|
+
@cd deps/jscoverage && git clean -fd
|
|
34
|
+
|
|
35
|
+
docs: docs/api.html $(HTMLDOCS)
|
|
36
|
+
|
|
37
|
+
%.html: %.md
|
|
38
|
+
@echo "... $< > $@"
|
|
39
|
+
@ronn -5 --pipe --fragment $< \
|
|
40
|
+
| cat docs/layout/head.html - docs/layout/foot.html \
|
|
41
|
+
> $@
|
|
42
|
+
|
|
43
|
+
docs/api.html: bin/expresso
|
|
44
|
+
dox \
|
|
45
|
+
--title "Expresso" \
|
|
46
|
+
--ribbon "http://github.com/visionmedia/expresso" \
|
|
47
|
+
--desc "Insanely fast TDD framework for [node](http://nodejs.org) featuring code coverage reporting." \
|
|
48
|
+
$< > $@
|
|
49
|
+
|
|
50
|
+
docclean:
|
|
51
|
+
rm -f docs/*.html
|
|
52
|
+
|
|
53
|
+
.PHONY: test test-cov install uninstall install-expresso install-jscov clean docs docclean
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
|
|
2
|
+
# Expresso
|
|
3
|
+
|
|
4
|
+
TDD framework for [nodejs](http://nodejs.org).
|
|
5
|
+
|
|
6
|
+
## Features
|
|
7
|
+
|
|
8
|
+
- light-weight
|
|
9
|
+
- intuitive async support
|
|
10
|
+
- intuitive test runner executable
|
|
11
|
+
- test coverage support and reporting
|
|
12
|
+
- uses the _assert_ module
|
|
13
|
+
- `assert.eql()` alias of `assert.deepEqual()`
|
|
14
|
+
- `assert.response()` http response utility
|
|
15
|
+
- `assert.includes()`
|
|
16
|
+
- `assert.type()`
|
|
17
|
+
- `assert.isNull()`
|
|
18
|
+
- `assert.isUndefined()`
|
|
19
|
+
- `assert.isNotNull()`
|
|
20
|
+
- `assert.isDefined()`
|
|
21
|
+
- `assert.match()`
|
|
22
|
+
- `assert.length()`
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
To install both expresso _and_ node-jscoverage run:
|
|
27
|
+
|
|
28
|
+
$ make install
|
|
29
|
+
|
|
30
|
+
To install expresso alone (no build required) run:
|
|
31
|
+
|
|
32
|
+
$ make install-expresso
|
|
33
|
+
|
|
34
|
+
Install via npm:
|
|
35
|
+
|
|
36
|
+
$ npm install expresso
|
|
37
|
+
|
|
38
|
+
## License
|
|
39
|
+
|
|
40
|
+
(The MIT License)
|
|
41
|
+
|
|
42
|
+
Copyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
|
43
|
+
|
|
44
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
45
|
+
a copy of this software and associated documentation files (the
|
|
46
|
+
'Software'), to deal in the Software without restriction, including
|
|
47
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
48
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
49
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
50
|
+
the following conditions:
|
|
51
|
+
|
|
52
|
+
The above copyright notice and this permission notice shall be
|
|
53
|
+
included in all copies or substantial portions of the Software.
|
|
54
|
+
|
|
55
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
56
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
57
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
58
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
59
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
60
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
61
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,856 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Expresso
|
|
5
|
+
* Copyright(c) TJ Holowaychuk <tj@vision-media.ca>
|
|
6
|
+
* (MIT Licensed)
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Module dependencies.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
var assert = require('assert'),
|
|
14
|
+
childProcess = require('child_process'),
|
|
15
|
+
http = require('http'),
|
|
16
|
+
path = require('path'),
|
|
17
|
+
sys = require('sys'),
|
|
18
|
+
cwd = process.cwd(),
|
|
19
|
+
fs = require('fs'),
|
|
20
|
+
defer;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Expresso version.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
var version = '0.7.2';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Failure count.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
var failures = 0;
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Number of tests executed.
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
var testcount = 0;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Whitelist of tests to run.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
var only = [];
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Boring output.
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
var boring = false;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Growl notifications.
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
var growl = false;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Server port.
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
var port = 5555;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Execute serially.
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
var serial = false;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Default timeout.
|
|
73
|
+
*/
|
|
74
|
+
|
|
75
|
+
var timeout = 2000;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Quiet output.
|
|
79
|
+
*/
|
|
80
|
+
|
|
81
|
+
var quiet = false;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Usage documentation.
|
|
85
|
+
*/
|
|
86
|
+
|
|
87
|
+
var usage = ''
|
|
88
|
+
+ '[bold]{Usage}: expresso [options] <file ...>'
|
|
89
|
+
+ '\n'
|
|
90
|
+
+ '\n[bold]{Options}:'
|
|
91
|
+
+ '\n -g, --growl Enable growl notifications'
|
|
92
|
+
+ '\n -c, --coverage Generate and report test coverage'
|
|
93
|
+
+ '\n -q, --quiet Suppress coverage report if 100%'
|
|
94
|
+
+ '\n -t, --timeout MS Timeout in milliseconds, defaults to 2000'
|
|
95
|
+
+ '\n -r, --require PATH Require the given module path'
|
|
96
|
+
+ '\n -o, --only TESTS Execute only the comma sperated TESTS (can be set several times)'
|
|
97
|
+
+ '\n -I, --include PATH Unshift the given path to require.paths'
|
|
98
|
+
+ '\n -p, --port NUM Port number for test servers, starts at 5555'
|
|
99
|
+
+ '\n -s, --serial Execute tests serially'
|
|
100
|
+
+ '\n -b, --boring Suppress ansi-escape colors'
|
|
101
|
+
+ '\n -v, --version Output version number'
|
|
102
|
+
+ '\n -h, --help Display help information'
|
|
103
|
+
+ '\n';
|
|
104
|
+
|
|
105
|
+
// Parse arguments
|
|
106
|
+
|
|
107
|
+
var files = [],
|
|
108
|
+
args = process.argv.slice(2);
|
|
109
|
+
|
|
110
|
+
while (args.length) {
|
|
111
|
+
var arg = args.shift();
|
|
112
|
+
switch (arg) {
|
|
113
|
+
case '-h':
|
|
114
|
+
case '--help':
|
|
115
|
+
print(usage + '\n');
|
|
116
|
+
process.exit(1);
|
|
117
|
+
break;
|
|
118
|
+
case '-v':
|
|
119
|
+
case '--version':
|
|
120
|
+
sys.puts(version);
|
|
121
|
+
process.exit(1);
|
|
122
|
+
break;
|
|
123
|
+
case '-i':
|
|
124
|
+
case '-I':
|
|
125
|
+
case '--include':
|
|
126
|
+
if (arg = args.shift()) {
|
|
127
|
+
require.paths.unshift(arg);
|
|
128
|
+
} else {
|
|
129
|
+
throw new Error('--include requires a path');
|
|
130
|
+
}
|
|
131
|
+
break;
|
|
132
|
+
case '-o':
|
|
133
|
+
case '--only':
|
|
134
|
+
if (arg = args.shift()) {
|
|
135
|
+
only = only.concat(arg.split(/ *, */));
|
|
136
|
+
} else {
|
|
137
|
+
throw new Error('--only requires comma-separated test names');
|
|
138
|
+
}
|
|
139
|
+
break;
|
|
140
|
+
case '-p':
|
|
141
|
+
case '--port':
|
|
142
|
+
if (arg = args.shift()) {
|
|
143
|
+
port = parseInt(arg, 10);
|
|
144
|
+
} else {
|
|
145
|
+
throw new Error('--port requires a number');
|
|
146
|
+
}
|
|
147
|
+
break;
|
|
148
|
+
case '-r':
|
|
149
|
+
case '--require':
|
|
150
|
+
if (arg = args.shift()) {
|
|
151
|
+
require(arg);
|
|
152
|
+
} else {
|
|
153
|
+
throw new Error('--require requires a path');
|
|
154
|
+
}
|
|
155
|
+
break;
|
|
156
|
+
case '-t':
|
|
157
|
+
case '--timeout':
|
|
158
|
+
if (arg = args.shift()) {
|
|
159
|
+
timeout = parseInt(arg, 10);
|
|
160
|
+
} else {
|
|
161
|
+
throw new Error('--timeout requires an argument');
|
|
162
|
+
}
|
|
163
|
+
break;
|
|
164
|
+
case '-c':
|
|
165
|
+
case '--cov':
|
|
166
|
+
case '--coverage':
|
|
167
|
+
defer = true;
|
|
168
|
+
childProcess.exec('rm -fr lib-cov && node-jscoverage lib lib-cov', function(err){
|
|
169
|
+
if (err) throw err;
|
|
170
|
+
require.paths.unshift('lib-cov');
|
|
171
|
+
run(files);
|
|
172
|
+
})
|
|
173
|
+
break;
|
|
174
|
+
case '-q':
|
|
175
|
+
case '--quiet':
|
|
176
|
+
quiet = true;
|
|
177
|
+
break;
|
|
178
|
+
case '-b':
|
|
179
|
+
case '--boring':
|
|
180
|
+
boring = true;
|
|
181
|
+
break;
|
|
182
|
+
case '-g':
|
|
183
|
+
case '--growl':
|
|
184
|
+
growl = true;
|
|
185
|
+
break;
|
|
186
|
+
case '-s':
|
|
187
|
+
case '--serial':
|
|
188
|
+
serial = true;
|
|
189
|
+
break;
|
|
190
|
+
default:
|
|
191
|
+
if (/\.js$/.test(arg)) {
|
|
192
|
+
files.push(arg);
|
|
193
|
+
}
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Colorized sys.error().
|
|
200
|
+
*
|
|
201
|
+
* @param {String} str
|
|
202
|
+
*/
|
|
203
|
+
|
|
204
|
+
function print(str){
|
|
205
|
+
sys.error(colorize(str));
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Colorize the given string using ansi-escape sequences.
|
|
210
|
+
* Disabled when --boring is set.
|
|
211
|
+
*
|
|
212
|
+
* @param {String} str
|
|
213
|
+
* @return {String}
|
|
214
|
+
*/
|
|
215
|
+
|
|
216
|
+
function colorize(str){
|
|
217
|
+
var colors = { bold: 1, red: 31, green: 32, yellow: 33 };
|
|
218
|
+
return str.replace(/\[(\w+)\]\{([^]*?)\}/g, function(_, color, str){
|
|
219
|
+
return boring
|
|
220
|
+
? str
|
|
221
|
+
: '\x1B[' + colors[color] + 'm' + str + '\x1B[0m';
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Alias deepEqual as eql for complex equality
|
|
226
|
+
|
|
227
|
+
assert.eql = assert.deepEqual;
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Assert that `val` is null.
|
|
231
|
+
*
|
|
232
|
+
* @param {Mixed} val
|
|
233
|
+
* @param {String} msg
|
|
234
|
+
*/
|
|
235
|
+
|
|
236
|
+
assert.isNull = function(val, msg) {
|
|
237
|
+
assert.strictEqual(null, val, msg);
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Assert that `val` is not null.
|
|
242
|
+
*
|
|
243
|
+
* @param {Mixed} val
|
|
244
|
+
* @param {String} msg
|
|
245
|
+
*/
|
|
246
|
+
|
|
247
|
+
assert.isNotNull = function(val, msg) {
|
|
248
|
+
assert.notStrictEqual(null, val, msg);
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Assert that `val` is undefined.
|
|
253
|
+
*
|
|
254
|
+
* @param {Mixed} val
|
|
255
|
+
* @param {String} msg
|
|
256
|
+
*/
|
|
257
|
+
|
|
258
|
+
assert.isUndefined = function(val, msg) {
|
|
259
|
+
assert.strictEqual(undefined, val, msg);
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Assert that `val` is not undefined.
|
|
264
|
+
*
|
|
265
|
+
* @param {Mixed} val
|
|
266
|
+
* @param {String} msg
|
|
267
|
+
*/
|
|
268
|
+
|
|
269
|
+
assert.isDefined = function(val, msg) {
|
|
270
|
+
assert.notStrictEqual(undefined, val, msg);
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Assert that `obj` is `type`.
|
|
275
|
+
*
|
|
276
|
+
* @param {Mixed} obj
|
|
277
|
+
* @param {String} type
|
|
278
|
+
* @api public
|
|
279
|
+
*/
|
|
280
|
+
|
|
281
|
+
assert.type = function(obj, type, msg){
|
|
282
|
+
var real = typeof obj;
|
|
283
|
+
msg = msg || 'typeof ' + sys.inspect(obj) + ' is ' + real + ', expected ' + type;
|
|
284
|
+
assert.ok(type === real, msg);
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Assert that `str` matches `regexp`.
|
|
289
|
+
*
|
|
290
|
+
* @param {String} str
|
|
291
|
+
* @param {RegExp} regexp
|
|
292
|
+
* @param {String} msg
|
|
293
|
+
*/
|
|
294
|
+
|
|
295
|
+
assert.match = function(str, regexp, msg) {
|
|
296
|
+
msg = msg || sys.inspect(str) + ' does not match ' + sys.inspect(regexp);
|
|
297
|
+
assert.ok(regexp.test(str), msg);
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Assert that `val` is within `obj`.
|
|
302
|
+
*
|
|
303
|
+
* Examples:
|
|
304
|
+
*
|
|
305
|
+
* assert.includes('foobar', 'bar');
|
|
306
|
+
* assert.includes(['foo', 'bar'], 'foo');
|
|
307
|
+
*
|
|
308
|
+
* @param {String|Array} obj
|
|
309
|
+
* @param {Mixed} val
|
|
310
|
+
* @param {String} msg
|
|
311
|
+
*/
|
|
312
|
+
|
|
313
|
+
assert.includes = function(obj, val, msg) {
|
|
314
|
+
msg = msg || sys.inspect(obj) + ' does not include ' + sys.inspect(val);
|
|
315
|
+
assert.ok(obj.indexOf(val) >= 0, msg);
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Assert length of `val` is `n`.
|
|
320
|
+
*
|
|
321
|
+
* @param {Mixed} val
|
|
322
|
+
* @param {Number} n
|
|
323
|
+
* @param {String} msg
|
|
324
|
+
*/
|
|
325
|
+
|
|
326
|
+
assert.length = function(val, n, msg) {
|
|
327
|
+
msg = msg || sys.inspect(val) + ' has length of ' + val.length + ', expected ' + n;
|
|
328
|
+
assert.equal(n, val.length, msg);
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Assert response from `server` with
|
|
333
|
+
* the given `req` object and `res` assertions object.
|
|
334
|
+
*
|
|
335
|
+
* @param {Server} server
|
|
336
|
+
* @param {Object} req
|
|
337
|
+
* @param {Object|Function} res
|
|
338
|
+
* @param {String} msg
|
|
339
|
+
*/
|
|
340
|
+
|
|
341
|
+
assert.response = function(server, req, res, msg){
|
|
342
|
+
// Check that the server is ready or defer
|
|
343
|
+
if (!server.fd) {
|
|
344
|
+
if (!('__deferred' in server)) {
|
|
345
|
+
server.__deferred = [];
|
|
346
|
+
}
|
|
347
|
+
server.__deferred.push(arguments);
|
|
348
|
+
if (!server.__started) {
|
|
349
|
+
server.listen(server.__port = port++, '127.0.0.1', function(){
|
|
350
|
+
if (server.__deferred) {
|
|
351
|
+
process.nextTick(function(){
|
|
352
|
+
server.__deferred.forEach(function(args){
|
|
353
|
+
assert.response.apply(assert, args);
|
|
354
|
+
});
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
server.__started = true;
|
|
359
|
+
}
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Callback as third or fourth arg
|
|
364
|
+
var callback = typeof res === 'function'
|
|
365
|
+
? res
|
|
366
|
+
: typeof msg === 'function'
|
|
367
|
+
? msg
|
|
368
|
+
: function(){};
|
|
369
|
+
|
|
370
|
+
// Default messate to test title
|
|
371
|
+
if (typeof msg === 'function') msg = null;
|
|
372
|
+
msg = msg || assert.testTitle;
|
|
373
|
+
msg += '. ';
|
|
374
|
+
|
|
375
|
+
// Pending responses
|
|
376
|
+
server.__pending = server.__pending || 0;
|
|
377
|
+
server.__pending++;
|
|
378
|
+
|
|
379
|
+
// Create client
|
|
380
|
+
if (!server.fd) {
|
|
381
|
+
server.listen(server.__port = port++, '127.0.0.1', issue);
|
|
382
|
+
} else {
|
|
383
|
+
issue();
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function issue(){
|
|
387
|
+
if (!server.client)
|
|
388
|
+
server.client = http.createClient(server.__port);
|
|
389
|
+
|
|
390
|
+
// Issue request
|
|
391
|
+
var timer,
|
|
392
|
+
client = server.client,
|
|
393
|
+
method = req.method || 'GET',
|
|
394
|
+
status = res.status || res.statusCode,
|
|
395
|
+
data = req.data || req.body,
|
|
396
|
+
requestTimeout = req.timeout || 0;
|
|
397
|
+
|
|
398
|
+
var request = client.request(method, req.url, req.headers);
|
|
399
|
+
|
|
400
|
+
// Timeout
|
|
401
|
+
if (requestTimeout) {
|
|
402
|
+
timer = setTimeout(function(){
|
|
403
|
+
--server.__pending || server.close();
|
|
404
|
+
delete req.timeout;
|
|
405
|
+
assert.fail(msg + 'Request timed out after ' + requestTimeout + 'ms.');
|
|
406
|
+
}, requestTimeout);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (data) request.write(data);
|
|
410
|
+
request.on('response', function(response){
|
|
411
|
+
response.body = '';
|
|
412
|
+
response.setEncoding('utf8');
|
|
413
|
+
response.on('data', function(chunk){ response.body += chunk; });
|
|
414
|
+
response.on('end', function(){
|
|
415
|
+
--server.__pending || server.close();
|
|
416
|
+
if (timer) clearTimeout(timer);
|
|
417
|
+
|
|
418
|
+
// Assert response body
|
|
419
|
+
if (res.body !== undefined) {
|
|
420
|
+
var eql = res.body instanceof RegExp
|
|
421
|
+
? res.body.test(response.body)
|
|
422
|
+
: res.body === response.body;
|
|
423
|
+
assert.ok(
|
|
424
|
+
eql,
|
|
425
|
+
msg + 'Invalid response body.\n'
|
|
426
|
+
+ ' Expected: ' + sys.inspect(res.body) + '\n'
|
|
427
|
+
+ ' Got: ' + sys.inspect(response.body)
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// Assert response status
|
|
432
|
+
if (typeof status === 'number') {
|
|
433
|
+
assert.equal(
|
|
434
|
+
response.statusCode,
|
|
435
|
+
status,
|
|
436
|
+
msg + colorize('Invalid response status code.\n'
|
|
437
|
+
+ ' Expected: [green]{' + status + '}\n'
|
|
438
|
+
+ ' Got: [red]{' + response.statusCode + '}')
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// Assert response headers
|
|
443
|
+
if (res.headers) {
|
|
444
|
+
var keys = Object.keys(res.headers);
|
|
445
|
+
for (var i = 0, len = keys.length; i < len; ++i) {
|
|
446
|
+
var name = keys[i],
|
|
447
|
+
actual = response.headers[name.toLowerCase()],
|
|
448
|
+
expected = res.headers[name],
|
|
449
|
+
eql = expected instanceof RegExp
|
|
450
|
+
? expected.test(actual)
|
|
451
|
+
: expected == actual;
|
|
452
|
+
assert.ok(
|
|
453
|
+
eql,
|
|
454
|
+
msg + colorize('Invalid response header [bold]{' + name + '}.\n'
|
|
455
|
+
+ ' Expected: [green]{' + expected + '}\n'
|
|
456
|
+
+ ' Got: [red]{' + actual + '}')
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// Callback
|
|
462
|
+
callback(response);
|
|
463
|
+
});
|
|
464
|
+
});
|
|
465
|
+
request.end();
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Pad the given string to the maximum width provided.
|
|
471
|
+
*
|
|
472
|
+
* @param {String} str
|
|
473
|
+
* @param {Number} width
|
|
474
|
+
* @return {String}
|
|
475
|
+
*/
|
|
476
|
+
|
|
477
|
+
function lpad(str, width) {
|
|
478
|
+
str = String(str);
|
|
479
|
+
var n = width - str.length;
|
|
480
|
+
if (n < 1) return str;
|
|
481
|
+
while (n--) str = ' ' + str;
|
|
482
|
+
return str;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Pad the given string to the maximum width provided.
|
|
487
|
+
*
|
|
488
|
+
* @param {String} str
|
|
489
|
+
* @param {Number} width
|
|
490
|
+
* @return {String}
|
|
491
|
+
*/
|
|
492
|
+
|
|
493
|
+
function rpad(str, width) {
|
|
494
|
+
str = String(str);
|
|
495
|
+
var n = width - str.length;
|
|
496
|
+
if (n < 1) return str;
|
|
497
|
+
while (n--) str = str + ' ';
|
|
498
|
+
return str;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Report test coverage.
|
|
503
|
+
*
|
|
504
|
+
* @param {Object} cov
|
|
505
|
+
*/
|
|
506
|
+
|
|
507
|
+
function reportCoverage(cov) {
|
|
508
|
+
// Stats
|
|
509
|
+
print('\n [bold]{Test Coverage}\n');
|
|
510
|
+
var sep = ' +------------------------------------------+----------+------+------+--------+',
|
|
511
|
+
lastSep = ' +----------+------+------+--------+';
|
|
512
|
+
sys.puts(sep);
|
|
513
|
+
sys.puts(' | filename | coverage | LOC | SLOC | missed |');
|
|
514
|
+
sys.puts(sep);
|
|
515
|
+
for (var name in cov) {
|
|
516
|
+
var file = cov[name];
|
|
517
|
+
if (Array.isArray(file)) {
|
|
518
|
+
sys.print(' | ' + rpad(name, 40));
|
|
519
|
+
sys.print(' | ' + lpad(file.coverage.toFixed(2), 8));
|
|
520
|
+
sys.print(' | ' + lpad(file.LOC, 4));
|
|
521
|
+
sys.print(' | ' + lpad(file.SLOC, 4));
|
|
522
|
+
sys.print(' | ' + lpad(file.totalMisses, 6));
|
|
523
|
+
sys.print(' |\n');
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
sys.puts(sep);
|
|
527
|
+
sys.print(' ' + rpad('', 40));
|
|
528
|
+
sys.print(' | ' + lpad(cov.coverage.toFixed(2), 8));
|
|
529
|
+
sys.print(' | ' + lpad(cov.LOC, 4));
|
|
530
|
+
sys.print(' | ' + lpad(cov.SLOC, 4));
|
|
531
|
+
sys.print(' | ' + lpad(cov.totalMisses, 6));
|
|
532
|
+
sys.print(' |\n');
|
|
533
|
+
sys.puts(lastSep);
|
|
534
|
+
// Source
|
|
535
|
+
for (var name in cov) {
|
|
536
|
+
if (name.match(/\.js$/)) {
|
|
537
|
+
var file = cov[name];
|
|
538
|
+
if ((file.coverage < 100) || !quiet) {
|
|
539
|
+
print('\n [bold]{' + name + '}:');
|
|
540
|
+
print(file.source);
|
|
541
|
+
sys.print('\n');
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* Populate code coverage data.
|
|
549
|
+
*
|
|
550
|
+
* @param {Object} cov
|
|
551
|
+
*/
|
|
552
|
+
|
|
553
|
+
function populateCoverage(cov) {
|
|
554
|
+
cov.LOC =
|
|
555
|
+
cov.SLOC =
|
|
556
|
+
cov.totalFiles =
|
|
557
|
+
cov.totalHits =
|
|
558
|
+
cov.totalMisses =
|
|
559
|
+
cov.coverage = 0;
|
|
560
|
+
for (var name in cov) {
|
|
561
|
+
var file = cov[name];
|
|
562
|
+
if (Array.isArray(file)) {
|
|
563
|
+
// Stats
|
|
564
|
+
++cov.totalFiles;
|
|
565
|
+
cov.totalHits += file.totalHits = coverage(file, true);
|
|
566
|
+
cov.totalMisses += file.totalMisses = coverage(file, false);
|
|
567
|
+
file.totalLines = file.totalHits + file.totalMisses;
|
|
568
|
+
cov.SLOC += file.SLOC = file.totalLines;
|
|
569
|
+
if (!file.source) file.source = [];
|
|
570
|
+
cov.LOC += file.LOC = file.source.length;
|
|
571
|
+
file.coverage = (file.totalHits / file.totalLines) * 100;
|
|
572
|
+
// Source
|
|
573
|
+
var width = file.source.length.toString().length;
|
|
574
|
+
file.source = file.source.map(function(line, i){
|
|
575
|
+
++i;
|
|
576
|
+
var hits = file[i] === 0 ? 0 : (file[i] || ' ');
|
|
577
|
+
if (!boring) {
|
|
578
|
+
if (hits === 0) {
|
|
579
|
+
hits = '\x1b[31m' + hits + '\x1b[0m';
|
|
580
|
+
line = '\x1b[41m' + line + '\x1b[0m';
|
|
581
|
+
} else {
|
|
582
|
+
hits = '\x1b[32m' + hits + '\x1b[0m';
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
return '\n ' + lpad(i, width) + ' | ' + hits + ' | ' + line;
|
|
586
|
+
}).join('');
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
cov.coverage = (cov.totalHits / cov.SLOC) * 100;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Total coverage for the given file data.
|
|
594
|
+
*
|
|
595
|
+
* @param {Array} data
|
|
596
|
+
* @return {Type}
|
|
597
|
+
*/
|
|
598
|
+
|
|
599
|
+
function coverage(data, val) {
|
|
600
|
+
var n = 0;
|
|
601
|
+
for (var i = 0, len = data.length; i < len; ++i) {
|
|
602
|
+
if (data[i] !== undefined && data[i] == val) ++n;
|
|
603
|
+
}
|
|
604
|
+
return n;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Test if all files have 100% coverage
|
|
609
|
+
*
|
|
610
|
+
* @param {Object} cov
|
|
611
|
+
* @return {Boolean}
|
|
612
|
+
*/
|
|
613
|
+
|
|
614
|
+
function hasFullCoverage(cov) {
|
|
615
|
+
for (var name in cov) {
|
|
616
|
+
var file = cov[name];
|
|
617
|
+
if (file instanceof Array) {
|
|
618
|
+
if (file.coverage !== 100) {
|
|
619
|
+
return false;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
return true;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Run the given test `files`, or try _test/*_.
|
|
628
|
+
*
|
|
629
|
+
* @param {Array} files
|
|
630
|
+
*/
|
|
631
|
+
|
|
632
|
+
function run(files) {
|
|
633
|
+
cursor(false);
|
|
634
|
+
if (!files.length) {
|
|
635
|
+
try {
|
|
636
|
+
files = fs.readdirSync('test').map(function(file){
|
|
637
|
+
return 'test/' + file;
|
|
638
|
+
});
|
|
639
|
+
} catch (err) {
|
|
640
|
+
print('\n failed to load tests in [bold]{./test}\n');
|
|
641
|
+
++failures;
|
|
642
|
+
process.exit(1);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
runFiles(files);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* Show the cursor when `show` is true, otherwise hide it.
|
|
650
|
+
*
|
|
651
|
+
* @param {Boolean} show
|
|
652
|
+
*/
|
|
653
|
+
|
|
654
|
+
function cursor(show) {
|
|
655
|
+
if (show) {
|
|
656
|
+
sys.print('\x1b[?25h');
|
|
657
|
+
} else {
|
|
658
|
+
sys.print('\x1b[?25l');
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* Run the given test `files`.
|
|
664
|
+
*
|
|
665
|
+
* @param {Array} files
|
|
666
|
+
*/
|
|
667
|
+
|
|
668
|
+
function runFiles(files) {
|
|
669
|
+
if (serial) {
|
|
670
|
+
(function next(){
|
|
671
|
+
if (files.length) {
|
|
672
|
+
runFile(files.shift(), next);
|
|
673
|
+
}
|
|
674
|
+
})();
|
|
675
|
+
} else {
|
|
676
|
+
files.forEach(runFile);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
/**
|
|
681
|
+
* Run tests for the given `file`, callback `fn()` when finished.
|
|
682
|
+
*
|
|
683
|
+
* @param {String} file
|
|
684
|
+
* @param {Function} fn
|
|
685
|
+
*/
|
|
686
|
+
|
|
687
|
+
function runFile(file, fn) {
|
|
688
|
+
if (file.match(/\.js$/)) {
|
|
689
|
+
var title = path.basename(file),
|
|
690
|
+
file = path.join(cwd, file),
|
|
691
|
+
mod = require(file.replace(/\.js$/, ''));
|
|
692
|
+
(function check(){
|
|
693
|
+
var len = Object.keys(mod).length;
|
|
694
|
+
if (len) {
|
|
695
|
+
runSuite(title, mod, fn);
|
|
696
|
+
} else {
|
|
697
|
+
setTimeout(check, 20);
|
|
698
|
+
}
|
|
699
|
+
})();
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
/**
|
|
704
|
+
* Report `err` for the given `test` and `suite`.
|
|
705
|
+
*
|
|
706
|
+
* @param {String} suite
|
|
707
|
+
* @param {String} test
|
|
708
|
+
* @param {Error} err
|
|
709
|
+
*/
|
|
710
|
+
|
|
711
|
+
function error(suite, test, err) {
|
|
712
|
+
++failures;
|
|
713
|
+
var name = err.name,
|
|
714
|
+
stack = err.stack ? err.stack.replace(err.name, '') : '',
|
|
715
|
+
label = test === 'uncaught'
|
|
716
|
+
? test
|
|
717
|
+
: suite + ' ' + test;
|
|
718
|
+
print('\n [bold]{' + label + '}: [red]{' + name + '}' + stack + '\n');
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
/**
|
|
722
|
+
* Run the given tests, callback `fn()` when finished.
|
|
723
|
+
*
|
|
724
|
+
* @param {String} title
|
|
725
|
+
* @param {Object} tests
|
|
726
|
+
* @param {Function} fn
|
|
727
|
+
*/
|
|
728
|
+
|
|
729
|
+
var dots = 0;
|
|
730
|
+
function runSuite(title, tests, fn) {
|
|
731
|
+
// Keys
|
|
732
|
+
var keys = only.length
|
|
733
|
+
? only.slice(0)
|
|
734
|
+
: Object.keys(tests);
|
|
735
|
+
|
|
736
|
+
// Setup
|
|
737
|
+
var setup = tests.setup || function(fn){ fn(); };
|
|
738
|
+
|
|
739
|
+
// Iterate tests
|
|
740
|
+
(function next(){
|
|
741
|
+
if (keys.length) {
|
|
742
|
+
var key,
|
|
743
|
+
test = tests[key = keys.shift()];
|
|
744
|
+
// Non-tests
|
|
745
|
+
if (key === 'setup') return next();
|
|
746
|
+
|
|
747
|
+
// Run test
|
|
748
|
+
if (test) {
|
|
749
|
+
try {
|
|
750
|
+
++testcount;
|
|
751
|
+
assert.testTitle = key;
|
|
752
|
+
if (serial) {
|
|
753
|
+
sys.print('.');
|
|
754
|
+
if (++dots % 25 === 0) sys.print('\n');
|
|
755
|
+
setup(function(){
|
|
756
|
+
if (test.length < 1) {
|
|
757
|
+
test();
|
|
758
|
+
next();
|
|
759
|
+
} else {
|
|
760
|
+
var id = setTimeout(function(){
|
|
761
|
+
throw new Error("'" + key + "' timed out");
|
|
762
|
+
}, timeout);
|
|
763
|
+
test(function(){
|
|
764
|
+
clearTimeout(id);
|
|
765
|
+
next();
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
});
|
|
769
|
+
} else {
|
|
770
|
+
test(function(fn){
|
|
771
|
+
process.on('beforeExit', function(){
|
|
772
|
+
try {
|
|
773
|
+
fn();
|
|
774
|
+
} catch (err) {
|
|
775
|
+
error(title, key, err);
|
|
776
|
+
}
|
|
777
|
+
});
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
} catch (err) {
|
|
781
|
+
error(title, key, err);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
if (!serial) next();
|
|
785
|
+
} else if (serial) {
|
|
786
|
+
fn();
|
|
787
|
+
}
|
|
788
|
+
})();
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
/**
|
|
792
|
+
* Report exceptions.
|
|
793
|
+
*/
|
|
794
|
+
|
|
795
|
+
function report() {
|
|
796
|
+
cursor(true);
|
|
797
|
+
process.emit('beforeExit');
|
|
798
|
+
if (failures) {
|
|
799
|
+
print('\n [bold]{Failures}: [red]{' + failures + '}\n\n');
|
|
800
|
+
notify('Failures: ' + failures);
|
|
801
|
+
} else {
|
|
802
|
+
if (serial) print('');
|
|
803
|
+
print('\n [green]{100%} ' + testcount + ' tests\n');
|
|
804
|
+
notify('100% ok');
|
|
805
|
+
}
|
|
806
|
+
if (typeof _$jscoverage === 'object') {
|
|
807
|
+
populateCoverage(_$jscoverage);
|
|
808
|
+
if (!hasFullCoverage(_$jscoverage) || !quiet) {
|
|
809
|
+
reportCoverage(_$jscoverage);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Growl notify the given `msg`.
|
|
816
|
+
*
|
|
817
|
+
* @param {String} msg
|
|
818
|
+
*/
|
|
819
|
+
|
|
820
|
+
function notify(msg) {
|
|
821
|
+
if (growl) {
|
|
822
|
+
childProcess.exec('growlnotify -name Expresso -m "' + msg + '"');
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// Report uncaught exceptions
|
|
827
|
+
|
|
828
|
+
process.on('uncaughtException', function(err){
|
|
829
|
+
error('uncaught', 'uncaught', err);
|
|
830
|
+
});
|
|
831
|
+
|
|
832
|
+
// Show cursor
|
|
833
|
+
|
|
834
|
+
['INT', 'TERM', 'QUIT'].forEach(function(sig){
|
|
835
|
+
process.on('SIG' + sig, function(){
|
|
836
|
+
cursor(true);
|
|
837
|
+
process.exit(1);
|
|
838
|
+
});
|
|
839
|
+
});
|
|
840
|
+
|
|
841
|
+
// Report test coverage when available
|
|
842
|
+
// and emit "beforeExit" event to perform
|
|
843
|
+
// final assertions
|
|
844
|
+
|
|
845
|
+
var orig = process.emit;
|
|
846
|
+
process.emit = function(event){
|
|
847
|
+
if (event === 'exit') {
|
|
848
|
+
report();
|
|
849
|
+
process.reallyExit(failures);
|
|
850
|
+
}
|
|
851
|
+
orig.apply(this, arguments);
|
|
852
|
+
};
|
|
853
|
+
|
|
854
|
+
// Run test files
|
|
855
|
+
|
|
856
|
+
if (!defer) run(files);
|