pax_global_header00006660000000000000000000000064123435207030014511gustar00rootroot0000000000000052 comment=869b5ad681b923a75c5e6fb3fcbab9a865b4115e mocha-1.20.1/000077500000000000000000000000001234352070300126615ustar00rootroot00000000000000mocha-1.20.1/.gitignore000066400000000000000000000001731234352070300146520ustar00rootroot00000000000000coverage.html lib-cov .DS_Store node_modules *.sock testing _mocha.js my-reporter.js *.sw* lib/browser/diff.js .idea *.iml mocha-1.20.1/.travis.yml000066400000000000000000000000541234352070300147710ustar00rootroot00000000000000language: node_js node_js: - 0.8 - 0.10 mocha-1.20.1/History.md000066400000000000000000000515621234352070300146550ustar00rootroot000000000000001.20.1 / 2014-06-03 ================== * update: should dependency to ~4.0.0 (#1231) 1.20.0 / 2014-05-28 ================== * add: filenames to suite objects (#1222) 1.19.0 / 2014-05-17 ================== * add: browser script option to package.json * add: export file in Mocha.Test objects (#1174) * add: add docs for wrapped node flags * fix: mocha.run() to return error status in browser (#1216) * fix: clean() to show failure details (#1205) * fix: regex that generates html for new keyword (#1201) * fix: sibling suites have inherited but separate contexts (#1164) 1.18.2 / 2014-03-18 ================== * fix: html runner was prevented from using #mocha as the default root el (#1162) 1.18.1 / 2014-03-18 ================== * fix: named before/after hooks in bdd, tdd, qunit interfaces (#1161) 1.18.0 / 2014-03-13 ================== * add: promise support (#329) * add: named before/after hooks (#966) 1.17.1 / 2014-01-22 ================== * fix: expected messages in should.js (should.js#168) * fix: expect errno global in node versions < v0.9.11 (#1111) * fix: unreliable checkGlobals optimization (#1110) 1.17.0 / 2014-01-09 ================== * add: able to require globals (describe, it, etc.) through mocha (#1077) * fix: abort previous run on --watch change (#1100) * fix: reset context for each --watch triggered run (#1099) * fix: error when cli can't resolve path or pattern (#799) * fix: canonicalize objects before stringifying and diffing them (#1079) * fix: make CR call behave like carriage return for non tty (#1087) 1.16.2 / 2013-12-23 ================== * fix: couple issues with ie 8 (#1082, #1081) * fix: issue running the xunit reporter in browsers (#1068) * fix: issue with firefox < 3.5 (#725) 1.16.1 / 2013-12-19 ================== * fix: recompiled for missed changes from the last release 1.16.0 / 2013-12-19 ================== * add: Runnable.globals(arr) for per test global whitelist (#1046) * add: mocha.throwError(err) for assertion libs to call (#985) * remove: --watch's spinner (#806) * fix: duplicate test output for multi-line specs in spec reporter (#1006) * fix: gracefully exit on SIGINT (#1063) * fix expose the specified ui only in the browser (#984) * fix: ensure process exit code is preserved when using --no-exit (#1059) * fix: return true from window.onerror handler (#868) * fix: xunit reporter to use process.stdout.write (#1068) * fix: utils.clean(str) indentation (#761) * fix: xunit reporter returning test duration a NaN (#1039) 1.15.1 / 2013-12-03 ================== * fix: recompiled for missed changes from the last release 1.15.0 / 2013-12-02 ================== * add: `--no-exit` to prevent `process.exit()` (#1018) * fix: using inline diffs (#1044) * fix: show pending test details in xunit reporter (#1051) * fix: faster global leak detection (#1024) * fix: yui compression (#1035) * fix: wrapping long lines in test results (#1030, #1031) * fix: handle errors in hooks (#1043) 1.14.0 / 2013-11-02 ================== * add: unified diff (#862) * add: set MOCHA_COLORS env var to use colors (#965) * add: able to override tests links in html reporters (#776) * remove: teamcity reporter (#954) * update: commander dependency to 2.0.0 (#1010) * fix: mocha --ui will try to require the ui if not built in, as --reporter does (#1022) * fix: send cursor commands only if isatty (#184, #1003) * fix: include assertion message in base reporter (#993, #991) * fix: consistent return of it, it.only, and describe, describe.only (#840) 1.13.0 / 2013-09-15 ================== * add: sort test files with --sort (#813) * update: diff depedency to 1.0.7 * update: glob dependency to 3.2.3 (#927) * fix: diffs show whitespace differences (#976) * fix: improve global leaks (#783) * fix: firefox window.getInterface leak * fix: accessing iframe via window[iframeIndex] leak * fix: faster global leak checking * fix: reporter pending css selector (#970) 1.12.1 / 2013-08-29 ================== * remove test.js from .gitignore * update included version of ms.js 1.12.0 / 2013-07-01 ================== * add: prevent diffs for differing types. Closes #900 * add `Mocha.process` hack for phantomjs * fix: use compilers with requires * fix regexps in diffs. Closes #890 * fix xunit NaN on failure. Closes #894 * fix: strip tab indentation in `clean` utility method * fix: textmate bundle installation 1.11.0 / 2013-06-12 ================== * add --prof support * add --harmony support * add --harmony-generators support * add "Uncaught " prefix to uncaught exceptions * add web workers support * add `suite.skip()` * change to output # of pending / passing even on failures. Closes #872 * fix: prevent hooks from being called if we are bailing * fix `this.timeout(0)` 1.10.0 / 2013-05-21 ================== * add add better globbing support for windows via `glob` module * add support to pass through flags such as --debug-brk=1234. Closes #852 * add test.only, test.skip to qunit interface * change to always use word-based diffs for now. Closes #733 * change `mocha init` tests.html to index.html * fix `process` global leak in the browser * fix: use resolve() instead of join() for --require * fix: filterLeaks() condition to not consider indices in global object as leaks * fix: restrict mocha.css styling to #mocha id * fix: save timer references to avoid Sinon interfering in the browser build. 1.9.0 / 2013-04-03 ================== * add improved setImmediate implementation * replace --ignore-leaks with --check-leaks * change default of ignoreLeaks to true. Closes #791 * remove scrolling for HTML reporter * fix retina support * fix tmbundle, restrict to js scope 1.8.2 / 2013-03-11 ================== * add `setImmediate` support for 0.10.x * fix mocha -w spinner on windows 1.8.1 / 2013-01-09 ================== * fix .bail() arity check causing it to default to true 1.8.0 / 2013-01-08 ================== * add Mocha() options bail support * add `Mocha#bail()` method * add instanceof check back for inheriting from Error * add component.json * add diff.js to browser build * update growl * fix TAP reporter failures comment :D 1.7.4 / 2012-12-06 ================== * add total number of passes and failures to TAP * remove .bind() calls. re #680 * fix indexOf. Closes #680 1.7.3 / 2012-11-30 ================== * fix uncaught error support for the browser * revert uncaught "fix" which breaks node 1.7.2 / 2012-11-28 ================== * fix uncaught errors to expose the original error message 1.7.0 / 2012-11-07 ================== * add `--async-only` support to prevent false positives for missing `done()` * add sorting by filename in code coverage * add HTML 5 doctype to browser template. * add play button to html reporter to rerun a single test * add `this.timeout(ms)` as Suite#timeout(ms). Closes #599 * update growl dependency to 1.6.x * fix encoding of test-case ?grep. Closes #637 * fix unicode chars on windows * fix dom globals in Opera/IE. Closes #243 * fix markdown reporter a tags * fix `this.timeout("5s")` support 1.6.0 / 2012-10-02 ================== * add object diffs when `err.showDiff` is present * add hiding of empty suites when pass/failures are toggled * add faster `.length` checks to `checkGlobals()` before performing the filter 1.5.0 / 2012-09-21 ================== * add `ms()` to `.slow()` and `.timeout()` * add `Mocha#checkLeaks()` to re-enable global leak checks * add `this.slow()` option [aheckmann] * add tab, CR, LF to error diffs for now * add faster `.checkGlobals()` solution [guille] * remove `fn.call()` from reduce util * remove `fn.call()` from filter util * fix forEach. Closes #582 * fix relaying of signals [TooTallNate] * fix TAP reporter grep number 1.4.2 / 2012-09-01 ================== * add support to multiple `Mocha#globals()` calls, and strings * add `mocha.reporter()` constructor support [jfirebaugh] * add `mocha.timeout()` * move query-string parser to utils.js * move highlight code to utils.js * fix third-party reporter support [exogen] * fix client-side API to match node-side [jfirebaugh] * fix mocha in iframe [joliss] 1.4.1 / 2012-08-28 ================== * add missing `Markdown` export * fix `Mocha#grep()`, escape regexp strings * fix reference error when `devicePixelRatio` is not defined. Closes #549 1.4.0 / 2012-08-22 ================== * add mkdir -p to `mocha init`. Closes #539 * add `.only()`. Closes #524 * add `.skip()`. Closes #524 * change str.trim() to use utils.trim(). Closes #533 * fix HTML progress indicator retina display * fix url-encoding of click-to-grep HTML functionality 1.3.2 / 2012-08-01 ================== * fix exports double-execution regression. Closes #531 1.3.1 / 2012-08-01 ================== * add passes/failures toggling to HTML reporter * add pending state to `xit()` and `xdescribe()` [Brian Moore] * add the @charset "UTF-8"; to fix #522 with FireFox. [Jonathan Creamer] * add border-bottom to #stats links * add check for runnable in `Runner#uncaught()`. Closes #494 * add 0.4 and 0.6 back to travis.yml * add `-E, --growl-errors` to growl on failures only * add prefixes to debug() names. Closes #497 * add `Mocha#invert()` to js api * change dot reporter to use sexy unicode dots * fix error when clicking pending test in HTML reporter * fix `make tm` 1.3.0 / 2012-07-05 ================== * add window scrolling to `HTML` reporter * add v8 `--trace-*` option support * add support for custom reports via `--reporter MODULE` * add `--invert` switch to invert `--grep` matches * fix export of `Nyan` reporter. Closes #495 * fix escaping of `HTML` suite titles. Closes #486 * fix `done()` called multiple times with an error test * change `--grep` - regexp escape the input 1.2.2 / 2012-06-28 ================== * Added 0.8.0 support 1.2.1 / 2012-06-25 ================== * Added `this.test.error(err)` support to after each hooks. Closes #287 * Added: export top-level suite on global mocha object (mocha.suite). Closes #448 * Fixed `js` code block format error in markdown reporter * Fixed deprecation warning when using `path.existsSync` * Fixed --globals with wildcard * Fixed chars in nyan when his head moves back * Remove `--growl` from test/mocha.opts. Closes #289 1.2.0 / 2012-06-17 ================== * Added `nyan` reporter [Atsuya Takagi] * Added `mocha init ` to copy client files * Added "specify" synonym for "it" [domenic] * Added global leak wildcard support [nathanbowser] * Fixed runner emitter leak. closes #432 * Fixed omission of .js extension. Closes #454 1.1.0 / 2012-05-30 ================== * Added: check each `mocha(1)` arg for directories to walk * Added `--recursive` [tricknotes] * Added `context` for BDD [hokaccha] * Added styling for new clickable titles * Added clickable suite titles to HTML reporter * Added warning when strings are thrown as errors * Changed: green arrows again in HTML reporter styling * Changed ul/li elements instead of divs for better copy-and-pasting [joliss] * Fixed issue #325 - add better grep support to js api * Fixed: save timer references to avoid Sinon interfering. 1.0.3 / 2012-04-30 ================== * Fixed string diff newlines * Fixed: removed mocha.css target. Closes #401 1.0.2 / 2012-04-25 ================== * Added HTML reporter duration. Closes #47 * Fixed: one postMessage event listener [exogen] * Fixed: allow --globals to be used multiple times. Closes #100 [brendannee] * Fixed #158: removes jquery include from browser tests * Fixed grep. Closes #372 [brendannee] * Fixed #166 - When grepping don't display the empty suites * Removed test/browser/style.css. Closes #385 1.0.1 / 2012-04-04 ================== * Fixed `.timeout()` in hooks * Fixed: allow callback for `mocha.run()` in client version * Fixed browser hook error display. Closes #361 1.0.0 / 2012-03-24 ================== * Added js API. Closes #265 * Added: initial run of tests with `--watch`. Closes #345 * Added: mark `location` as a global on the CS. Closes #311 * Added `markdown` reporter (github flavour) * Added: scrolling menu to coverage.html. Closes #335 * Added source line to html report for Safari [Tyson Tate] * Added "min" reporter, useful for `--watch` [Jakub Nešetřil] * Added support for arbitrary compilers via . Closes #338 [Ian Young] * Added Teamcity export to lib/reporters/index [Michael Riley] * Fixed chopping of first char in error reporting. Closes #334 [reported by topfunky] * Fixed terrible FF / Opera stack traces 0.14.1 / 2012-03-06 ================== * Added lib-cov to _.npmignore_ * Added reporter to `mocha.run([reporter])` as argument * Added some margin-top to the HTML reporter * Removed jQuery dependency * Fixed `--watch`: purge require cache. Closes #266 0.14.0 / 2012-03-01 ================== * Added string diff support for terminal reporters 0.13.0 / 2012-02-23 ================== * Added preliminary test coverage support. Closes #5 * Added `HTMLCov` reporter * Added `JSONCov` reporter [kunklejr] * Added `xdescribe()` and `xit()` to the BDD interface. Closes #263 (docs * Changed: make json reporter output pretty json * Fixed node-inspector support, swapped `--debug` for `debug` to match node. needed) Closes #247 0.12.1 / 2012-02-14 ================== * Added `npm docs mocha` support [TooTallNate] * Added a `Context` object used for hook and test-case this. Closes #253 * Fixed `Suite#clone()` `.ctx` reference. Closes #262 0.12.0 / 2012-02-02 ================== * Added .coffee `--watch` support. Closes #242 * Added support to `--require` files relative to the CWD. Closes #241 * Added quick n dirty syntax highlighting. Closes #248 * Changed: made HTML progress indicator smaller * Fixed xunit errors attribute [dhendo] 0.10.2 / 2012-01-21 ================== * Fixed suite count in reporter stats. Closes #222 * Fixed `done()` after timeout error reporting [Phil Sung] * Changed the 0-based errors to 1 0.10.1 / 2012-01-17 ================== * Added support for node 0.7.x * Fixed absolute path support. Closes #215 [kompiro] * Fixed `--no-colors` option [Jussi Virtanen] * Fixed Arial CSS typo in the correct file 0.10.0 / 2012-01-13 ================== * Added `-b, --bail` to exit on first exception [guillermo] * Added support for `-gc` / `--expose-gc` [TooTallNate] * Added `qunit`-inspired interface * Added MIT LICENSE. Closes #194 * Added: `--watch` all .js in the CWD. Closes #139 * Fixed `self.test` reference in runner. Closes #189 * Fixed double reporting of uncaught exceptions after timeout. Closes #195 0.8.2 / 2012-01-05 ================== * Added test-case context support. Closes #113 * Fixed exit status. Closes #187 * Update commander. Closes #190 0.8.1 / 2011-12-30 ================== * Fixed reporting of uncaught exceptions. Closes #183 * Fixed error message defaulting [indutny] * Changed mocha(1) from bash to node for windows [Nathan Rajlich] 0.8.0 / 2011-12-28 ================== * Added `XUnit` reporter [FeeFighters/visionmedia] * Added `say(1)` notification support [Maciej Małecki] * Changed: fail when done() is invoked with a non-Error. Closes #171 * Fixed `err.stack`, defaulting to message. Closes #180 * Fixed: `make tm` mkdir -p the dest. Closes #137 * Fixed mocha(1) --help bin name * Fixed `-d` for `--debug` support 0.7.1 / 2011-12-22 ================== * Removed `mocha-debug(1)`, use `mocha --debug` * Fixed CWD relative requires * Fixed growl issue on windows [Raynos] * Fixed: platform specific line endings [TooTallNate] * Fixed: escape strings in HTML reporter. Closes #164 0.7.0 / 2011-12-18 ================== * Added support for IE{7,8} [guille] * Changed: better browser nextTick implementation [guille] 0.6.0 / 2011-12-18 ================== * Added setZeroTimeout timeout for browser (nicer stack traces). Closes #153 * Added "view source" on hover for HTML reporter to make it obvious * Changed: replace custom growl with growl lib * Fixed duplicate reporting for HTML reporter. Closes #154 * Fixed silent hook errors in the HTML reporter. Closes #150 0.5.0 / 2011-12-14 ================== * Added: push node_modules directory onto module.paths for relative require Closes #93 * Added teamcity reporter [blindsey] * Fixed: recover from uncaught exceptions for tests. Closes #94 * Fixed: only emit "test end" for uncaught within test, not hook 0.4.0 / 2011-12-14 ================== * Added support for test-specific timeouts via `this.timeout(0)`. Closes #134 * Added guillermo's client-side EventEmitter. Closes #132 * Added progress indicator to the HTML reporter * Fixed slow browser tests. Closes #135 * Fixed "suite" color for light terminals * Fixed `require()` leak spotted by [guillermo] 0.3.6 / 2011-12-09 ================== * Removed suite merging (for now) 0.3.5 / 2011-12-08 ================== * Added support for `window.onerror` [guillermo] * Fixed: clear timeout on uncaught exceptions. Closes #131 [guillermo] * Added `mocha.css` to PHONY list. * Added `mocha.js` to PHONY list. 0.3.4 / 2011-12-08 ================== * Added: allow `done()` to be called with non-Error * Added: return Runner from `mocha.run()`. Closes #126 * Fixed: run afterEach even on failures. Closes #125 * Fixed clobbering of current runnable. Closes #121 0.3.3 / 2011-12-08 ================== * Fixed hook timeouts. Closes #120 * Fixed uncaught exceptions in hooks 0.3.2 / 2011-12-05 ================== * Fixed weird reporting when `err.message` is not present 0.3.1 / 2011-12-04 ================== * Fixed hook event emitter leak. Closes #117 * Fixed: export `Spec` constructor. Closes #116 0.3.0 / 2011-12-04 ================== * Added `-w, --watch`. Closes #72 * Added `--ignore-leaks` to ignore global leak checking * Added browser `?grep=pattern` support * Added `--globals ` to specify accepted globals. Closes #99 * Fixed `mocha-debug(1)` on some systems. Closes #232 * Fixed growl total, use `runner.total` 0.2.0 / 2011-11-30 ================== * Added `--globals ` to specify accepted globals. Closes #99 * Fixed funky highlighting of messages. Closes #97 * Fixed `mocha-debug(1)`. Closes #232 * Fixed growl total, use runner.total 0.1.0 / 2011-11-29 ================== * Added `suiteSetup` and `suiteTeardown` to TDD interface [David Henderson] * Added growl icons. Closes #84 * Fixed coffee-script support 0.0.8 / 2011-11-25 ================== * Fixed: use `Runner#total` for accurate reporting 0.0.7 / 2011-11-25 ================== * Added `Hook` * Added `Runnable` * Changed: `Test` is `Runnable` * Fixed global leak reporting in hooks * Fixed: > 2 calls to done() only report the error once * Fixed: clear timer on failure. Closes #80 0.0.6 / 2011-11-25 ================== * Fixed return on immediate async error. Closes #80 0.0.5 / 2011-11-24 ================== * Fixed: make mocha.opts whitespace less picky [kkaefer] 0.0.4 / 2011-11-24 ================== * Added `--interfaces` * Added `--reporters` * Added `-c, --colors`. Closes #69 * Fixed hook timeouts 0.0.3 / 2011-11-23 ================== * Added `-C, --no-colors` to explicitly disable * Added coffee-script support 0.0.2 / 2011-11-22 ================== * Fixed global leak detection due to Safari bind() change * Fixed: escape html entities in Doc reporter * Fixed: escape html entities in HTML reporter * Fixed pending test support for HTML reporter. Closes #66 0.0.1 / 2011-11-22 ================== * Added `--timeout` second shorthand support, ex `--timeout 3s`. * Fixed "test end" event for uncaughtExceptions. Closes #61 0.0.1-alpha6 / 2011-11-19 ================== * Added travis CI support (needs enabling when public) * Added preliminary browser support * Added `make mocha.css` target. Closes #45 * Added stack trace to TAP errors. Closes #52 * Renamed tearDown to teardown. Closes #49 * Fixed: cascading hooksc. Closes #30 * Fixed some colors for non-tty * Fixed errors thrown in sync test-cases due to nextTick * Fixed Base.window.width... again give precedence to 0.6.x 0.0.1-alpha5 / 2011-11-17 ================== * Added `doc` reporter. Closes #33 * Added suite merging. Closes #28 * Added TextMate bundle and `make tm`. Closes #20 0.0.1-alpha4 / 2011-11-15 ================== * Fixed getWindowSize() for 0.4.x 0.0.1-alpha3 / 2011-11-15 ================== * Added `-s, --slow ` to specify "slow" test threshold * Added `mocha-debug(1)` * Added `mocha.opts` support. Closes #31 * Added: default [files] to _test/*.js_ * Added protection against multiple calls to `done()`. Closes #35 * Changed: bright yellow for slow Dot reporter tests 0.0.1-alpha1 / 2011-11-08 ================== * Missed this one :) 0.0.1-alpha1 / 2011-11-08 ================== * Initial release mocha-1.20.1/LICENSE000066400000000000000000000021171234352070300136670ustar00rootroot00000000000000(The MIT License) Copyright (c) 2011-2014 TJ Holowaychuk 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. mocha-1.20.1/Makefile000066400000000000000000000063651234352070300143330ustar00rootroot00000000000000 REPORTER ?= dot TM_BUNDLE = JavaScript\ mocha.tmbundle SRC = $(shell find lib -name "*.js" -type f | sort) SUPPORT = $(wildcard support/*.js) all: mocha.js lib/browser/diff.js: node_modules/diff/diff.js cp node_modules/diff/diff.js lib/browser/diff.js mocha.js: $(SRC) $(SUPPORT) lib/browser/diff.js @node support/compile $(SRC) @cat \ support/head.js \ _mocha.js \ support/tail.js \ support/foot.js \ > mocha.js clean: rm -f mocha.js rm -fr lib-cov rm -f coverage.html test-cov: lib-cov @COV=1 $(MAKE) test REPORTER=html-cov > coverage.html lib-cov: @rm -fr ./$@ @jscoverage lib $@ test: test-unit test-all: test-bdd test-tdd test-qunit test-exports test-unit test-grep test-jsapi test-compilers test-sort test-glob test-requires test-reporters test-only test-jsapi: @node test/jsapi test-unit: @./bin/mocha \ --reporter $(REPORTER) \ test/acceptance/*.js \ --growl \ test/*.js test-compilers: @./bin/mocha \ --reporter $(REPORTER) \ --compilers coffee:coffee-script,foo:./test/compiler/foo \ test/acceptance/test.coffee \ test/acceptance/test.foo test-requires: @./bin/mocha \ --reporter $(REPORTER) \ --compilers coffee:coffee-script \ --require test/acceptance/require/a.js \ --require test/acceptance/require/b.coffee \ --require test/acceptance/require/c.js \ --require test/acceptance/require/d.coffee \ test/acceptance/require/require.js test-bdd: @./bin/mocha \ --reporter $(REPORTER) \ --ui bdd \ test/acceptance/interfaces/bdd test-tdd: @./bin/mocha \ --reporter $(REPORTER) \ --ui tdd \ test/acceptance/interfaces/tdd test-qunit: @./bin/mocha \ --reporter $(REPORTER) \ --ui qunit \ test/acceptance/interfaces/qunit test-exports: @./bin/mocha \ --reporter $(REPORTER) \ --ui exports \ test/acceptance/interfaces/exports test-grep: @./bin/mocha \ --reporter $(REPORTER) \ --grep fast \ test/acceptance/misc/grep test-invert: @./bin/mocha \ --reporter $(REPORTER) \ --grep slow \ --invert \ test/acceptance/misc/grep test-bail: @./bin/mocha \ --reporter $(REPORTER) \ --bail \ test/acceptance/misc/bail test-async-only: @./bin/mocha \ --reporter $(REPORTER) \ --async-only \ test/acceptance/misc/asyncOnly test-glob: @./test/acceptance/glob/glob.sh test-reporters: @./bin/mocha \ --reporter $(REPORTER) \ test/reporters/*.js test-only: @./bin/mocha \ --reporter $(REPORTER) \ --ui tdd \ test/acceptance/misc/only/tdd @./bin/mocha \ --reporter $(REPORTER) \ --ui bdd \ test/acceptance/misc/only/bdd @./bin/mocha \ --reporter $(REPORTER) \ --ui qunit \ test/acceptance/misc/only/qunit test-sort: @./bin/mocha \ --reporter $(REPORTER) \ --sort \ test/acceptance/sort non-tty: @./bin/mocha \ --reporter dot \ test/acceptance/interfaces/bdd 2>&1 > /tmp/dot.out @echo dot: @cat /tmp/dot.out @./bin/mocha \ --reporter list \ test/acceptance/interfaces/bdd 2>&1 > /tmp/list.out @echo list: @cat /tmp/list.out @./bin/mocha \ --reporter spec \ test/acceptance/interfaces/bdd 2>&1 > /tmp/spec.out @echo spec: @cat /tmp/spec.out tm: @open editors/$(TM_BUNDLE) .PHONY: test-cov test-jsapi test-compilers watch test test-all test-bdd test-tdd test-qunit test-exports test-unit non-tty test-grep tm clean mocha-1.20.1/Readme.md000066400000000000000000000147161234352070300144110ustar00rootroot00000000000000 [![Build Status](https://secure.travis-ci.org/visionmedia/mocha.png)](http://travis-ci.org/visionmedia/mocha) [![Mocha test framework](http://f.cl.ly/items/3l1k0n2A1U3M1I1L210p/Screen%20Shot%202012-02-24%20at%202.21.43%20PM.png)](http://visionmedia.github.io/mocha) Mocha is a simple, flexible, fun JavaScript test framework for node.js and the browser. For more information view the [documentation](http://visionmedia.github.io/mocha). ## Contributors ``` project : mocha repo age : 2 years, 4 months ago commits : 1314 active : 372 days files : 141 authors : 582 TJ Holowaychuk 44.3% 389 Tj Holowaychuk 29.6% 46 Travis Jeffery 3.5% 31 Guillermo Rauch 2.4% 13 Attila Domokos 1.0% 10 John Firebaugh 0.8% 8 Jo Liss 0.6% 7 Nathan Rajlich 0.5% 6 Mike Pennisi 0.5% 6 James Carr 0.5% 6 Brendan Nee 0.5% 5 Aaron Heckmann 0.4% 5 Ryunosuke SATO 0.4% 4 hokaccha 0.3% 4 Joshua Krall 0.3% 4 Xavier Antoviaque 0.3% 3 Jesse Dailey 0.2% 3 Forbes Lindesay 0.2% 3 Sindre Sorhus 0.2% 3 Cory Thomas 0.2% 3 Fredrik Enestad 0.2% 3 Ben Lindsey 0.2% 3 Tyson Tate 0.2% 3 Mathieu Desvé 0.2% 3 Valentin Agachi 0.2% 3 Wil Moore III 0.2% 3 Merrick Christensen 0.2% 3 eiji.ienaga 0.2% 3 fool2fish 0.2% 3 Nathan Bowser 0.2% 3 Paul Miller 0.2% 2 Juzer Ali 0.2% 2 Pete Hawkins 0.2% 2 Jonas Westerlund 0.2% 2 Arian Stolwijk 0.2% 2 Quang Van 0.2% 2 Glen Mailer 0.2% 2 Justin DuJardin 0.2% 2 FARKAS Máté 0.2% 2 Raynos 0.2% 2 Michael Riley 0.2% 2 Michael Schoonmaker 0.2% 2 Domenic Denicola 0.2% 2 Simon Gaeremynck 0.2% 2 Konstantin Käfer 0.2% 2 domenic 0.2% 2 Paul Armstrong 0.2% 2 fcrisci 0.2% 2 Alexander Early 0.2% 2 Shawn Krisman 0.2% 2 Brian Beck 0.2% 2 Nathan Alderson 0.2% 2 David Henderson 0.2% 2 Timo Tijhof 0.2% 2 Ian Storm Taylor 0.2% 2 travis jeffery 0.2% 1 Matt Smith 0.1% 1 Matthew Shanley 0.1% 1 Nathan Black 0.1% 1 Phil Sung 0.1% 1 R56 0.1% 1 Refael Ackermann 0.1% 1 Richard Dingwall 0.1% 1 Romain Prieto 0.1% 1 Roman Neuhauser 0.1% 1 Roman Shtylman 0.1% 1 Russ Bradberry 0.1% 1 Russell Munson 0.1% 1 Rustem Mustafin 0.1% 1 Salehen Shovon Rahman 0.1% 1 Sasha Koss 0.1% 1 Seiya Konno 0.1% 1 Simon Goumaz 0.1% 1 Standa Opichal 0.1% 1 Stephen Mathieson 0.1% 1 Steve Mason 0.1% 1 Tapiwa Kelvin 0.1% 1 Teddy Zeenny 0.1% 1 Tim Ehat 0.1% 1 Vadim Nikitin 0.1% 1 Victor Costan 0.1% 1 Will Langstroth 0.1% 1 Yanis Wang 0.1% 1 Yuest Wang 0.1% 1 abrkn 0.1% 1 airportyh 0.1% 1 badunk 0.1% 1 fengmk2 0.1% 1 grasGendarme 0.1% 1 lodr 0.1% 1 tgautier@yahoo.com 0.1% 1 traleig1 0.1% 1 vlad 0.1% 1 yuitest 0.1% 1 Adam Crabtree 0.1% 1 Andreas Brekken 0.1% 1 Andreas Lind Petersen 0.1% 1 Andrew Nesbitt 0.1% 1 Andrey Popp 0.1% 1 Arnaud Brousseau 0.1% 1 Atsuya Takagi 0.1% 1 Austin Birch 0.1% 1 Bjørge Næss 0.1% 1 Brian Lalor 0.1% 1 Brian M. Carlson 0.1% 1 Brian Moore 0.1% 1 Bryan Donovan 0.1% 1 Casey Foster 0.1% 1 ChrisWren 0.1% 1 Corey Butler 0.1% 1 Daniel Stockman 0.1% 1 Dave McKenna 0.1% 1 Di Wu 0.1% 1 Dmitry Shirokov 0.1% 1 Fedor Indutny 0.1% 1 Florian Margaine 0.1% 1 Frederico Silva 0.1% 1 Fredrik Lindin 0.1% 1 Gareth Murphy 0.1% 1 Gavin Mogan 0.1% 1 Glen Huang 0.1% 1 Greg Perkins 0.1% 1 Harry Brundage 0.1% 1 Herman Junge 0.1% 1 Ian Young 0.1% 1 Ivan 0.1% 1 JP Bochi 0.1% 1 Jaakko Salonen 0.1% 1 Jakub Nešetřil 0.1% 1 James Bowes 0.1% 1 James Lal 0.1% 1 Jason Barry 0.1% 1 Javier Aranda 0.1% 1 Jeff Kunkle 0.1% 1 Jeremy Martin 0.1% 1 Jimmy Cuadra 0.1% 1 Jonathan Creamer 0.1% 1 Jussi Virtanen 0.1% 1 Katie Gengler 0.1% 1 Kazuhito Hokamura 0.1% 1 Kirill Korolyov 0.1% 1 Koen Punt 0.1% 1 Laszlo Bacsi 0.1% 1 Liam Newman 0.1% 1 László Bácsi 0.1% 1 Maciej Małecki 0.1% 1 Mal Graty 0.1% 1 Marc Kuo 0.1% 1 Matt Robenolt 0.1% ``` ## Links - [Google Group](http://groups.google.com/group/mochajs) - [Wiki](https://github.com/visionmedia/mocha/wiki) - Mocha [Extensions and reporters](https://github.com/visionmedia/mocha/wiki) mocha-1.20.1/bin/000077500000000000000000000000001234352070300134315ustar00rootroot00000000000000mocha-1.20.1/bin/_mocha000077500000000000000000000246411234352070300146140ustar00rootroot00000000000000#!/usr/bin/env node /** * Module dependencies. */ var program = require('commander') , sprintf = require('util').format , path = require('path') , fs = require('fs') , glob = require('glob') , resolve = path.resolve , exists = fs.existsSync || path.existsSync , Mocha = require('../') , utils = Mocha.utils , interfaces = Mocha.interfaces , join = path.join , basename = path.basename , cwd = process.cwd() , mocha = new Mocha; /** * Save timer references to avoid Sinon interfering (see GH-237). */ var Date = global.Date , setTimeout = global.setTimeout , setInterval = global.setInterval , clearTimeout = global.clearTimeout , clearInterval = global.clearInterval; /** * Files. */ var files = []; /** * Globals. */ var globals = []; /** * Requires. */ var requires = []; /** * Images. */ var images = { fail: __dirname + '/../images/error.png' , pass: __dirname + '/../images/ok.png' }; // options program .version(JSON.parse(fs.readFileSync(__dirname + '/../package.json', 'utf8')).version) .usage('[debug] [options] [files]') .option('-r, --require ', 'require the given module') .option('-R, --reporter ', 'specify the reporter to use', 'dot') .option('-u, --ui ', 'specify user-interface (bdd|tdd|exports)', 'bdd') .option('-g, --grep ', 'only run tests matching ') .option('-i, --invert', 'inverts --grep matches') .option('-t, --timeout ', 'set test-case timeout in milliseconds [2000]') .option('-s, --slow ', '"slow" test threshold in milliseconds [75]') .option('-w, --watch', 'watch files for changes') .option('-c, --colors', 'force enabling of colors') .option('-C, --no-colors', 'force disabling of colors') .option('-G, --growl', 'enable growl notification support') .option('-d, --debug', "enable node's debugger, synonym for node --debug") .option('-b, --bail', "bail after first test failure") .option('-A, --async-only', "force all tests to take a callback (async)") .option('-S, --sort', "sort test files") .option('--recursive', 'include sub directories') .option('--debug-brk', "enable node's debugger breaking on the first line") .option('--globals ', 'allow the given comma-delimited global [names]', list, []) .option('--harmony', 'enable all harmony features (except typeof)') .option('--harmony-proxies', 'enable harmony proxies') .option('--harmony-collections', 'enable harmony collections (sets, maps, and weak maps)') .option('--harmony-generators', 'enable harmony generators') .option('--prof', 'log statistical profiling information') .option('-gc', '--expose-gc', 'expose gc extension') .option('--trace', 'trace function calls') .option('--check-leaks', 'check for global variable leaks') .option('--interfaces', 'display available interfaces') .option('--reporters', 'display available reporters') .option('--compilers :,...', 'use the given module(s) to compile files', list, []) .option('--inline-diffs', 'display actual/expected differences inline within each string') .option('--no-exit', 'require a clean shutdown of the event loop: mocha will not call process.exit') program.name = 'mocha'; // init command program .command('init ') .description('initialize a client-side mocha setup at ') .action(function(path){ var mkdir = require('mkdirp'); mkdir.sync(path); var css = fs.readFileSync(join(__dirname, '..', 'mocha.css')); var js = fs.readFileSync(join(__dirname, '..', 'mocha.js')); var tmpl = fs.readFileSync(join(__dirname, '..', 'lib/template.html')); fs.writeFileSync(join(path, 'mocha.css'), css); fs.writeFileSync(join(path, 'mocha.js'), js); fs.writeFileSync(join(path, 'tests.js'), ''); fs.writeFileSync(join(path, 'index.html'), tmpl); process.exit(0); }); // --globals program.on('globals', function(val){ globals = globals.concat(list(val)); }); // --reporters program.on('reporters', function(){ console.log(); console.log(' dot - dot matrix'); console.log(' doc - html documentation'); console.log(' spec - hierarchical spec list'); console.log(' json - single json object'); console.log(' progress - progress bar'); console.log(' list - spec-style listing'); console.log(' tap - test-anything-protocol'); console.log(' landing - unicode landing strip'); console.log(' xunit - xunit reporter'); console.log(' html-cov - HTML test coverage'); console.log(' json-cov - JSON test coverage'); console.log(' min - minimal reporter (great with --watch)'); console.log(' json-stream - newline delimited json events'); console.log(' markdown - markdown documentation (github flavour)'); console.log(' nyan - nyan cat!'); console.log(); process.exit(); }); // --interfaces program.on('interfaces', function(){ console.log(''); console.log(' bdd'); console.log(' tdd'); console.log(' qunit'); console.log(' exports'); console.log(''); process.exit(); }); // -r, --require module.paths.push(cwd, join(cwd, 'node_modules')); program.on('require', function(mod){ var abs = exists(mod) || exists(mod + '.js'); if (abs) mod = resolve(mod); requires.push(mod); }); // mocha.opts support try { var opts = fs.readFileSync('test/mocha.opts', 'utf8') .trim() .split(/\s+/); process.argv = process.argv .slice(0, 2) .concat(opts.concat(process.argv.slice(2))); } catch (err) { // ignore } // parse args program.parse(process.argv); // infinite stack traces Error.stackTraceLimit = Infinity; // TODO: config // reporter mocha.reporter(program.reporter); // interface mocha.ui(program.ui); // load reporter try { Reporter = require('../lib/reporters/' + program.reporter); } catch (err) { try { Reporter = require(program.reporter); } catch (err) { throw new Error('reporter "' + program.reporter + '" does not exist'); } } // --no-colors if (!program.colors) mocha.useColors(false); // --colors if (~process.argv.indexOf('--colors') || ~process.argv.indexOf('-c')) { mocha.useColors(true); } // --inline-diffs if (program.inlineDiffs) mocha.useInlineDiffs(true); // --slow if (program.slow) mocha.suite.slow(program.slow); // --timeout if (program.timeout) mocha.suite.timeout(program.timeout); // --bail mocha.suite.bail(program.bail); // --grep if (program.grep) mocha.grep(new RegExp(program.grep)); // --invert if (program.invert) mocha.invert(); // --check-leaks if (program.checkLeaks) mocha.checkLeaks(); // --growl if (program.growl) mocha.growl(); // --async-only if (program.asyncOnly) mocha.asyncOnly(); // --globals mocha.globals(globals); // custom compiler support var extensions = ['js']; program.compilers.forEach(function(c) { var compiler = c.split(':') , ext = compiler[0] , mod = compiler[1]; if (mod[0] == '.') mod = join(process.cwd(), mod); require(mod); extensions.push(ext); }); var re = new RegExp('\\.(' + extensions.join('|') + ')$'); // requires requires.forEach(function(mod) { require(mod); }); // files var files = [] , args = program.args; // default files to test/*.{js,coffee} if (!args.length) args.push('test'); args.forEach(function(arg){ files = files.concat(lookupFiles(arg, program.recursive)); }); // resolve files = files.map(function(path){ return resolve(path); }); if (program.sort) { files.sort(); } // --watch var runner; if (program.watch) { console.log(); hideCursor(); process.on('SIGINT', function(){ showCursor(); console.log('\n'); process.exit(); }); var watchFiles = utils.files(cwd); var runAgain = false; function loadAndRun() { try { mocha.files = files; runAgain = false; runner = mocha.run(function(){ runner = null; if (runAgain) { rerun(); } }); } catch(e) { console.log(e.stack); } } function purge() { watchFiles.forEach(function(file){ delete require.cache[file]; }); } loadAndRun(); function rerun() { purge(); stop() mocha.suite = mocha.suite.clone(); mocha.suite.ctx = new Mocha.Context; mocha.ui(program.ui); loadAndRun(); } utils.watch(watchFiles, function(){ runAgain = true; if (runner) { runner.abort(); } else { rerun(); } }); return; } // load mocha.files = files; runner = mocha.run(program.exit ? process.exit : exitLater); function exitLater(code) { process.on('exit', function() { process.exit(code) }) } process.on('SIGINT', function() { runner.abort(); }) // enable growl notifications function growl(runner, reporter) { var notify = require('growl'); runner.on('end', function(){ var stats = reporter.stats; if (stats.failures) { var msg = stats.failures + ' of ' + runner.total + ' tests failed'; notify(msg, { name: 'mocha', title: 'Failed', image: images.fail }); } else { notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', { name: 'mocha' , title: 'Passed' , image: images.pass }); } }); } /** * Parse list. */ function list(str) { return str.split(/ *, */); } /** * Hide the cursor. */ function hideCursor(){ process.stdout.write('\u001b[?25l'); }; /** * Show the cursor. */ function showCursor(){ process.stdout.write('\u001b[?25h'); }; /** * Stop play()ing. */ function stop() { process.stdout.write('\u001b[2K'); clearInterval(play.timer); } /** * Lookup file names at the given `path`. */ function lookupFiles(path, recursive) { var files = []; if (!exists(path)) { if (exists(path + '.js')) { path += '.js' } else { files = glob.sync(path); if (!files.length) throw new Error("cannot resolve path (or pattern) '" + path + "'"); return files; } } var stat = fs.statSync(path); if (stat.isFile()) return path; fs.readdirSync(path).forEach(function(file){ file = join(path, file); var stat = fs.statSync(file); if (stat.isDirectory()) { if (recursive) files = files.concat(lookupFiles(file, recursive)); return } if (!stat.isFile() || !re.test(file) || basename(file)[0] == '.') return; files.push(file); }); return files; } /** * Play the given array of strings. */ function play(arr, interval) { var len = arr.length , interval = interval || 100 , i = 0; play.timer = setInterval(function(){ var str = arr[i++ % len]; process.stdout.write('\u001b[0G' + str); }, interval); } mocha-1.20.1/bin/mocha000077500000000000000000000022141234352070300144450ustar00rootroot00000000000000#!/usr/bin/env node /** * This tiny wrapper file checks for known node flags and appends them * when found, before invoking the "real" _mocha(1) executable. */ var spawn = require('child_process').spawn , args = [ __dirname + '/_mocha' ]; process.argv.slice(2).forEach(function(arg){ var flag = arg.split('=')[0]; switch (flag) { case '-d': args.unshift('--debug'); break; case 'debug': case '--debug': case '--debug-brk': args.unshift(arg); break; case '-gc': case '--expose-gc': args.unshift('--expose-gc'); break; case '--gc-global': case '--harmony': case '--harmony-proxies': case '--harmony-collections': case '--harmony-generators': case '--prof': args.unshift(arg); break; default: if (0 == arg.indexOf('--trace')) args.unshift(arg); else args.push(arg); break; } }); var proc = spawn(process.argv[0], args, { customFds: [0,1,2] }); proc.on('exit', function (code, signal) { process.on('exit', function(){ if (signal) { process.kill(process.pid, signal); } else { process.exit(code); } }); }); mocha-1.20.1/bower.json000066400000000000000000000004771234352070300147020ustar00rootroot00000000000000{ "name": "mocha", "version": "1.20.1", "main": [ "mocha.js", "mocha.css" ], "ignore": [ "bin", "editors", "images", "lib", "support", "test", ".gitignore", ".npmignore", ".travis.yml", "component.json", "index.js", "Makefile", "package.json" ] } mocha-1.20.1/component.json000066400000000000000000000004371234352070300155620ustar00rootroot00000000000000{ "name": "mocha", "version": "1.20.1", "repo": "visionmedia/mocha", "description": "simple, flexible, fun test framework", "keywords": [ "mocha", "test", "bdd", "tdd", "tap" ], "main": "mocha.js", "scripts": ["mocha.js"], "styles": ["mocha.css"] } mocha-1.20.1/editors/000077500000000000000000000000001234352070300143325ustar00rootroot00000000000000mocha-1.20.1/editors/JavaScript mocha.tmbundle/000077500000000000000000000000001234352070300212615ustar00rootroot00000000000000mocha-1.20.1/editors/JavaScript mocha.tmbundle/Snippets/000077500000000000000000000000001234352070300230665ustar00rootroot00000000000000mocha-1.20.1/editors/JavaScript mocha.tmbundle/Snippets/bdd - after each.tmSnippet000066400000000000000000000007261234352070300276110ustar00rootroot00000000000000 content afterEach(function(){ $0 }) name bdd - after each scope source.js tabTrigger ae uuid 7B4DA8F4-2064-468B-B252-054148419B4B mocha-1.20.1/editors/JavaScript mocha.tmbundle/Snippets/bdd - after.tmSnippet000066400000000000000000000007141234352070300267250ustar00rootroot00000000000000 content after(function(){ $0 }) name bdd - after scope source.js tabTrigger a uuid A49A87F9-399E-4D74-A489-C535BB06D487 mocha-1.20.1/editors/JavaScript mocha.tmbundle/Snippets/bdd - before each.tmSnippet000066400000000000000000000007301234352070300277450ustar00rootroot00000000000000 content beforeEach(function(){ $0 }) name bdd - before each scope source.js tabTrigger be uuid 7AB064E3-EFBB-4FA7-98CA-9E87C10CC04E mocha-1.20.1/editors/JavaScript mocha.tmbundle/Snippets/bdd - before.tmSnippet000066400000000000000000000007161234352070300270700ustar00rootroot00000000000000 content before(function(){ $0 }) name bdd - before scope source.js tabTrigger b uuid DF6F1F42-F80A-4A24-AF78-376F19070C4C mocha-1.20.1/editors/JavaScript mocha.tmbundle/Snippets/bdd - describe.tmSnippet000066400000000000000000000007321234352070300274040ustar00rootroot00000000000000 content describe('$1', function(){ $0 }) name bdd - describe scope source.js tabTrigger des uuid 4AA1FB50-9BB9-400E-A140-D61C39BDFDF5 mocha-1.20.1/editors/JavaScript mocha.tmbundle/Snippets/bdd - it.tmSnippet000066400000000000000000000007241234352070300262410ustar00rootroot00000000000000 content it('should $1', function(){ $0 }) name bdd - it scope source.js tabTrigger it uuid 591AE071-95E4-4E1E-B0F3-A7DAF41595EE mocha-1.20.1/editors/JavaScript mocha.tmbundle/Snippets/tdd - assert.tmSnippet000066400000000000000000000007001234352070300271420ustar00rootroot00000000000000 content assert($0); name tdd - assert scope source.js tabTrigger as uuid 9D920EC2-6A72-4108-B5A0-591AFA61C740 mocha-1.20.1/editors/JavaScript mocha.tmbundle/Snippets/tdd - assert_deepEqual.tmSnippet000066400000000000000000000007311234352070300311330ustar00rootroot00000000000000 content assert.deepEqual($1, $2); name tdd - assert.deepEqual scope source.js tabTrigger deq uuid 7D21FF16-E2E1-46BB-AD6B-82AD767A0822 mocha-1.20.1/editors/JavaScript mocha.tmbundle/Snippets/tdd - assert_equal.tmSnippet000066400000000000000000000007201234352070300303330ustar00rootroot00000000000000 content assert.equal($1, $2); name tdd - assert.equal scope source.js tabTrigger eq uuid 4868D5C0-075D-44A8-B41B-A14E8350C0F8 mocha-1.20.1/editors/JavaScript mocha.tmbundle/Snippets/tdd - assert_fail.tmSnippet000066400000000000000000000007141234352070300301420ustar00rootroot00000000000000 content assert.fail($0); name tdd - assert.fail scope source.js tabTrigger fail uuid 11756F3A-5F08-445C-B5B6-30605838BC6F mocha-1.20.1/editors/JavaScript mocha.tmbundle/Snippets/tdd - assert_isFunction.tmSnippet000066400000000000000000000007271234352070300313540ustar00rootroot00000000000000 content assert.isFunction($0); name tdd - assert.isFunction scope source.js tabTrigger isf uuid 83DFFD36-2C46-4C92-8950-64665D32DC8E mocha-1.20.1/editors/JavaScript mocha.tmbundle/Snippets/tdd - setup.tmSnippet000066400000000000000000000007221234352070300270050ustar00rootroot00000000000000 content setup(function() { $0 }); name tdd - setup scope source.js tabTrigger setup uuid DCEE796A-900D-4922-BAF0-39C9B91A15E1 mocha-1.20.1/editors/JavaScript mocha.tmbundle/Snippets/tdd - suite.tmSnippet000066400000000000000000000007301234352070300267750ustar00rootroot00000000000000 content suite('$1', function() { $0 }); name tdd - suite scope source.js tabTrigger suite uuid 2E65C1BE-A568-4868-95BF-E8C958EA5BA5 mocha-1.20.1/editors/JavaScript mocha.tmbundle/Snippets/tdd - teardown.tmSnippet000066400000000000000000000007331234352070300274720ustar00rootroot00000000000000 content teardown(function() { $0 }); name tdd - teardown scope source.js tabTrigger teardown uuid 9472B167-BEC1-45FD-BA1C-68A99961D8FF mocha-1.20.1/editors/JavaScript mocha.tmbundle/Snippets/tdd - test.tmSnippet000066400000000000000000000007251234352070300266270ustar00rootroot00000000000000 content test('$1', function() { $0 }); name tdd - test scope source.js tabTrigger test uuid F6E3DF27-3458-4ADD-91A3-B6EF11E1D81E mocha-1.20.1/editors/JavaScript mocha.tmbundle/info.plist000066400000000000000000000012601234352070300232700ustar00rootroot00000000000000 name JavaScript mocha ordering 4AA1FB50-9BB9-400E-A140-D61C39BDFDF5 591AE071-95E4-4E1E-B0F3-A7DAF41595EE DF6F1F42-F80A-4A24-AF78-376F19070C4C A49A87F9-399E-4D74-A489-C535BB06D487 7AB064E3-EFBB-4FA7-98CA-9E87C10CC04E 7B4DA8F4-2064-468B-B252-054148419B4B uuid 094ACE33-0C0E-422A-B3F7-5B919F5B1239 mocha-1.20.1/images/000077500000000000000000000000001234352070300141265ustar00rootroot00000000000000mocha-1.20.1/images/error.png000066400000000000000000000006341234352070300157700ustar00rootroot00000000000000PNG  IHDRש`PLTEXaa33DD%% $$񂂾<s+ޤ0Z,0ͣ< |C#%_,M6 IENDB`mocha-1.20.1/images/ok.png000066400000000000000000000006041234352070300152450ustar00rootroot00000000000000PNG  IHDRש`PLTEZ6[6b;c;c;uMvNWf>qIyQ|TkCsJwOnFh@^c;gtRNS%) 6. pRIDATxڵ DQ""~2{^_aSKڏ# }@_CRvFOHoE09b 99CP/1{C~@;{~yJJ1zcJ `m3 ahZ&:շuÚn{ЭNp p/j(.q0IENDB`mocha-1.20.1/index.js000066400000000000000000000001341234352070300143240ustar00rootroot00000000000000 module.exports = process.env.COV ? require('./lib-cov/mocha') : require('./lib/mocha');mocha-1.20.1/lib/000077500000000000000000000000001234352070300134275ustar00rootroot00000000000000mocha-1.20.1/lib/browser/000077500000000000000000000000001234352070300151125ustar00rootroot00000000000000mocha-1.20.1/lib/browser/debug.js000066400000000000000000000000761234352070300165410ustar00rootroot00000000000000 module.exports = function(type){ return function(){ } }; mocha-1.20.1/lib/browser/events.js000066400000000000000000000055321234352070300167610ustar00rootroot00000000000000 /** * Module exports. */ exports.EventEmitter = EventEmitter; /** * Check if `obj` is an array. */ function isArray(obj) { return '[object Array]' == {}.toString.call(obj); } /** * Event emitter constructor. * * @api public */ function EventEmitter(){}; /** * Adds a listener. * * @api public */ EventEmitter.prototype.on = function (name, fn) { if (!this.$events) { this.$events = {}; } if (!this.$events[name]) { this.$events[name] = fn; } else if (isArray(this.$events[name])) { this.$events[name].push(fn); } else { this.$events[name] = [this.$events[name], fn]; } return this; }; EventEmitter.prototype.addListener = EventEmitter.prototype.on; /** * Adds a volatile listener. * * @api public */ EventEmitter.prototype.once = function (name, fn) { var self = this; function on () { self.removeListener(name, on); fn.apply(this, arguments); }; on.listener = fn; this.on(name, on); return this; }; /** * Removes a listener. * * @api public */ EventEmitter.prototype.removeListener = function (name, fn) { if (this.$events && this.$events[name]) { var list = this.$events[name]; if (isArray(list)) { var pos = -1; for (var i = 0, l = list.length; i < l; i++) { if (list[i] === fn || (list[i].listener && list[i].listener === fn)) { pos = i; break; } } if (pos < 0) { return this; } list.splice(pos, 1); if (!list.length) { delete this.$events[name]; } } else if (list === fn || (list.listener && list.listener === fn)) { delete this.$events[name]; } } return this; }; /** * Removes all listeners for an event. * * @api public */ EventEmitter.prototype.removeAllListeners = function (name) { if (name === undefined) { this.$events = {}; return this; } if (this.$events && this.$events[name]) { this.$events[name] = null; } return this; }; /** * Gets all listeners for a certain event. * * @api public */ EventEmitter.prototype.listeners = function (name) { if (!this.$events) { this.$events = {}; } if (!this.$events[name]) { this.$events[name] = []; } if (!isArray(this.$events[name])) { this.$events[name] = [this.$events[name]]; } return this.$events[name]; }; /** * Emits an event. * * @api public */ EventEmitter.prototype.emit = function (name) { if (!this.$events) { return false; } var handler = this.$events[name]; if (!handler) { return false; } var args = [].slice.call(arguments, 1); if ('function' == typeof handler) { handler.apply(this, args); } else if (isArray(handler)) { var listeners = handler.slice(); for (var i = 0, l = listeners.length; i < l; i++) { listeners[i].apply(this, args); } } else { return false; } return true; };mocha-1.20.1/lib/browser/fs.js000066400000000000000000000000001234352070300160460ustar00rootroot00000000000000mocha-1.20.1/lib/browser/path.js000066400000000000000000000000001234352070300163720ustar00rootroot00000000000000mocha-1.20.1/lib/browser/progress.js000066400000000000000000000042061234352070300173160ustar00rootroot00000000000000/** * Expose `Progress`. */ module.exports = Progress; /** * Initialize a new `Progress` indicator. */ function Progress() { this.percent = 0; this.size(0); this.fontSize(11); this.font('helvetica, arial, sans-serif'); } /** * Set progress size to `n`. * * @param {Number} n * @return {Progress} for chaining * @api public */ Progress.prototype.size = function(n){ this._size = n; return this; }; /** * Set text to `str`. * * @param {String} str * @return {Progress} for chaining * @api public */ Progress.prototype.text = function(str){ this._text = str; return this; }; /** * Set font size to `n`. * * @param {Number} n * @return {Progress} for chaining * @api public */ Progress.prototype.fontSize = function(n){ this._fontSize = n; return this; }; /** * Set font `family`. * * @param {String} family * @return {Progress} for chaining */ Progress.prototype.font = function(family){ this._font = family; return this; }; /** * Update percentage to `n`. * * @param {Number} n * @return {Progress} for chaining */ Progress.prototype.update = function(n){ this.percent = n; return this; }; /** * Draw on `ctx`. * * @param {CanvasRenderingContext2d} ctx * @return {Progress} for chaining */ Progress.prototype.draw = function(ctx){ try { var percent = Math.min(this.percent, 100) , size = this._size , half = size / 2 , x = half , y = half , rad = half - 1 , fontSize = this._fontSize; ctx.font = fontSize + 'px ' + this._font; var angle = Math.PI * 2 * (percent / 100); ctx.clearRect(0, 0, size, size); // outer circle ctx.strokeStyle = '#9f9f9f'; ctx.beginPath(); ctx.arc(x, y, rad, 0, angle, false); ctx.stroke(); // inner circle ctx.strokeStyle = '#eee'; ctx.beginPath(); ctx.arc(x, y, rad - 1, 0, angle, true); ctx.stroke(); // text var text = this._text || (percent | 0) + '%' , w = ctx.measureText(text).width; ctx.fillText( text , x - w / 2 + 1 , y + fontSize / 2 - 1); } catch (ex) {} //don't fail if we can't render progress return this; }; mocha-1.20.1/lib/browser/tty.js000066400000000000000000000004141234352070300162670ustar00rootroot00000000000000 exports.isatty = function(){ return true; }; exports.getWindowSize = function(){ if ('innerHeight' in global) { return [global.innerHeight, global.innerWidth]; } else { // In a Web Worker, the DOM Window is not available. return [640, 480]; } }; mocha-1.20.1/lib/context.js000066400000000000000000000021161234352070300154510ustar00rootroot00000000000000 /** * Expose `Context`. */ module.exports = Context; /** * Initialize a new `Context`. * * @api private */ function Context(){} /** * Set or get the context `Runnable` to `runnable`. * * @param {Runnable} runnable * @return {Context} * @api private */ Context.prototype.runnable = function(runnable){ if (0 == arguments.length) return this._runnable; this.test = this._runnable = runnable; return this; }; /** * Set test timeout `ms`. * * @param {Number} ms * @return {Context} self * @api private */ Context.prototype.timeout = function(ms){ this.runnable().timeout(ms); return this; }; /** * Set test slowness threshold `ms`. * * @param {Number} ms * @return {Context} self * @api private */ Context.prototype.slow = function(ms){ this.runnable().slow(ms); return this; }; /** * Inspect the context void of `._runnable`. * * @return {String} * @api private */ Context.prototype.inspect = function(){ return JSON.stringify(this, function(key, val){ if ('_runnable' == key) return; if ('test' == key) return; return val; }, 2); }; mocha-1.20.1/lib/hook.js000066400000000000000000000013121234352070300147220ustar00rootroot00000000000000 /** * Module dependencies. */ var Runnable = require('./runnable'); /** * Expose `Hook`. */ module.exports = Hook; /** * Initialize a new `Hook` with the given `title` and callback `fn`. * * @param {String} title * @param {Function} fn * @api private */ function Hook(title, fn) { Runnable.call(this, title, fn); this.type = 'hook'; } /** * Inherit from `Runnable.prototype`. */ Hook.prototype.__proto__ = Runnable.prototype; /** * Get or set the test `err`. * * @param {Error} err * @return {Error} * @api public */ Hook.prototype.error = function(err){ if (0 == arguments.length) { var err = this._error; this._error = null; return err; } this._error = err; }; mocha-1.20.1/lib/interfaces/000077500000000000000000000000001234352070300155525ustar00rootroot00000000000000mocha-1.20.1/lib/interfaces/bdd.js000066400000000000000000000053771234352070300166550ustar00rootroot00000000000000 /** * Module dependencies. */ var Suite = require('../suite') , Test = require('../test') , utils = require('../utils'); /** * BDD-style interface: * * describe('Array', function(){ * describe('#indexOf()', function(){ * it('should return -1 when not present', function(){ * * }); * * it('should return the index when present', function(){ * * }); * }); * }); * */ module.exports = function(suite){ var suites = [suite]; suite.on('pre-require', function(context, file, mocha){ /** * Execute before running tests. */ context.before = function(name, fn){ suites[0].beforeAll(name, fn); }; /** * Execute after running tests. */ context.after = function(name, fn){ suites[0].afterAll(name, fn); }; /** * Execute before each test case. */ context.beforeEach = function(name, fn){ suites[0].beforeEach(name, fn); }; /** * Execute after each test case. */ context.afterEach = function(name, fn){ suites[0].afterEach(name, fn); }; /** * Describe a "suite" with the given `title` * and callback `fn` containing nested suites * and/or tests. */ context.describe = context.context = function(title, fn){ var suite = Suite.create(suites[0], title); suite.file = file; suites.unshift(suite); fn.call(suite); suites.shift(); return suite; }; /** * Pending describe. */ context.xdescribe = context.xcontext = context.describe.skip = function(title, fn){ var suite = Suite.create(suites[0], title); suite.pending = true; suites.unshift(suite); fn.call(suite); suites.shift(); }; /** * Exclusive suite. */ context.describe.only = function(title, fn){ var suite = context.describe(title, fn); mocha.grep(suite.fullTitle()); return suite; }; /** * Describe a specification or test-case * with the given `title` and callback `fn` * acting as a thunk. */ context.it = context.specify = function(title, fn){ var suite = suites[0]; if (suite.pending) var fn = null; var test = new Test(title, fn); test.file = file; suite.addTest(test); return test; }; /** * Exclusive test-case. */ context.it.only = function(title, fn){ var test = context.it(title, fn); var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$'; mocha.grep(new RegExp(reString)); return test; }; /** * Pending test case. */ context.xit = context.xspecify = context.it.skip = function(title){ context.it(title); }; }); }; mocha-1.20.1/lib/interfaces/exports.js000066400000000000000000000024121234352070300176130ustar00rootroot00000000000000 /** * Module dependencies. */ var Suite = require('../suite') , Test = require('../test'); /** * TDD-style interface: * * exports.Array = { * '#indexOf()': { * 'should return -1 when the value is not present': function(){ * * }, * * 'should return the correct index when the value is present': function(){ * * } * } * }; * */ module.exports = function(suite){ var suites = [suite]; suite.on('require', visit); function visit(obj, file) { var suite; for (var key in obj) { if ('function' == typeof obj[key]) { var fn = obj[key]; switch (key) { case 'before': suites[0].beforeAll(fn); break; case 'after': suites[0].afterAll(fn); break; case 'beforeEach': suites[0].beforeEach(fn); break; case 'afterEach': suites[0].afterEach(fn); break; default: var test = new Test(key, fn); test.file = file; suites[0].addTest(test); } } else { var suite = Suite.create(suites[0], key); suites.unshift(suite); visit(obj[key]); suites.shift(); } } } }; mocha-1.20.1/lib/interfaces/index.js000066400000000000000000000002151234352070300172150ustar00rootroot00000000000000 exports.bdd = require('./bdd'); exports.tdd = require('./tdd'); exports.qunit = require('./qunit'); exports.exports = require('./exports'); mocha-1.20.1/lib/interfaces/qunit.js000066400000000000000000000045521234352070300172560ustar00rootroot00000000000000 /** * Module dependencies. */ var Suite = require('../suite') , Test = require('../test') , utils = require('../utils'); /** * QUnit-style interface: * * suite('Array'); * * test('#length', function(){ * var arr = [1,2,3]; * ok(arr.length == 3); * }); * * test('#indexOf()', function(){ * var arr = [1,2,3]; * ok(arr.indexOf(1) == 0); * ok(arr.indexOf(2) == 1); * ok(arr.indexOf(3) == 2); * }); * * suite('String'); * * test('#length', function(){ * ok('foo'.length == 3); * }); * */ module.exports = function(suite){ var suites = [suite]; suite.on('pre-require', function(context, file, mocha){ /** * Execute before running tests. */ context.before = function(name, fn){ suites[0].beforeAll(name, fn); }; /** * Execute after running tests. */ context.after = function(name, fn){ suites[0].afterAll(name, fn); }; /** * Execute before each test case. */ context.beforeEach = function(name, fn){ suites[0].beforeEach(name, fn); }; /** * Execute after each test case. */ context.afterEach = function(name, fn){ suites[0].afterEach(name, fn); }; /** * Describe a "suite" with the given `title`. */ context.suite = function(title){ if (suites.length > 1) suites.shift(); var suite = Suite.create(suites[0], title); suite.file = file; suites.unshift(suite); return suite; }; /** * Exclusive test-case. */ context.suite.only = function(title, fn){ var suite = context.suite(title, fn); mocha.grep(suite.fullTitle()); }; /** * Describe a specification or test-case * with the given `title` and callback `fn` * acting as a thunk. */ context.test = function(title, fn){ var test = new Test(title, fn); test.file = file; suites[0].addTest(test); return test; }; /** * Exclusive test-case. */ context.test.only = function(title, fn){ var test = context.test(title, fn); var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$'; mocha.grep(new RegExp(reString)); }; /** * Pending test case. */ context.test.skip = function(title){ context.test(title); }; }); }; mocha-1.20.1/lib/interfaces/tdd.js000066400000000000000000000053151234352070300166670ustar00rootroot00000000000000 /** * Module dependencies. */ var Suite = require('../suite') , Test = require('../test') , utils = require('../utils');; /** * TDD-style interface: * * suite('Array', function(){ * suite('#indexOf()', function(){ * suiteSetup(function(){ * * }); * * test('should return -1 when not present', function(){ * * }); * * test('should return the index when present', function(){ * * }); * * suiteTeardown(function(){ * * }); * }); * }); * */ module.exports = function(suite){ var suites = [suite]; suite.on('pre-require', function(context, file, mocha){ /** * Execute before each test case. */ context.setup = function(name, fn){ suites[0].beforeEach(name, fn); }; /** * Execute after each test case. */ context.teardown = function(name, fn){ suites[0].afterEach(name, fn); }; /** * Execute before the suite. */ context.suiteSetup = function(name, fn){ suites[0].beforeAll(name, fn); }; /** * Execute after the suite. */ context.suiteTeardown = function(name, fn){ suites[0].afterAll(name, fn); }; /** * Describe a "suite" with the given `title` * and callback `fn` containing nested suites * and/or tests. */ context.suite = function(title, fn){ var suite = Suite.create(suites[0], title); suite.file = file; suites.unshift(suite); fn.call(suite); suites.shift(); return suite; }; /** * Pending suite. */ context.suite.skip = function(title, fn) { var suite = Suite.create(suites[0], title); suite.pending = true; suites.unshift(suite); fn.call(suite); suites.shift(); }; /** * Exclusive test-case. */ context.suite.only = function(title, fn){ var suite = context.suite(title, fn); mocha.grep(suite.fullTitle()); }; /** * Describe a specification or test-case * with the given `title` and callback `fn` * acting as a thunk. */ context.test = function(title, fn){ var suite = suites[0]; if (suite.pending) var fn = null; var test = new Test(title, fn); test.file = file; suite.addTest(test); return test; }; /** * Exclusive test-case. */ context.test.only = function(title, fn){ var test = context.test(title, fn); var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$'; mocha.grep(new RegExp(reString)); }; /** * Pending test case. */ context.test.skip = function(title){ context.test(title); }; }); }; mocha-1.20.1/lib/mocha.js000066400000000000000000000200511234352070300150520ustar00rootroot00000000000000/*! * mocha * Copyright(c) 2011 TJ Holowaychuk * MIT Licensed */ /** * Module dependencies. */ var path = require('path') , utils = require('./utils'); /** * Expose `Mocha`. */ exports = module.exports = Mocha; /** * Expose internals. */ exports.utils = utils; exports.interfaces = require('./interfaces'); exports.reporters = require('./reporters'); exports.Runnable = require('./runnable'); exports.Context = require('./context'); exports.Runner = require('./runner'); exports.Suite = require('./suite'); exports.Hook = require('./hook'); exports.Test = require('./test'); /** * Return image `name` path. * * @param {String} name * @return {String} * @api private */ function image(name) { return __dirname + '/../images/' + name + '.png'; } /** * Setup mocha with `options`. * * Options: * * - `ui` name "bdd", "tdd", "exports" etc * - `reporter` reporter instance, defaults to `mocha.reporters.Dot` * - `globals` array of accepted globals * - `timeout` timeout in milliseconds * - `bail` bail on the first test failure * - `slow` milliseconds to wait before considering a test slow * - `ignoreLeaks` ignore global leaks * - `grep` string or regexp to filter tests with * * @param {Object} options * @api public */ function Mocha(options) { options = options || {}; this.files = []; this.options = options; this.grep(options.grep); this.suite = new exports.Suite('', new exports.Context); this.ui(options.ui); this.bail(options.bail); this.reporter(options.reporter); if (null != options.timeout) this.timeout(options.timeout); this.useColors(options.useColors) if (options.slow) this.slow(options.slow); this.suite.on('pre-require', function (context) { exports.afterEach = context.afterEach || context.teardown; exports.after = context.after || context.suiteTeardown; exports.beforeEach = context.beforeEach || context.setup; exports.before = context.before || context.suiteSetup; exports.describe = context.describe || context.suite; exports.it = context.it || context.test; exports.setup = context.setup || context.beforeEach; exports.suiteSetup = context.suiteSetup || context.before; exports.suiteTeardown = context.suiteTeardown || context.after; exports.suite = context.suite || context.describe; exports.teardown = context.teardown || context.afterEach; exports.test = context.test || context.it; }); } /** * Enable or disable bailing on the first failure. * * @param {Boolean} [bail] * @api public */ Mocha.prototype.bail = function(bail){ if (0 == arguments.length) bail = true; this.suite.bail(bail); return this; }; /** * Add test `file`. * * @param {String} file * @api public */ Mocha.prototype.addFile = function(file){ this.files.push(file); return this; }; /** * Set reporter to `reporter`, defaults to "dot". * * @param {String|Function} reporter name or constructor * @api public */ Mocha.prototype.reporter = function(reporter){ if ('function' == typeof reporter) { this._reporter = reporter; } else { reporter = reporter || 'dot'; var _reporter; try { _reporter = require('./reporters/' + reporter); } catch (err) {}; if (!_reporter) try { _reporter = require(reporter); } catch (err) {}; if (!_reporter && reporter === 'teamcity') console.warn('The Teamcity reporter was moved to a package named ' + 'mocha-teamcity-reporter ' + '(https://npmjs.org/package/mocha-teamcity-reporter).'); if (!_reporter) throw new Error('invalid reporter "' + reporter + '"'); this._reporter = _reporter; } return this; }; /** * Set test UI `name`, defaults to "bdd". * * @param {String} bdd * @api public */ Mocha.prototype.ui = function(name){ name = name || 'bdd'; this._ui = exports.interfaces[name]; if (!this._ui) try { this._ui = require(name); } catch (err) {}; if (!this._ui) throw new Error('invalid interface "' + name + '"'); this._ui = this._ui(this.suite); return this; }; /** * Load registered files. * * @api private */ Mocha.prototype.loadFiles = function(fn){ var self = this; var suite = this.suite; var pending = this.files.length; this.files.forEach(function(file){ file = path.resolve(file); suite.emit('pre-require', global, file, self); suite.emit('require', require(file), file, self); suite.emit('post-require', global, file, self); --pending || (fn && fn()); }); }; /** * Enable growl support. * * @api private */ Mocha.prototype._growl = function(runner, reporter) { var notify = require('growl'); runner.on('end', function(){ var stats = reporter.stats; if (stats.failures) { var msg = stats.failures + ' of ' + runner.total + ' tests failed'; notify(msg, { name: 'mocha', title: 'Failed', image: image('error') }); } else { notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', { name: 'mocha' , title: 'Passed' , image: image('ok') }); } }); }; /** * Add regexp to grep, if `re` is a string it is escaped. * * @param {RegExp|String} re * @return {Mocha} * @api public */ Mocha.prototype.grep = function(re){ this.options.grep = 'string' == typeof re ? new RegExp(utils.escapeRegexp(re)) : re; return this; }; /** * Invert `.grep()` matches. * * @return {Mocha} * @api public */ Mocha.prototype.invert = function(){ this.options.invert = true; return this; }; /** * Ignore global leaks. * * @param {Boolean} ignore * @return {Mocha} * @api public */ Mocha.prototype.ignoreLeaks = function(ignore){ this.options.ignoreLeaks = !!ignore; return this; }; /** * Enable global leak checking. * * @return {Mocha} * @api public */ Mocha.prototype.checkLeaks = function(){ this.options.ignoreLeaks = false; return this; }; /** * Enable growl support. * * @return {Mocha} * @api public */ Mocha.prototype.growl = function(){ this.options.growl = true; return this; }; /** * Ignore `globals` array or string. * * @param {Array|String} globals * @return {Mocha} * @api public */ Mocha.prototype.globals = function(globals){ this.options.globals = (this.options.globals || []).concat(globals); return this; }; /** * Emit color output. * * @param {Boolean} colors * @return {Mocha} * @api public */ Mocha.prototype.useColors = function(colors){ this.options.useColors = arguments.length && colors != undefined ? colors : true; return this; }; /** * Use inline diffs rather than +/-. * * @param {Boolean} inlineDiffs * @return {Mocha} * @api public */ Mocha.prototype.useInlineDiffs = function(inlineDiffs) { this.options.useInlineDiffs = arguments.length && inlineDiffs != undefined ? inlineDiffs : false; return this; }; /** * Set the timeout in milliseconds. * * @param {Number} timeout * @return {Mocha} * @api public */ Mocha.prototype.timeout = function(timeout){ this.suite.timeout(timeout); return this; }; /** * Set slowness threshold in milliseconds. * * @param {Number} slow * @return {Mocha} * @api public */ Mocha.prototype.slow = function(slow){ this.suite.slow(slow); return this; }; /** * Makes all tests async (accepting a callback) * * @return {Mocha} * @api public */ Mocha.prototype.asyncOnly = function(){ this.options.asyncOnly = true; return this; }; /** * Run tests and invoke `fn()` when complete. * * @param {Function} fn * @return {Runner} * @api public */ Mocha.prototype.run = function(fn){ if (this.files.length) this.loadFiles(); var suite = this.suite; var options = this.options; options.files = this.files; var runner = new exports.Runner(suite); var reporter = new this._reporter(runner, options); runner.ignoreLeaks = false !== options.ignoreLeaks; runner.asyncOnly = options.asyncOnly; if (options.grep) runner.grep(options.grep, options.invert); if (options.globals) runner.globals(options.globals); if (options.growl) this._growl(runner, reporter); exports.reporters.Base.useColors = options.useColors; exports.reporters.Base.inlineDiffs = options.useInlineDiffs; return runner.run(fn); }; mocha-1.20.1/lib/ms.js000066400000000000000000000037711234352070300144140ustar00rootroot00000000000000/** * Helpers. */ var s = 1000; var m = s * 60; var h = m * 60; var d = h * 24; var y = d * 365.25; /** * Parse or format the given `val`. * * Options: * * - `long` verbose formatting [false] * * @param {String|Number} val * @param {Object} options * @return {String|Number} * @api public */ module.exports = function(val, options){ options = options || {}; if ('string' == typeof val) return parse(val); return options.long ? longFormat(val) : shortFormat(val); }; /** * Parse the given `str` and return milliseconds. * * @param {String} str * @return {Number} * @api private */ function parse(str) { var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str); if (!match) return; var n = parseFloat(match[1]); var type = (match[2] || 'ms').toLowerCase(); switch (type) { case 'years': case 'year': case 'y': return n * y; case 'days': case 'day': case 'd': return n * d; case 'hours': case 'hour': case 'h': return n * h; case 'minutes': case 'minute': case 'm': return n * m; case 'seconds': case 'second': case 's': return n * s; case 'ms': return n; } } /** * Short format for `ms`. * * @param {Number} ms * @return {String} * @api private */ function shortFormat(ms) { if (ms >= d) return Math.round(ms / d) + 'd'; if (ms >= h) return Math.round(ms / h) + 'h'; if (ms >= m) return Math.round(ms / m) + 'm'; if (ms >= s) return Math.round(ms / s) + 's'; return ms + 'ms'; } /** * Long format for `ms`. * * @param {Number} ms * @return {String} * @api private */ function longFormat(ms) { return plural(ms, d, 'day') || plural(ms, h, 'hour') || plural(ms, m, 'minute') || plural(ms, s, 'second') || ms + ' ms'; } /** * Pluralization helper. */ function plural(ms, n, name) { if (ms < n) return; if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name; return Math.ceil(ms / n) + ' ' + name + 's'; } mocha-1.20.1/lib/reporters/000077500000000000000000000000001234352070300154545ustar00rootroot00000000000000mocha-1.20.1/lib/reporters/base.js000066400000000000000000000245531234352070300167350ustar00rootroot00000000000000 /** * Module dependencies. */ var tty = require('tty') , diff = require('diff') , ms = require('../ms') , utils = require('../utils'); /** * Save timer references to avoid Sinon interfering (see GH-237). */ var Date = global.Date , setTimeout = global.setTimeout , setInterval = global.setInterval , clearTimeout = global.clearTimeout , clearInterval = global.clearInterval; /** * Check if both stdio streams are associated with a tty. */ var isatty = tty.isatty(1) && tty.isatty(2); /** * Expose `Base`. */ exports = module.exports = Base; /** * Enable coloring by default. */ exports.useColors = isatty || (process.env.MOCHA_COLORS !== undefined); /** * Inline diffs instead of +/- */ exports.inlineDiffs = false; /** * Default color map. */ exports.colors = { 'pass': 90 , 'fail': 31 , 'bright pass': 92 , 'bright fail': 91 , 'bright yellow': 93 , 'pending': 36 , 'suite': 0 , 'error title': 0 , 'error message': 31 , 'error stack': 90 , 'checkmark': 32 , 'fast': 90 , 'medium': 33 , 'slow': 31 , 'green': 32 , 'light': 90 , 'diff gutter': 90 , 'diff added': 42 , 'diff removed': 41 }; /** * Default symbol map. */ exports.symbols = { ok: '✓', err: '✖', dot: '․' }; // With node.js on Windows: use symbols available in terminal default fonts if ('win32' == process.platform) { exports.symbols.ok = '\u221A'; exports.symbols.err = '\u00D7'; exports.symbols.dot = '.'; } /** * Color `str` with the given `type`, * allowing colors to be disabled, * as well as user-defined color * schemes. * * @param {String} type * @param {String} str * @return {String} * @api private */ var color = exports.color = function(type, str) { if (!exports.useColors) return str; return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m'; }; /** * Expose term window size, with some * defaults for when stderr is not a tty. */ exports.window = { width: isatty ? process.stdout.getWindowSize ? process.stdout.getWindowSize(1)[0] : tty.getWindowSize()[1] : 75 }; /** * Expose some basic cursor interactions * that are common among reporters. */ exports.cursor = { hide: function(){ isatty && process.stdout.write('\u001b[?25l'); }, show: function(){ isatty && process.stdout.write('\u001b[?25h'); }, deleteLine: function(){ isatty && process.stdout.write('\u001b[2K'); }, beginningOfLine: function(){ isatty && process.stdout.write('\u001b[0G'); }, CR: function(){ if (isatty) { exports.cursor.deleteLine(); exports.cursor.beginningOfLine(); } else { process.stdout.write('\r'); } } }; /** * Outut the given `failures` as a list. * * @param {Array} failures * @api public */ exports.list = function(failures){ console.error(); failures.forEach(function(test, i){ // format var fmt = color('error title', ' %s) %s:\n') + color('error message', ' %s') + color('error stack', '\n%s\n'); // msg var err = test.err , message = err.message || '' , stack = err.stack || message , index = stack.indexOf(message) + message.length , msg = stack.slice(0, index) , actual = err.actual , expected = err.expected , escape = true; // uncaught if (err.uncaught) { msg = 'Uncaught ' + msg; } // explicitly show diff if (err.showDiff && sameType(actual, expected)) { escape = false; err.actual = actual = stringify(canonicalize(actual)); err.expected = expected = stringify(canonicalize(expected)); } // actual / expected diff if ('string' == typeof actual && 'string' == typeof expected) { fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n'); var match = message.match(/^([^:]+): expected/); msg = '\n ' + color('error message', match ? match[1] : msg); if (exports.inlineDiffs) { msg += inlineDiff(err, escape); } else { msg += unifiedDiff(err, escape); } } // indent stack trace without msg stack = stack.slice(index ? index + 1 : index) .replace(/^/gm, ' '); console.error(fmt, (i + 1), test.fullTitle(), msg, stack); }); }; /** * Initialize a new `Base` reporter. * * All other reporters generally * inherit from this reporter, providing * stats such as test duration, number * of tests passed / failed etc. * * @param {Runner} runner * @api public */ function Base(runner) { var self = this , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 } , failures = this.failures = []; if (!runner) return; this.runner = runner; runner.stats = stats; runner.on('start', function(){ stats.start = new Date; }); runner.on('suite', function(suite){ stats.suites = stats.suites || 0; suite.root || stats.suites++; }); runner.on('test end', function(test){ stats.tests = stats.tests || 0; stats.tests++; }); runner.on('pass', function(test){ stats.passes = stats.passes || 0; var medium = test.slow() / 2; test.speed = test.duration > test.slow() ? 'slow' : test.duration > medium ? 'medium' : 'fast'; stats.passes++; }); runner.on('fail', function(test, err){ stats.failures = stats.failures || 0; stats.failures++; test.err = err; failures.push(test); }); runner.on('end', function(){ stats.end = new Date; stats.duration = new Date - stats.start; }); runner.on('pending', function(){ stats.pending++; }); } /** * Output common epilogue used by many of * the bundled reporters. * * @api public */ Base.prototype.epilogue = function(){ var stats = this.stats; var tests; var fmt; console.log(); // passes fmt = color('bright pass', ' ') + color('green', ' %d passing') + color('light', ' (%s)'); console.log(fmt, stats.passes || 0, ms(stats.duration)); // pending if (stats.pending) { fmt = color('pending', ' ') + color('pending', ' %d pending'); console.log(fmt, stats.pending); } // failures if (stats.failures) { fmt = color('fail', ' %d failing'); console.error(fmt, stats.failures); Base.list(this.failures); console.error(); } console.log(); }; /** * Pad the given `str` to `len`. * * @param {String} str * @param {String} len * @return {String} * @api private */ function pad(str, len) { str = String(str); return Array(len - str.length + 1).join(' ') + str; } /** * Returns an inline diff between 2 strings with coloured ANSI output * * @param {Error} Error with actual/expected * @return {String} Diff * @api private */ function inlineDiff(err, escape) { var msg = errorDiff(err, 'WordsWithSpace', escape); // linenos var lines = msg.split('\n'); if (lines.length > 4) { var width = String(lines.length).length; msg = lines.map(function(str, i){ return pad(++i, width) + ' |' + ' ' + str; }).join('\n'); } // legend msg = '\n' + color('diff removed', 'actual') + ' ' + color('diff added', 'expected') + '\n\n' + msg + '\n'; // indent msg = msg.replace(/^/gm, ' '); return msg; } /** * Returns a unified diff between 2 strings * * @param {Error} Error with actual/expected * @return {String} Diff * @api private */ function unifiedDiff(err, escape) { var indent = ' '; function cleanUp(line) { if (escape) { line = escapeInvisibles(line); } if (line[0] === '+') return indent + colorLines('diff added', line); if (line[0] === '-') return indent + colorLines('diff removed', line); if (line.match(/\@\@/)) return null; if (line.match(/\\ No newline/)) return null; else return indent + line; } function notBlank(line) { return line != null; } msg = diff.createPatch('string', err.actual, err.expected); var lines = msg.split('\n').splice(4); return '\n ' + colorLines('diff added', '+ expected') + ' ' + colorLines('diff removed', '- actual') + '\n\n' + lines.map(cleanUp).filter(notBlank).join('\n'); } /** * Return a character diff for `err`. * * @param {Error} err * @return {String} * @api private */ function errorDiff(err, type, escape) { var actual = escape ? escapeInvisibles(err.actual) : err.actual; var expected = escape ? escapeInvisibles(err.expected) : err.expected; return diff['diff' + type](actual, expected).map(function(str){ if (str.added) return colorLines('diff added', str.value); if (str.removed) return colorLines('diff removed', str.value); return str.value; }).join(''); } /** * Returns a string with all invisible characters in plain text * * @param {String} line * @return {String} * @api private */ function escapeInvisibles(line) { return line.replace(/\t/g, '') .replace(/\r/g, '') .replace(/\n/g, '\n'); } /** * Color lines for `str`, using the color `name`. * * @param {String} name * @param {String} str * @return {String} * @api private */ function colorLines(name, str) { return str.split('\n').map(function(str){ return color(name, str); }).join('\n'); } /** * Stringify `obj`. * * @param {Object} obj * @return {String} * @api private */ function stringify(obj) { if (obj instanceof RegExp) return obj.toString(); return JSON.stringify(obj, null, 2); } /** * Return a new object that has the keys in sorted order. * @param {Object} obj * @return {Object} * @api private */ function canonicalize(obj, stack) { stack = stack || []; if (utils.indexOf(stack, obj) !== -1) return obj; var canonicalizedObj; if ('[object Array]' == {}.toString.call(obj)) { stack.push(obj); canonicalizedObj = utils.map(obj, function(item) { return canonicalize(item, stack); }); stack.pop(); } else if (typeof obj === 'object' && obj !== null) { stack.push(obj); canonicalizedObj = {}; utils.forEach(utils.keys(obj).sort(), function(key) { canonicalizedObj[key] = canonicalize(obj[key], stack); }); stack.pop(); } else { canonicalizedObj = obj; } return canonicalizedObj; } /** * Check that a / b have the same type. * * @param {Object} a * @param {Object} b * @return {Boolean} * @api private */ function sameType(a, b) { a = Object.prototype.toString.call(a); b = Object.prototype.toString.call(b); return a == b; } mocha-1.20.1/lib/reporters/doc.js000066400000000000000000000022101234352070300165520ustar00rootroot00000000000000 /** * Module dependencies. */ var Base = require('./base') , utils = require('../utils'); /** * Expose `Doc`. */ exports = module.exports = Doc; /** * Initialize a new `Doc` reporter. * * @param {Runner} runner * @api public */ function Doc(runner) { Base.call(this, runner); var self = this , stats = this.stats , total = runner.total , indents = 2; function indent() { return Array(indents).join(' '); } runner.on('suite', function(suite){ if (suite.root) return; ++indents; console.log('%s
', indent()); ++indents; console.log('%s

%s

', indent(), utils.escape(suite.title)); console.log('%s
', indent()); }); runner.on('suite end', function(suite){ if (suite.root) return; console.log('%s
', indent()); --indents; console.log('%s
', indent()); --indents; }); runner.on('pass', function(test){ console.log('%s
%s
', indent(), utils.escape(test.title)); var code = utils.escape(utils.clean(test.fn.toString())); console.log('%s
%s
', indent(), code); }); } mocha-1.20.1/lib/reporters/dot.js000066400000000000000000000022501234352070300165770ustar00rootroot00000000000000 /** * Module dependencies. */ var Base = require('./base') , color = Base.color; /** * Expose `Dot`. */ exports = module.exports = Dot; /** * Initialize a new `Dot` matrix test reporter. * * @param {Runner} runner * @api public */ function Dot(runner) { Base.call(this, runner); var self = this , stats = this.stats , width = Base.window.width * .75 | 0 , n = 0; runner.on('start', function(){ process.stdout.write('\n '); }); runner.on('pending', function(test){ process.stdout.write(color('pending', Base.symbols.dot)); }); runner.on('pass', function(test){ if (++n % width == 0) process.stdout.write('\n '); if ('slow' == test.speed) { process.stdout.write(color('bright yellow', Base.symbols.dot)); } else { process.stdout.write(color(test.speed, Base.symbols.dot)); } }); runner.on('fail', function(test, err){ if (++n % width == 0) process.stdout.write('\n '); process.stdout.write(color('fail', Base.symbols.dot)); }); runner.on('end', function(){ console.log(); self.epilogue(); }); } /** * Inherit from `Base.prototype`. */ Dot.prototype.__proto__ = Base.prototype;mocha-1.20.1/lib/reporters/html-cov.js000066400000000000000000000015541234352070300175500ustar00rootroot00000000000000 /** * Module dependencies. */ var JSONCov = require('./json-cov') , fs = require('fs'); /** * Expose `HTMLCov`. */ exports = module.exports = HTMLCov; /** * Initialize a new `JsCoverage` reporter. * * @param {Runner} runner * @api public */ function HTMLCov(runner) { var jade = require('jade') , file = __dirname + '/templates/coverage.jade' , str = fs.readFileSync(file, 'utf8') , fn = jade.compile(str, { filename: file }) , self = this; JSONCov.call(this, runner, false); runner.on('end', function(){ process.stdout.write(fn({ cov: self.cov , coverageClass: coverageClass })); }); } /** * Return coverage class for `n`. * * @return {String} * @api private */ function coverageClass(n) { if (n >= 75) return 'high'; if (n >= 50) return 'medium'; if (n >= 25) return 'low'; return 'terrible'; }mocha-1.20.1/lib/reporters/html.js000066400000000000000000000157311234352070300167650ustar00rootroot00000000000000 /** * Module dependencies. */ var Base = require('./base') , utils = require('../utils') , Progress = require('../browser/progress') , escape = utils.escape; /** * Save timer references to avoid Sinon interfering (see GH-237). */ var Date = global.Date , setTimeout = global.setTimeout , setInterval = global.setInterval , clearTimeout = global.clearTimeout , clearInterval = global.clearInterval; /** * Expose `HTML`. */ exports = module.exports = HTML; /** * Stats template. */ var statsTemplate = ''; /** * Initialize a new `HTML` reporter. * * @param {Runner} runner * @api public */ function HTML(runner) { Base.call(this, runner); var self = this , stats = this.stats , total = runner.total , stat = fragment(statsTemplate) , items = stat.getElementsByTagName('li') , passes = items[1].getElementsByTagName('em')[0] , passesLink = items[1].getElementsByTagName('a')[0] , failures = items[2].getElementsByTagName('em')[0] , failuresLink = items[2].getElementsByTagName('a')[0] , duration = items[3].getElementsByTagName('em')[0] , canvas = stat.getElementsByTagName('canvas')[0] , report = fragment('
    ') , stack = [report] , progress , ctx , root = document.getElementById('mocha'); if (canvas.getContext) { var ratio = window.devicePixelRatio || 1; canvas.style.width = canvas.width; canvas.style.height = canvas.height; canvas.width *= ratio; canvas.height *= ratio; ctx = canvas.getContext('2d'); ctx.scale(ratio, ratio); progress = new Progress; } if (!root) return error('#mocha div missing, add it to your document'); // pass toggle on(passesLink, 'click', function(){ unhide(); var name = /pass/.test(report.className) ? '' : ' pass'; report.className = report.className.replace(/fail|pass/g, '') + name; if (report.className.trim()) hideSuitesWithout('test pass'); }); // failure toggle on(failuresLink, 'click', function(){ unhide(); var name = /fail/.test(report.className) ? '' : ' fail'; report.className = report.className.replace(/fail|pass/g, '') + name; if (report.className.trim()) hideSuitesWithout('test fail'); }); root.appendChild(stat); root.appendChild(report); if (progress) progress.size(40); runner.on('suite', function(suite){ if (suite.root) return; // suite var url = self.suiteURL(suite); var el = fragment('
  • %s

  • ', url, escape(suite.title)); // container stack[0].appendChild(el); stack.unshift(document.createElement('ul')); el.appendChild(stack[0]); }); runner.on('suite end', function(suite){ if (suite.root) return; stack.shift(); }); runner.on('fail', function(test, err){ if ('hook' == test.type) runner.emit('test end', test); }); runner.on('test end', function(test){ // TODO: add to stats var percent = stats.tests / this.total * 100 | 0; if (progress) progress.update(percent).draw(ctx); // update stats var ms = new Date - stats.start; text(passes, stats.passes); text(failures, stats.failures); text(duration, (ms / 1000).toFixed(2)); // test if ('passed' == test.state) { var url = self.testURL(test); var el = fragment('
  • %e%ems

  • ', test.speed, test.title, test.duration, url); } else if (test.pending) { var el = fragment('
  • %e

  • ', test.title); } else { var el = fragment('
  • %e

  • ', test.title, encodeURIComponent(test.fullTitle())); var str = test.err.stack || test.err.toString(); // FF / Opera do not add the message if (!~str.indexOf(test.err.message)) { str = test.err.message + '\n' + str; } // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we // check for the result of the stringifying. if ('[object Error]' == str) str = test.err.message; // Safari doesn't give you a stack. Let's at least provide a source line. if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) { str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")"; } el.appendChild(fragment('
    %e
    ', str)); } // toggle code // TODO: defer if (!test.pending) { var h2 = el.getElementsByTagName('h2')[0]; on(h2, 'click', function(){ pre.style.display = 'none' == pre.style.display ? 'block' : 'none'; }); var pre = fragment('
    %e
    ', utils.clean(test.fn.toString())); el.appendChild(pre); pre.style.display = 'none'; } // Don't call .appendChild if #mocha-report was already .shift()'ed off the stack. if (stack[0]) stack[0].appendChild(el); }); } /** * Provide suite URL * * @param {Object} [suite] */ HTML.prototype.suiteURL = function(suite){ return '?grep=' + encodeURIComponent(suite.fullTitle()); }; /** * Provide test URL * * @param {Object} [test] */ HTML.prototype.testURL = function(test){ return '?grep=' + encodeURIComponent(test.fullTitle()); }; /** * Display error `msg`. */ function error(msg) { document.body.appendChild(fragment('
    %s
    ', msg)); } /** * Return a DOM fragment from `html`. */ function fragment(html) { var args = arguments , div = document.createElement('div') , i = 1; div.innerHTML = html.replace(/%([se])/g, function(_, type){ switch (type) { case 's': return String(args[i++]); case 'e': return escape(args[i++]); } }); return div.firstChild; } /** * Check for suites that do not have elements * with `classname`, and hide them. */ function hideSuitesWithout(classname) { var suites = document.getElementsByClassName('suite'); for (var i = 0; i < suites.length; i++) { var els = suites[i].getElementsByClassName(classname); if (0 == els.length) suites[i].className += ' hidden'; } } /** * Unhide .hidden suites. */ function unhide() { var els = document.getElementsByClassName('suite hidden'); for (var i = 0; i < els.length; ++i) { els[i].className = els[i].className.replace('suite hidden', 'suite'); } } /** * Set `el` text to `str`. */ function text(el, str) { if (el.textContent) { el.textContent = str; } else { el.innerText = str; } } /** * Listen on `event` with callback `fn`. */ function on(el, event, fn) { if (el.addEventListener) { el.addEventListener(event, fn, false); } else { el.attachEvent('on' + event, fn); } } mocha-1.20.1/lib/reporters/index.js000066400000000000000000000011561234352070300171240ustar00rootroot00000000000000 exports.Base = require('./base'); exports.Dot = require('./dot'); exports.Doc = require('./doc'); exports.TAP = require('./tap'); exports.JSON = require('./json'); exports.HTML = require('./html'); exports.List = require('./list'); exports.Min = require('./min'); exports.Spec = require('./spec'); exports.Nyan = require('./nyan'); exports.XUnit = require('./xunit'); exports.Markdown = require('./markdown'); exports.Progress = require('./progress'); exports.Landing = require('./landing'); exports.JSONCov = require('./json-cov'); exports.HTMLCov = require('./html-cov'); exports.JSONStream = require('./json-stream'); mocha-1.20.1/lib/reporters/json-cov.js000066400000000000000000000053161234352070300175550ustar00rootroot00000000000000 /** * Module dependencies. */ var Base = require('./base'); /** * Expose `JSONCov`. */ exports = module.exports = JSONCov; /** * Initialize a new `JsCoverage` reporter. * * @param {Runner} runner * @param {Boolean} output * @api public */ function JSONCov(runner, output) { var self = this , output = 1 == arguments.length ? true : output; Base.call(this, runner); var tests = [] , failures = [] , passes = []; runner.on('test end', function(test){ tests.push(test); }); runner.on('pass', function(test){ passes.push(test); }); runner.on('fail', function(test){ failures.push(test); }); runner.on('end', function(){ var cov = global._$jscoverage || {}; var result = self.cov = map(cov); result.stats = self.stats; result.tests = tests.map(clean); result.failures = failures.map(clean); result.passes = passes.map(clean); if (!output) return; process.stdout.write(JSON.stringify(result, null, 2 )); }); } /** * Map jscoverage data to a JSON structure * suitable for reporting. * * @param {Object} cov * @return {Object} * @api private */ function map(cov) { var ret = { instrumentation: 'node-jscoverage' , sloc: 0 , hits: 0 , misses: 0 , coverage: 0 , files: [] }; for (var filename in cov) { var data = coverage(filename, cov[filename]); ret.files.push(data); ret.hits += data.hits; ret.misses += data.misses; ret.sloc += data.sloc; } ret.files.sort(function(a, b) { return a.filename.localeCompare(b.filename); }); if (ret.sloc > 0) { ret.coverage = (ret.hits / ret.sloc) * 100; } return ret; }; /** * Map jscoverage data for a single source file * to a JSON structure suitable for reporting. * * @param {String} filename name of the source file * @param {Object} data jscoverage coverage data * @return {Object} * @api private */ function coverage(filename, data) { var ret = { filename: filename, coverage: 0, hits: 0, misses: 0, sloc: 0, source: {} }; data.source.forEach(function(line, num){ num++; if (data[num] === 0) { ret.misses++; ret.sloc++; } else if (data[num] !== undefined) { ret.hits++; ret.sloc++; } ret.source[num] = { source: line , coverage: data[num] === undefined ? '' : data[num] }; }); ret.coverage = ret.hits / ret.sloc * 100; return ret; } /** * Return a plain-object representation of `test` * free of cyclic properties etc. * * @param {Object} test * @return {Object} * @api private */ function clean(test) { return { title: test.title , fullTitle: test.fullTitle() , duration: test.duration } } mocha-1.20.1/lib/reporters/json-stream.js000066400000000000000000000020431234352070300202530ustar00rootroot00000000000000 /** * Module dependencies. */ var Base = require('./base') , color = Base.color; /** * Expose `List`. */ exports = module.exports = List; /** * Initialize a new `List` test reporter. * * @param {Runner} runner * @api public */ function List(runner) { Base.call(this, runner); var self = this , stats = this.stats , total = runner.total; runner.on('start', function(){ console.log(JSON.stringify(['start', { total: total }])); }); runner.on('pass', function(test){ console.log(JSON.stringify(['pass', clean(test)])); }); runner.on('fail', function(test, err){ console.log(JSON.stringify(['fail', clean(test)])); }); runner.on('end', function(){ process.stdout.write(JSON.stringify(['end', self.stats])); }); } /** * Return a plain-object representation of `test` * free of cyclic properties etc. * * @param {Object} test * @return {Object} * @api private */ function clean(test) { return { title: test.title , fullTitle: test.fullTitle() , duration: test.duration } }mocha-1.20.1/lib/reporters/json.js000066400000000000000000000022031234352070300167600ustar00rootroot00000000000000 /** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `JSON`. */ exports = module.exports = JSONReporter; /** * Initialize a new `JSON` reporter. * * @param {Runner} runner * @api public */ function JSONReporter(runner) { var self = this; Base.call(this, runner); var tests = [] , failures = [] , passes = []; runner.on('test end', function(test){ tests.push(test); }); runner.on('pass', function(test){ passes.push(test); }); runner.on('fail', function(test){ failures.push(test); }); runner.on('end', function(){ var obj = { stats: self.stats, tests: tests.map(clean), failures: failures.map(clean), passes: passes.map(clean) }; process.stdout.write(JSON.stringify(obj, null, 2)); }); } /** * Return a plain-object representation of `test` * free of cyclic properties etc. * * @param {Object} test * @return {Object} * @api private */ function clean(test) { return { title: test.title, fullTitle: test.fullTitle(), duration: test.duration, err: test.err } } mocha-1.20.1/lib/reporters/landing.js000066400000000000000000000032531234352070300174310ustar00rootroot00000000000000 /** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `Landing`. */ exports = module.exports = Landing; /** * Airplane color. */ Base.colors.plane = 0; /** * Airplane crash color. */ Base.colors['plane crash'] = 31; /** * Runway color. */ Base.colors.runway = 90; /** * Initialize a new `Landing` reporter. * * @param {Runner} runner * @api public */ function Landing(runner) { Base.call(this, runner); var self = this , stats = this.stats , width = Base.window.width * .75 | 0 , total = runner.total , stream = process.stdout , plane = color('plane', '✈') , crashed = -1 , n = 0; function runway() { var buf = Array(width).join('-'); return ' ' + color('runway', buf); } runner.on('start', function(){ stream.write('\n '); cursor.hide(); }); runner.on('test end', function(test){ // check if the plane crashed var col = -1 == crashed ? width * ++n / total | 0 : crashed; // show the crash if ('failed' == test.state) { plane = color('plane crash', '✈'); crashed = col; } // render landing strip stream.write('\u001b[4F\n\n'); stream.write(runway()); stream.write('\n '); stream.write(color('runway', Array(col).join('⋅'))); stream.write(plane) stream.write(color('runway', Array(width - col).join('⋅') + '\n')); stream.write(runway()); stream.write('\u001b[0m'); }); runner.on('end', function(){ cursor.show(); console.log(); self.epilogue(); }); } /** * Inherit from `Base.prototype`. */ Landing.prototype.__proto__ = Base.prototype;mocha-1.20.1/lib/reporters/list.js000066400000000000000000000023021234352070300167620ustar00rootroot00000000000000 /** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `List`. */ exports = module.exports = List; /** * Initialize a new `List` test reporter. * * @param {Runner} runner * @api public */ function List(runner) { Base.call(this, runner); var self = this , stats = this.stats , n = 0; runner.on('start', function(){ console.log(); }); runner.on('test', function(test){ process.stdout.write(color('pass', ' ' + test.fullTitle() + ': ')); }); runner.on('pending', function(test){ var fmt = color('checkmark', ' -') + color('pending', ' %s'); console.log(fmt, test.fullTitle()); }); runner.on('pass', function(test){ var fmt = color('checkmark', ' '+Base.symbols.dot) + color('pass', ' %s: ') + color(test.speed, '%dms'); cursor.CR(); console.log(fmt, test.fullTitle(), test.duration); }); runner.on('fail', function(test, err){ cursor.CR(); console.log(color('fail', ' %d) %s'), ++n, test.fullTitle()); }); runner.on('end', self.epilogue.bind(self)); } /** * Inherit from `Base.prototype`. */ List.prototype.__proto__ = Base.prototype; mocha-1.20.1/lib/reporters/markdown.js000066400000000000000000000035031234352070300176350ustar00rootroot00000000000000/** * Module dependencies. */ var Base = require('./base') , utils = require('../utils'); /** * Expose `Markdown`. */ exports = module.exports = Markdown; /** * Initialize a new `Markdown` reporter. * * @param {Runner} runner * @api public */ function Markdown(runner) { Base.call(this, runner); var self = this , stats = this.stats , level = 0 , buf = ''; function title(str) { return Array(level).join('#') + ' ' + str; } function indent() { return Array(level).join(' '); } function mapTOC(suite, obj) { var ret = obj; obj = obj[suite.title] = obj[suite.title] || { suite: suite }; suite.suites.forEach(function(suite){ mapTOC(suite, obj); }); return ret; } function stringifyTOC(obj, level) { ++level; var buf = ''; var link; for (var key in obj) { if ('suite' == key) continue; if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n'; if (key) buf += Array(level).join(' ') + link; buf += stringifyTOC(obj[key], level); } --level; return buf; } function generateTOC(suite) { var obj = mapTOC(suite, {}); return stringifyTOC(obj, 0); } generateTOC(runner.suite); runner.on('suite', function(suite){ ++level; var slug = utils.slug(suite.fullTitle()); buf += '' + '\n'; buf += title(suite.title) + '\n'; }); runner.on('suite end', function(suite){ --level; }); runner.on('pass', function(test){ var code = utils.clean(test.fn.toString()); buf += test.title + '.\n'; buf += '\n```js\n'; buf += code + '\n'; buf += '```\n\n'; }); runner.on('end', function(){ process.stdout.write('# TOC\n'); process.stdout.write(generateTOC(runner.suite)); process.stdout.write(buf); }); }mocha-1.20.1/lib/reporters/min.js000066400000000000000000000011331234352070300165730ustar00rootroot00000000000000 /** * Module dependencies. */ var Base = require('./base'); /** * Expose `Min`. */ exports = module.exports = Min; /** * Initialize a new `Min` minimal test reporter (best used with --watch). * * @param {Runner} runner * @api public */ function Min(runner) { Base.call(this, runner); runner.on('start', function(){ // clear screen process.stdout.write('\u001b[2J'); // set cursor position process.stdout.write('\u001b[1;3H'); }); runner.on('end', this.epilogue.bind(this)); } /** * Inherit from `Base.prototype`. */ Min.prototype.__proto__ = Base.prototype; mocha-1.20.1/lib/reporters/nyan.js000066400000000000000000000115411234352070300167610ustar00rootroot00000000000000/** * Module dependencies. */ var Base = require('./base') , color = Base.color; /** * Expose `Dot`. */ exports = module.exports = NyanCat; /** * Initialize a new `Dot` matrix test reporter. * * @param {Runner} runner * @api public */ function NyanCat(runner) { Base.call(this, runner); var self = this , stats = this.stats , width = Base.window.width * .75 | 0 , rainbowColors = this.rainbowColors = self.generateColors() , colorIndex = this.colorIndex = 0 , numerOfLines = this.numberOfLines = 4 , trajectories = this.trajectories = [[], [], [], []] , nyanCatWidth = this.nyanCatWidth = 11 , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth) , scoreboardWidth = this.scoreboardWidth = 5 , tick = this.tick = 0 , n = 0; runner.on('start', function(){ Base.cursor.hide(); self.draw(); }); runner.on('pending', function(test){ self.draw(); }); runner.on('pass', function(test){ self.draw(); }); runner.on('fail', function(test, err){ self.draw(); }); runner.on('end', function(){ Base.cursor.show(); for (var i = 0; i < self.numberOfLines; i++) write('\n'); self.epilogue(); }); } /** * Draw the nyan cat * * @api private */ NyanCat.prototype.draw = function(){ this.appendRainbow(); this.drawScoreboard(); this.drawRainbow(); this.drawNyanCat(); this.tick = !this.tick; }; /** * Draw the "scoreboard" showing the number * of passes, failures and pending tests. * * @api private */ NyanCat.prototype.drawScoreboard = function(){ var stats = this.stats; var colors = Base.colors; function draw(color, n) { write(' '); write('\u001b[' + color + 'm' + n + '\u001b[0m'); write('\n'); } draw(colors.green, stats.passes); draw(colors.fail, stats.failures); draw(colors.pending, stats.pending); write('\n'); this.cursorUp(this.numberOfLines); }; /** * Append the rainbow. * * @api private */ NyanCat.prototype.appendRainbow = function(){ var segment = this.tick ? '_' : '-'; var rainbowified = this.rainbowify(segment); for (var index = 0; index < this.numberOfLines; index++) { var trajectory = this.trajectories[index]; if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift(); trajectory.push(rainbowified); } }; /** * Draw the rainbow. * * @api private */ NyanCat.prototype.drawRainbow = function(){ var self = this; this.trajectories.forEach(function(line, index) { write('\u001b[' + self.scoreboardWidth + 'C'); write(line.join('')); write('\n'); }); this.cursorUp(this.numberOfLines); }; /** * Draw the nyan cat * * @api private */ NyanCat.prototype.drawNyanCat = function() { var self = this; var startWidth = this.scoreboardWidth + this.trajectories[0].length; var color = '\u001b[' + startWidth + 'C'; var padding = ''; write(color); write('_,------,'); write('\n'); write(color); padding = self.tick ? ' ' : ' '; write('_|' + padding + '/\\_/\\ '); write('\n'); write(color); padding = self.tick ? '_' : '__'; var tail = self.tick ? '~' : '^'; var face; write(tail + '|' + padding + this.face() + ' '); write('\n'); write(color); padding = self.tick ? ' ' : ' '; write(padding + '"" "" '); write('\n'); this.cursorUp(this.numberOfLines); }; /** * Draw nyan cat face. * * @return {String} * @api private */ NyanCat.prototype.face = function() { var stats = this.stats; if (stats.failures) { return '( x .x)'; } else if (stats.pending) { return '( o .o)'; } else if(stats.passes) { return '( ^ .^)'; } else { return '( - .-)'; } } /** * Move cursor up `n`. * * @param {Number} n * @api private */ NyanCat.prototype.cursorUp = function(n) { write('\u001b[' + n + 'A'); }; /** * Move cursor down `n`. * * @param {Number} n * @api private */ NyanCat.prototype.cursorDown = function(n) { write('\u001b[' + n + 'B'); }; /** * Generate rainbow colors. * * @return {Array} * @api private */ NyanCat.prototype.generateColors = function(){ var colors = []; for (var i = 0; i < (6 * 7); i++) { var pi3 = Math.floor(Math.PI / 3); var n = (i * (1.0 / 6)); var r = Math.floor(3 * Math.sin(n) + 3); var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3); var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3); colors.push(36 * r + 6 * g + b + 16); } return colors; }; /** * Apply rainbow to the given `str`. * * @param {String} str * @return {String} * @api private */ NyanCat.prototype.rainbowify = function(str){ var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length]; this.colorIndex += 1; return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m'; }; /** * Stdout helper. */ function write(string) { process.stdout.write(string); } /** * Inherit from `Base.prototype`. */ NyanCat.prototype.__proto__ = Base.prototype; mocha-1.20.1/lib/reporters/progress.js000066400000000000000000000034651234352070300176660ustar00rootroot00000000000000 /** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `Progress`. */ exports = module.exports = Progress; /** * General progress bar color. */ Base.colors.progress = 90; /** * Initialize a new `Progress` bar test reporter. * * @param {Runner} runner * @param {Object} options * @api public */ function Progress(runner, options) { Base.call(this, runner); var self = this , options = options || {} , stats = this.stats , width = Base.window.width * .50 | 0 , total = runner.total , complete = 0 , max = Math.max; // default chars options.open = options.open || '['; options.complete = options.complete || '▬'; options.incomplete = options.incomplete || Base.symbols.dot; options.close = options.close || ']'; options.verbose = false; // tests started runner.on('start', function(){ console.log(); cursor.hide(); }); // tests complete runner.on('test end', function(){ complete++; var incomplete = total - complete , percent = complete / total , n = width * percent | 0 , i = width - n; cursor.CR(); process.stdout.write('\u001b[J'); process.stdout.write(color('progress', ' ' + options.open)); process.stdout.write(Array(n).join(options.complete)); process.stdout.write(Array(i).join(options.incomplete)); process.stdout.write(color('progress', options.close)); if (options.verbose) { process.stdout.write(color('progress', ' ' + complete + ' of ' + total)); } }); // tests are complete, output some stats // and the failures if any runner.on('end', function(){ cursor.show(); console.log(); self.epilogue(); }); } /** * Inherit from `Base.prototype`. */ Progress.prototype.__proto__ = Base.prototype; mocha-1.20.1/lib/reporters/spec.js000066400000000000000000000031341234352070300167450ustar00rootroot00000000000000 /** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `Spec`. */ exports = module.exports = Spec; /** * Initialize a new `Spec` test reporter. * * @param {Runner} runner * @api public */ function Spec(runner) { Base.call(this, runner); var self = this , stats = this.stats , indents = 0 , n = 0; function indent() { return Array(indents).join(' ') } runner.on('start', function(){ console.log(); }); runner.on('suite', function(suite){ ++indents; console.log(color('suite', '%s%s'), indent(), suite.title); }); runner.on('suite end', function(suite){ --indents; if (1 == indents) console.log(); }); runner.on('pending', function(test){ var fmt = indent() + color('pending', ' - %s'); console.log(fmt, test.title); }); runner.on('pass', function(test){ if ('fast' == test.speed) { var fmt = indent() + color('checkmark', ' ' + Base.symbols.ok) + color('pass', ' %s '); cursor.CR(); console.log(fmt, test.title); } else { var fmt = indent() + color('checkmark', ' ' + Base.symbols.ok) + color('pass', ' %s ') + color(test.speed, '(%dms)'); cursor.CR(); console.log(fmt, test.title, test.duration); } }); runner.on('fail', function(test, err){ cursor.CR(); console.log(indent() + color('fail', ' %d) %s'), ++n, test.title); }); runner.on('end', self.epilogue.bind(self)); } /** * Inherit from `Base.prototype`. */ Spec.prototype.__proto__ = Base.prototype; mocha-1.20.1/lib/reporters/tap.js000066400000000000000000000024331234352070300166000ustar00rootroot00000000000000 /** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `TAP`. */ exports = module.exports = TAP; /** * Initialize a new `TAP` reporter. * * @param {Runner} runner * @api public */ function TAP(runner) { Base.call(this, runner); var self = this , stats = this.stats , n = 1 , passes = 0 , failures = 0; runner.on('start', function(){ var total = runner.grepTotal(runner.suite); console.log('%d..%d', 1, total); }); runner.on('test end', function(){ ++n; }); runner.on('pending', function(test){ console.log('ok %d %s # SKIP -', n, title(test)); }); runner.on('pass', function(test){ passes++; console.log('ok %d %s', n, title(test)); }); runner.on('fail', function(test, err){ failures++; console.log('not ok %d %s', n, title(test)); if (err.stack) console.log(err.stack.replace(/^/gm, ' ')); }); runner.on('end', function(){ console.log('# tests ' + (passes + failures)); console.log('# pass ' + passes); console.log('# fail ' + failures); }); } /** * Return a TAP-safe title of `test` * * @param {Object} test * @return {String} * @api private */ function title(test) { return test.fullTitle().replace(/#/g, ''); } mocha-1.20.1/lib/reporters/templates/000077500000000000000000000000001234352070300174525ustar00rootroot00000000000000mocha-1.20.1/lib/reporters/templates/coverage.jade000066400000000000000000000025531234352070300220770ustar00rootroot00000000000000!!! 5 html head title Coverage include script.html include style.html body #coverage h1#overview Coverage include menu #stats(class=coverageClass(cov.coverage)) .percentage #{cov.coverage | 0}% .sloc= cov.sloc .hits= cov.hits .misses= cov.misses #files for file in cov.files .file h2(id=file.filename)= file.filename #stats(class=coverageClass(file.coverage)) .percentage #{file.coverage | 0}% .sloc= file.sloc .hits= file.hits .misses= file.misses table#source thead tr th Line th Hits th Source tbody for line, number in file.source if line.coverage > 0 tr.hit td.line= number td.hits= line.coverage td.source= line.source else if 0 === line.coverage tr.miss td.line= number td.hits 0 td.source= line.source else tr td.line= number td.hits td.source= line.source || ' ' mocha-1.20.1/lib/reporters/templates/menu.jade000066400000000000000000000006461234352070300212510ustar00rootroot00000000000000#menu li a(href='#overview') overview for file in cov.files li span.cov(class=coverageClass(file.coverage)) #{file.coverage | 0} a(href='##{file.filename}') segments = file.filename.split('/') basename = segments.pop() if segments.length span.dirname= segments.join('/') + '/' span.basename= basename a#logo(href='http://visionmedia.github.io/mocha/') m mocha-1.20.1/lib/reporters/templates/script.html000066400000000000000000000011401234352070300216400ustar00rootroot00000000000000 mocha-1.20.1/lib/reporters/templates/style.html000066400000000000000000000411561234352070300215070ustar00rootroot00000000000000mocha-1.20.1/lib/reporters/xunit.js000066400000000000000000000045071234352070300171670ustar00rootroot00000000000000 /** * Module dependencies. */ var Base = require('./base') , utils = require('../utils') , escape = utils.escape; /** * Save timer references to avoid Sinon interfering (see GH-237). */ var Date = global.Date , setTimeout = global.setTimeout , setInterval = global.setInterval , clearTimeout = global.clearTimeout , clearInterval = global.clearInterval; /** * Expose `XUnit`. */ exports = module.exports = XUnit; /** * Initialize a new `XUnit` reporter. * * @param {Runner} runner * @api public */ function XUnit(runner) { Base.call(this, runner); var stats = this.stats , tests = [] , self = this; runner.on('pending', function(test){ tests.push(test); }); runner.on('pass', function(test){ tests.push(test); }); runner.on('fail', function(test){ tests.push(test); }); runner.on('end', function(){ console.log(tag('testsuite', { name: 'Mocha Tests' , tests: stats.tests , failures: stats.failures , errors: stats.failures , skipped: stats.tests - stats.failures - stats.passes , timestamp: (new Date).toUTCString() , time: (stats.duration / 1000) || 0 }, false)); tests.forEach(test); console.log(''); }); } /** * Inherit from `Base.prototype`. */ XUnit.prototype.__proto__ = Base.prototype; /** * Output tag for the given `test.` */ function test(test) { var attrs = { classname: test.parent.fullTitle() , name: test.title , time: (test.duration / 1000) || 0 }; if ('failed' == test.state) { var err = test.err; attrs.message = escape(err.message); console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack)))); } else if (test.pending) { console.log(tag('testcase', attrs, false, tag('skipped', {}, true))); } else { console.log(tag('testcase', attrs, true) ); } } /** * HTML tag helper. */ function tag(name, attrs, close, content) { var end = close ? '/>' : '>' , pairs = [] , tag; for (var key in attrs) { pairs.push(key + '="' + escape(attrs[key]) + '"'); } tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end; if (content) tag += content + ''; } mocha-1.20.1/lib/runnable.js000066400000000000000000000106551234352070300156020ustar00rootroot00000000000000 /** * Module dependencies. */ var EventEmitter = require('events').EventEmitter , debug = require('debug')('mocha:runnable') , milliseconds = require('./ms'); /** * Save timer references to avoid Sinon interfering (see GH-237). */ var Date = global.Date , setTimeout = global.setTimeout , setInterval = global.setInterval , clearTimeout = global.clearTimeout , clearInterval = global.clearInterval; /** * Object#toString(). */ var toString = Object.prototype.toString; /** * Expose `Runnable`. */ module.exports = Runnable; /** * Initialize a new `Runnable` with the given `title` and callback `fn`. * * @param {String} title * @param {Function} fn * @api private */ function Runnable(title, fn) { this.title = title; this.fn = fn; this.async = fn && fn.length; this.sync = ! this.async; this._timeout = 2000; this._slow = 75; this.timedOut = false; } /** * Inherit from `EventEmitter.prototype`. */ Runnable.prototype.__proto__ = EventEmitter.prototype; /** * Set & get timeout `ms`. * * @param {Number|String} ms * @return {Runnable|Number} ms or self * @api private */ Runnable.prototype.timeout = function(ms){ if (0 == arguments.length) return this._timeout; if ('string' == typeof ms) ms = milliseconds(ms); debug('timeout %d', ms); this._timeout = ms; if (this.timer) this.resetTimeout(); return this; }; /** * Set & get slow `ms`. * * @param {Number|String} ms * @return {Runnable|Number} ms or self * @api private */ Runnable.prototype.slow = function(ms){ if (0 === arguments.length) return this._slow; if ('string' == typeof ms) ms = milliseconds(ms); debug('timeout %d', ms); this._slow = ms; return this; }; /** * Return the full title generated by recursively * concatenating the parent's full title. * * @return {String} * @api public */ Runnable.prototype.fullTitle = function(){ return this.parent.fullTitle() + ' ' + this.title; }; /** * Clear the timeout. * * @api private */ Runnable.prototype.clearTimeout = function(){ clearTimeout(this.timer); }; /** * Inspect the runnable void of private properties. * * @return {String} * @api private */ Runnable.prototype.inspect = function(){ return JSON.stringify(this, function(key, val){ if ('_' == key[0]) return; if ('parent' == key) return '#'; if ('ctx' == key) return '#'; return val; }, 2); }; /** * Reset the timeout. * * @api private */ Runnable.prototype.resetTimeout = function(){ var self = this; var ms = this.timeout() || 1e9; this.clearTimeout(); this.timer = setTimeout(function(){ self.callback(new Error('timeout of ' + ms + 'ms exceeded')); self.timedOut = true; }, ms); }; /** * Whitelist these globals for this test run * * @api private */ Runnable.prototype.globals = function(arr){ var self = this; this._allowedGlobals = arr; }; /** * Run the test and invoke `fn(err)`. * * @param {Function} fn * @api private */ Runnable.prototype.run = function(fn){ var self = this , ms = this.timeout() , start = new Date , ctx = this.ctx , finished , emitted; if (ctx) ctx.runnable(this); // called multiple times function multiple(err) { if (emitted) return; emitted = true; self.emit('error', err || new Error('done() called multiple times')); } // finished function done(err) { if (self.timedOut) return; if (finished) return multiple(err); self.clearTimeout(); self.duration = new Date - start; finished = true; fn(err); } // for .resetTimeout() this.callback = done; // explicit async with `done` argument if (this.async) { this.resetTimeout(); try { this.fn.call(ctx, function(err){ if (err instanceof Error || toString.call(err) === "[object Error]") return done(err); if (null != err) return done(new Error('done() invoked with non-Error: ' + err)); done(); }); } catch (err) { done(err); } return; } if (this.asyncOnly) { return done(new Error('--async-only option in use without declaring `done()`')); } // sync or promise-returning try { if (this.pending) { done(); } else { callFn(this.fn); } } catch (err) { done(err); } function callFn(fn) { var result = fn.call(ctx); if (result && typeof result.then === 'function') { self.resetTimeout(); result.then(function(){ done() }, done); } else { done(); } } }; mocha-1.20.1/lib/runner.js000066400000000000000000000333471234352070300153100ustar00rootroot00000000000000/** * Module dependencies. */ var EventEmitter = require('events').EventEmitter , debug = require('debug')('mocha:runner') , Test = require('./test') , utils = require('./utils') , filter = utils.filter , keys = utils.keys; /** * Non-enumerable globals. */ var globals = [ 'setTimeout', 'clearTimeout', 'setInterval', 'clearInterval', 'XMLHttpRequest', 'Date' ]; /** * Expose `Runner`. */ module.exports = Runner; /** * Initialize a `Runner` for the given `suite`. * * Events: * * - `start` execution started * - `end` execution complete * - `suite` (suite) test suite execution started * - `suite end` (suite) all tests (and sub-suites) have finished * - `test` (test) test execution started * - `test end` (test) test completed * - `hook` (hook) hook execution started * - `hook end` (hook) hook complete * - `pass` (test) test passed * - `fail` (test, err) test failed * - `pending` (test) test pending * * @api public */ function Runner(suite) { var self = this; this._globals = []; this._abort = false; this.suite = suite; this.total = suite.total(); this.failures = 0; this.on('test end', function(test){ self.checkGlobals(test); }); this.on('hook end', function(hook){ self.checkGlobals(hook); }); this.grep(/.*/); this.globals(this.globalProps().concat(extraGlobals())); } /** * Wrapper for setImmediate, process.nextTick, or browser polyfill. * * @param {Function} fn * @api private */ Runner.immediately = global.setImmediate || process.nextTick; /** * Inherit from `EventEmitter.prototype`. */ Runner.prototype.__proto__ = EventEmitter.prototype; /** * Run tests with full titles matching `re`. Updates runner.total * with number of tests matched. * * @param {RegExp} re * @param {Boolean} invert * @return {Runner} for chaining * @api public */ Runner.prototype.grep = function(re, invert){ debug('grep %s', re); this._grep = re; this._invert = invert; this.total = this.grepTotal(this.suite); return this; }; /** * Returns the number of tests matching the grep search for the * given suite. * * @param {Suite} suite * @return {Number} * @api public */ Runner.prototype.grepTotal = function(suite) { var self = this; var total = 0; suite.eachTest(function(test){ var match = self._grep.test(test.fullTitle()); if (self._invert) match = !match; if (match) total++; }); return total; }; /** * Return a list of global properties. * * @return {Array} * @api private */ Runner.prototype.globalProps = function() { var props = utils.keys(global); // non-enumerables for (var i = 0; i < globals.length; ++i) { if (~utils.indexOf(props, globals[i])) continue; props.push(globals[i]); } return props; }; /** * Allow the given `arr` of globals. * * @param {Array} arr * @return {Runner} for chaining * @api public */ Runner.prototype.globals = function(arr){ if (0 == arguments.length) return this._globals; debug('globals %j', arr); this._globals = this._globals.concat(arr); return this; }; /** * Check for global variable leaks. * * @api private */ Runner.prototype.checkGlobals = function(test){ if (this.ignoreLeaks) return; var ok = this._globals; var globals = this.globalProps(); var leaks; if (test) { ok = ok.concat(test._allowedGlobals || []); } if(this.prevGlobalsLength == globals.length) return; this.prevGlobalsLength = globals.length; leaks = filterLeaks(ok, globals); this._globals = this._globals.concat(leaks); if (leaks.length > 1) { this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + '')); } else if (leaks.length) { this.fail(test, new Error('global leak detected: ' + leaks[0])); } }; /** * Fail the given `test`. * * @param {Test} test * @param {Error} err * @api private */ Runner.prototype.fail = function(test, err){ ++this.failures; test.state = 'failed'; if ('string' == typeof err) { err = new Error('the string "' + err + '" was thrown, throw an Error :)'); } this.emit('fail', test, err); }; /** * Fail the given `hook` with `err`. * * Hook failures work in the following pattern: * - If bail, then exit * - Failed `before` hook skips all tests in a suite and subsuites, * but jumps to corresponding `after` hook * - Failed `before each` hook skips remaining tests in a * suite and jumps to corresponding `after each` hook, * which is run only once * - Failed `after` hook does not alter * execution order * - Failed `after each` hook skips remaining tests in a * suite and subsuites, but executes other `after each` * hooks * * @param {Hook} hook * @param {Error} err * @api private */ Runner.prototype.failHook = function(hook, err){ this.fail(hook, err); if (this.suite.bail()) { this.emit('end'); } }; /** * Run hook `name` callbacks and then invoke `fn()`. * * @param {String} name * @param {Function} function * @api private */ Runner.prototype.hook = function(name, fn){ var suite = this.suite , hooks = suite['_' + name] , self = this , timer; function next(i) { var hook = hooks[i]; if (!hook) return fn(); if (self.failures && suite.bail()) return fn(); self.currentRunnable = hook; hook.ctx.currentTest = self.test; self.emit('hook', hook); hook.on('error', function(err){ self.failHook(hook, err); }); hook.run(function(err){ hook.removeAllListeners('error'); var testError = hook.error(); if (testError) self.fail(self.test, testError); if (err) { self.failHook(hook, err); // stop executing hooks, notify callee of hook err return fn(err); } self.emit('hook end', hook); delete hook.ctx.currentTest; next(++i); }); } Runner.immediately(function(){ next(0); }); }; /** * Run hook `name` for the given array of `suites` * in order, and callback `fn(err, errSuite)`. * * @param {String} name * @param {Array} suites * @param {Function} fn * @api private */ Runner.prototype.hooks = function(name, suites, fn){ var self = this , orig = this.suite; function next(suite) { self.suite = suite; if (!suite) { self.suite = orig; return fn(); } self.hook(name, function(err){ if (err) { var errSuite = self.suite; self.suite = orig; return fn(err, errSuite); } next(suites.pop()); }); } next(suites.pop()); }; /** * Run hooks from the top level down. * * @param {String} name * @param {Function} fn * @api private */ Runner.prototype.hookUp = function(name, fn){ var suites = [this.suite].concat(this.parents()).reverse(); this.hooks(name, suites, fn); }; /** * Run hooks from the bottom up. * * @param {String} name * @param {Function} fn * @api private */ Runner.prototype.hookDown = function(name, fn){ var suites = [this.suite].concat(this.parents()); this.hooks(name, suites, fn); }; /** * Return an array of parent Suites from * closest to furthest. * * @return {Array} * @api private */ Runner.prototype.parents = function(){ var suite = this.suite , suites = []; while (suite = suite.parent) suites.push(suite); return suites; }; /** * Run the current test and callback `fn(err)`. * * @param {Function} fn * @api private */ Runner.prototype.runTest = function(fn){ var test = this.test , self = this; if (this.asyncOnly) test.asyncOnly = true; try { test.on('error', function(err){ self.fail(test, err); }); test.run(fn); } catch (err) { fn(err); } }; /** * Run tests in the given `suite` and invoke * the callback `fn()` when complete. * * @param {Suite} suite * @param {Function} fn * @api private */ Runner.prototype.runTests = function(suite, fn){ var self = this , tests = suite.tests.slice() , test; function hookErr(err, errSuite, after) { // before/after Each hook for errSuite failed: var orig = self.suite; // for failed 'after each' hook start from errSuite parent, // otherwise start from errSuite itself self.suite = after ? errSuite.parent : errSuite; if (self.suite) { // call hookUp afterEach self.hookUp('afterEach', function(err2, errSuite2) { self.suite = orig; // some hooks may fail even now if (err2) return hookErr(err2, errSuite2, true); // report error suite fn(errSuite); }); } else { // there is no need calling other 'after each' hooks self.suite = orig; fn(errSuite); } } function next(err, errSuite) { // if we bail after first err if (self.failures && suite._bail) return fn(); if (self._abort) return fn(); if (err) return hookErr(err, errSuite, true); // next test test = tests.shift(); // all done if (!test) return fn(); // grep var match = self._grep.test(test.fullTitle()); if (self._invert) match = !match; if (!match) return next(); // pending if (test.pending) { self.emit('pending', test); self.emit('test end', test); return next(); } // execute test and hook(s) self.emit('test', self.test = test); self.hookDown('beforeEach', function(err, errSuite){ if (err) return hookErr(err, errSuite, false); self.currentRunnable = self.test; self.runTest(function(err){ test = self.test; if (err) { self.fail(test, err); self.emit('test end', test); return self.hookUp('afterEach', next); } test.state = 'passed'; self.emit('pass', test); self.emit('test end', test); self.hookUp('afterEach', next); }); }); } this.next = next; next(); }; /** * Run the given `suite` and invoke the * callback `fn()` when complete. * * @param {Suite} suite * @param {Function} fn * @api private */ Runner.prototype.runSuite = function(suite, fn){ var total = this.grepTotal(suite) , self = this , i = 0; debug('run suite %s', suite.fullTitle()); if (!total) return fn(); this.emit('suite', this.suite = suite); function next(errSuite) { if (errSuite) { // current suite failed on a hook from errSuite if (errSuite == suite) { // if errSuite is current suite // continue to the next sibling suite return done(); } else { // errSuite is among the parents of current suite // stop execution of errSuite and all sub-suites return done(errSuite); } } if (self._abort) return done(); var curr = suite.suites[i++]; if (!curr) return done(); self.runSuite(curr, next); } function done(errSuite) { self.suite = suite; self.hook('afterAll', function(){ self.emit('suite end', suite); fn(errSuite); }); } this.hook('beforeAll', function(err){ if (err) return done(); self.runTests(suite, next); }); }; /** * Handle uncaught exceptions. * * @param {Error} err * @api private */ Runner.prototype.uncaught = function(err){ debug('uncaught exception %s', err.message); var runnable = this.currentRunnable; if (!runnable || 'failed' == runnable.state) return; runnable.clearTimeout(); err.uncaught = true; this.fail(runnable, err); // recover from test if ('test' == runnable.type) { this.emit('test end', runnable); this.hookUp('afterEach', this.next); return; } // bail on hooks this.emit('end'); }; /** * Run the root suite and invoke `fn(failures)` * on completion. * * @param {Function} fn * @return {Runner} for chaining * @api public */ Runner.prototype.run = function(fn){ var self = this , fn = fn || function(){}; function uncaught(err){ self.uncaught(err); } debug('start'); // callback this.on('end', function(){ debug('end'); process.removeListener('uncaughtException', uncaught); fn(self.failures); }); // run suites this.emit('start'); this.runSuite(this.suite, function(){ debug('finished running'); self.emit('end'); }); // uncaught exception process.on('uncaughtException', uncaught); return this; }; /** * Cleanly abort execution * * @return {Runner} for chaining * @api public */ Runner.prototype.abort = function(){ debug('aborting'); this._abort = true; } /** * Filter leaks with the given globals flagged as `ok`. * * @param {Array} ok * @param {Array} globals * @return {Array} * @api private */ function filterLeaks(ok, globals) { return filter(globals, function(key){ // Firefox and Chrome exposes iframes as index inside the window object if (/^d+/.test(key)) return false; // in firefox // if runner runs in an iframe, this iframe's window.getInterface method not init at first // it is assigned in some seconds if (global.navigator && /^getInterface/.test(key)) return false; // an iframe could be approached by window[iframeIndex] // in ie6,7,8 and opera, iframeIndex is enumerable, this could cause leak if (global.navigator && /^\d+/.test(key)) return false; // Opera and IE expose global variables for HTML element IDs (issue #243) if (/^mocha-/.test(key)) return false; var matched = filter(ok, function(ok){ if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]); return key == ok; }); return matched.length == 0 && (!global.navigator || 'onerror' !== key); }); } /** * Array of globals dependent on the environment. * * @return {Array} * @api private */ function extraGlobals() { if (typeof(process) === 'object' && typeof(process.version) === 'string') { var nodeVersion = process.version.split('.').reduce(function(a, v) { return a << 8 | v; }); // 'errno' was renamed to process._errno in v0.9.11. if (nodeVersion < 0x00090B) { return ['errno']; } } return []; } mocha-1.20.1/lib/suite.js000066400000000000000000000147631234352070300151310ustar00rootroot00000000000000 /** * Module dependencies. */ var EventEmitter = require('events').EventEmitter , debug = require('debug')('mocha:suite') , milliseconds = require('./ms') , utils = require('./utils') , Hook = require('./hook'); /** * Expose `Suite`. */ exports = module.exports = Suite; /** * Create a new `Suite` with the given `title` * and parent `Suite`. When a suite with the * same title is already present, that suite * is returned to provide nicer reporter * and more flexible meta-testing. * * @param {Suite} parent * @param {String} title * @return {Suite} * @api public */ exports.create = function(parent, title){ var suite = new Suite(title, parent.ctx); suite.parent = parent; if (parent.pending) suite.pending = true; title = suite.fullTitle(); parent.addSuite(suite); return suite; }; /** * Initialize a new `Suite` with the given * `title` and `ctx`. * * @param {String} title * @param {Context} ctx * @api private */ function Suite(title, parentContext) { this.title = title; var context = function() {}; context.prototype = parentContext; this.ctx = new context(); this.suites = []; this.tests = []; this.pending = false; this._beforeEach = []; this._beforeAll = []; this._afterEach = []; this._afterAll = []; this.root = !title; this._timeout = 2000; this._slow = 75; this._bail = false; } /** * Inherit from `EventEmitter.prototype`. */ Suite.prototype.__proto__ = EventEmitter.prototype; /** * Return a clone of this `Suite`. * * @return {Suite} * @api private */ Suite.prototype.clone = function(){ var suite = new Suite(this.title); debug('clone'); suite.ctx = this.ctx; suite.timeout(this.timeout()); suite.slow(this.slow()); suite.bail(this.bail()); return suite; }; /** * Set timeout `ms` or short-hand such as "2s". * * @param {Number|String} ms * @return {Suite|Number} for chaining * @api private */ Suite.prototype.timeout = function(ms){ if (0 == arguments.length) return this._timeout; if ('string' == typeof ms) ms = milliseconds(ms); debug('timeout %d', ms); this._timeout = parseInt(ms, 10); return this; }; /** * Set slow `ms` or short-hand such as "2s". * * @param {Number|String} ms * @return {Suite|Number} for chaining * @api private */ Suite.prototype.slow = function(ms){ if (0 === arguments.length) return this._slow; if ('string' == typeof ms) ms = milliseconds(ms); debug('slow %d', ms); this._slow = ms; return this; }; /** * Sets whether to bail after first error. * * @parma {Boolean} bail * @return {Suite|Number} for chaining * @api private */ Suite.prototype.bail = function(bail){ if (0 == arguments.length) return this._bail; debug('bail %s', bail); this._bail = bail; return this; }; /** * Run `fn(test[, done])` before running tests. * * @param {Function} fn * @return {Suite} for chaining * @api private */ Suite.prototype.beforeAll = function(title, fn){ if (this.pending) return this; if ('function' === typeof title) { fn = title; title = fn.name; } title = '"before all" hook' + (title ? ': ' + title : ''); var hook = new Hook(title, fn); hook.parent = this; hook.timeout(this.timeout()); hook.slow(this.slow()); hook.ctx = this.ctx; this._beforeAll.push(hook); this.emit('beforeAll', hook); return this; }; /** * Run `fn(test[, done])` after running tests. * * @param {Function} fn * @return {Suite} for chaining * @api private */ Suite.prototype.afterAll = function(title, fn){ if (this.pending) return this; if ('function' === typeof title) { fn = title; title = fn.name; } title = '"after all" hook' + (title ? ': ' + title : ''); var hook = new Hook(title, fn); hook.parent = this; hook.timeout(this.timeout()); hook.slow(this.slow()); hook.ctx = this.ctx; this._afterAll.push(hook); this.emit('afterAll', hook); return this; }; /** * Run `fn(test[, done])` before each test case. * * @param {Function} fn * @return {Suite} for chaining * @api private */ Suite.prototype.beforeEach = function(title, fn){ if (this.pending) return this; if ('function' === typeof title) { fn = title; title = fn.name; } title = '"before each" hook' + (title ? ': ' + title : ''); var hook = new Hook(title, fn); hook.parent = this; hook.timeout(this.timeout()); hook.slow(this.slow()); hook.ctx = this.ctx; this._beforeEach.push(hook); this.emit('beforeEach', hook); return this; }; /** * Run `fn(test[, done])` after each test case. * * @param {Function} fn * @return {Suite} for chaining * @api private */ Suite.prototype.afterEach = function(title, fn){ if (this.pending) return this; if ('function' === typeof title) { fn = title; title = fn.name; } title = '"after each" hook' + (title ? ': ' + title : ''); var hook = new Hook(title, fn); hook.parent = this; hook.timeout(this.timeout()); hook.slow(this.slow()); hook.ctx = this.ctx; this._afterEach.push(hook); this.emit('afterEach', hook); return this; }; /** * Add a test `suite`. * * @param {Suite} suite * @return {Suite} for chaining * @api private */ Suite.prototype.addSuite = function(suite){ suite.parent = this; suite.timeout(this.timeout()); suite.slow(this.slow()); suite.bail(this.bail()); this.suites.push(suite); this.emit('suite', suite); return this; }; /** * Add a `test` to this suite. * * @param {Test} test * @return {Suite} for chaining * @api private */ Suite.prototype.addTest = function(test){ test.parent = this; test.timeout(this.timeout()); test.slow(this.slow()); test.ctx = this.ctx; this.tests.push(test); this.emit('test', test); return this; }; /** * Return the full title generated by recursively * concatenating the parent's full title. * * @return {String} * @api public */ Suite.prototype.fullTitle = function(){ if (this.parent) { var full = this.parent.fullTitle(); if (full) return full + ' ' + this.title; } return this.title; }; /** * Return the total number of tests. * * @return {Number} * @api public */ Suite.prototype.total = function(){ return utils.reduce(this.suites, function(sum, suite){ return sum + suite.total(); }, 0) + this.tests.length; }; /** * Iterates through each suite recursively to find * all tests. Applies a function in the format * `fn(test)`. * * @param {Function} fn * @return {Suite} * @api private */ Suite.prototype.eachTest = function(fn){ utils.forEach(this.tests, fn); utils.forEach(this.suites, function(suite){ suite.eachTest(fn); }); return this; }; mocha-1.20.1/lib/template.html000066400000000000000000000007331234352070300161330ustar00rootroot00000000000000 Mocha
    mocha-1.20.1/lib/test.js000066400000000000000000000007301234352070300147440ustar00rootroot00000000000000 /** * Module dependencies. */ var Runnable = require('./runnable'); /** * Expose `Test`. */ module.exports = Test; /** * Initialize a new `Test` with the given `title` and callback `fn`. * * @param {String} title * @param {Function} fn * @api private */ function Test(title, fn) { Runnable.call(this, title, fn); this.pending = !fn; this.type = 'test'; } /** * Inherit from `Runnable.prototype`. */ Test.prototype.__proto__ = Runnable.prototype; mocha-1.20.1/lib/utils.js000066400000000000000000000130541234352070300151300ustar00rootroot00000000000000/** * Module dependencies. */ var fs = require('fs') , path = require('path') , join = path.join , debug = require('debug')('mocha:watch'); /** * Ignored directories. */ var ignore = ['node_modules', '.git']; /** * Escape special characters in the given string of html. * * @param {String} html * @return {String} * @api private */ exports.escape = function(html){ return String(html) .replace(/&/g, '&') .replace(/"/g, '"') .replace(//g, '>'); }; /** * Array#forEach (<=IE8) * * @param {Array} array * @param {Function} fn * @param {Object} scope * @api private */ exports.forEach = function(arr, fn, scope){ for (var i = 0, l = arr.length; i < l; i++) fn.call(scope, arr[i], i); }; /** * Array#map (<=IE8) * * @param {Array} array * @param {Function} fn * @param {Object} scope * @api private */ exports.map = function(arr, fn, scope){ var result = []; for (var i = 0, l = arr.length; i < l; i++) result.push(fn.call(scope, arr[i], i)); return result; }; /** * Array#indexOf (<=IE8) * * @parma {Array} arr * @param {Object} obj to find index of * @param {Number} start * @api private */ exports.indexOf = function(arr, obj, start){ for (var i = start || 0, l = arr.length; i < l; i++) { if (arr[i] === obj) return i; } return -1; }; /** * Array#reduce (<=IE8) * * @param {Array} array * @param {Function} fn * @param {Object} initial value * @api private */ exports.reduce = function(arr, fn, val){ var rval = val; for (var i = 0, l = arr.length; i < l; i++) { rval = fn(rval, arr[i], i, arr); } return rval; }; /** * Array#filter (<=IE8) * * @param {Array} array * @param {Function} fn * @api private */ exports.filter = function(arr, fn){ var ret = []; for (var i = 0, l = arr.length; i < l; i++) { var val = arr[i]; if (fn(val, i, arr)) ret.push(val); } return ret; }; /** * Object.keys (<=IE8) * * @param {Object} obj * @return {Array} keys * @api private */ exports.keys = Object.keys || function(obj) { var keys = [] , has = Object.prototype.hasOwnProperty // for `window` on <=IE8 for (var key in obj) { if (has.call(obj, key)) { keys.push(key); } } return keys; }; /** * Watch the given `files` for changes * and invoke `fn(file)` on modification. * * @param {Array} files * @param {Function} fn * @api private */ exports.watch = function(files, fn){ var options = { interval: 100 }; files.forEach(function(file){ debug('file %s', file); fs.watchFile(file, options, function(curr, prev){ if (prev.mtime < curr.mtime) fn(file); }); }); }; /** * Ignored files. */ function ignored(path){ return !~ignore.indexOf(path); } /** * Lookup files in the given `dir`. * * @return {Array} * @api private */ exports.files = function(dir, ret){ ret = ret || []; fs.readdirSync(dir) .filter(ignored) .forEach(function(path){ path = join(dir, path); if (fs.statSync(path).isDirectory()) { exports.files(path, ret); } else if (path.match(/\.(js|coffee|litcoffee|coffee.md)$/)) { ret.push(path); } }); return ret; }; /** * Compute a slug from the given `str`. * * @param {String} str * @return {String} * @api private */ exports.slug = function(str){ return str .toLowerCase() .replace(/ +/g, '-') .replace(/[^-\w]/g, ''); }; /** * Strip the function definition from `str`, * and re-indent for pre whitespace. */ exports.clean = function(str) { str = str .replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, '') .replace(/^function *\(.*\) *{/, '') .replace(/\s+\}$/, ''); var spaces = str.match(/^\n?( *)/)[1].length , tabs = str.match(/^\n?(\t*)/)[1].length , re = new RegExp('^\n?' + (tabs ? '\t' : ' ') + '{' + (tabs ? tabs : spaces) + '}', 'gm'); str = str.replace(re, ''); return exports.trim(str); }; /** * Escape regular expression characters in `str`. * * @param {String} str * @return {String} * @api private */ exports.escapeRegexp = function(str){ return str.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&"); }; /** * Trim the given `str`. * * @param {String} str * @return {String} * @api private */ exports.trim = function(str){ return str.replace(/^\s+|\s+$/g, ''); }; /** * Parse the given `qs`. * * @param {String} qs * @return {Object} * @api private */ exports.parseQuery = function(qs){ return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair){ var i = pair.indexOf('=') , key = pair.slice(0, i) , val = pair.slice(++i); obj[key] = decodeURIComponent(val); return obj; }, {}); }; /** * Highlight the given string of `js`. * * @param {String} js * @return {String} * @api private */ function highlight(js) { return js .replace(//g, '>') .replace(/\/\/(.*)/gm, '//$1') .replace(/('.*?')/gm, '$1') .replace(/(\d+\.\d+)/gm, '$1') .replace(/(\d+)/gm, '$1') .replace(/\bnew[ \t]+(\w+)/gm, 'new $1') .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '$1') } /** * Highlight the contents of tag `name`. * * @param {String} name * @api private */ exports.highlightTags = function(name) { var code = document.getElementsByTagName(name); for (var i = 0, len = code.length; i < len; ++i) { code[i].innerHTML = highlight(code[i].innerHTML); } }; mocha-1.20.1/media/000077500000000000000000000000001234352070300137405ustar00rootroot00000000000000mocha-1.20.1/media/logo.svg000066400000000000000000000012251234352070300154210ustar00rootroot00000000000000 mocha mocha-1.20.1/mocha.css000066400000000000000000000102221234352070300144570ustar00rootroot00000000000000@charset "utf-8"; body { margin:0; } #mocha { font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; margin: 60px 50px; } #mocha ul, #mocha li { margin: 0; padding: 0; } #mocha ul { list-style: none; } #mocha h1, #mocha h2 { margin: 0; } #mocha h1 { margin-top: 15px; font-size: 1em; font-weight: 200; } #mocha h1 a { text-decoration: none; color: inherit; } #mocha h1 a:hover { text-decoration: underline; } #mocha .suite .suite h1 { margin-top: 0; font-size: .8em; } #mocha .hidden { display: none; } #mocha h2 { font-size: 12px; font-weight: normal; cursor: pointer; } #mocha .suite { margin-left: 15px; } #mocha .test { margin-left: 15px; overflow: hidden; } #mocha .test.pending:hover h2::after { content: '(pending)'; font-family: arial, sans-serif; } #mocha .test.pass.medium .duration { background: #c09853; } #mocha .test.pass.slow .duration { background: #b94a48; } #mocha .test.pass::before { content: '✓'; font-size: 12px; display: block; float: left; margin-right: 5px; color: #00d6b2; } #mocha .test.pass .duration { font-size: 9px; margin-left: 5px; padding: 2px 5px; color: #fff; -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); box-shadow: inset 0 1px 1px rgba(0,0,0,.2); -webkit-border-radius: 5px; -moz-border-radius: 5px; -ms-border-radius: 5px; -o-border-radius: 5px; border-radius: 5px; } #mocha .test.pass.fast .duration { display: none; } #mocha .test.pending { color: #0b97c4; } #mocha .test.pending::before { content: '◦'; color: #0b97c4; } #mocha .test.fail { color: #c00; } #mocha .test.fail pre { color: black; } #mocha .test.fail::before { content: '✖'; font-size: 12px; display: block; float: left; margin-right: 5px; color: #c00; } #mocha .test pre.error { color: #c00; max-height: 300px; overflow: auto; } /** * (1): approximate for browsers not supporting calc * (2): 42 = 2*15 + 2*10 + 2*1 (padding + margin + border) * ^^ seriously */ #mocha .test pre { display: block; float: left; clear: left; font: 12px/1.5 monaco, monospace; margin: 5px; padding: 15px; border: 1px solid #eee; max-width: 85%; /*(1)*/ max-width: calc(100% - 42px); /*(2)*/ word-wrap: break-word; border-bottom-color: #ddd; -webkit-border-radius: 3px; -webkit-box-shadow: 0 1px 3px #eee; -moz-border-radius: 3px; -moz-box-shadow: 0 1px 3px #eee; border-radius: 3px; } #mocha .test h2 { position: relative; } #mocha .test a.replay { position: absolute; top: 3px; right: 0; text-decoration: none; vertical-align: middle; display: block; width: 15px; height: 15px; line-height: 15px; text-align: center; background: #eee; font-size: 15px; -moz-border-radius: 15px; border-radius: 15px; -webkit-transition: opacity 200ms; -moz-transition: opacity 200ms; transition: opacity 200ms; opacity: 0.3; color: #888; } #mocha .test:hover a.replay { opacity: 1; } #mocha-report.pass .test.fail { display: none; } #mocha-report.fail .test.pass { display: none; } #mocha-report.pending .test.pass, #mocha-report.pending .test.fail { display: none; } #mocha-report.pending .test.pass.pending { display: block; } #mocha-error { color: #c00; font-size: 1.5em; font-weight: 100; letter-spacing: 1px; } #mocha-stats { position: fixed; top: 15px; right: 10px; font-size: 12px; margin: 0; color: #888; z-index: 1; } #mocha-stats .progress { float: right; padding-top: 0; } #mocha-stats em { color: black; } #mocha-stats a { text-decoration: none; color: inherit; } #mocha-stats a:hover { border-bottom: 1px solid #eee; } #mocha-stats li { display: inline-block; margin: 0 5px; list-style: none; padding-top: 11px; } #mocha-stats canvas { width: 40px; height: 40px; } #mocha code .comment { color: #ddd; } #mocha code .init { color: #2f6fad; } #mocha code .string { color: #5890ad; } #mocha code .keyword { color: #8a6343; } #mocha code .number { color: #2f6fad; } @media screen and (max-device-width: 480px) { #mocha { margin: 60px 0px; } #mocha #stats { position: absolute; } } mocha-1.20.1/mocha.js000066400000000000000000003622261234352070300143210ustar00rootroot00000000000000;(function(){ // 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.charAt(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("browser/debug.js", function(module, exports, require){ module.exports = function(type){ return function(){ } }; }); // module: browser/debug.js require.register("browser/diff.js", function(module, exports, require){ /* See LICENSE file for terms of use */ /* * Text diff implementation. * * This library supports the following APIS: * JsDiff.diffChars: Character by character diff * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace * JsDiff.diffLines: Line based diff * * JsDiff.diffCss: Diff targeted at CSS content * * These methods are based on the implementation proposed in * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986). * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927 */ var JsDiff = (function() { /*jshint maxparams: 5*/ function clonePath(path) { return { newPos: path.newPos, components: path.components.slice(0) }; } function removeEmpty(array) { var ret = []; for (var i = 0; i < array.length; i++) { if (array[i]) { ret.push(array[i]); } } return ret; } function escapeHTML(s) { var n = s; n = n.replace(/&/g, '&'); n = n.replace(//g, '>'); n = n.replace(/"/g, '"'); return n; } var Diff = function(ignoreWhitespace) { this.ignoreWhitespace = ignoreWhitespace; }; Diff.prototype = { diff: function(oldString, newString) { // Handle the identity case (this is due to unrolling editLength == 0 if (newString === oldString) { return [{ value: newString }]; } if (!newString) { return [{ value: oldString, removed: true }]; } if (!oldString) { return [{ value: newString, added: true }]; } newString = this.tokenize(newString); oldString = this.tokenize(oldString); var newLen = newString.length, oldLen = oldString.length; var maxEditLength = newLen + oldLen; var bestPath = [{ newPos: -1, components: [] }]; // Seed editLength = 0 var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0); if (bestPath[0].newPos+1 >= newLen && oldPos+1 >= oldLen) { return bestPath[0].components; } for (var editLength = 1; editLength <= maxEditLength; editLength++) { for (var diagonalPath = -1*editLength; diagonalPath <= editLength; diagonalPath+=2) { var basePath; var addPath = bestPath[diagonalPath-1], removePath = bestPath[diagonalPath+1]; oldPos = (removePath ? removePath.newPos : 0) - diagonalPath; if (addPath) { // No one else is going to attempt to use this value, clear it bestPath[diagonalPath-1] = undefined; } var canAdd = addPath && addPath.newPos+1 < newLen; var canRemove = removePath && 0 <= oldPos && oldPos < oldLen; if (!canAdd && !canRemove) { bestPath[diagonalPath] = undefined; continue; } // Select the diagonal that we want to branch from. We select the prior // path whose position in the new string is the farthest from the origin // and does not pass the bounds of the diff graph if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) { basePath = clonePath(removePath); this.pushComponent(basePath.components, oldString[oldPos], undefined, true); } else { basePath = clonePath(addPath); basePath.newPos++; this.pushComponent(basePath.components, newString[basePath.newPos], true, undefined); } var oldPos = this.extractCommon(basePath, newString, oldString, diagonalPath); if (basePath.newPos+1 >= newLen && oldPos+1 >= oldLen) { return basePath.components; } else { bestPath[diagonalPath] = basePath; } } } }, pushComponent: function(components, value, added, removed) { var last = components[components.length-1]; if (last && last.added === added && last.removed === removed) { // We need to clone here as the component clone operation is just // as shallow array clone components[components.length-1] = {value: this.join(last.value, value), added: added, removed: removed }; } else { components.push({value: value, added: added, removed: removed }); } }, extractCommon: function(basePath, newString, oldString, diagonalPath) { var newLen = newString.length, oldLen = oldString.length, newPos = basePath.newPos, oldPos = newPos - diagonalPath; while (newPos+1 < newLen && oldPos+1 < oldLen && this.equals(newString[newPos+1], oldString[oldPos+1])) { newPos++; oldPos++; this.pushComponent(basePath.components, newString[newPos], undefined, undefined); } basePath.newPos = newPos; return oldPos; }, equals: function(left, right) { var reWhitespace = /\S/; if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) { return true; } else { return left === right; } }, join: function(left, right) { return left + right; }, tokenize: function(value) { return value; } }; var CharDiff = new Diff(); var WordDiff = new Diff(true); var WordWithSpaceDiff = new Diff(); WordDiff.tokenize = WordWithSpaceDiff.tokenize = function(value) { return removeEmpty(value.split(/(\s+|\b)/)); }; var CssDiff = new Diff(true); CssDiff.tokenize = function(value) { return removeEmpty(value.split(/([{}:;,]|\s+)/)); }; var LineDiff = new Diff(); LineDiff.tokenize = function(value) { return value.split(/^/m); }; return { Diff: Diff, diffChars: function(oldStr, newStr) { return CharDiff.diff(oldStr, newStr); }, diffWords: function(oldStr, newStr) { return WordDiff.diff(oldStr, newStr); }, diffWordsWithSpace: function(oldStr, newStr) { return WordWithSpaceDiff.diff(oldStr, newStr); }, diffLines: function(oldStr, newStr) { return LineDiff.diff(oldStr, newStr); }, diffCss: function(oldStr, newStr) { return CssDiff.diff(oldStr, newStr); }, createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) { var ret = []; ret.push('Index: ' + fileName); ret.push('==================================================================='); ret.push('--- ' + fileName + (typeof oldHeader === 'undefined' ? '' : '\t' + oldHeader)); ret.push('+++ ' + fileName + (typeof newHeader === 'undefined' ? '' : '\t' + newHeader)); var diff = LineDiff.diff(oldStr, newStr); if (!diff[diff.length-1].value) { diff.pop(); // Remove trailing newline add } diff.push({value: '', lines: []}); // Append an empty value to make cleanup easier function contextLines(lines) { return lines.map(function(entry) { return ' ' + entry; }); } function eofNL(curRange, i, current) { var last = diff[diff.length-2], isLast = i === diff.length-2, isLastOfType = i === diff.length-3 && (current.added !== last.added || current.removed !== last.removed); // Figure out if this is the last line for the given file and missing NL if (!/\n$/.test(current.value) && (isLast || isLastOfType)) { curRange.push('\\ No newline at end of file'); } } var oldRangeStart = 0, newRangeStart = 0, curRange = [], oldLine = 1, newLine = 1; for (var i = 0; i < diff.length; i++) { var current = diff[i], lines = current.lines || current.value.replace(/\n$/, '').split('\n'); current.lines = lines; if (current.added || current.removed) { if (!oldRangeStart) { var prev = diff[i-1]; oldRangeStart = oldLine; newRangeStart = newLine; if (prev) { curRange = contextLines(prev.lines.slice(-4)); oldRangeStart -= curRange.length; newRangeStart -= curRange.length; } } curRange.push.apply(curRange, lines.map(function(entry) { return (current.added?'+':'-') + entry; })); eofNL(curRange, i, current); if (current.added) { newLine += lines.length; } else { oldLine += lines.length; } } else { if (oldRangeStart) { // Close out any changes that have been output (or join overlapping) if (lines.length <= 8 && i < diff.length-2) { // Overlapping curRange.push.apply(curRange, contextLines(lines)); } else { // end the range and output var contextSize = Math.min(lines.length, 4); ret.push( '@@ -' + oldRangeStart + ',' + (oldLine-oldRangeStart+contextSize) + ' +' + newRangeStart + ',' + (newLine-newRangeStart+contextSize) + ' @@'); ret.push.apply(ret, curRange); ret.push.apply(ret, contextLines(lines.slice(0, contextSize))); if (lines.length <= 4) { eofNL(ret, i, current); } oldRangeStart = 0; newRangeStart = 0; curRange = []; } } oldLine += lines.length; newLine += lines.length; } } return ret.join('\n') + '\n'; }, applyPatch: function(oldStr, uniDiff) { var diffstr = uniDiff.split('\n'); var diff = []; var remEOFNL = false, addEOFNL = false; for (var i = (diffstr[0][0]==='I'?4:0); i < diffstr.length; i++) { if(diffstr[i][0] === '@') { var meh = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/); diff.unshift({ start:meh[3], oldlength:meh[2], oldlines:[], newlength:meh[4], newlines:[] }); } else if(diffstr[i][0] === '+') { diff[0].newlines.push(diffstr[i].substr(1)); } else if(diffstr[i][0] === '-') { diff[0].oldlines.push(diffstr[i].substr(1)); } else if(diffstr[i][0] === ' ') { diff[0].newlines.push(diffstr[i].substr(1)); diff[0].oldlines.push(diffstr[i].substr(1)); } else if(diffstr[i][0] === '\\') { if (diffstr[i-1][0] === '+') { remEOFNL = true; } else if(diffstr[i-1][0] === '-') { addEOFNL = true; } } } var str = oldStr.split('\n'); for (var i = diff.length - 1; i >= 0; i--) { var d = diff[i]; for (var j = 0; j < d.oldlength; j++) { if(str[d.start-1+j] !== d.oldlines[j]) { return false; } } Array.prototype.splice.apply(str,[d.start-1,+d.oldlength].concat(d.newlines)); } if (remEOFNL) { while (!str[str.length-1]) { str.pop(); } } else if (addEOFNL) { str.push(''); } return str.join('\n'); }, convertChangesToXML: function(changes){ var ret = []; for ( var i = 0; i < changes.length; i++) { var change = changes[i]; if (change.added) { ret.push(''); } else if (change.removed) { ret.push(''); } ret.push(escapeHTML(change.value)); if (change.added) { ret.push(''); } else if (change.removed) { ret.push(''); } } return ret.join(''); }, // See: http://code.google.com/p/google-diff-match-patch/wiki/API convertChangesToDMP: function(changes){ var ret = [], change; for ( var i = 0; i < changes.length; i++) { change = changes[i]; ret.push([(change.added ? 1 : change.removed ? -1 : 0), change.value]); } return ret; } }; })(); if (typeof module !== 'undefined') { module.exports = JsDiff; } }); // module: browser/diff.js require.register("browser/events.js", function(module, exports, require){ /** * Module exports. */ exports.EventEmitter = EventEmitter; /** * Check if `obj` is an array. */ function isArray(obj) { return '[object Array]' == {}.toString.call(obj); } /** * Event emitter constructor. * * @api public */ function EventEmitter(){}; /** * Adds a listener. * * @api public */ EventEmitter.prototype.on = function (name, fn) { if (!this.$events) { this.$events = {}; } if (!this.$events[name]) { this.$events[name] = fn; } else if (isArray(this.$events[name])) { this.$events[name].push(fn); } else { this.$events[name] = [this.$events[name], fn]; } return this; }; EventEmitter.prototype.addListener = EventEmitter.prototype.on; /** * Adds a volatile listener. * * @api public */ EventEmitter.prototype.once = function (name, fn) { var self = this; function on () { self.removeListener(name, on); fn.apply(this, arguments); }; on.listener = fn; this.on(name, on); return this; }; /** * Removes a listener. * * @api public */ EventEmitter.prototype.removeListener = function (name, fn) { if (this.$events && this.$events[name]) { var list = this.$events[name]; if (isArray(list)) { var pos = -1; for (var i = 0, l = list.length; i < l; i++) { if (list[i] === fn || (list[i].listener && list[i].listener === fn)) { pos = i; break; } } if (pos < 0) { return this; } list.splice(pos, 1); if (!list.length) { delete this.$events[name]; } } else if (list === fn || (list.listener && list.listener === fn)) { delete this.$events[name]; } } return this; }; /** * Removes all listeners for an event. * * @api public */ EventEmitter.prototype.removeAllListeners = function (name) { if (name === undefined) { this.$events = {}; return this; } if (this.$events && this.$events[name]) { this.$events[name] = null; } return this; }; /** * Gets all listeners for a certain event. * * @api public */ EventEmitter.prototype.listeners = function (name) { if (!this.$events) { this.$events = {}; } if (!this.$events[name]) { this.$events[name] = []; } if (!isArray(this.$events[name])) { this.$events[name] = [this.$events[name]]; } return this.$events[name]; }; /** * Emits an event. * * @api public */ EventEmitter.prototype.emit = function (name) { if (!this.$events) { return false; } var handler = this.$events[name]; if (!handler) { return false; } var args = [].slice.call(arguments, 1); if ('function' == typeof handler) { handler.apply(this, args); } else if (isArray(handler)) { var listeners = handler.slice(); for (var i = 0, l = listeners.length; i < l; i++) { listeners[i].apply(this, args); } } else { return false; } return true; }; }); // module: browser/events.js require.register("browser/fs.js", function(module, exports, require){ }); // module: browser/fs.js require.register("browser/path.js", function(module, exports, require){ }); // module: browser/path.js require.register("browser/progress.js", function(module, exports, require){ /** * Expose `Progress`. */ module.exports = Progress; /** * Initialize a new `Progress` indicator. */ function Progress() { this.percent = 0; this.size(0); this.fontSize(11); this.font('helvetica, arial, sans-serif'); } /** * Set progress size to `n`. * * @param {Number} n * @return {Progress} for chaining * @api public */ Progress.prototype.size = function(n){ this._size = n; return this; }; /** * Set text to `str`. * * @param {String} str * @return {Progress} for chaining * @api public */ Progress.prototype.text = function(str){ this._text = str; return this; }; /** * Set font size to `n`. * * @param {Number} n * @return {Progress} for chaining * @api public */ Progress.prototype.fontSize = function(n){ this._fontSize = n; return this; }; /** * Set font `family`. * * @param {String} family * @return {Progress} for chaining */ Progress.prototype.font = function(family){ this._font = family; return this; }; /** * Update percentage to `n`. * * @param {Number} n * @return {Progress} for chaining */ Progress.prototype.update = function(n){ this.percent = n; return this; }; /** * Draw on `ctx`. * * @param {CanvasRenderingContext2d} ctx * @return {Progress} for chaining */ Progress.prototype.draw = function(ctx){ try { var percent = Math.min(this.percent, 100) , size = this._size , half = size / 2 , x = half , y = half , rad = half - 1 , fontSize = this._fontSize; ctx.font = fontSize + 'px ' + this._font; var angle = Math.PI * 2 * (percent / 100); ctx.clearRect(0, 0, size, size); // outer circle ctx.strokeStyle = '#9f9f9f'; ctx.beginPath(); ctx.arc(x, y, rad, 0, angle, false); ctx.stroke(); // inner circle ctx.strokeStyle = '#eee'; ctx.beginPath(); ctx.arc(x, y, rad - 1, 0, angle, true); ctx.stroke(); // text var text = this._text || (percent | 0) + '%' , w = ctx.measureText(text).width; ctx.fillText( text , x - w / 2 + 1 , y + fontSize / 2 - 1); } catch (ex) {} //don't fail if we can't render progress return this; }; }); // module: browser/progress.js require.register("browser/tty.js", function(module, exports, require){ exports.isatty = function(){ return true; }; exports.getWindowSize = function(){ if ('innerHeight' in global) { return [global.innerHeight, global.innerWidth]; } else { // In a Web Worker, the DOM Window is not available. return [640, 480]; } }; }); // module: browser/tty.js require.register("context.js", function(module, exports, require){ /** * Expose `Context`. */ module.exports = Context; /** * Initialize a new `Context`. * * @api private */ function Context(){} /** * Set or get the context `Runnable` to `runnable`. * * @param {Runnable} runnable * @return {Context} * @api private */ Context.prototype.runnable = function(runnable){ if (0 == arguments.length) return this._runnable; this.test = this._runnable = runnable; return this; }; /** * Set test timeout `ms`. * * @param {Number} ms * @return {Context} self * @api private */ Context.prototype.timeout = function(ms){ this.runnable().timeout(ms); return this; }; /** * Set test slowness threshold `ms`. * * @param {Number} ms * @return {Context} self * @api private */ Context.prototype.slow = function(ms){ this.runnable().slow(ms); return this; }; /** * Inspect the context void of `._runnable`. * * @return {String} * @api private */ Context.prototype.inspect = function(){ return JSON.stringify(this, function(key, val){ if ('_runnable' == key) return; if ('test' == key) return; return val; }, 2); }; }); // module: context.js require.register("hook.js", function(module, exports, require){ /** * Module dependencies. */ var Runnable = require('./runnable'); /** * Expose `Hook`. */ module.exports = Hook; /** * Initialize a new `Hook` with the given `title` and callback `fn`. * * @param {String} title * @param {Function} fn * @api private */ function Hook(title, fn) { Runnable.call(this, title, fn); this.type = 'hook'; } /** * Inherit from `Runnable.prototype`. */ function F(){}; F.prototype = Runnable.prototype; Hook.prototype = new F; Hook.prototype.constructor = Hook; /** * Get or set the test `err`. * * @param {Error} err * @return {Error} * @api public */ Hook.prototype.error = function(err){ if (0 == arguments.length) { var err = this._error; this._error = null; return err; } this._error = err; }; }); // module: hook.js require.register("interfaces/bdd.js", function(module, exports, require){ /** * Module dependencies. */ var Suite = require('../suite') , Test = require('../test') , utils = require('../utils'); /** * BDD-style interface: * * describe('Array', function(){ * describe('#indexOf()', function(){ * it('should return -1 when not present', function(){ * * }); * * it('should return the index when present', function(){ * * }); * }); * }); * */ module.exports = function(suite){ var suites = [suite]; suite.on('pre-require', function(context, file, mocha){ /** * Execute before running tests. */ context.before = function(name, fn){ suites[0].beforeAll(name, fn); }; /** * Execute after running tests. */ context.after = function(name, fn){ suites[0].afterAll(name, fn); }; /** * Execute before each test case. */ context.beforeEach = function(name, fn){ suites[0].beforeEach(name, fn); }; /** * Execute after each test case. */ context.afterEach = function(name, fn){ suites[0].afterEach(name, fn); }; /** * Describe a "suite" with the given `title` * and callback `fn` containing nested suites * and/or tests. */ context.describe = context.context = function(title, fn){ var suite = Suite.create(suites[0], title); suites.unshift(suite); fn.call(suite); suites.shift(); return suite; }; /** * Pending describe. */ context.xdescribe = context.xcontext = context.describe.skip = function(title, fn){ var suite = Suite.create(suites[0], title); suite.pending = true; suites.unshift(suite); fn.call(suite); suites.shift(); }; /** * Exclusive suite. */ context.describe.only = function(title, fn){ var suite = context.describe(title, fn); mocha.grep(suite.fullTitle()); return suite; }; /** * Describe a specification or test-case * with the given `title` and callback `fn` * acting as a thunk. */ context.it = context.specify = function(title, fn){ var suite = suites[0]; if (suite.pending) var fn = null; var test = new Test(title, fn); suite.addTest(test); return test; }; /** * Exclusive test-case. */ context.it.only = function(title, fn){ var test = context.it(title, fn); var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$'; mocha.grep(new RegExp(reString)); return test; }; /** * Pending test case. */ context.xit = context.xspecify = context.it.skip = function(title){ context.it(title); }; }); }; }); // module: interfaces/bdd.js require.register("interfaces/exports.js", function(module, exports, require){ /** * Module dependencies. */ var Suite = require('../suite') , Test = require('../test'); /** * TDD-style interface: * * exports.Array = { * '#indexOf()': { * 'should return -1 when the value is not present': function(){ * * }, * * 'should return the correct index when the value is present': function(){ * * } * } * }; * */ module.exports = function(suite){ var suites = [suite]; suite.on('require', visit); function visit(obj) { var suite; for (var key in obj) { if ('function' == typeof obj[key]) { var fn = obj[key]; switch (key) { case 'before': suites[0].beforeAll(fn); break; case 'after': suites[0].afterAll(fn); break; case 'beforeEach': suites[0].beforeEach(fn); break; case 'afterEach': suites[0].afterEach(fn); break; default: suites[0].addTest(new Test(key, fn)); } } else { var suite = Suite.create(suites[0], key); suites.unshift(suite); visit(obj[key]); suites.shift(); } } } }; }); // module: interfaces/exports.js require.register("interfaces/index.js", function(module, exports, require){ exports.bdd = require('./bdd'); exports.tdd = require('./tdd'); exports.qunit = require('./qunit'); exports.exports = require('./exports'); }); // module: interfaces/index.js require.register("interfaces/qunit.js", function(module, exports, require){ /** * Module dependencies. */ var Suite = require('../suite') , Test = require('../test') , utils = require('../utils'); /** * QUnit-style interface: * * suite('Array'); * * test('#length', function(){ * var arr = [1,2,3]; * ok(arr.length == 3); * }); * * test('#indexOf()', function(){ * var arr = [1,2,3]; * ok(arr.indexOf(1) == 0); * ok(arr.indexOf(2) == 1); * ok(arr.indexOf(3) == 2); * }); * * suite('String'); * * test('#length', function(){ * ok('foo'.length == 3); * }); * */ module.exports = function(suite){ var suites = [suite]; suite.on('pre-require', function(context, file, mocha){ /** * Execute before running tests. */ context.before = function(name, fn){ suites[0].beforeAll(name, fn); }; /** * Execute after running tests. */ context.after = function(name, fn){ suites[0].afterAll(name, fn); }; /** * Execute before each test case. */ context.beforeEach = function(name, fn){ suites[0].beforeEach(name, fn); }; /** * Execute after each test case. */ context.afterEach = function(name, fn){ suites[0].afterEach(name, fn); }; /** * Describe a "suite" with the given `title`. */ context.suite = function(title){ if (suites.length > 1) suites.shift(); var suite = Suite.create(suites[0], title); suites.unshift(suite); return suite; }; /** * Exclusive test-case. */ context.suite.only = function(title, fn){ var suite = context.suite(title, fn); mocha.grep(suite.fullTitle()); }; /** * Describe a specification or test-case * with the given `title` and callback `fn` * acting as a thunk. */ context.test = function(title, fn){ var test = new Test(title, fn); suites[0].addTest(test); return test; }; /** * Exclusive test-case. */ context.test.only = function(title, fn){ var test = context.test(title, fn); var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$'; mocha.grep(new RegExp(reString)); }; /** * Pending test case. */ context.test.skip = function(title){ context.test(title); }; }); }; }); // module: interfaces/qunit.js require.register("interfaces/tdd.js", function(module, exports, require){ /** * Module dependencies. */ var Suite = require('../suite') , Test = require('../test') , utils = require('../utils');; /** * TDD-style interface: * * suite('Array', function(){ * suite('#indexOf()', function(){ * suiteSetup(function(){ * * }); * * test('should return -1 when not present', function(){ * * }); * * test('should return the index when present', function(){ * * }); * * suiteTeardown(function(){ * * }); * }); * }); * */ module.exports = function(suite){ var suites = [suite]; suite.on('pre-require', function(context, file, mocha){ /** * Execute before each test case. */ context.setup = function(name, fn){ suites[0].beforeEach(name, fn); }; /** * Execute after each test case. */ context.teardown = function(name, fn){ suites[0].afterEach(name, fn); }; /** * Execute before the suite. */ context.suiteSetup = function(name, fn){ suites[0].beforeAll(name, fn); }; /** * Execute after the suite. */ context.suiteTeardown = function(name, fn){ suites[0].afterAll(name, fn); }; /** * Describe a "suite" with the given `title` * and callback `fn` containing nested suites * and/or tests. */ context.suite = function(title, fn){ var suite = Suite.create(suites[0], title); suites.unshift(suite); fn.call(suite); suites.shift(); return suite; }; /** * Pending suite. */ context.suite.skip = function(title, fn) { var suite = Suite.create(suites[0], title); suite.pending = true; suites.unshift(suite); fn.call(suite); suites.shift(); }; /** * Exclusive test-case. */ context.suite.only = function(title, fn){ var suite = context.suite(title, fn); mocha.grep(suite.fullTitle()); }; /** * Describe a specification or test-case * with the given `title` and callback `fn` * acting as a thunk. */ context.test = function(title, fn){ var suite = suites[0]; if (suite.pending) var fn = null; var test = new Test(title, fn); suite.addTest(test); return test; }; /** * Exclusive test-case. */ context.test.only = function(title, fn){ var test = context.test(title, fn); var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$'; mocha.grep(new RegExp(reString)); }; /** * Pending test case. */ context.test.skip = function(title){ context.test(title); }; }); }; }); // module: interfaces/tdd.js require.register("mocha.js", function(module, exports, require){ /*! * mocha * Copyright(c) 2011 TJ Holowaychuk * MIT Licensed */ /** * Module dependencies. */ var path = require('browser/path') , utils = require('./utils'); /** * Expose `Mocha`. */ exports = module.exports = Mocha; /** * Expose internals. */ exports.utils = utils; exports.interfaces = require('./interfaces'); exports.reporters = require('./reporters'); exports.Runnable = require('./runnable'); exports.Context = require('./context'); exports.Runner = require('./runner'); exports.Suite = require('./suite'); exports.Hook = require('./hook'); exports.Test = require('./test'); /** * Return image `name` path. * * @param {String} name * @return {String} * @api private */ function image(name) { return __dirname + '/../images/' + name + '.png'; } /** * Setup mocha with `options`. * * Options: * * - `ui` name "bdd", "tdd", "exports" etc * - `reporter` reporter instance, defaults to `mocha.reporters.Dot` * - `globals` array of accepted globals * - `timeout` timeout in milliseconds * - `bail` bail on the first test failure * - `slow` milliseconds to wait before considering a test slow * - `ignoreLeaks` ignore global leaks * - `grep` string or regexp to filter tests with * * @param {Object} options * @api public */ function Mocha(options) { options = options || {}; this.files = []; this.options = options; this.grep(options.grep); this.suite = new exports.Suite('', new exports.Context); this.ui(options.ui); this.bail(options.bail); this.reporter(options.reporter); if (null != options.timeout) this.timeout(options.timeout); this.useColors(options.useColors) if (options.slow) this.slow(options.slow); this.suite.on('pre-require', function (context) { exports.afterEach = context.afterEach || context.teardown; exports.after = context.after || context.suiteTeardown; exports.beforeEach = context.beforeEach || context.setup; exports.before = context.before || context.suiteSetup; exports.describe = context.describe || context.suite; exports.it = context.it || context.test; exports.setup = context.setup || context.beforeEach; exports.suiteSetup = context.suiteSetup || context.before; exports.suiteTeardown = context.suiteTeardown || context.after; exports.suite = context.suite || context.describe; exports.teardown = context.teardown || context.afterEach; exports.test = context.test || context.it; }); } /** * Enable or disable bailing on the first failure. * * @param {Boolean} [bail] * @api public */ Mocha.prototype.bail = function(bail){ if (0 == arguments.length) bail = true; this.suite.bail(bail); return this; }; /** * Add test `file`. * * @param {String} file * @api public */ Mocha.prototype.addFile = function(file){ this.files.push(file); return this; }; /** * Set reporter to `reporter`, defaults to "dot". * * @param {String|Function} reporter name or constructor * @api public */ Mocha.prototype.reporter = function(reporter){ if ('function' == typeof reporter) { this._reporter = reporter; } else { reporter = reporter || 'dot'; var _reporter; try { _reporter = require('./reporters/' + reporter); } catch (err) {}; if (!_reporter) try { _reporter = require(reporter); } catch (err) {}; if (!_reporter && reporter === 'teamcity') console.warn('The Teamcity reporter was moved to a package named ' + 'mocha-teamcity-reporter ' + '(https://npmjs.org/package/mocha-teamcity-reporter).'); if (!_reporter) throw new Error('invalid reporter "' + reporter + '"'); this._reporter = _reporter; } return this; }; /** * Set test UI `name`, defaults to "bdd". * * @param {String} bdd * @api public */ Mocha.prototype.ui = function(name){ name = name || 'bdd'; this._ui = exports.interfaces[name]; if (!this._ui) try { this._ui = require(name); } catch (err) {}; if (!this._ui) throw new Error('invalid interface "' + name + '"'); this._ui = this._ui(this.suite); return this; }; /** * Load registered files. * * @api private */ Mocha.prototype.loadFiles = function(fn){ var self = this; var suite = this.suite; var pending = this.files.length; this.files.forEach(function(file){ file = path.resolve(file); suite.emit('pre-require', global, file, self); suite.emit('require', require(file), file, self); suite.emit('post-require', global, file, self); --pending || (fn && fn()); }); }; /** * Enable growl support. * * @api private */ Mocha.prototype._growl = function(runner, reporter) { var notify = require('growl'); runner.on('end', function(){ var stats = reporter.stats; if (stats.failures) { var msg = stats.failures + ' of ' + runner.total + ' tests failed'; notify(msg, { name: 'mocha', title: 'Failed', image: image('error') }); } else { notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', { name: 'mocha' , title: 'Passed' , image: image('ok') }); } }); }; /** * Add regexp to grep, if `re` is a string it is escaped. * * @param {RegExp|String} re * @return {Mocha} * @api public */ Mocha.prototype.grep = function(re){ this.options.grep = 'string' == typeof re ? new RegExp(utils.escapeRegexp(re)) : re; return this; }; /** * Invert `.grep()` matches. * * @return {Mocha} * @api public */ Mocha.prototype.invert = function(){ this.options.invert = true; return this; }; /** * Ignore global leaks. * * @param {Boolean} ignore * @return {Mocha} * @api public */ Mocha.prototype.ignoreLeaks = function(ignore){ this.options.ignoreLeaks = !!ignore; return this; }; /** * Enable global leak checking. * * @return {Mocha} * @api public */ Mocha.prototype.checkLeaks = function(){ this.options.ignoreLeaks = false; return this; }; /** * Enable growl support. * * @return {Mocha} * @api public */ Mocha.prototype.growl = function(){ this.options.growl = true; return this; }; /** * Ignore `globals` array or string. * * @param {Array|String} globals * @return {Mocha} * @api public */ Mocha.prototype.globals = function(globals){ this.options.globals = (this.options.globals || []).concat(globals); return this; }; /** * Emit color output. * * @param {Boolean} colors * @return {Mocha} * @api public */ Mocha.prototype.useColors = function(colors){ this.options.useColors = arguments.length && colors != undefined ? colors : true; return this; }; /** * Use inline diffs rather than +/-. * * @param {Boolean} inlineDiffs * @return {Mocha} * @api public */ Mocha.prototype.useInlineDiffs = function(inlineDiffs) { this.options.useInlineDiffs = arguments.length && inlineDiffs != undefined ? inlineDiffs : false; return this; }; /** * Set the timeout in milliseconds. * * @param {Number} timeout * @return {Mocha} * @api public */ Mocha.prototype.timeout = function(timeout){ this.suite.timeout(timeout); return this; }; /** * Set slowness threshold in milliseconds. * * @param {Number} slow * @return {Mocha} * @api public */ Mocha.prototype.slow = function(slow){ this.suite.slow(slow); return this; }; /** * Makes all tests async (accepting a callback) * * @return {Mocha} * @api public */ Mocha.prototype.asyncOnly = function(){ this.options.asyncOnly = true; return this; }; /** * Run tests and invoke `fn()` when complete. * * @param {Function} fn * @return {Runner} * @api public */ Mocha.prototype.run = function(fn){ if (this.files.length) this.loadFiles(); var suite = this.suite; var options = this.options; options.files = this.files; var runner = new exports.Runner(suite); var reporter = new this._reporter(runner, options); runner.ignoreLeaks = false !== options.ignoreLeaks; runner.asyncOnly = options.asyncOnly; if (options.grep) runner.grep(options.grep, options.invert); if (options.globals) runner.globals(options.globals); if (options.growl) this._growl(runner, reporter); exports.reporters.Base.useColors = options.useColors; exports.reporters.Base.inlineDiffs = options.useInlineDiffs; return runner.run(fn); }; }); // module: mocha.js require.register("ms.js", function(module, exports, require){ /** * Helpers. */ var s = 1000; var m = s * 60; var h = m * 60; var d = h * 24; var y = d * 365.25; /** * Parse or format the given `val`. * * Options: * * - `long` verbose formatting [false] * * @param {String|Number} val * @param {Object} options * @return {String|Number} * @api public */ module.exports = function(val, options){ options = options || {}; if ('string' == typeof val) return parse(val); return options.long ? longFormat(val) : shortFormat(val); }; /** * Parse the given `str` and return milliseconds. * * @param {String} str * @return {Number} * @api private */ function parse(str) { var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str); if (!match) return; var n = parseFloat(match[1]); var type = (match[2] || 'ms').toLowerCase(); switch (type) { case 'years': case 'year': case 'y': return n * y; case 'days': case 'day': case 'd': return n * d; case 'hours': case 'hour': case 'h': return n * h; case 'minutes': case 'minute': case 'm': return n * m; case 'seconds': case 'second': case 's': return n * s; case 'ms': return n; } } /** * Short format for `ms`. * * @param {Number} ms * @return {String} * @api private */ function shortFormat(ms) { if (ms >= d) return Math.round(ms / d) + 'd'; if (ms >= h) return Math.round(ms / h) + 'h'; if (ms >= m) return Math.round(ms / m) + 'm'; if (ms >= s) return Math.round(ms / s) + 's'; return ms + 'ms'; } /** * Long format for `ms`. * * @param {Number} ms * @return {String} * @api private */ function longFormat(ms) { return plural(ms, d, 'day') || plural(ms, h, 'hour') || plural(ms, m, 'minute') || plural(ms, s, 'second') || ms + ' ms'; } /** * Pluralization helper. */ function plural(ms, n, name) { if (ms < n) return; if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name; return Math.ceil(ms / n) + ' ' + name + 's'; } }); // module: ms.js require.register("reporters/base.js", function(module, exports, require){ /** * Module dependencies. */ var tty = require('browser/tty') , diff = require('browser/diff') , ms = require('../ms') , utils = require('../utils'); /** * Save timer references to avoid Sinon interfering (see GH-237). */ var Date = global.Date , setTimeout = global.setTimeout , setInterval = global.setInterval , clearTimeout = global.clearTimeout , clearInterval = global.clearInterval; /** * Check if both stdio streams are associated with a tty. */ var isatty = tty.isatty(1) && tty.isatty(2); /** * Expose `Base`. */ exports = module.exports = Base; /** * Enable coloring by default. */ exports.useColors = isatty || (process.env.MOCHA_COLORS !== undefined); /** * Inline diffs instead of +/- */ exports.inlineDiffs = false; /** * Default color map. */ exports.colors = { 'pass': 90 , 'fail': 31 , 'bright pass': 92 , 'bright fail': 91 , 'bright yellow': 93 , 'pending': 36 , 'suite': 0 , 'error title': 0 , 'error message': 31 , 'error stack': 90 , 'checkmark': 32 , 'fast': 90 , 'medium': 33 , 'slow': 31 , 'green': 32 , 'light': 90 , 'diff gutter': 90 , 'diff added': 42 , 'diff removed': 41 }; /** * Default symbol map. */ exports.symbols = { ok: '✓', err: '✖', dot: '․' }; // With node.js on Windows: use symbols available in terminal default fonts if ('win32' == process.platform) { exports.symbols.ok = '\u221A'; exports.symbols.err = '\u00D7'; exports.symbols.dot = '.'; } /** * Color `str` with the given `type`, * allowing colors to be disabled, * as well as user-defined color * schemes. * * @param {String} type * @param {String} str * @return {String} * @api private */ var color = exports.color = function(type, str) { if (!exports.useColors) return str; return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m'; }; /** * Expose term window size, with some * defaults for when stderr is not a tty. */ exports.window = { width: isatty ? process.stdout.getWindowSize ? process.stdout.getWindowSize(1)[0] : tty.getWindowSize()[1] : 75 }; /** * Expose some basic cursor interactions * that are common among reporters. */ exports.cursor = { hide: function(){ isatty && process.stdout.write('\u001b[?25l'); }, show: function(){ isatty && process.stdout.write('\u001b[?25h'); }, deleteLine: function(){ isatty && process.stdout.write('\u001b[2K'); }, beginningOfLine: function(){ isatty && process.stdout.write('\u001b[0G'); }, CR: function(){ if (isatty) { exports.cursor.deleteLine(); exports.cursor.beginningOfLine(); } else { process.stdout.write('\r'); } } }; /** * Outut the given `failures` as a list. * * @param {Array} failures * @api public */ exports.list = function(failures){ console.error(); failures.forEach(function(test, i){ // format var fmt = color('error title', ' %s) %s:\n') + color('error message', ' %s') + color('error stack', '\n%s\n'); // msg var err = test.err , message = err.message || '' , stack = err.stack || message , index = stack.indexOf(message) + message.length , msg = stack.slice(0, index) , actual = err.actual , expected = err.expected , escape = true; // uncaught if (err.uncaught) { msg = 'Uncaught ' + msg; } // explicitly show diff if (err.showDiff && sameType(actual, expected)) { escape = false; err.actual = actual = stringify(canonicalize(actual)); err.expected = expected = stringify(canonicalize(expected)); } // actual / expected diff if ('string' == typeof actual && 'string' == typeof expected) { fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n'); var match = message.match(/^([^:]+): expected/); msg = '\n ' + color('error message', match ? match[1] : msg); if (exports.inlineDiffs) { msg += inlineDiff(err, escape); } else { msg += unifiedDiff(err, escape); } } // indent stack trace without msg stack = stack.slice(index ? index + 1 : index) .replace(/^/gm, ' '); console.error(fmt, (i + 1), test.fullTitle(), msg, stack); }); }; /** * Initialize a new `Base` reporter. * * All other reporters generally * inherit from this reporter, providing * stats such as test duration, number * of tests passed / failed etc. * * @param {Runner} runner * @api public */ function Base(runner) { var self = this , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 } , failures = this.failures = []; if (!runner) return; this.runner = runner; runner.stats = stats; runner.on('start', function(){ stats.start = new Date; }); runner.on('suite', function(suite){ stats.suites = stats.suites || 0; suite.root || stats.suites++; }); runner.on('test end', function(test){ stats.tests = stats.tests || 0; stats.tests++; }); runner.on('pass', function(test){ stats.passes = stats.passes || 0; var medium = test.slow() / 2; test.speed = test.duration > test.slow() ? 'slow' : test.duration > medium ? 'medium' : 'fast'; stats.passes++; }); runner.on('fail', function(test, err){ stats.failures = stats.failures || 0; stats.failures++; test.err = err; failures.push(test); }); runner.on('end', function(){ stats.end = new Date; stats.duration = new Date - stats.start; }); runner.on('pending', function(){ stats.pending++; }); } /** * Output common epilogue used by many of * the bundled reporters. * * @api public */ Base.prototype.epilogue = function(){ var stats = this.stats; var tests; var fmt; console.log(); // passes fmt = color('bright pass', ' ') + color('green', ' %d passing') + color('light', ' (%s)'); console.log(fmt, stats.passes || 0, ms(stats.duration)); // pending if (stats.pending) { fmt = color('pending', ' ') + color('pending', ' %d pending'); console.log(fmt, stats.pending); } // failures if (stats.failures) { fmt = color('fail', ' %d failing'); console.error(fmt, stats.failures); Base.list(this.failures); console.error(); } console.log(); }; /** * Pad the given `str` to `len`. * * @param {String} str * @param {String} len * @return {String} * @api private */ function pad(str, len) { str = String(str); return Array(len - str.length + 1).join(' ') + str; } /** * Returns an inline diff between 2 strings with coloured ANSI output * * @param {Error} Error with actual/expected * @return {String} Diff * @api private */ function inlineDiff(err, escape) { var msg = errorDiff(err, 'WordsWithSpace', escape); // linenos var lines = msg.split('\n'); if (lines.length > 4) { var width = String(lines.length).length; msg = lines.map(function(str, i){ return pad(++i, width) + ' |' + ' ' + str; }).join('\n'); } // legend msg = '\n' + color('diff removed', 'actual') + ' ' + color('diff added', 'expected') + '\n\n' + msg + '\n'; // indent msg = msg.replace(/^/gm, ' '); return msg; } /** * Returns a unified diff between 2 strings * * @param {Error} Error with actual/expected * @return {String} Diff * @api private */ function unifiedDiff(err, escape) { var indent = ' '; function cleanUp(line) { if (escape) { line = escapeInvisibles(line); } if (line[0] === '+') return indent + colorLines('diff added', line); if (line[0] === '-') return indent + colorLines('diff removed', line); if (line.match(/\@\@/)) return null; if (line.match(/\\ No newline/)) return null; else return indent + line; } function notBlank(line) { return line != null; } msg = diff.createPatch('string', err.actual, err.expected); var lines = msg.split('\n').splice(4); return '\n ' + colorLines('diff added', '+ expected') + ' ' + colorLines('diff removed', '- actual') + '\n\n' + lines.map(cleanUp).filter(notBlank).join('\n'); } /** * Return a character diff for `err`. * * @param {Error} err * @return {String} * @api private */ function errorDiff(err, type, escape) { var actual = escape ? escapeInvisibles(err.actual) : err.actual; var expected = escape ? escapeInvisibles(err.expected) : err.expected; return diff['diff' + type](actual, expected).map(function(str){ if (str.added) return colorLines('diff added', str.value); if (str.removed) return colorLines('diff removed', str.value); return str.value; }).join(''); } /** * Returns a string with all invisible characters in plain text * * @param {String} line * @return {String} * @api private */ function escapeInvisibles(line) { return line.replace(/\t/g, '') .replace(/\r/g, '') .replace(/\n/g, '\n'); } /** * Color lines for `str`, using the color `name`. * * @param {String} name * @param {String} str * @return {String} * @api private */ function colorLines(name, str) { return str.split('\n').map(function(str){ return color(name, str); }).join('\n'); } /** * Stringify `obj`. * * @param {Object} obj * @return {String} * @api private */ function stringify(obj) { if (obj instanceof RegExp) return obj.toString(); return JSON.stringify(obj, null, 2); } /** * Return a new object that has the keys in sorted order. * @param {Object} obj * @return {Object} * @api private */ function canonicalize(obj, stack) { stack = stack || []; if (utils.indexOf(stack, obj) !== -1) return obj; var canonicalizedObj; if ('[object Array]' == {}.toString.call(obj)) { stack.push(obj); canonicalizedObj = utils.map(obj, function(item) { return canonicalize(item, stack); }); stack.pop(); } else if (typeof obj === 'object' && obj !== null) { stack.push(obj); canonicalizedObj = {}; utils.forEach(utils.keys(obj).sort(), function(key) { canonicalizedObj[key] = canonicalize(obj[key], stack); }); stack.pop(); } else { canonicalizedObj = obj; } return canonicalizedObj; } /** * Check that a / b have the same type. * * @param {Object} a * @param {Object} b * @return {Boolean} * @api private */ function sameType(a, b) { a = Object.prototype.toString.call(a); b = Object.prototype.toString.call(b); return a == b; } }); // module: reporters/base.js require.register("reporters/doc.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , utils = require('../utils'); /** * Expose `Doc`. */ exports = module.exports = Doc; /** * Initialize a new `Doc` reporter. * * @param {Runner} runner * @api public */ function Doc(runner) { Base.call(this, runner); var self = this , stats = this.stats , total = runner.total , indents = 2; function indent() { return Array(indents).join(' '); } runner.on('suite', function(suite){ if (suite.root) return; ++indents; console.log('%s
    ', indent()); ++indents; console.log('%s

    %s

    ', indent(), utils.escape(suite.title)); console.log('%s
    ', indent()); }); runner.on('suite end', function(suite){ if (suite.root) return; console.log('%s
    ', indent()); --indents; console.log('%s
    ', indent()); --indents; }); runner.on('pass', function(test){ console.log('%s
    %s
    ', indent(), utils.escape(test.title)); var code = utils.escape(utils.clean(test.fn.toString())); console.log('%s
    %s
    ', indent(), code); }); } }); // module: reporters/doc.js require.register("reporters/dot.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , color = Base.color; /** * Expose `Dot`. */ exports = module.exports = Dot; /** * Initialize a new `Dot` matrix test reporter. * * @param {Runner} runner * @api public */ function Dot(runner) { Base.call(this, runner); var self = this , stats = this.stats , width = Base.window.width * .75 | 0 , n = 0; runner.on('start', function(){ process.stdout.write('\n '); }); runner.on('pending', function(test){ process.stdout.write(color('pending', Base.symbols.dot)); }); runner.on('pass', function(test){ if (++n % width == 0) process.stdout.write('\n '); if ('slow' == test.speed) { process.stdout.write(color('bright yellow', Base.symbols.dot)); } else { process.stdout.write(color(test.speed, Base.symbols.dot)); } }); runner.on('fail', function(test, err){ if (++n % width == 0) process.stdout.write('\n '); process.stdout.write(color('fail', Base.symbols.dot)); }); runner.on('end', function(){ console.log(); self.epilogue(); }); } /** * Inherit from `Base.prototype`. */ function F(){}; F.prototype = Base.prototype; Dot.prototype = new F; Dot.prototype.constructor = Dot; }); // module: reporters/dot.js require.register("reporters/html-cov.js", function(module, exports, require){ /** * Module dependencies. */ var JSONCov = require('./json-cov') , fs = require('browser/fs'); /** * Expose `HTMLCov`. */ exports = module.exports = HTMLCov; /** * Initialize a new `JsCoverage` reporter. * * @param {Runner} runner * @api public */ function HTMLCov(runner) { var jade = require('jade') , file = __dirname + '/templates/coverage.jade' , str = fs.readFileSync(file, 'utf8') , fn = jade.compile(str, { filename: file }) , self = this; JSONCov.call(this, runner, false); runner.on('end', function(){ process.stdout.write(fn({ cov: self.cov , coverageClass: coverageClass })); }); } /** * Return coverage class for `n`. * * @return {String} * @api private */ function coverageClass(n) { if (n >= 75) return 'high'; if (n >= 50) return 'medium'; if (n >= 25) return 'low'; return 'terrible'; } }); // module: reporters/html-cov.js require.register("reporters/html.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , utils = require('../utils') , Progress = require('../browser/progress') , escape = utils.escape; /** * Save timer references to avoid Sinon interfering (see GH-237). */ var Date = global.Date , setTimeout = global.setTimeout , setInterval = global.setInterval , clearTimeout = global.clearTimeout , clearInterval = global.clearInterval; /** * Expose `HTML`. */ exports = module.exports = HTML; /** * Stats template. */ var statsTemplate = ''; /** * Initialize a new `HTML` reporter. * * @param {Runner} runner * @api public */ function HTML(runner) { Base.call(this, runner); var self = this , stats = this.stats , total = runner.total , stat = fragment(statsTemplate) , items = stat.getElementsByTagName('li') , passes = items[1].getElementsByTagName('em')[0] , passesLink = items[1].getElementsByTagName('a')[0] , failures = items[2].getElementsByTagName('em')[0] , failuresLink = items[2].getElementsByTagName('a')[0] , duration = items[3].getElementsByTagName('em')[0] , canvas = stat.getElementsByTagName('canvas')[0] , report = fragment('
      ') , stack = [report] , progress , ctx , root = document.getElementById('mocha'); if (canvas.getContext) { var ratio = window.devicePixelRatio || 1; canvas.style.width = canvas.width; canvas.style.height = canvas.height; canvas.width *= ratio; canvas.height *= ratio; ctx = canvas.getContext('2d'); ctx.scale(ratio, ratio); progress = new Progress; } if (!root) return error('#mocha div missing, add it to your document'); // pass toggle on(passesLink, 'click', function(){ unhide(); var name = /pass/.test(report.className) ? '' : ' pass'; report.className = report.className.replace(/fail|pass/g, '') + name; if (report.className.trim()) hideSuitesWithout('test pass'); }); // failure toggle on(failuresLink, 'click', function(){ unhide(); var name = /fail/.test(report.className) ? '' : ' fail'; report.className = report.className.replace(/fail|pass/g, '') + name; if (report.className.trim()) hideSuitesWithout('test fail'); }); root.appendChild(stat); root.appendChild(report); if (progress) progress.size(40); runner.on('suite', function(suite){ if (suite.root) return; // suite var url = self.suiteURL(suite); var el = fragment('
    • %s

    • ', url, escape(suite.title)); // container stack[0].appendChild(el); stack.unshift(document.createElement('ul')); el.appendChild(stack[0]); }); runner.on('suite end', function(suite){ if (suite.root) return; stack.shift(); }); runner.on('fail', function(test, err){ if ('hook' == test.type) runner.emit('test end', test); }); runner.on('test end', function(test){ // TODO: add to stats var percent = stats.tests / this.total * 100 | 0; if (progress) progress.update(percent).draw(ctx); // update stats var ms = new Date - stats.start; text(passes, stats.passes); text(failures, stats.failures); text(duration, (ms / 1000).toFixed(2)); // test if ('passed' == test.state) { var url = self.testURL(test); var el = fragment('
    • %e%ems

    • ', test.speed, test.title, test.duration, url); } else if (test.pending) { var el = fragment('
    • %e

    • ', test.title); } else { var el = fragment('
    • %e

    • ', test.title, encodeURIComponent(test.fullTitle())); var str = test.err.stack || test.err.toString(); // FF / Opera do not add the message if (!~str.indexOf(test.err.message)) { str = test.err.message + '\n' + str; } // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we // check for the result of the stringifying. if ('[object Error]' == str) str = test.err.message; // Safari doesn't give you a stack. Let's at least provide a source line. if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) { str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")"; } el.appendChild(fragment('
      %e
      ', str)); } // toggle code // TODO: defer if (!test.pending) { var h2 = el.getElementsByTagName('h2')[0]; on(h2, 'click', function(){ pre.style.display = 'none' == pre.style.display ? 'block' : 'none'; }); var pre = fragment('
      %e
      ', utils.clean(test.fn.toString())); el.appendChild(pre); pre.style.display = 'none'; } // Don't call .appendChild if #mocha-report was already .shift()'ed off the stack. if (stack[0]) stack[0].appendChild(el); }); } /** * Provide suite URL * * @param {Object} [suite] */ HTML.prototype.suiteURL = function(suite){ return '?grep=' + encodeURIComponent(suite.fullTitle()); }; /** * Provide test URL * * @param {Object} [test] */ HTML.prototype.testURL = function(test){ return '?grep=' + encodeURIComponent(test.fullTitle()); }; /** * Display error `msg`. */ function error(msg) { document.body.appendChild(fragment('
      %s
      ', msg)); } /** * Return a DOM fragment from `html`. */ function fragment(html) { var args = arguments , div = document.createElement('div') , i = 1; div.innerHTML = html.replace(/%([se])/g, function(_, type){ switch (type) { case 's': return String(args[i++]); case 'e': return escape(args[i++]); } }); return div.firstChild; } /** * Check for suites that do not have elements * with `classname`, and hide them. */ function hideSuitesWithout(classname) { var suites = document.getElementsByClassName('suite'); for (var i = 0; i < suites.length; i++) { var els = suites[i].getElementsByClassName(classname); if (0 == els.length) suites[i].className += ' hidden'; } } /** * Unhide .hidden suites. */ function unhide() { var els = document.getElementsByClassName('suite hidden'); for (var i = 0; i < els.length; ++i) { els[i].className = els[i].className.replace('suite hidden', 'suite'); } } /** * Set `el` text to `str`. */ function text(el, str) { if (el.textContent) { el.textContent = str; } else { el.innerText = str; } } /** * Listen on `event` with callback `fn`. */ function on(el, event, fn) { if (el.addEventListener) { el.addEventListener(event, fn, false); } else { el.attachEvent('on' + event, fn); } } }); // module: reporters/html.js require.register("reporters/index.js", function(module, exports, require){ exports.Base = require('./base'); exports.Dot = require('./dot'); exports.Doc = require('./doc'); exports.TAP = require('./tap'); exports.JSON = require('./json'); exports.HTML = require('./html'); exports.List = require('./list'); exports.Min = require('./min'); exports.Spec = require('./spec'); exports.Nyan = require('./nyan'); exports.XUnit = require('./xunit'); exports.Markdown = require('./markdown'); exports.Progress = require('./progress'); exports.Landing = require('./landing'); exports.JSONCov = require('./json-cov'); exports.HTMLCov = require('./html-cov'); exports.JSONStream = require('./json-stream'); }); // module: reporters/index.js require.register("reporters/json-cov.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base'); /** * Expose `JSONCov`. */ exports = module.exports = JSONCov; /** * Initialize a new `JsCoverage` reporter. * * @param {Runner} runner * @param {Boolean} output * @api public */ function JSONCov(runner, output) { var self = this , output = 1 == arguments.length ? true : output; Base.call(this, runner); var tests = [] , failures = [] , passes = []; runner.on('test end', function(test){ tests.push(test); }); runner.on('pass', function(test){ passes.push(test); }); runner.on('fail', function(test){ failures.push(test); }); runner.on('end', function(){ var cov = global._$jscoverage || {}; var result = self.cov = map(cov); result.stats = self.stats; result.tests = tests.map(clean); result.failures = failures.map(clean); result.passes = passes.map(clean); if (!output) return; process.stdout.write(JSON.stringify(result, null, 2 )); }); } /** * Map jscoverage data to a JSON structure * suitable for reporting. * * @param {Object} cov * @return {Object} * @api private */ function map(cov) { var ret = { instrumentation: 'node-jscoverage' , sloc: 0 , hits: 0 , misses: 0 , coverage: 0 , files: [] }; for (var filename in cov) { var data = coverage(filename, cov[filename]); ret.files.push(data); ret.hits += data.hits; ret.misses += data.misses; ret.sloc += data.sloc; } ret.files.sort(function(a, b) { return a.filename.localeCompare(b.filename); }); if (ret.sloc > 0) { ret.coverage = (ret.hits / ret.sloc) * 100; } return ret; }; /** * Map jscoverage data for a single source file * to a JSON structure suitable for reporting. * * @param {String} filename name of the source file * @param {Object} data jscoverage coverage data * @return {Object} * @api private */ function coverage(filename, data) { var ret = { filename: filename, coverage: 0, hits: 0, misses: 0, sloc: 0, source: {} }; data.source.forEach(function(line, num){ num++; if (data[num] === 0) { ret.misses++; ret.sloc++; } else if (data[num] !== undefined) { ret.hits++; ret.sloc++; } ret.source[num] = { source: line , coverage: data[num] === undefined ? '' : data[num] }; }); ret.coverage = ret.hits / ret.sloc * 100; return ret; } /** * Return a plain-object representation of `test` * free of cyclic properties etc. * * @param {Object} test * @return {Object} * @api private */ function clean(test) { return { title: test.title , fullTitle: test.fullTitle() , duration: test.duration } } }); // module: reporters/json-cov.js require.register("reporters/json-stream.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , color = Base.color; /** * Expose `List`. */ exports = module.exports = List; /** * Initialize a new `List` test reporter. * * @param {Runner} runner * @api public */ function List(runner) { Base.call(this, runner); var self = this , stats = this.stats , total = runner.total; runner.on('start', function(){ console.log(JSON.stringify(['start', { total: total }])); }); runner.on('pass', function(test){ console.log(JSON.stringify(['pass', clean(test)])); }); runner.on('fail', function(test, err){ console.log(JSON.stringify(['fail', clean(test)])); }); runner.on('end', function(){ process.stdout.write(JSON.stringify(['end', self.stats])); }); } /** * Return a plain-object representation of `test` * free of cyclic properties etc. * * @param {Object} test * @return {Object} * @api private */ function clean(test) { return { title: test.title , fullTitle: test.fullTitle() , duration: test.duration } } }); // module: reporters/json-stream.js require.register("reporters/json.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `JSON`. */ exports = module.exports = JSONReporter; /** * Initialize a new `JSON` reporter. * * @param {Runner} runner * @api public */ function JSONReporter(runner) { var self = this; Base.call(this, runner); var tests = [] , failures = [] , passes = []; runner.on('test end', function(test){ tests.push(test); }); runner.on('pass', function(test){ passes.push(test); }); runner.on('fail', function(test){ failures.push(test); }); runner.on('end', function(){ var obj = { stats: self.stats , tests: tests.map(clean) , failures: failures.map(clean) , passes: passes.map(clean) }; process.stdout.write(JSON.stringify(obj, null, 2)); }); } /** * Return a plain-object representation of `test` * free of cyclic properties etc. * * @param {Object} test * @return {Object} * @api private */ function clean(test) { return { title: test.title , fullTitle: test.fullTitle() , duration: test.duration } } }); // module: reporters/json.js require.register("reporters/landing.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `Landing`. */ exports = module.exports = Landing; /** * Airplane color. */ Base.colors.plane = 0; /** * Airplane crash color. */ Base.colors['plane crash'] = 31; /** * Runway color. */ Base.colors.runway = 90; /** * Initialize a new `Landing` reporter. * * @param {Runner} runner * @api public */ function Landing(runner) { Base.call(this, runner); var self = this , stats = this.stats , width = Base.window.width * .75 | 0 , total = runner.total , stream = process.stdout , plane = color('plane', '✈') , crashed = -1 , n = 0; function runway() { var buf = Array(width).join('-'); return ' ' + color('runway', buf); } runner.on('start', function(){ stream.write('\n '); cursor.hide(); }); runner.on('test end', function(test){ // check if the plane crashed var col = -1 == crashed ? width * ++n / total | 0 : crashed; // show the crash if ('failed' == test.state) { plane = color('plane crash', '✈'); crashed = col; } // render landing strip stream.write('\u001b[4F\n\n'); stream.write(runway()); stream.write('\n '); stream.write(color('runway', Array(col).join('⋅'))); stream.write(plane) stream.write(color('runway', Array(width - col).join('⋅') + '\n')); stream.write(runway()); stream.write('\u001b[0m'); }); runner.on('end', function(){ cursor.show(); console.log(); self.epilogue(); }); } /** * Inherit from `Base.prototype`. */ function F(){}; F.prototype = Base.prototype; Landing.prototype = new F; Landing.prototype.constructor = Landing; }); // module: reporters/landing.js require.register("reporters/list.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `List`. */ exports = module.exports = List; /** * Initialize a new `List` test reporter. * * @param {Runner} runner * @api public */ function List(runner) { Base.call(this, runner); var self = this , stats = this.stats , n = 0; runner.on('start', function(){ console.log(); }); runner.on('test', function(test){ process.stdout.write(color('pass', ' ' + test.fullTitle() + ': ')); }); runner.on('pending', function(test){ var fmt = color('checkmark', ' -') + color('pending', ' %s'); console.log(fmt, test.fullTitle()); }); runner.on('pass', function(test){ var fmt = color('checkmark', ' '+Base.symbols.dot) + color('pass', ' %s: ') + color(test.speed, '%dms'); cursor.CR(); console.log(fmt, test.fullTitle(), test.duration); }); runner.on('fail', function(test, err){ cursor.CR(); console.log(color('fail', ' %d) %s'), ++n, test.fullTitle()); }); runner.on('end', self.epilogue.bind(self)); } /** * Inherit from `Base.prototype`. */ function F(){}; F.prototype = Base.prototype; List.prototype = new F; List.prototype.constructor = List; }); // module: reporters/list.js require.register("reporters/markdown.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , utils = require('../utils'); /** * Expose `Markdown`. */ exports = module.exports = Markdown; /** * Initialize a new `Markdown` reporter. * * @param {Runner} runner * @api public */ function Markdown(runner) { Base.call(this, runner); var self = this , stats = this.stats , level = 0 , buf = ''; function title(str) { return Array(level).join('#') + ' ' + str; } function indent() { return Array(level).join(' '); } function mapTOC(suite, obj) { var ret = obj; obj = obj[suite.title] = obj[suite.title] || { suite: suite }; suite.suites.forEach(function(suite){ mapTOC(suite, obj); }); return ret; } function stringifyTOC(obj, level) { ++level; var buf = ''; var link; for (var key in obj) { if ('suite' == key) continue; if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n'; if (key) buf += Array(level).join(' ') + link; buf += stringifyTOC(obj[key], level); } --level; return buf; } function generateTOC(suite) { var obj = mapTOC(suite, {}); return stringifyTOC(obj, 0); } generateTOC(runner.suite); runner.on('suite', function(suite){ ++level; var slug = utils.slug(suite.fullTitle()); buf += '' + '\n'; buf += title(suite.title) + '\n'; }); runner.on('suite end', function(suite){ --level; }); runner.on('pass', function(test){ var code = utils.clean(test.fn.toString()); buf += test.title + '.\n'; buf += '\n```js\n'; buf += code + '\n'; buf += '```\n\n'; }); runner.on('end', function(){ process.stdout.write('# TOC\n'); process.stdout.write(generateTOC(runner.suite)); process.stdout.write(buf); }); } }); // module: reporters/markdown.js require.register("reporters/min.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base'); /** * Expose `Min`. */ exports = module.exports = Min; /** * Initialize a new `Min` minimal test reporter (best used with --watch). * * @param {Runner} runner * @api public */ function Min(runner) { Base.call(this, runner); runner.on('start', function(){ // clear screen process.stdout.write('\u001b[2J'); // set cursor position process.stdout.write('\u001b[1;3H'); }); runner.on('end', this.epilogue.bind(this)); } /** * Inherit from `Base.prototype`. */ function F(){}; F.prototype = Base.prototype; Min.prototype = new F; Min.prototype.constructor = Min; }); // module: reporters/min.js require.register("reporters/nyan.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , color = Base.color; /** * Expose `Dot`. */ exports = module.exports = NyanCat; /** * Initialize a new `Dot` matrix test reporter. * * @param {Runner} runner * @api public */ function NyanCat(runner) { Base.call(this, runner); var self = this , stats = this.stats , width = Base.window.width * .75 | 0 , rainbowColors = this.rainbowColors = self.generateColors() , colorIndex = this.colorIndex = 0 , numerOfLines = this.numberOfLines = 4 , trajectories = this.trajectories = [[], [], [], []] , nyanCatWidth = this.nyanCatWidth = 11 , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth) , scoreboardWidth = this.scoreboardWidth = 5 , tick = this.tick = 0 , n = 0; runner.on('start', function(){ Base.cursor.hide(); self.draw(); }); runner.on('pending', function(test){ self.draw(); }); runner.on('pass', function(test){ self.draw(); }); runner.on('fail', function(test, err){ self.draw(); }); runner.on('end', function(){ Base.cursor.show(); for (var i = 0; i < self.numberOfLines; i++) write('\n'); self.epilogue(); }); } /** * Draw the nyan cat * * @api private */ NyanCat.prototype.draw = function(){ this.appendRainbow(); this.drawScoreboard(); this.drawRainbow(); this.drawNyanCat(); this.tick = !this.tick; }; /** * Draw the "scoreboard" showing the number * of passes, failures and pending tests. * * @api private */ NyanCat.prototype.drawScoreboard = function(){ var stats = this.stats; var colors = Base.colors; function draw(color, n) { write(' '); write('\u001b[' + color + 'm' + n + '\u001b[0m'); write('\n'); } draw(colors.green, stats.passes); draw(colors.fail, stats.failures); draw(colors.pending, stats.pending); write('\n'); this.cursorUp(this.numberOfLines); }; /** * Append the rainbow. * * @api private */ NyanCat.prototype.appendRainbow = function(){ var segment = this.tick ? '_' : '-'; var rainbowified = this.rainbowify(segment); for (var index = 0; index < this.numberOfLines; index++) { var trajectory = this.trajectories[index]; if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift(); trajectory.push(rainbowified); } }; /** * Draw the rainbow. * * @api private */ NyanCat.prototype.drawRainbow = function(){ var self = this; this.trajectories.forEach(function(line, index) { write('\u001b[' + self.scoreboardWidth + 'C'); write(line.join('')); write('\n'); }); this.cursorUp(this.numberOfLines); }; /** * Draw the nyan cat * * @api private */ NyanCat.prototype.drawNyanCat = function() { var self = this; var startWidth = this.scoreboardWidth + this.trajectories[0].length; var color = '\u001b[' + startWidth + 'C'; var padding = ''; write(color); write('_,------,'); write('\n'); write(color); padding = self.tick ? ' ' : ' '; write('_|' + padding + '/\\_/\\ '); write('\n'); write(color); padding = self.tick ? '_' : '__'; var tail = self.tick ? '~' : '^'; var face; write(tail + '|' + padding + this.face() + ' '); write('\n'); write(color); padding = self.tick ? ' ' : ' '; write(padding + '"" "" '); write('\n'); this.cursorUp(this.numberOfLines); }; /** * Draw nyan cat face. * * @return {String} * @api private */ NyanCat.prototype.face = function() { var stats = this.stats; if (stats.failures) { return '( x .x)'; } else if (stats.pending) { return '( o .o)'; } else if(stats.passes) { return '( ^ .^)'; } else { return '( - .-)'; } } /** * Move cursor up `n`. * * @param {Number} n * @api private */ NyanCat.prototype.cursorUp = function(n) { write('\u001b[' + n + 'A'); }; /** * Move cursor down `n`. * * @param {Number} n * @api private */ NyanCat.prototype.cursorDown = function(n) { write('\u001b[' + n + 'B'); }; /** * Generate rainbow colors. * * @return {Array} * @api private */ NyanCat.prototype.generateColors = function(){ var colors = []; for (var i = 0; i < (6 * 7); i++) { var pi3 = Math.floor(Math.PI / 3); var n = (i * (1.0 / 6)); var r = Math.floor(3 * Math.sin(n) + 3); var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3); var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3); colors.push(36 * r + 6 * g + b + 16); } return colors; }; /** * Apply rainbow to the given `str`. * * @param {String} str * @return {String} * @api private */ NyanCat.prototype.rainbowify = function(str){ var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length]; this.colorIndex += 1; return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m'; }; /** * Stdout helper. */ function write(string) { process.stdout.write(string); } /** * Inherit from `Base.prototype`. */ function F(){}; F.prototype = Base.prototype; NyanCat.prototype = new F; NyanCat.prototype.constructor = NyanCat; }); // module: reporters/nyan.js require.register("reporters/progress.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `Progress`. */ exports = module.exports = Progress; /** * General progress bar color. */ Base.colors.progress = 90; /** * Initialize a new `Progress` bar test reporter. * * @param {Runner} runner * @param {Object} options * @api public */ function Progress(runner, options) { Base.call(this, runner); var self = this , options = options || {} , stats = this.stats , width = Base.window.width * .50 | 0 , total = runner.total , complete = 0 , max = Math.max; // default chars options.open = options.open || '['; options.complete = options.complete || '▬'; options.incomplete = options.incomplete || Base.symbols.dot; options.close = options.close || ']'; options.verbose = false; // tests started runner.on('start', function(){ console.log(); cursor.hide(); }); // tests complete runner.on('test end', function(){ complete++; var incomplete = total - complete , percent = complete / total , n = width * percent | 0 , i = width - n; cursor.CR(); process.stdout.write('\u001b[J'); process.stdout.write(color('progress', ' ' + options.open)); process.stdout.write(Array(n).join(options.complete)); process.stdout.write(Array(i).join(options.incomplete)); process.stdout.write(color('progress', options.close)); if (options.verbose) { process.stdout.write(color('progress', ' ' + complete + ' of ' + total)); } }); // tests are complete, output some stats // and the failures if any runner.on('end', function(){ cursor.show(); console.log(); self.epilogue(); }); } /** * Inherit from `Base.prototype`. */ function F(){}; F.prototype = Base.prototype; Progress.prototype = new F; Progress.prototype.constructor = Progress; }); // module: reporters/progress.js require.register("reporters/spec.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `Spec`. */ exports = module.exports = Spec; /** * Initialize a new `Spec` test reporter. * * @param {Runner} runner * @api public */ function Spec(runner) { Base.call(this, runner); var self = this , stats = this.stats , indents = 0 , n = 0; function indent() { return Array(indents).join(' ') } runner.on('start', function(){ console.log(); }); runner.on('suite', function(suite){ ++indents; console.log(color('suite', '%s%s'), indent(), suite.title); }); runner.on('suite end', function(suite){ --indents; if (1 == indents) console.log(); }); runner.on('pending', function(test){ var fmt = indent() + color('pending', ' - %s'); console.log(fmt, test.title); }); runner.on('pass', function(test){ if ('fast' == test.speed) { var fmt = indent() + color('checkmark', ' ' + Base.symbols.ok) + color('pass', ' %s '); cursor.CR(); console.log(fmt, test.title); } else { var fmt = indent() + color('checkmark', ' ' + Base.symbols.ok) + color('pass', ' %s ') + color(test.speed, '(%dms)'); cursor.CR(); console.log(fmt, test.title, test.duration); } }); runner.on('fail', function(test, err){ cursor.CR(); console.log(indent() + color('fail', ' %d) %s'), ++n, test.title); }); runner.on('end', self.epilogue.bind(self)); } /** * Inherit from `Base.prototype`. */ function F(){}; F.prototype = Base.prototype; Spec.prototype = new F; Spec.prototype.constructor = Spec; }); // module: reporters/spec.js require.register("reporters/tap.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , cursor = Base.cursor , color = Base.color; /** * Expose `TAP`. */ exports = module.exports = TAP; /** * Initialize a new `TAP` reporter. * * @param {Runner} runner * @api public */ function TAP(runner) { Base.call(this, runner); var self = this , stats = this.stats , n = 1 , passes = 0 , failures = 0; runner.on('start', function(){ var total = runner.grepTotal(runner.suite); console.log('%d..%d', 1, total); }); runner.on('test end', function(){ ++n; }); runner.on('pending', function(test){ console.log('ok %d %s # SKIP -', n, title(test)); }); runner.on('pass', function(test){ passes++; console.log('ok %d %s', n, title(test)); }); runner.on('fail', function(test, err){ failures++; console.log('not ok %d %s', n, title(test)); if (err.stack) console.log(err.stack.replace(/^/gm, ' ')); }); runner.on('end', function(){ console.log('# tests ' + (passes + failures)); console.log('# pass ' + passes); console.log('# fail ' + failures); }); } /** * Return a TAP-safe title of `test` * * @param {Object} test * @return {String} * @api private */ function title(test) { return test.fullTitle().replace(/#/g, ''); } }); // module: reporters/tap.js require.register("reporters/xunit.js", function(module, exports, require){ /** * Module dependencies. */ var Base = require('./base') , utils = require('../utils') , escape = utils.escape; /** * Save timer references to avoid Sinon interfering (see GH-237). */ var Date = global.Date , setTimeout = global.setTimeout , setInterval = global.setInterval , clearTimeout = global.clearTimeout , clearInterval = global.clearInterval; /** * Expose `XUnit`. */ exports = module.exports = XUnit; /** * Initialize a new `XUnit` reporter. * * @param {Runner} runner * @api public */ function XUnit(runner) { Base.call(this, runner); var stats = this.stats , tests = [] , self = this; runner.on('pending', function(test){ tests.push(test); }); runner.on('pass', function(test){ tests.push(test); }); runner.on('fail', function(test){ tests.push(test); }); runner.on('end', function(){ console.log(tag('testsuite', { name: 'Mocha Tests' , tests: stats.tests , failures: stats.failures , errors: stats.failures , skipped: stats.tests - stats.failures - stats.passes , timestamp: (new Date).toUTCString() , time: (stats.duration / 1000) || 0 }, false)); tests.forEach(test); console.log(''); }); } /** * Inherit from `Base.prototype`. */ function F(){}; F.prototype = Base.prototype; XUnit.prototype = new F; XUnit.prototype.constructor = XUnit; /** * Output tag for the given `test.` */ function test(test) { var attrs = { classname: test.parent.fullTitle() , name: test.title , time: (test.duration / 1000) || 0 }; if ('failed' == test.state) { var err = test.err; attrs.message = escape(err.message); console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack)))); } else if (test.pending) { console.log(tag('testcase', attrs, false, tag('skipped', {}, true))); } else { console.log(tag('testcase', attrs, true) ); } } /** * HTML tag helper. */ function tag(name, attrs, close, content) { var end = close ? '/>' : '>' , pairs = [] , tag; for (var key in attrs) { pairs.push(key + '="' + escape(attrs[key]) + '"'); } tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end; if (content) tag += content + ''; } }); // module: reporters/xunit.js require.register("runnable.js", function(module, exports, require){ /** * Module dependencies. */ var EventEmitter = require('browser/events').EventEmitter , debug = require('browser/debug')('mocha:runnable') , milliseconds = require('./ms'); /** * Save timer references to avoid Sinon interfering (see GH-237). */ var Date = global.Date , setTimeout = global.setTimeout , setInterval = global.setInterval , clearTimeout = global.clearTimeout , clearInterval = global.clearInterval; /** * Object#toString(). */ var toString = Object.prototype.toString; /** * Expose `Runnable`. */ module.exports = Runnable; /** * Initialize a new `Runnable` with the given `title` and callback `fn`. * * @param {String} title * @param {Function} fn * @api private */ function Runnable(title, fn) { this.title = title; this.fn = fn; this.async = fn && fn.length; this.sync = ! this.async; this._timeout = 2000; this._slow = 75; this.timedOut = false; } /** * Inherit from `EventEmitter.prototype`. */ function F(){}; F.prototype = EventEmitter.prototype; Runnable.prototype = new F; Runnable.prototype.constructor = Runnable; /** * Set & get timeout `ms`. * * @param {Number|String} ms * @return {Runnable|Number} ms or self * @api private */ Runnable.prototype.timeout = function(ms){ if (0 == arguments.length) return this._timeout; if ('string' == typeof ms) ms = milliseconds(ms); debug('timeout %d', ms); this._timeout = ms; if (this.timer) this.resetTimeout(); return this; }; /** * Set & get slow `ms`. * * @param {Number|String} ms * @return {Runnable|Number} ms or self * @api private */ Runnable.prototype.slow = function(ms){ if (0 === arguments.length) return this._slow; if ('string' == typeof ms) ms = milliseconds(ms); debug('timeout %d', ms); this._slow = ms; return this; }; /** * Return the full title generated by recursively * concatenating the parent's full title. * * @return {String} * @api public */ Runnable.prototype.fullTitle = function(){ return this.parent.fullTitle() + ' ' + this.title; }; /** * Clear the timeout. * * @api private */ Runnable.prototype.clearTimeout = function(){ clearTimeout(this.timer); }; /** * Inspect the runnable void of private properties. * * @return {String} * @api private */ Runnable.prototype.inspect = function(){ return JSON.stringify(this, function(key, val){ if ('_' == key[0]) return; if ('parent' == key) return '#'; if ('ctx' == key) return '#'; return val; }, 2); }; /** * Reset the timeout. * * @api private */ Runnable.prototype.resetTimeout = function(){ var self = this; var ms = this.timeout() || 1e9; this.clearTimeout(); this.timer = setTimeout(function(){ self.callback(new Error('timeout of ' + ms + 'ms exceeded')); self.timedOut = true; }, ms); }; /** * Whitelist these globals for this test run * * @api private */ Runnable.prototype.globals = function(arr){ var self = this; this._allowedGlobals = arr; }; /** * Run the test and invoke `fn(err)`. * * @param {Function} fn * @api private */ Runnable.prototype.run = function(fn){ var self = this , ms = this.timeout() , start = new Date , ctx = this.ctx , finished , emitted; if (ctx) ctx.runnable(this); // called multiple times function multiple(err) { if (emitted) return; emitted = true; self.emit('error', err || new Error('done() called multiple times')); } // finished function done(err) { if (self.timedOut) return; if (finished) return multiple(err); self.clearTimeout(); self.duration = new Date - start; finished = true; fn(err); } // for .resetTimeout() this.callback = done; // explicit async with `done` argument if (this.async) { this.resetTimeout(); try { this.fn.call(ctx, function(err){ if (err instanceof Error || toString.call(err) === "[object Error]") return done(err); if (null != err) return done(new Error('done() invoked with non-Error: ' + err)); done(); }); } catch (err) { done(err); } return; } if (this.asyncOnly) { return done(new Error('--async-only option in use without declaring `done()`')); } // sync or promise-returning try { if (this.pending) { done(); } else { callFn(this.fn); } } catch (err) { done(err); } function callFn(fn) { var result = fn.call(ctx); if (result && typeof result.then === 'function') { self.resetTimeout(); result.then(function(){ done() }, done); } else { done(); } } }; }); // module: runnable.js require.register("runner.js", function(module, exports, require){ /** * Module dependencies. */ var EventEmitter = require('browser/events').EventEmitter , debug = require('browser/debug')('mocha:runner') , Test = require('./test') , utils = require('./utils') , filter = utils.filter , keys = utils.keys; /** * Non-enumerable globals. */ var globals = [ 'setTimeout', 'clearTimeout', 'setInterval', 'clearInterval', 'XMLHttpRequest', 'Date' ]; /** * Expose `Runner`. */ module.exports = Runner; /** * Initialize a `Runner` for the given `suite`. * * Events: * * - `start` execution started * - `end` execution complete * - `suite` (suite) test suite execution started * - `suite end` (suite) all tests (and sub-suites) have finished * - `test` (test) test execution started * - `test end` (test) test completed * - `hook` (hook) hook execution started * - `hook end` (hook) hook complete * - `pass` (test) test passed * - `fail` (test, err) test failed * - `pending` (test) test pending * * @api public */ function Runner(suite) { var self = this; this._globals = []; this._abort = false; this.suite = suite; this.total = suite.total(); this.failures = 0; this.on('test end', function(test){ self.checkGlobals(test); }); this.on('hook end', function(hook){ self.checkGlobals(hook); }); this.grep(/.*/); this.globals(this.globalProps().concat(extraGlobals())); } /** * Wrapper for setImmediate, process.nextTick, or browser polyfill. * * @param {Function} fn * @api private */ Runner.immediately = global.setImmediate || process.nextTick; /** * Inherit from `EventEmitter.prototype`. */ function F(){}; F.prototype = EventEmitter.prototype; Runner.prototype = new F; Runner.prototype.constructor = Runner; /** * Run tests with full titles matching `re`. Updates runner.total * with number of tests matched. * * @param {RegExp} re * @param {Boolean} invert * @return {Runner} for chaining * @api public */ Runner.prototype.grep = function(re, invert){ debug('grep %s', re); this._grep = re; this._invert = invert; this.total = this.grepTotal(this.suite); return this; }; /** * Returns the number of tests matching the grep search for the * given suite. * * @param {Suite} suite * @return {Number} * @api public */ Runner.prototype.grepTotal = function(suite) { var self = this; var total = 0; suite.eachTest(function(test){ var match = self._grep.test(test.fullTitle()); if (self._invert) match = !match; if (match) total++; }); return total; }; /** * Return a list of global properties. * * @return {Array} * @api private */ Runner.prototype.globalProps = function() { var props = utils.keys(global); // non-enumerables for (var i = 0; i < globals.length; ++i) { if (~utils.indexOf(props, globals[i])) continue; props.push(globals[i]); } return props; }; /** * Allow the given `arr` of globals. * * @param {Array} arr * @return {Runner} for chaining * @api public */ Runner.prototype.globals = function(arr){ if (0 == arguments.length) return this._globals; debug('globals %j', arr); this._globals = this._globals.concat(arr); return this; }; /** * Check for global variable leaks. * * @api private */ Runner.prototype.checkGlobals = function(test){ if (this.ignoreLeaks) return; var ok = this._globals; var globals = this.globalProps(); var isNode = process.kill; var leaks; if (test) { ok = ok.concat(test._allowedGlobals || []); } if(this.prevGlobalsLength == globals.length) return; this.prevGlobalsLength = globals.length; leaks = filterLeaks(ok, globals); this._globals = this._globals.concat(leaks); if (leaks.length > 1) { this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + '')); } else if (leaks.length) { this.fail(test, new Error('global leak detected: ' + leaks[0])); } }; /** * Fail the given `test`. * * @param {Test} test * @param {Error} err * @api private */ Runner.prototype.fail = function(test, err){ ++this.failures; test.state = 'failed'; if ('string' == typeof err) { err = new Error('the string "' + err + '" was thrown, throw an Error :)'); } this.emit('fail', test, err); }; /** * Fail the given `hook` with `err`. * * Hook failures work in the following pattern: * - If bail, then exit * - Failed `before` hook skips all tests in a suite and subsuites, * but jumps to corresponding `after` hook * - Failed `before each` hook skips remaining tests in a * suite and jumps to corresponding `after each` hook, * which is run only once * - Failed `after` hook does not alter * execution order * - Failed `after each` hook skips remaining tests in a * suite and subsuites, but executes other `after each` * hooks * * @param {Hook} hook * @param {Error} err * @api private */ Runner.prototype.failHook = function(hook, err){ this.fail(hook, err); if (this.suite.bail()) { this.emit('end'); } }; /** * Run hook `name` callbacks and then invoke `fn()`. * * @param {String} name * @param {Function} function * @api private */ Runner.prototype.hook = function(name, fn){ var suite = this.suite , hooks = suite['_' + name] , self = this , timer; function next(i) { var hook = hooks[i]; if (!hook) return fn(); if (self.failures && suite.bail()) return fn(); self.currentRunnable = hook; hook.ctx.currentTest = self.test; self.emit('hook', hook); hook.on('error', function(err){ self.failHook(hook, err); }); hook.run(function(err){ hook.removeAllListeners('error'); var testError = hook.error(); if (testError) self.fail(self.test, testError); if (err) { self.failHook(hook, err); // stop executing hooks, notify callee of hook err return fn(err); } self.emit('hook end', hook); delete hook.ctx.currentTest; next(++i); }); } Runner.immediately(function(){ next(0); }); }; /** * Run hook `name` for the given array of `suites` * in order, and callback `fn(err, errSuite)`. * * @param {String} name * @param {Array} suites * @param {Function} fn * @api private */ Runner.prototype.hooks = function(name, suites, fn){ var self = this , orig = this.suite; function next(suite) { self.suite = suite; if (!suite) { self.suite = orig; return fn(); } self.hook(name, function(err){ if (err) { var errSuite = self.suite; self.suite = orig; return fn(err, errSuite); } next(suites.pop()); }); } next(suites.pop()); }; /** * Run hooks from the top level down. * * @param {String} name * @param {Function} fn * @api private */ Runner.prototype.hookUp = function(name, fn){ var suites = [this.suite].concat(this.parents()).reverse(); this.hooks(name, suites, fn); }; /** * Run hooks from the bottom up. * * @param {String} name * @param {Function} fn * @api private */ Runner.prototype.hookDown = function(name, fn){ var suites = [this.suite].concat(this.parents()); this.hooks(name, suites, fn); }; /** * Return an array of parent Suites from * closest to furthest. * * @return {Array} * @api private */ Runner.prototype.parents = function(){ var suite = this.suite , suites = []; while (suite = suite.parent) suites.push(suite); return suites; }; /** * Run the current test and callback `fn(err)`. * * @param {Function} fn * @api private */ Runner.prototype.runTest = function(fn){ var test = this.test , self = this; if (this.asyncOnly) test.asyncOnly = true; try { test.on('error', function(err){ self.fail(test, err); }); test.run(fn); } catch (err) { fn(err); } }; /** * Run tests in the given `suite` and invoke * the callback `fn()` when complete. * * @param {Suite} suite * @param {Function} fn * @api private */ Runner.prototype.runTests = function(suite, fn){ var self = this , tests = suite.tests.slice() , test; function hookErr(err, errSuite, after) { // before/after Each hook for errSuite failed: var orig = self.suite; // for failed 'after each' hook start from errSuite parent, // otherwise start from errSuite itself self.suite = after ? errSuite.parent : errSuite; if (self.suite) { // call hookUp afterEach self.hookUp('afterEach', function(err2, errSuite2) { self.suite = orig; // some hooks may fail even now if (err2) return hookErr(err2, errSuite2, true); // report error suite fn(errSuite); }); } else { // there is no need calling other 'after each' hooks self.suite = orig; fn(errSuite); } } function next(err, errSuite) { // if we bail after first err if (self.failures && suite._bail) return fn(); if (self._abort) return fn(); if (err) return hookErr(err, errSuite, true); // next test test = tests.shift(); // all done if (!test) return fn(); // grep var match = self._grep.test(test.fullTitle()); if (self._invert) match = !match; if (!match) return next(); // pending if (test.pending) { self.emit('pending', test); self.emit('test end', test); return next(); } // execute test and hook(s) self.emit('test', self.test = test); self.hookDown('beforeEach', function(err, errSuite){ if (err) return hookErr(err, errSuite, false); self.currentRunnable = self.test; self.runTest(function(err){ test = self.test; if (err) { self.fail(test, err); self.emit('test end', test); return self.hookUp('afterEach', next); } test.state = 'passed'; self.emit('pass', test); self.emit('test end', test); self.hookUp('afterEach', next); }); }); } this.next = next; next(); }; /** * Run the given `suite` and invoke the * callback `fn()` when complete. * * @param {Suite} suite * @param {Function} fn * @api private */ Runner.prototype.runSuite = function(suite, fn){ var total = this.grepTotal(suite) , self = this , i = 0; debug('run suite %s', suite.fullTitle()); if (!total) return fn(); this.emit('suite', this.suite = suite); function next(errSuite) { if (errSuite) { // current suite failed on a hook from errSuite if (errSuite == suite) { // if errSuite is current suite // continue to the next sibling suite return done(); } else { // errSuite is among the parents of current suite // stop execution of errSuite and all sub-suites return done(errSuite); } } if (self._abort) return done(); var curr = suite.suites[i++]; if (!curr) return done(); self.runSuite(curr, next); } function done(errSuite) { self.suite = suite; self.hook('afterAll', function(){ self.emit('suite end', suite); fn(errSuite); }); } this.hook('beforeAll', function(err){ if (err) return done(); self.runTests(suite, next); }); }; /** * Handle uncaught exceptions. * * @param {Error} err * @api private */ Runner.prototype.uncaught = function(err){ debug('uncaught exception %s', err.message); var runnable = this.currentRunnable; if (!runnable || 'failed' == runnable.state) return; runnable.clearTimeout(); err.uncaught = true; this.fail(runnable, err); // recover from test if ('test' == runnable.type) { this.emit('test end', runnable); this.hookUp('afterEach', this.next); return; } // bail on hooks this.emit('end'); }; /** * Run the root suite and invoke `fn(failures)` * on completion. * * @param {Function} fn * @return {Runner} for chaining * @api public */ Runner.prototype.run = function(fn){ var self = this , fn = fn || function(){}; function uncaught(err){ self.uncaught(err); } debug('start'); // callback this.on('end', function(){ debug('end'); process.removeListener('uncaughtException', uncaught); fn(self.failures); }); // run suites this.emit('start'); this.runSuite(this.suite, function(){ debug('finished running'); self.emit('end'); }); // uncaught exception process.on('uncaughtException', uncaught); return this; }; /** * Cleanly abort execution * * @return {Runner} for chaining * @api public */ Runner.prototype.abort = function(){ debug('aborting'); this._abort = true; } /** * Filter leaks with the given globals flagged as `ok`. * * @param {Array} ok * @param {Array} globals * @return {Array} * @api private */ function filterLeaks(ok, globals) { return filter(globals, function(key){ // Firefox and Chrome exposes iframes as index inside the window object if (/^d+/.test(key)) return false; // in firefox // if runner runs in an iframe, this iframe's window.getInterface method not init at first // it is assigned in some seconds if (global.navigator && /^getInterface/.test(key)) return false; // an iframe could be approached by window[iframeIndex] // in ie6,7,8 and opera, iframeIndex is enumerable, this could cause leak if (global.navigator && /^\d+/.test(key)) return false; // Opera and IE expose global variables for HTML element IDs (issue #243) if (/^mocha-/.test(key)) return false; var matched = filter(ok, function(ok){ if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]); return key == ok; }); return matched.length == 0 && (!global.navigator || 'onerror' !== key); }); } /** * Array of globals dependent on the environment. * * @return {Array} * @api private */ function extraGlobals() { if (typeof(process) === 'object' && typeof(process.version) === 'string') { var nodeVersion = process.version.split('.').reduce(function(a, v) { return a << 8 | v; }); // 'errno' was renamed to process._errno in v0.9.11. if (nodeVersion < 0x00090B) { return ['errno']; } } return []; } }); // module: runner.js require.register("suite.js", function(module, exports, require){ /** * Module dependencies. */ var EventEmitter = require('browser/events').EventEmitter , debug = require('browser/debug')('mocha:suite') , milliseconds = require('./ms') , utils = require('./utils') , Hook = require('./hook'); /** * Expose `Suite`. */ exports = module.exports = Suite; /** * Create a new `Suite` with the given `title` * and parent `Suite`. When a suite with the * same title is already present, that suite * is returned to provide nicer reporter * and more flexible meta-testing. * * @param {Suite} parent * @param {String} title * @return {Suite} * @api public */ exports.create = function(parent, title){ var suite = new Suite(title, parent.ctx); suite.parent = parent; if (parent.pending) suite.pending = true; title = suite.fullTitle(); parent.addSuite(suite); return suite; }; /** * Initialize a new `Suite` with the given * `title` and `ctx`. * * @param {String} title * @param {Context} ctx * @api private */ function Suite(title, parentContext) { this.title = title; var context = function () {}; context.prototype = parentContext; this.ctx = new context(); this.suites = []; this.tests = []; this.pending = false; this._beforeEach = []; this._beforeAll = []; this._afterEach = []; this._afterAll = []; this.root = !title; this._timeout = 2000; this._slow = 75; this._bail = false; } /** * Inherit from `EventEmitter.prototype`. */ function F(){}; F.prototype = EventEmitter.prototype; Suite.prototype = new F; Suite.prototype.constructor = Suite; /** * Return a clone of this `Suite`. * * @return {Suite} * @api private */ Suite.prototype.clone = function(){ var suite = new Suite(this.title); debug('clone'); suite.ctx = this.ctx; suite.timeout(this.timeout()); suite.slow(this.slow()); suite.bail(this.bail()); return suite; }; /** * Set timeout `ms` or short-hand such as "2s". * * @param {Number|String} ms * @return {Suite|Number} for chaining * @api private */ Suite.prototype.timeout = function(ms){ if (0 == arguments.length) return this._timeout; if ('string' == typeof ms) ms = milliseconds(ms); debug('timeout %d', ms); this._timeout = parseInt(ms, 10); return this; }; /** * Set slow `ms` or short-hand such as "2s". * * @param {Number|String} ms * @return {Suite|Number} for chaining * @api private */ Suite.prototype.slow = function(ms){ if (0 === arguments.length) return this._slow; if ('string' == typeof ms) ms = milliseconds(ms); debug('slow %d', ms); this._slow = ms; return this; }; /** * Sets whether to bail after first error. * * @parma {Boolean} bail * @return {Suite|Number} for chaining * @api private */ Suite.prototype.bail = function(bail){ if (0 == arguments.length) return this._bail; debug('bail %s', bail); this._bail = bail; return this; }; /** * Run `fn(test[, done])` before running tests. * * @param {Function} fn * @return {Suite} for chaining * @api private */ Suite.prototype.beforeAll = function(title, fn){ if (this.pending) return this; if ('function' === typeof title) { fn = title; title = fn.name; } title = '"before all" hook' + (title ? ': ' + title : ''); var hook = new Hook(title, fn); hook.parent = this; hook.timeout(this.timeout()); hook.slow(this.slow()); hook.ctx = this.ctx; this._beforeAll.push(hook); this.emit('beforeAll', hook); return this; }; /** * Run `fn(test[, done])` after running tests. * * @param {Function} fn * @return {Suite} for chaining * @api private */ Suite.prototype.afterAll = function(title, fn){ if (this.pending) return this; if ('function' === typeof title) { fn = title; title = fn.name; } title = '"after all" hook' + (title ? ': ' + title : ''); var hook = new Hook(title, fn); hook.parent = this; hook.timeout(this.timeout()); hook.slow(this.slow()); hook.ctx = this.ctx; this._afterAll.push(hook); this.emit('afterAll', hook); return this; }; /** * Run `fn(test[, done])` before each test case. * * @param {Function} fn * @return {Suite} for chaining * @api private */ Suite.prototype.beforeEach = function(title, fn){ if (this.pending) return this; if ('function' === typeof title) { fn = title; title = fn.name; } title = '"before each" hook' + (title ? ': ' + title : ''); var hook = new Hook(title, fn); hook.parent = this; hook.timeout(this.timeout()); hook.slow(this.slow()); hook.ctx = this.ctx; this._beforeEach.push(hook); this.emit('beforeEach', hook); return this; }; /** * Run `fn(test[, done])` after each test case. * * @param {Function} fn * @return {Suite} for chaining * @api private */ Suite.prototype.afterEach = function(title, fn){ if (this.pending) return this; if ('function' === typeof title) { fn = title; title = fn.name; } title = '"after each" hook' + (title ? ': ' + title : ''); var hook = new Hook(title, fn); hook.parent = this; hook.timeout(this.timeout()); hook.slow(this.slow()); hook.ctx = this.ctx; this._afterEach.push(hook); this.emit('afterEach', hook); return this; }; /** * Add a test `suite`. * * @param {Suite} suite * @return {Suite} for chaining * @api private */ Suite.prototype.addSuite = function(suite){ suite.parent = this; suite.timeout(this.timeout()); suite.slow(this.slow()); suite.bail(this.bail()); this.suites.push(suite); this.emit('suite', suite); return this; }; /** * Add a `test` to this suite. * * @param {Test} test * @return {Suite} for chaining * @api private */ Suite.prototype.addTest = function(test){ test.parent = this; test.timeout(this.timeout()); test.slow(this.slow()); test.ctx = this.ctx; this.tests.push(test); this.emit('test', test); return this; }; /** * Return the full title generated by recursively * concatenating the parent's full title. * * @return {String} * @api public */ Suite.prototype.fullTitle = function(){ if (this.parent) { var full = this.parent.fullTitle(); if (full) return full + ' ' + this.title; } return this.title; }; /** * Return the total number of tests. * * @return {Number} * @api public */ Suite.prototype.total = function(){ return utils.reduce(this.suites, function(sum, suite){ return sum + suite.total(); }, 0) + this.tests.length; }; /** * Iterates through each suite recursively to find * all tests. Applies a function in the format * `fn(test)`. * * @param {Function} fn * @return {Suite} * @api private */ Suite.prototype.eachTest = function(fn){ utils.forEach(this.tests, fn); utils.forEach(this.suites, function(suite){ suite.eachTest(fn); }); return this; }; }); // module: suite.js require.register("test.js", function(module, exports, require){ /** * Module dependencies. */ var Runnable = require('./runnable'); /** * Expose `Test`. */ module.exports = Test; /** * Initialize a new `Test` with the given `title` and callback `fn`. * * @param {String} title * @param {Function} fn * @api private */ function Test(title, fn) { Runnable.call(this, title, fn); this.pending = !fn; this.type = 'test'; } /** * Inherit from `Runnable.prototype`. */ function F(){}; F.prototype = Runnable.prototype; Test.prototype = new F; Test.prototype.constructor = Test; }); // module: test.js require.register("utils.js", function(module, exports, require){ /** * Module dependencies. */ var fs = require('browser/fs') , path = require('browser/path') , join = path.join , debug = require('browser/debug')('mocha:watch'); /** * Ignored directories. */ var ignore = ['node_modules', '.git']; /** * Escape special characters in the given string of html. * * @param {String} html * @return {String} * @api private */ exports.escape = function(html){ return String(html) .replace(/&/g, '&') .replace(/"/g, '"') .replace(//g, '>'); }; /** * Array#forEach (<=IE8) * * @param {Array} array * @param {Function} fn * @param {Object} scope * @api private */ exports.forEach = function(arr, fn, scope){ for (var i = 0, l = arr.length; i < l; i++) fn.call(scope, arr[i], i); }; /** * Array#map (<=IE8) * * @param {Array} array * @param {Function} fn * @param {Object} scope * @api private */ exports.map = function(arr, fn, scope){ var result = []; for (var i = 0, l = arr.length; i < l; i++) result.push(fn.call(scope, arr[i], i)); return result; }; /** * Array#indexOf (<=IE8) * * @parma {Array} arr * @param {Object} obj to find index of * @param {Number} start * @api private */ exports.indexOf = function(arr, obj, start){ for (var i = start || 0, l = arr.length; i < l; i++) { if (arr[i] === obj) return i; } return -1; }; /** * Array#reduce (<=IE8) * * @param {Array} array * @param {Function} fn * @param {Object} initial value * @api private */ exports.reduce = function(arr, fn, val){ var rval = val; for (var i = 0, l = arr.length; i < l; i++) { rval = fn(rval, arr[i], i, arr); } return rval; }; /** * Array#filter (<=IE8) * * @param {Array} array * @param {Function} fn * @api private */ exports.filter = function(arr, fn){ var ret = []; for (var i = 0, l = arr.length; i < l; i++) { var val = arr[i]; if (fn(val, i, arr)) ret.push(val); } return ret; }; /** * Object.keys (<=IE8) * * @param {Object} obj * @return {Array} keys * @api private */ exports.keys = Object.keys || function(obj) { var keys = [] , has = Object.prototype.hasOwnProperty // for `window` on <=IE8 for (var key in obj) { if (has.call(obj, key)) { keys.push(key); } } return keys; }; /** * Watch the given `files` for changes * and invoke `fn(file)` on modification. * * @param {Array} files * @param {Function} fn * @api private */ exports.watch = function(files, fn){ var options = { interval: 100 }; files.forEach(function(file){ debug('file %s', file); fs.watchFile(file, options, function(curr, prev){ if (prev.mtime < curr.mtime) fn(file); }); }); }; /** * Ignored files. */ function ignored(path){ return !~ignore.indexOf(path); } /** * Lookup files in the given `dir`. * * @return {Array} * @api private */ exports.files = function(dir, ret){ ret = ret || []; fs.readdirSync(dir) .filter(ignored) .forEach(function(path){ path = join(dir, path); if (fs.statSync(path).isDirectory()) { exports.files(path, ret); } else if (path.match(/\.(js|coffee|litcoffee|coffee.md)$/)) { ret.push(path); } }); return ret; }; /** * Compute a slug from the given `str`. * * @param {String} str * @return {String} * @api private */ exports.slug = function(str){ return str .toLowerCase() .replace(/ +/g, '-') .replace(/[^-\w]/g, ''); }; /** * Strip the function definition from `str`, * and re-indent for pre whitespace. */ exports.clean = function(str) { str = str .replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, '') .replace(/^function *\(.*\) *{/, '') .replace(/\s+\}$/, ''); var spaces = str.match(/^\n?( *)/)[1].length , tabs = str.match(/^\n?(\t*)/)[1].length , re = new RegExp('^\n?' + (tabs ? '\t' : ' ') + '{' + (tabs ? tabs : spaces) + '}', 'gm'); str = str.replace(re, ''); return exports.trim(str); }; /** * Escape regular expression characters in `str`. * * @param {String} str * @return {String} * @api private */ exports.escapeRegexp = function(str){ return str.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&"); }; /** * Trim the given `str`. * * @param {String} str * @return {String} * @api private */ exports.trim = function(str){ return str.replace(/^\s+|\s+$/g, ''); }; /** * Parse the given `qs`. * * @param {String} qs * @return {Object} * @api private */ exports.parseQuery = function(qs){ return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair){ var i = pair.indexOf('=') , key = pair.slice(0, i) , val = pair.slice(++i); obj[key] = decodeURIComponent(val); return obj; }, {}); }; /** * Highlight the given string of `js`. * * @param {String} js * @return {String} * @api private */ function highlight(js) { return js .replace(//g, '>') .replace(/\/\/(.*)/gm, '//$1') .replace(/('.*?')/gm, '$1') .replace(/(\d+\.\d+)/gm, '$1') .replace(/(\d+)/gm, '$1') .replace(/\bnew *(\w+)/gm, 'new $1') .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '$1') } /** * Highlight the contents of tag `name`. * * @param {String} name * @api private */ exports.highlightTags = function(name) { var code = document.getElementsByTagName(name); for (var i = 0, len = code.length; i < len; ++i) { code[i].innerHTML = highlight(code[i].innerHTML); } }; }); // module: utils.js // The global object is "self" in Web Workers. global = (function() { return this; })(); /** * Save timer references to avoid Sinon interfering (see GH-237). */ var Date = global.Date; var setTimeout = global.setTimeout; var setInterval = global.setInterval; var clearTimeout = global.clearTimeout; var clearInterval = global.clearInterval; /** * Node shims. * * These are meant only to allow * mocha.js to run untouched, not * to allow running node code in * the browser. */ var process = {}; process.exit = function(status){}; process.stdout = {}; var uncaughtExceptionHandlers = []; /** * Remove uncaughtException listener. */ process.removeListener = function(e, fn){ if ('uncaughtException' == e) { global.onerror = function() {}; var i = Mocha.utils.indexOf(uncaughtExceptionHandlers, fn); if (i != -1) { uncaughtExceptionHandlers.splice(i, 1); } } }; /** * Implements uncaughtException listener. */ process.on = function(e, fn){ if ('uncaughtException' == e) { global.onerror = function(err, url, line){ fn(new Error(err + ' (' + url + ':' + line + ')')); return true; }; uncaughtExceptionHandlers.push(fn); } }; /** * Expose mocha. */ var Mocha = global.Mocha = require('mocha'), mocha = global.mocha = new Mocha({ reporter: 'html' }); // The BDD UI is registered by default, but no UI will be functional in the // browser without an explicit call to the overridden `mocha.ui` (see below). // Ensure that this default UI does not expose its methods to the global scope. mocha.suite.removeAllListeners('pre-require'); var immediateQueue = [] , immediateTimeout; function timeslice() { var immediateStart = new Date().getTime(); while (immediateQueue.length && (new Date().getTime() - immediateStart) < 100) { immediateQueue.shift()(); } if (immediateQueue.length) { immediateTimeout = setTimeout(timeslice, 0); } else { immediateTimeout = null; } } /** * High-performance override of Runner.immediately. */ Mocha.Runner.immediately = function(callback) { immediateQueue.push(callback); if (!immediateTimeout) { immediateTimeout = setTimeout(timeslice, 0); } }; /** * Function to allow assertion libraries to throw errors directly into mocha. * This is useful when running tests in a browser because window.onerror will * only receive the 'message' attribute of the Error. */ mocha.throwError = function(err) { Mocha.utils.forEach(uncaughtExceptionHandlers, function (fn) { fn(err); }); throw err; }; /** * Override ui to ensure that the ui functions are initialized. * Normally this would happen in Mocha.prototype.loadFiles. */ mocha.ui = function(ui){ Mocha.prototype.ui.call(this, ui); this.suite.emit('pre-require', global, null, this); return this; }; /** * Setup mocha with the given setting options. */ mocha.setup = function(opts){ if ('string' == typeof opts) opts = { ui: opts }; for (var opt in opts) this[opt](opts[opt]); return this; }; /** * Run mocha, returning the Runner. */ mocha.run = function(fn){ var options = mocha.options; mocha.globals('location'); var query = Mocha.utils.parseQuery(global.location.search || ''); if (query.grep) mocha.grep(query.grep); if (query.invert) mocha.invert(); return Mocha.prototype.run.call(mocha, function(){ // The DOM Document is not available in Web Workers. if (global.document) { Mocha.utils.highlightTags('code'); } if (fn) fn(); }); }; /** * Expose the process shim. */ Mocha.process = process; })();mocha-1.20.1/package.json000066400000000000000000000020131234352070300151430ustar00rootroot00000000000000{ "name": "mocha", "version": "1.20.1", "description": "simple, flexible, fun test framework", "keywords": [ "mocha", "test", "bdd", "tdd", "tap" ], "author": "TJ Holowaychuk ", "repository": { "type": "git", "url": "git://github.com/visionmedia/mocha.git" }, "main": "./index", "browser": "./mocha.js", "bin": { "mocha": "./bin/mocha", "_mocha": "./bin/_mocha" }, "engines": { "node": ">= 0.4.x" }, "scripts": { "test": "make test-all" }, "dependencies": { "commander": "2.0.0", "growl": "1.7.x", "jade": "0.26.3", "diff": "1.0.7", "debug": "*", "mkdirp": "0.3.5", "glob": "3.2.3" }, "devDependencies": { "coffee-script": "1.2", "should": "~4.0.0" }, "files": [ "bin", "images", "lib", "index.js", "mocha.css", "mocha.js", "LICENSE" ], "licenses": [ { "type": "MIT", "url": "https://raw.github.com/visionmedia/mocha/master/LICENSE" } ] } mocha-1.20.1/support/000077500000000000000000000000001234352070300143755ustar00rootroot00000000000000mocha-1.20.1/support/compile.js000066400000000000000000000067171234352070300163760ustar00rootroot00000000000000 /** * 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(' \u001b[90mcompile : \u001b[0m\u001b[36m%s\u001b[0m', file); files[file] = ~js.indexOf('require: off') ? js : parse(js); --pending || compile(); }); }); /** * Parse the given `js`. */ function parse(js) { return parseRequires(parseInheritance(js)); } /** * Parse requires. */ function parseRequires(js) { return js .replace(/require\('events'\)/g, "require('browser/events')") .replace(/require\('debug'\)/g, "require('browser/debug')") .replace(/require\('path'\)/g, "require('browser/path')") .replace(/require\('diff'\)/g, "require('browser/diff')") .replace(/require\('tty'\)/g, "require('browser/tty')") .replace(/require\('fs'\)/g, "require('browser/fs')") } /** * Parse __proto__. */ function parseInheritance(js) { return js .replace(/^ *(\w+)\.prototype\.__proto__ * = *(\w+)\.prototype *;?/gm, function(_, child, parent){ return 'function F(){};\n' + 'F.prototype = ' + parent + '.prototype;\n' + child + '.prototype = new F;\n' + child + '.prototype.constructor = '+ child + ';\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('_mocha.js', buf, function(err){ if (err) throw err; console.log(' \u001b[90m create : \u001b[0m\u001b[36m%s\u001b[0m', 'mocha.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.charAt(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('/')); }; }, /** * Register a module. */ register: function(path, fn){ require.modules[path] = fn; } }; mocha-1.20.1/support/foot.js000066400000000000000000000000051234352070300156750ustar00rootroot00000000000000})();mocha-1.20.1/support/head.js000066400000000000000000000000161234352070300156310ustar00rootroot00000000000000;(function(){ mocha-1.20.1/support/tail.js000066400000000000000000000067621234352070300156770ustar00rootroot00000000000000// The global object is "self" in Web Workers. global = (function() { return this; })(); /** * Save timer references to avoid Sinon interfering (see GH-237). */ var Date = global.Date; var setTimeout = global.setTimeout; var setInterval = global.setInterval; var clearTimeout = global.clearTimeout; var clearInterval = global.clearInterval; /** * Node shims. * * These are meant only to allow * mocha.js to run untouched, not * to allow running node code in * the browser. */ var process = {}; process.exit = function(status){}; process.stdout = {}; var uncaughtExceptionHandlers = []; /** * Remove uncaughtException listener. */ process.removeListener = function(e, fn){ if ('uncaughtException' == e) { global.onerror = function() {}; var i = Mocha.utils.indexOf(uncaughtExceptionHandlers, fn); if (i != -1) { uncaughtExceptionHandlers.splice(i, 1); } } }; /** * Implements uncaughtException listener. */ process.on = function(e, fn){ if ('uncaughtException' == e) { global.onerror = function(err, url, line){ fn(new Error(err + ' (' + url + ':' + line + ')')); return true; }; uncaughtExceptionHandlers.push(fn); } }; /** * Expose mocha. */ var Mocha = global.Mocha = require('mocha'), mocha = global.mocha = new Mocha({ reporter: 'html' }); // The BDD UI is registered by default, but no UI will be functional in the // browser without an explicit call to the overridden `mocha.ui` (see below). // Ensure that this default UI does not expose its methods to the global scope. mocha.suite.removeAllListeners('pre-require'); var immediateQueue = [] , immediateTimeout; function timeslice() { var immediateStart = new Date().getTime(); while (immediateQueue.length && (new Date().getTime() - immediateStart) < 100) { immediateQueue.shift()(); } if (immediateQueue.length) { immediateTimeout = setTimeout(timeslice, 0); } else { immediateTimeout = null; } } /** * High-performance override of Runner.immediately. */ Mocha.Runner.immediately = function(callback) { immediateQueue.push(callback); if (!immediateTimeout) { immediateTimeout = setTimeout(timeslice, 0); } }; /** * Function to allow assertion libraries to throw errors directly into mocha. * This is useful when running tests in a browser because window.onerror will * only receive the 'message' attribute of the Error. */ mocha.throwError = function(err) { Mocha.utils.forEach(uncaughtExceptionHandlers, function (fn) { fn(err); }); throw err; }; /** * Override ui to ensure that the ui functions are initialized. * Normally this would happen in Mocha.prototype.loadFiles. */ mocha.ui = function(ui){ Mocha.prototype.ui.call(this, ui); this.suite.emit('pre-require', global, null, this); return this; }; /** * Setup mocha with the given setting options. */ mocha.setup = function(opts){ if ('string' == typeof opts) opts = { ui: opts }; for (var opt in opts) this[opt](opts[opt]); return this; }; /** * Run mocha, returning the Runner. */ mocha.run = function(fn){ var options = mocha.options; mocha.globals('location'); var query = Mocha.utils.parseQuery(global.location.search || ''); if (query.grep) mocha.grep(query.grep); if (query.invert) mocha.invert(); return Mocha.prototype.run.call(mocha, function(err){ // The DOM Document is not available in Web Workers. if (global.document) { Mocha.utils.highlightTags('code'); } if (fn) fn(err); }); }; /** * Expose the process shim. */ Mocha.process = process; mocha-1.20.1/test/000077500000000000000000000000001234352070300136405ustar00rootroot00000000000000mocha-1.20.1/test/acceptance/000077500000000000000000000000001234352070300157265ustar00rootroot00000000000000mocha-1.20.1/test/acceptance/context.js000066400000000000000000000032071234352070300177520ustar00rootroot00000000000000 describe('Context', function(){ beforeEach(function(){ this.calls = ['before']; }) describe('nested', function(){ beforeEach(function(){ this.calls.push('before two'); }) it('should work', function(){ this.calls.should.eql(['before', 'before two']); this.calls.push('test'); }) after(function(){ this.calls.should.eql(['before', 'before two', 'test']); this.calls.push('after two'); }) }) after(function(){ this.calls.should.eql(['before', 'before two', 'test', 'after two']); }) }) describe('Context Siblings', function(){ beforeEach(function(){ this.calls = ['before']; }) describe('sequestered sibling', function(){ beforeEach(function(){ this.calls.push('before two'); this.hiddenFromSibling = 'This should be hidden'; }) it('should work', function(){ this.hiddenFromSibling.should.eql('This should be hidden') }) }) describe('sibling verifiction', function(){ beforeEach(function(){ this.calls.push('before sibling'); }) it('should not have value set within a sibling describe', function(){ 'This should be hidden'.should.not.eql(this.hiddenFromSibling); this.visibleFromTestSibling = 'Visible from test sibling'; }) it('should allow test siblings to modify shared context', function(){ 'Visible from test sibling'.should.eql(this.visibleFromTestSibling); }) it('should have reset this.calls before describe', function(){ this.calls.should.eql(['before', 'before sibling']); }) }) after(function(){ this.calls.should.eql(['before', 'before sibling']); }) }) mocha-1.20.1/test/acceptance/diffs.js000066400000000000000000000045161234352070300173650ustar00rootroot00000000000000 var fs = require('fs') , cssin = fs.readFileSync('test/acceptance/fixtures/css.in', 'ascii') , cssout = fs.readFileSync('test/acceptance/fixtures/css.out', 'ascii'); describe('diffs', function(){ // uncomment the assertions, and run with different params to check the output // ex: --color, --no-color, --unified-diff it('should display a diff for small strings', function(){ var expected = 'foo bar baz' , actual = 'foo rar baz'; // expected.should.eql(actual); }); it('should display a diff of canonicalized objects', function(){ var actual = { name: 'travis j', age: 23 } , expected = { age: 23, name: 'travis' }; // actual.should.eql(expected); }); it('should display a diff for medium strings', function(){ var expected = 'foo bar baz\nfoo bar baz\nfoo bar baz' , actual = 'foo bar baz\nfoo rar baz\nfoo bar raz'; // expected.should.eql(actual); }); it('should display a diff for entire object dumps', function(){ var expected = { name: 'joe', age: 30, address: {city: 'new york', country: 'us' }} , actual = { name: 'joel', age: 30, address: {city: 'new york', country: 'usa' }}; // actual.should.eql(expected); }); it('should display a diff for multi-line strings', function(){ var expected = 'one two three\nfour five six\nseven eight nine'; var actual = 'one two three\nfour zzzz six\nseven eight nine'; // actual.should.eql(expected); }); it('should display a diff for entire object dumps', function(){ var expected = { name: 'joe', age: 30, address: {city: 'new york', country: 'us' }} var actual = { name: 'joel', age: 30, address: {city: 'new york', country: 'usa' }}; // actual.should.eql(expected); }); it('should display a full-comparison with escaped special characters', function(){ var expected = 'one\ttab\ntwo\t\ttabs'; var actual = 'one\ttab\ntwo\t\t\ttabs'; //actual.should.equal(expected); }); it('should display a word diff for large strings', function(){ // cssin.should.equal(cssout); }); it('should work with objects', function(){ var tobi = { name: 'tobi', species: 'ferret', color: 'white', age: 2 }; var loki = { name: 'loki', species: 'ferret', color: 'brown', age: 2 }; // tobi.should.eql(loki); }); }); mocha-1.20.1/test/acceptance/duration.js000066400000000000000000000010131234352070300201040ustar00rootroot00000000000000 describe('durations', function(){ describe('when slow', function(){ it('should highlight in red', function(done){ setTimeout(function(){ done(); }, 100); }) }) describe('when reasonable', function(){ it('should highlight in yellow', function(done){ setTimeout(function(){ done(); }, 50); }) }) describe('when fast', function(){ it('should highlight in green', function(done){ setTimeout(function(){ done(); }, 10); }) }) }) mocha-1.20.1/test/acceptance/fixtures/000077500000000000000000000000001234352070300175775ustar00rootroot00000000000000mocha-1.20.1/test/acceptance/fixtures/css.in000066400000000000000000000001721234352070300207170ustar00rootroot00000000000000body { font: "Helvetica Neue", Helvetica, arial, sans-serif; background: black; color: white; } a { color: blue }mocha-1.20.1/test/acceptance/fixtures/css.out000066400000000000000000000002211234352070300211130ustar00rootroot00000000000000body { font: "Helvetica Neue", Helvetica, arial, sans-serif; background: black; color: #fff; } a { color: blue; } foo { bar: 'baz'; }mocha-1.20.1/test/acceptance/fs.js000066400000000000000000000006251234352070300166770ustar00rootroot00000000000000 var fs = require('fs'); describe('fs.readFile()', function(){ describe('when the file exists', function(){ it('should succeed', function(done){ fs.writeFile('/tmp/mocha', 'wahoo', done) }) }) describe('when the file does not exist', function(){ it('should fail', function(done){ // uncomment // fs.readFile('/tmp/does-not-exist', done); done(); }) }) }) mocha-1.20.1/test/acceptance/glob/000077500000000000000000000000001234352070300166515ustar00rootroot00000000000000mocha-1.20.1/test/acceptance/glob/glob.js000066400000000000000000000001711234352070300201310ustar00rootroot00000000000000 describe('globbing test', function(){ it('should find this test', function(){ // see glob.sh for details }) }); mocha-1.20.1/test/acceptance/glob/glob.sh000077500000000000000000000034561234352070300201430ustar00rootroot00000000000000#!/bin/bash REL_SCRIPT_DIR="`dirname \"$0\"`" SCRIPT_DIR="`( cd \"$REL_SCRIPT_DIR\" && pwd )`" cd $SCRIPT_DIR || { echo Could not cd to $SCRIPT_DIR from `pwd` exit 1 } ../../../bin/mocha -R json-stream ./*.js > /tmp/mocha-glob.txt || { echo Globbing ./*.js in `pwd` failed. exit 1 } cat /tmp/mocha-glob.txt | grep -q -F '["end",{"suites":1,"tests":1,"passes":1,"pending":0,"failures":0,' || { echo Globbing ./*.js in `pwd` should match glob.js with one test inside. exit 1 } ../../../bin/mocha -R json-stream ./*-none.js 2> /tmp/mocha-glob.txt && { echo Globbing './*-none.js' in `pwd` failed. exit 1 } cat /tmp/mocha-glob.txt | grep -q -F 'cannot resolve path' || { echo Globbing './*-none.js' in `pwd` should match no files and run no tests. exit 1 } # Globbing in windows command-shell differs completely from unix-style globbing. # In bash, the shell expands globs and passes the result to executables. # In windows, the shell passes globs unexpanded, executables do expansion if they support it. # Adding single-quotes around the glob below makes bash pass glob unexpanded, # allowing us to test windows-style globbing in bash. ../../../bin/mocha -R json-stream './*.js' > /tmp/mocha-glob.txt || { echo Globbing './*.js' in `pwd` failed. exit 1 } cat /tmp/mocha-glob.txt | grep -q -F '["end",{"suites":1,"tests":1,"passes":1,"pending":0,"failures":0,' || { echo Globbing './*.js' in `pwd` should match glob.js with one test inside. exit 1 } ../../../bin/mocha -R json-stream './*-none.js' 2> /tmp/mocha-glob.txt && { echo Globbing './*-none.js' in `pwd` failed. exit 1 } cat /tmp/mocha-glob.txt | grep -q -F 'cannot resolve path' || { echo Globbing './*-none.js' in `pwd` should match no files and run no tests. exit 1 } echo Glob-test passed. mocha-1.20.1/test/acceptance/globals.js000066400000000000000000000016061234352070300177120ustar00rootroot00000000000000 describe('global leaks', function(){ before(function(){ // uncomment to test // foo = 'hey'; // bar = 'hey'; }) beforeEach(function(){ // uncomment to test // foo = 'bar' }); it('should cause tests to fail', function(){ // uncomment to test // foo = 'bar'; // bar = 'baz'; // baz = 'raz'; }); it('should pass when accepted', function(){ global.okGlobalA = 1; global.okGlobalB = 1; global.okGlobalC = 1; }) it('should pass with wildcard', function(){ global.callback123 = 'foo'; global.callback345 = 'bar'; }); it('should pass when prefixed "mocha-"', function(){ // Opera and IE do this for HTML element IDs anyway // but to sure we can assert this in any browser, simulate it. global['mocha-example'] = { nodeType: 1 }; }); afterEach(function(){ // uncomment to test // foo = 'bar' }); }); mocha-1.20.1/test/acceptance/http.js000066400000000000000000000005341234352070300172450ustar00rootroot00000000000000 var http = require('http'); var server = http.createServer(function(req, res){ res.end('Hello World\n'); }) server.listen(8888); describe('http', function(){ it('should provide an example', function(done){ http.get({ path: '/', port: 8888 }, function(res){ res.should.have.property('statusCode', 200); done(); }) }) })mocha-1.20.1/test/acceptance/interfaces/000077500000000000000000000000001234352070300200515ustar00rootroot00000000000000mocha-1.20.1/test/acceptance/interfaces/bdd.js000066400000000000000000000015311234352070300211400ustar00rootroot00000000000000 describe('Array', function(){ describe('#indexOf()', function(){ it('should return -1 when the value is not present', function(){ [1,2,3].indexOf(5).should.equal(-1); [1,2,3].indexOf(0).should.equal(-1); }) it('should return the correct index when the value is present', function(){ [1,2,3].indexOf(1).should.equal(0); [1,2,3].indexOf(2).should.equal(1); [1,2,3].indexOf(3).should.equal(2); }) }) }) describe('Array', function(){ describe('#pop()', function(){ it('should remove and return the last value', function(){ var arr = [1,2,3]; arr.pop().should.equal(3); arr.should.eql([1,2]); }) }) }) context('Array', function(){ beforeEach(function(){ this.arr = [1,2,3]; }) specify('has a length property', function(){ this.arr.length.should.equal(3); }) }) mocha-1.20.1/test/acceptance/interfaces/exports.js000066400000000000000000000015771234352070300221250ustar00rootroot00000000000000 var calls = []; exports.Array = { before: function(){ calls.push('before'); }, after: function(){ calls.push('after'); calls.should.eql([ 'before' , 'before each' , 'one' , 'after each' , 'before each' , 'two' , 'after each' , 'after']); }, '#indexOf()': { beforeEach: function(){ calls.push('before each'); }, afterEach: function(){ calls.push('after each'); }, 'should return -1 when the value is not present': function(){ calls.push('one'); [1,2,3].indexOf(5).should.equal(-1); [1,2,3].indexOf(0).should.equal(-1); }, 'should return the correct index when the value is present': function(){ calls.push('two'); [1,2,3].indexOf(1).should.equal(0); [1,2,3].indexOf(2).should.equal(1); [1,2,3].indexOf(3).should.equal(2); } } }; mocha-1.20.1/test/acceptance/interfaces/qunit.js000066400000000000000000000005621234352070300215520ustar00rootroot00000000000000 function ok(expr, msg) { if (!expr) throw new Error(msg); } suite('Array'); test('#length', function(){ var arr = [1,2,3]; ok(arr.length == 3); }); test('#indexOf()', function(){ var arr = [1,2,3]; ok(arr.indexOf(1) == 0); ok(arr.indexOf(2) == 1); ok(arr.indexOf(3) == 2); }); suite('String'); test('#length', function(){ ok('foo'.length == 3); });mocha-1.20.1/test/acceptance/interfaces/tdd.js000066400000000000000000000021321234352070300211600ustar00rootroot00000000000000 suite('Array', function(){ suite('#indexOf()', function(){ var initialValue = 32; suiteSetup(function(done){ initialValue.should.eql(32); initialValue = 42; done(); }); test('should return -1 when the value is not present', function(){ initialValue.should.eql(42); [1,2,3].indexOf(5).should.equal(-1); [1,2,3].indexOf(0).should.equal(-1); }); test('should return the correct index when the value is present', function(){ initialValue.should.eql(42); [1,2,3].indexOf(1).should.equal(0); [1,2,3].indexOf(2).should.equal(1); [1,2,3].indexOf(3).should.equal(2); }); test.skip('should skip this test', function(){ var zero = 0; zero.should.equal(1, 'this test should have been skipped'); }); suite.skip('should skip this suite', function(){ test('should skip this test', function(){ var zero = 0; zero.should.equal(1, 'this test should have been skipped'); }); }); suiteTeardown(function(done){ initialValue.should.eql(42); done(); }); }); }); mocha-1.20.1/test/acceptance/misc/000077500000000000000000000000001234352070300166615ustar00rootroot00000000000000mocha-1.20.1/test/acceptance/misc/asyncOnly.js000066400000000000000000000002161234352070300211750ustar00rootroot00000000000000 describe('asyncOnly', function(){ it('should display an error', function(){ }) it('should pass', function(done){ done(); }) }) mocha-1.20.1/test/acceptance/misc/bail.js000066400000000000000000000007521234352070300201320ustar00rootroot00000000000000 describe('bail', function(){ it('should only display this error', function(done){ throw new Error('this should be displayed'); }) it('should not display this error', function(done){ throw new Error('this should not be displayed'); }) }) describe('bail-2', function(){ before(function(done){ throw new Error('this hook should not be displayed'); }) it('should not display this error', function(done){ throw new Error('this should not be displayed'); }) }) mocha-1.20.1/test/acceptance/misc/cascade.js000066400000000000000000000020231234352070300205770ustar00rootroot00000000000000 describe('one', function(){ before(function(){ console.log('before one'); }) after(function(){ console.log('after one'); }) beforeEach(function(){ console.log(' before each one'); }) afterEach(function(){ console.log(' after each one'); }) describe('two', function(){ before(function(){ console.log(' before two'); }) after(function(){ console.log(' after two'); }) beforeEach(function(){ console.log(' before each two'); }) afterEach(function(){ console.log(' after each two'); }) describe('three', function(){ before(function(){ console.log(' before three'); }) after(function(){ console.log(' after three'); }) beforeEach(function(){ console.log(' before each three'); }) afterEach(function(){ console.log(' after each three'); }) it('should three', function(){ console.log(' TEST three'); }) }) }) }) mocha-1.20.1/test/acceptance/misc/exit.js000066400000000000000000000006421234352070300201720ustar00rootroot00000000000000describe('exit', function(){ //note --bail works nicely in that it still allows an 'early exit' in an error scenario it('should not exit even in error scenario if called with --no-exit', function(done){ done(new Error('failure')); }) it('should take a long time to exit if called with --no-exit', function(done){ done(); setTimeout(function() { console.log('all done'); }, 2500) }) }) mocha-1.20.1/test/acceptance/misc/grep.js000066400000000000000000000005621234352070300201570ustar00rootroot00000000000000 describe('grep', function(){ describe('fast', function(){ it('should run fast', function(){ }) it('should run fast again', function(){ }) }) describe('slow', function(){ it('should run slow', function(done){ setTimeout(done, 1000); }) it('should run slow again', function(done){ setTimeout(done, 1000); }) }) }) mocha-1.20.1/test/acceptance/misc/many.js000066400000000000000000000010541234352070300201630ustar00rootroot00000000000000// Useful for testing SIGINT handler // use env.big_number to tune iterations so that you have time to ctrl+c describe('a load of tests', function(){ it('should fail the first test', function(){ throw new Error('this should appear in the summary'); }) var iterations = (process.env.big_number || 1e7); function work() { var a = 0; for(var i=0; i it 'should work', -> obj.should.eql foo: 'bar'mocha-1.20.1/test/acceptance/test.foo000066400000000000000000000000021234352070300174020ustar00rootroot000000000000001 mocha-1.20.1/test/acceptance/timeout.js000066400000000000000000000006021234352070300177500ustar00rootroot00000000000000 describe('timeouts', function(){ beforeEach(function(done){ // uncomment // setTimeout(done, 3000); done(); }) it('should error on timeout', function(done){ // uncomment // setTimeout(done, 3000); done(); }) it('should allow overriding per-test', function(done){ this.timeout(1000); setTimeout(function(){ done(); }, 300); }) }) mocha-1.20.1/test/acceptance/uncaught.js000066400000000000000000000005321234352070300201020ustar00rootroot00000000000000 describe('uncaught', function(){ beforeEach(function(done){ process.nextTick(function(){ // throw new Error('oh noes'); done(); }); }) it('should report properly', function(done){ process.nextTick(function(){ // if you uncomment this :) // throw new Error("I'm uncaught!"); done(); }) }) })mocha-1.20.1/test/acceptance/utils.js000066400000000000000000000033031234352070300174230ustar00rootroot00000000000000var utils = require('../../lib/utils'); describe('lib/utils', function () { describe('clean', function () { it("should format a single line test function", function () { var fn = [ "function () {" , " var a = 1;" , "}" ].join("\n"); utils.clean(fn).should.equal("var a = 1;"); }); it("should format a multi line test indented with spaces", function () { // and no new lines after curly braces, shouldn't matter var fn = [ "function(){ var a = 1;" , " var b = 2;" // this one has more spaces , " var c = 3; }" ].join("\n"); utils.clean(fn).should.equal("var a = 1;\n var b = 2;\nvar c = 3;"); }); it("should format a multi line test indented with tabs", function () { var fn = [ "function (arg1, arg2) {" , "\tif (true) {" , "\t\tvar a = 1;" , "\t}" , "}" ].join("\n"); utils.clean(fn).should.equal("if (true) {\n\tvar a = 1;\n}"); }); it("should format functions saved in windows style - spaces", function () { var fn = [ "function (one) {" , " do {", , ' "nothing";', , " } while (false);" , ' }' ].join("\r\n"); utils.clean(fn).should.equal('do {\n "nothing";\n} while (false);'); }); it("should format functions saved in windows style - tabs", function () { var fn = [ "function ( ) {" , "\tif (false) {" , "\t\tvar json = {" , '\t\t\tone : 1' , '\t\t};' , "\t}" , "}" ].join("\r\n"); utils.clean(fn).should.equal("if (false) {\n\tvar json = {\n\t\tone : 1\n\t};\n}"); }); }); });mocha-1.20.1/test/browser/000077500000000000000000000000001234352070300153235ustar00rootroot00000000000000mocha-1.20.1/test/browser/array.js000066400000000000000000000016241234352070300170020ustar00rootroot00000000000000describe('Array', function(){ describe('#push()', function(){ it('should append a value', function(){ foo = 'asdf' var arr = []; arr.push('foo'); arr.push('bar'); arr.push('baz'); assert('foo' == arr[0]); // to test indentation assert('bar' == arr[1]); assert('baz' == arr[2]); }) it('should return the length', function(){ var arr = []; assert(1 == arr.push('foo')); assert(2 == arr.push('bar')); assert(3 == arr.push('baz')); }) }) }) describe('Array', function(){ describe('#pop()', function(){ it('should remove and return the last value', function(){ var arr = [1,2,3]; assert(arr.pop() == 3); assert(arr.pop() == 2); assert(arr.pop() == -1); }) it('should adjust .length', function(){ var arr = [1,2,3]; arr.pop(); assert(arr.length == 2); }) }) }) mocha-1.20.1/test/browser/index.html000066400000000000000000000016311234352070300173210ustar00rootroot00000000000000 Mocha
      mocha-1.20.1/test/browser/large.html000066400000000000000000000011701234352070300173020ustar00rootroot00000000000000 Mocha
      mocha-1.20.1/test/browser/large.js000066400000000000000000000024021234352070300167510ustar00rootroot00000000000000 var n = 30; while (n--) { describe('Array ' + n, function(){ var arr; beforeEach(function(){ arr = [1,2,3]; }) describe('#indexOf()', function(){ it('should return -1 when the value is not present', function(){ assert(-1 == arr.indexOf(5)); }) it('should return the correct index when the value is present', function(done){ assert(0 == arr.indexOf(1)); assert(1 == arr.indexOf(2)); done(); }) }) }) } describe('something', function(){ it('should provide a useful error', function(done){ setTimeout(function(){ throw new Error('boom'); done(); }, 1); }) it('should provide an even better error on phantomjs', function(done){ setTimeout(function(){ var AssertionError = function(message, actual, expected) { this.message = message; this.actual = actual; this.expected = expected; this.showDiff = true; }; AssertionError.prototype = Object.create(Error.prototype); AssertionError.prototype.name = 'AssertionError'; AssertionError.prototype.constructor = AssertionError; mocha.throwError(new AssertionError('kabooom', 'text with a typo', 'text without a typo')); done(); }, 1); }) })mocha-1.20.1/test/browser/opts.html000066400000000000000000000014571234352070300172050ustar00rootroot00000000000000 Mocha
      mocha-1.20.1/test/browser/opts.js000066400000000000000000000002011234352070300166370ustar00rootroot00000000000000describe('Options', function() { it('should set timeout value', function() { assert(this.test._timeout === 1500); }); }) mocha-1.20.1/test/compiler/000077500000000000000000000000001234352070300154525ustar00rootroot00000000000000mocha-1.20.1/test/compiler/foo.js000066400000000000000000000004751234352070300166010ustar00rootroot00000000000000var fs = require('fs'); require.extensions['.foo'] = function(module, filename) { var content; content = fs.readFileSync(filename, 'utf8'); var test = 'describe("custom compiler",function(){ it("should work",function() { ' + content + '.should.eql(1); }); });'; return module._compile(test, filename); }; mocha-1.20.1/test/grep.js000066400000000000000000000023361234352070300151370ustar00rootroot00000000000000 var Mocha = require('../'); describe('Mocha', function(){ describe('"grep" option', function(){ it('should add a RegExp to the mocha.options object', function(){ var mocha = new Mocha({ grep: /foo/ }); mocha.options.grep.toString().should.equal('/foo/'); }) it('should convert grep string to a RegExp', function(){ var mocha = new Mocha({ grep: 'foo' }); mocha.options.grep.toString().should.equal('/foo/'); }) }) describe('.grep()', function(){ it('should add a RegExp to the mocha.options object', function(){ var mocha = new Mocha; mocha.grep(/foo/); mocha.options.grep.toString().should.equal('/foo/'); }) it('should convert grep string to a RegExp', function(){ var mocha = new Mocha; mocha.grep('foo'); mocha.options.grep.toString().should.equal('/foo/'); }) it('should return it\'s parent Mocha object for chainability', function(){ var mocha = new Mocha; mocha.grep().should.equal(mocha); }) }) describe('"invert" option', function(){ it('should add a Boolean to the mocha.options object', function(){ var mocha = new Mocha({ invert: true }); mocha.options.invert.should.be.ok; }) }) }) mocha-1.20.1/test/hook.async.js000066400000000000000000000052761234352070300162640ustar00rootroot00000000000000 describe('async', function(){ var calls = []; before(function(){ calls.push('root before all'); }) after(function(){ calls.push('root after all'); calls.should.eql([ 'root before all' , 'before all' , 'parent before' , 'before' , 'before test one' , 'one' , 'after' , 'after test one passed' , 'parent after' , 'parent before' , 'before' , 'before test two' , 'two' , 'after' , 'after test two passed' , 'parent after' , 'parent before' , 'before' , 'before test three' , 'three' , 'after' , 'after test three passed' , 'parent after' , 'after all' , 'root after all']); }) beforeEach(function(){ calls.push('parent before'); }) afterEach(function(){ calls.push('parent after' ); }) describe('hooks', function(){ before(function(){ calls.push('before all'); }); after(function(){ calls.push('after all'); }); beforeEach(function(done){ var ctx = this; process.nextTick(function(){ calls.push('before'); if (ctx.currentTest) { calls.push('before test ' + ctx.currentTest.title); } done(); }) }) it('one', function(done){ calls.should.eql([ 'root before all' , 'before all' , 'parent before' , 'before' , 'before test one']); calls.push('one'); process.nextTick(done); }) it('two', function(){ calls.should.eql([ 'root before all' , 'before all' , 'parent before' , 'before' , 'before test one' , 'one' , 'after' , 'after test one passed' , 'parent after' , 'parent before' , 'before' , 'before test two']); calls.push('two'); }) it('three', function(){ calls.should.eql([ 'root before all' , 'before all' , 'parent before' , 'before' , 'before test one' , 'one' , 'after' , 'after test one passed' , 'parent after' , 'parent before' , 'before' , 'before test two' , 'two' , 'after' , 'after test two passed' , 'parent after' , 'parent before' , 'before' , 'before test three']); calls.push('three'); }) afterEach(function(done){ var ctx = this; process.nextTick(function(){ calls.push('after'); if (ctx.currentTest) { calls.push('after test ' + ctx.currentTest.title + ' ' + ctx.currentTest.state); } done(); }) }) }) }) mocha-1.20.1/test/hook.err.js000066400000000000000000000202471234352070300157320ustar00rootroot00000000000000describe('hook error handling', function(){ // Lines in this test should be uncommented to see actual behavior // You will also see errors in hooks describe('before hook error', function() { var calls = []; describe('spec 1', function () { describe('spec 1 nested', function () { it('should not be called, because hook error was in a parent suite', function() { calls.push('test nested'); }) }) before(function(){ calls.push('before'); // throw new Error('before hook error'); }) after(function(){ calls.push('after'); }) it('should not be called because of error in before hook', function() { calls.push('test'); }) }) describe('spec 2', function () { before(function(){ calls.push('before 2'); }) after(function(){ calls.push('after 2'); }) it('should be called, because hook error was in a sibling suite', function() { calls.push('test 2'); }) }) after(function () { // calls.should.eql(['before', 'after', 'before 2', 'test 2', 'after 2']); }) }) describe('before each hook error', function() { var calls = []; describe('spec 1', function () { describe('spec 1 nested', function () { it('should not be called, because hook error was in a parent suite', function() { calls.push('test nested'); }) }) beforeEach(function(){ calls.push('before'); // throw new Error('before each hook error'); }) afterEach(function(){ calls.push('after'); }) it('should not be called because of error in before each hook', function() { calls.push('test'); }) }) describe('spec 2', function () { before(function(){ calls.push('before 2'); }) after(function(){ calls.push('after 2'); }) it('should be called, because hook error was in a sibling suite', function() { calls.push('test 2'); }) }) after(function () { // This should be called ! // calls.should.eql(['before', 'after', 'before 2', 'test 2', 'after 2']); }) }) describe('after hook error', function() { var calls = []; describe('spec 1', function () { describe('spec 1 nested', function () { it('should be called, because hook error will happen after parent suite', function() { calls.push('test nested'); }) }) before(function(){ calls.push('before'); }) after(function(){ calls.push('after'); // throw new Error('after hook error'); }) it('should be called because error is in after hook', function() { calls.push('test'); }) }) describe('spec 2', function () { before(function(){ calls.push('before 2'); }) after(function(){ calls.push('after 2'); }) it('should be called, because hook error was in a sibling suite', function() { calls.push('test 2'); }) }) after(function () { // Even this should be called ! // calls.should.eql(['before', 'test', 'test nested', 'after', 'before 2', 'test 2', 'after 2']); }) }) describe('after each hook error', function() { var calls = []; describe('spec 1', function () { describe('spec 1 nested', function () { it('should not be called, because hook error has already happened in parent suite', function() { calls.push('test nested'); }) }) beforeEach(function(){ calls.push('before'); }) afterEach(function(){ calls.push('after'); // throw new Error('after each hook error'); }) it('should be called because error is in after each hook, and this is the first test', function() { calls.push('test'); }) it('should not be called because error is in after each hook, and this is the second test', function() { calls.push('another test'); }) }) describe('spec 2', function () { before(function(){ calls.push('before 2'); }) after(function(){ calls.push('after 2'); }) it('should be called, because hook error was in a sibling suite', function() { calls.push('test 2'); }) }) after(function () { // This should be called ! // calls.should.eql(['before', 'test', 'after', 'before 2', 'test 2', 'after 2']); }) }) describe('multiple hook errors', function() { var calls = []; before(function(){ calls.push("root before"); }); beforeEach(function(){ calls.push("root before each"); }); describe('1', function(){ beforeEach(function() { calls.push('1 before each') }) describe('1.1', function(){ before(function() { calls.push('1.1 before'); }); beforeEach(function() { calls.push('1.1 before each') // throw new Error('1.1 before each hook failed') }); it('1.1 test 1', function () {calls.push('1.1 test 1')}); it('1.1 test 2', function () {calls.push('1.1 test 2')}); afterEach(function() { calls.push("1.1 after each"); }); after(function(){ calls.push("1.1 after"); // throw new Error('1.1 after hook failed') }); }); describe('1.2', function(){ before(function() { calls.push('1.2 before'); }); beforeEach(function() { calls.push('1.2 before each') }); it('1.2 test 1', function () {calls.push('1.2 test 1')}); it('1.2 test 2', function () {calls.push('1.2 test 2')}); afterEach(function() { calls.push("1.2 after each"); // throw new Error('1.2 after each hook failed') }); after(function(){ calls.push("1.2 after"); }); }); afterEach(function() { calls.push('1 after each') }) after(function(){ calls.push("1 after"); }); }) describe('2', function(){ beforeEach(function() { calls.push('2 before each') // throw new Error('2 before each hook failed') }) describe('2.1', function(){ before(function() { calls.push('2.1 before'); }); beforeEach(function() { calls.push('2.1 before each') }); it('2.1 test 1', function () {calls.push('2.1 test 1')}); it('2.1 test 2', function () {calls.push('2.1 test 2')}); afterEach(function() { calls.push("2.1 after each"); }); after(function(){ calls.push("2.1 after"); }); }); describe('2.2', function(){ before(function() { calls.push('2.2 before'); }); beforeEach(function() { calls.push('2.2 before each') }); it('2.2 test 1', function () {calls.push('2.2 test 1')}); it('2.2 test 2', function () {calls.push('2.2 test 2')}); afterEach(function() { calls.push("2.2 after each"); }); after(function(){ calls.push("2.2 after"); }); }); afterEach(function() { calls.push('2 after each') // throw new Error('2 after each hook failed') }) after(function(){ calls.push("2 after"); }); }) after(function(){ calls.push("root after"); /* calls.should.eql([ "root before", "1.1 before", "root before each", "1 before each", "1.1 before each", "1.1 after each", "1 after each", "root after each", "1.1 after", "1.2 before", "root before each", "1 before each", "1.2 before each", "1.2 test 1", "1.2 after each", "1 after each", "root after each", "1.2 after", "1 after", "2.1 before", "root before each", "2 before each", "2 after each", "root after each", "2.1 after", "2 after", "root after" ]); */ }); afterEach(function(){ calls.push("root after each"); }); }) })mocha-1.20.1/test/hook.sync.js000066400000000000000000000041011234352070300161050ustar00rootroot00000000000000 describe('serial', function(){ var calls = []; beforeEach(function(){ calls.push('parent before'); }) afterEach(function(){ calls.push('parent after'); }) describe('hooks', function(){ beforeEach(function(){ calls.push('before'); if (this.currentTest) { calls.push('before test ' + this.currentTest.title); } }) it('one', function(){ calls.should.eql([ 'parent before' , 'before' , 'before test one']); calls.push('one'); }) it('two', function(){ calls.should.eql([ 'parent before' , 'before' , 'before test one' , 'one' , 'after' , 'after test one passed' , 'parent after' , 'parent before' , 'before' , 'before test two']); calls.push('two'); }) it('three', function(){ calls.should.eql([ 'parent before' , 'before' , 'before test one' , 'one' , 'after' , 'after test one passed' , 'parent after' , 'parent before' , 'before' , 'before test two' , 'two' , 'after' , 'after test two passed' , 'parent after' , 'parent before' , 'before' , 'before test three']); calls.push('three'); }) afterEach(function(){ calls.push('after'); if (this.currentTest) { calls.push('after test ' + this.currentTest.title + ' ' + this.currentTest.state); } }) after(function(){ calls.should.eql([ 'parent before' , 'before' , 'before test one' , 'one' , 'after' , 'after test one passed' , 'parent after' , 'parent before' , 'before' , 'before test two' , 'two' , 'after' , 'after test two passed' , 'parent after' , 'parent before' , 'before' , 'before test three' , 'three' , 'after' , 'after test three passed' , 'parent after']); }) }) })mocha-1.20.1/test/hook.sync.nested.js000066400000000000000000000050041234352070300173710ustar00rootroot00000000000000 describe('serial', function(){ describe('nested', function(){ var calls = []; beforeEach(function(){ calls.push('parent before'); if (this.currentTest) { calls.push('parent before test ' + this.currentTest.title); } }) afterEach(function(){ calls.push('parent after'); if (this.currentTest) { calls.push('parent after test ' + this.currentTest.title + ' ' + this.currentTest.state); } }); it('foo', function(){ calls.should.eql([ 'parent before' , 'parent before test foo']); calls.push('foo'); }) it('bar', function(){ calls.should.eql([ 'parent before' , 'parent before test foo' , 'foo' , 'parent after' , 'parent after test foo passed' , 'parent before' , 'parent before test bar']); }) describe('hooks', function(){ beforeEach(function(){ calls.push('before'); if (this.currentTest) { calls.push('before test ' + this.currentTest.title); } }) it('one', function(){ calls.should.eql([ 'parent before' , 'parent before test foo' , 'foo' , 'parent after' , 'parent after test foo passed' , 'parent before' , 'parent before test bar' , 'parent after' , 'parent after test bar passed' , 'parent before' , 'parent before test one' , 'before' , 'before test one']); calls.push('one'); }) it('two', function(){ calls.should.eql([ 'parent before' , 'parent before test foo' , 'foo' , 'parent after' , 'parent after test foo passed' , 'parent before' , 'parent before test bar' , 'parent after' , 'parent after test bar passed' , 'parent before' , 'parent before test one' , 'before' , 'before test one' , 'one' , 'after' , 'after test one passed' , 'parent after' , 'parent after test one passed' , 'parent before' , 'parent before test two' , 'before' , 'before test two']); calls.push('two'); }); afterEach(function(){ calls.push('after'); if (this.currentTest) { calls.push('after test ' + this.currentTest.title + ' ' + this.currentTest.state); } }) }) }) }) mocha-1.20.1/test/hook.timeout.js000066400000000000000000000001711234352070300166220ustar00rootroot00000000000000 before(function(done){ this.timeout(100); setTimeout(done, 50); }) it('should work', function(done) { done(); });mocha-1.20.1/test/http.meta.2.js000066400000000000000000000032751234352070300162510ustar00rootroot00000000000000 var http = require('http'); var server = http.createServer(function(req, res){ var accept = req.headers.accept || '' , json = ~accept.indexOf('json'); switch (req.url) { case '/': res.end('hello'); break; case '/users': if (json) { res.end('["tobi","loki","jane"]'); } else { res.end('tobi, loki, jane'); } break; } }) server.listen(8899); function get(url) { var fields , expected , header = {}; function request(done) { http.get({ path: url, port: 8899, headers: header }, function(res){ var buf = ''; res.should.have.property('statusCode', 200); res.setEncoding('utf8'); res.on('data', function(chunk){ buf += chunk }); res.on('end', function(){ buf.should.equal(expected); done(); }); }) } return { set: function(field, val){ header[field] = val; return this; }, should: { respond: function(body){ fields = Object.keys(header).map(function(field){ return field + ': ' + header[field]; }).join(', '); expected = body; describe('GET ' + url, function(){ if (fields) { describe('when given ' + fields, function(){ it('should respond with "' + body + '"', request); }); } else { it('should respond with "' + body + '"', request); } }); } } }; } describe('http server', function(){ get('/') .should .respond('hello') get('/users') .should .respond('tobi, loki, jane') get('/users') .set('Accept', 'application/json') .should .respond('["tobi","loki","jane"]') })mocha-1.20.1/test/http.meta.js000066400000000000000000000022351234352070300161040ustar00rootroot00000000000000 var http = require('http'); var server = http.createServer(function(req, res){ var accept = req.headers.accept || '' , json = ~accept.indexOf('json'); switch (req.url) { case '/': res.end('hello'); break; case '/users': if (json) { res.end('["tobi","loki","jane"]'); } else { res.end('tobi, loki, jane'); } break; } }) server.listen(8889); function get(url, body, header) { return function(done){ http.get({ path: url, port: 8889, headers: header }, function(res){ var buf = ''; res.should.have.property('statusCode', 200); res.setEncoding('utf8'); res.on('data', function(chunk){ buf += chunk }); res.on('end', function(){ buf.should.equal(body); done(); }); }) } } describe('http requests', function(){ describe('GET /', function(){ it('should respond with hello', get('/', 'hello')) }) describe('GET /users', function(){ it('should respond with users', get('/users', 'tobi, loki, jane')) it('should respond with users', get('/users', '["tobi","loki","jane"]', { Accept: 'application/json' })) }) })mocha-1.20.1/test/jsapi/000077500000000000000000000000001234352070300147465ustar00rootroot00000000000000mocha-1.20.1/test/jsapi/index.js000066400000000000000000000014511234352070300164140ustar00rootroot00000000000000 var Mocha = require('../../') , path = require('path'); var mocha = new Mocha({ ui: 'bdd', globals: ['okGlobalA', 'okGlobalB', 'okGlobalC', 'callback*'], // ignoreLeaks: true, growl: true }); // mocha.reporter('spec'); require('should'); mocha.addFile('test/suite.js'); mocha.addFile('test/runner.js'); mocha.addFile('test/runnable.js'); mocha.addFile('test/hook.sync.js'); mocha.addFile('test/hook.sync.nested.js'); mocha.addFile('test/hook.async.js'); mocha.addFile('test/acceptance/duration.js'); mocha.addFile('test/acceptance/fs.js'); mocha.addFile('test/acceptance/globals.js'); mocha.addFile('test/acceptance/pending.js'); mocha.addFile('test/acceptance/timeout.js'); mocha.run(function(){ console.log('done'); }).on('pass', function(test){ // console.log('... %s', test.title); }); mocha-1.20.1/test/mocha.opts000066400000000000000000000001751234352070300156410ustar00rootroot00000000000000--require should --reporter dot --ui bdd --globals okGlobalA,okGlobalB --globals okGlobalC --globals callback* --timeout 200 mocha-1.20.1/test/reporters/000077500000000000000000000000001234352070300156655ustar00rootroot00000000000000mocha-1.20.1/test/reporters/nyan.js000066400000000000000000000021251234352070300171700ustar00rootroot00000000000000var reporters = require('../../').reporters , NyanCat = reporters.Nyan; describe('nyan face', function () { it('nyan face:(x .x) when "failures" at least one', function () { var nyanCat = new NyanCat({on: function(){}}); nyanCat.stats = { passes: 2, pending: 1, failures: 1 }; nyanCat.face.call(nyanCat).should.equal('( x .x)'); }); it('expected nyan face:(x .x) when "peinding" at least one and no failing', function () { var nyanCat = new NyanCat({on: function(){}}); nyanCat.stats = { passes: 2, pending: 1, failures: 0 }; nyanCat.face.call(nyanCat).should.equal('( o .o)'); }); it('expected nyan face:(^ .^) when "passing" only', function () { var nyanCat = new NyanCat({on: function(){}}); nyanCat.stats = { passes: 1, pending: 0, failures: 0 }; nyanCat.face.call(nyanCat).should.equal('( ^ .^)'); }); it('nyan face:(- .-) when otherwise', function (done) { var nyanCat = new NyanCat({on: function(){}}); nyanCat.stats = { passes: 0, pending: 0, failures: 0 }; nyanCat.face.call(nyanCat).should.equal('( - .-)'); done(); }); }) mocha-1.20.1/test/runnable.js000066400000000000000000000217211234352070300160070ustar00rootroot00000000000000 var mocha = require('../') , Runnable = mocha.Runnable , EventEmitter = require('events').EventEmitter; describe('Runnable(title, fn)', function(){ // For every test we poison the global time-related methods. // runnable.js etc. should keep its own local copy, in order to fix GH-237. // NB: we can't poison global.Date because the normal implementation of // global.setTimeout uses it [1] so if the runnable.js keeps a copy of // global.setTimeout (like it's supposed to), that will blow up. // [1]: https://github.com/joyent/node/blob/7fc835afe362ebd30a0dbec81d3360bd24525222/lib/timers.js#L74 var setTimeout = global.setTimeout , setInterval = global.setInterval , clearTimeout = global.clearTimeout , clearInterval = global.clearInterval; function poisonPill() { throw new Error("Don't use global time-related stuff."); } beforeEach(function(){ global.setTimeout = global.setInterval = global.clearTimeout = global.clearInterval = poisonPill; }) afterEach(function(){ global.setTimeout = setTimeout; global.setInterval = setInterval; global.clearTimeout = clearTimeout; global.clearInterval = clearInterval; }) describe('#timeout(ms)', function(){ it('should set the timeout', function(){ var run = new Runnable; run.timeout(1000) run.timeout().should.equal(1000); }) }) describe('#slow(ms)', function(){ it('should set the slow threshold', function(){ var run = new Runnable; run.slow(100) run.slow().should.equal(100); }) }) describe('.title', function(){ it('should be present', function(){ new Runnable('foo').title.should.equal('foo'); }) }) describe('when arity >= 1', function(){ it('should be .async', function(){ var run = new Runnable('foo', function(done){}); run.async.should.equal(1); run.sync.should.be.false; }) }) describe('when arity == 0', function(){ it('should be .sync', function(){ var run = new Runnable('foo', function(){}); run.async.should.be.equal(0); run.sync.should.be.true; }) }) describe('#globals', function(){ it('should allow for whitelisting globals', function(done){ var test = new Runnable('foo', function(){}); test.async.should.be.equal(0); test.sync.should.be.true; test.globals(['foobar']); test.run(done); }) }) describe('.run(fn)', function(){ describe('when .pending', function(){ it('should not invoke the callback', function(done){ var test = new Runnable('foo', function(){ throw new Error('should not be called'); }); test.pending = true; test.run(done); }) }) describe('when sync', function(){ describe('without error', function(){ it('should invoke the callback', function(done){ var calls = 0; var test = new Runnable('foo', function(){ ++calls; }); test.run(function(err){ calls.should.equal(1); test.duration.should.be.type('number'); done(err); }) }) }) describe('when an exception is thrown', function(){ it('should invoke the callback', function(done){ var calls = 0; var test = new Runnable('foo', function(){ ++calls; throw new Error('fail'); }); test.run(function(err){ calls.should.equal(1); err.message.should.equal('fail'); done(); }) }) }) }) describe('when async', function(){ describe('without error', function(){ it('should invoke the callback', function(done){ var calls = 0; var test = new Runnable('foo', function(done){ process.nextTick(done); }); test.run(done); }) }) describe('when the callback is invoked several times', function(){ describe('without an error', function(){ it('should emit a single "error" event', function(done){ var calls = 0; var errCalls = 0; var test = new Runnable('foo', function(done){ process.nextTick(done); process.nextTick(done); process.nextTick(done); process.nextTick(done); }); test.on('error', function(err){ ++errCalls; err.message.should.equal('done() called multiple times'); calls.should.equal(1); errCalls.should.equal(1); done(); }); test.run(function(){ ++calls; }); }) }) describe('with an error', function(){ it('should emit a single "error" event', function(done){ var calls = 0; var errCalls = 0; var test = new Runnable('foo', function(done){ done(new Error('fail')); process.nextTick(done); done(new Error('fail')); process.nextTick(done); process.nextTick(done); }); test.on('error', function(err){ ++errCalls; err.message.should.equal('fail'); calls.should.equal(1); errCalls.should.equal(1); done(); }); test.run(function(){ ++calls; }); }) }) }) describe('when an exception is thrown', function(){ it('should invoke the callback', function(done){ var calls = 0; var test = new Runnable('foo', function(done){ throw new Error('fail'); process.nextTick(done); }); test.run(function(err){ err.message.should.equal('fail'); done(); }); }) }) describe('when an error is passed', function(){ it('should invoke the callback', function(done){ var calls = 0; var test = new Runnable('foo', function(done){ done(new Error('fail')); }); test.run(function(err){ err.message.should.equal('fail'); done(); }); }) }) it('should allow updating the timeout', function(done){ var callCount = 0; var increment = function() { callCount++; }; var test = new Runnable('foo', function(done){ setTimeout(increment, 1); setTimeout(increment, 100); }); test.timeout(10); test.run(function(err){ err.should.be.ok; callCount.should.equal(1); done(); }); }) it('should allow a timeout of 0') }) describe('when fn returns a promise', function(){ describe('when the promise is fulfilled with no value', function(){ var fulfilledPromise = { then: function (fulfilled, rejected) { process.nextTick(fulfilled); } }; it('should invoke the callback', function(done){ var test = new Runnable('foo', function(){ return fulfilledPromise; }); test.run(done); }) }) describe('when the promise is fulfilled with a value', function(){ var fulfilledPromise = { then: function (fulfilled, rejected) { process.nextTick(function () { fulfilled({}); }); } }; it('should invoke the callback', function(done){ var test = new Runnable('foo', function(){ return fulfilledPromise; }); test.run(done); }) }) describe('when the promise is rejected', function(){ var expectedErr = new Error('fail'); var rejectedPromise = { then: function (fulfilled, rejected) { process.nextTick(function () { rejected(expectedErr); }); } }; it('should invoke the callback', function(done){ var test = new Runnable('foo', function(){ return rejectedPromise; }); test.run(function(err){ err.should.equal(expectedErr); done(); }); }) }) describe('when the promise takes too long to settle', function(){ var foreverPendingPromise = { then: function () { } }; it('should give the timeout error', function(done){ var test = new Runnable('foo', function(){ return foreverPendingPromise; }); test.timeout(10); test.run(function(err){ err.should.be.ok; done(); }); }) }) }) describe('when fn returns a non-promise', function(){ it('should invoke the callback', function(done){ var test = new Runnable('foo', function(){ return { then: "i ran my tests" }; }); test.run(done); }) }) }) }) mocha-1.20.1/test/runner.js000066400000000000000000000166531234352070300155220ustar00rootroot00000000000000 var mocha = require('../') , Suite = mocha.Suite , Runner = mocha.Runner , Test = mocha.Test; describe('Runner', function(){ var suite, runner; beforeEach(function(){ suite = new Suite(null, 'root'); runner = new Runner(suite); }) describe('.grep()', function(){ it('should update the runner.total with number of matched tests', function(){ suite.addTest(new Test('im a test about lions')); suite.addTest(new Test('im another test about lions')); suite.addTest(new Test('im a test about bears')); var newRunner = new Runner(suite); newRunner.grep(/lions/); newRunner.total.should.equal(2); }) it('should update the runner.total with number of matched tests when inverted', function(){ suite.addTest(new Test('im a test about lions')); suite.addTest(new Test('im another test about lions')); suite.addTest(new Test('im a test about bears')); var newRunner = new Runner(suite); newRunner.grep(/lions/, true); newRunner.total.should.equal(1); }) }) describe('.grepTotal()', function(){ it('should return the total number of matched tests', function(){ suite.addTest(new Test('im a test about lions')); suite.addTest(new Test('im another test about lions')); suite.addTest(new Test('im a test about bears')); runner.grep(/lions/); runner.grepTotal(suite).should.equal(2); }) it('should return the total number of matched tests when inverted', function(){ suite.addTest(new Test('im a test about lions')); suite.addTest(new Test('im another test about lions')); suite.addTest(new Test('im a test about bears')); runner.grep(/lions/, true); runner.grepTotal(suite).should.equal(1); }) }) describe('.globalProps()', function(){ it('should include common non enumerable globals', function() { var props = runner.globalProps(); props.should.containEql('setTimeout'); props.should.containEql('clearTimeout'); props.should.containEql('setInterval'); props.should.containEql('clearInterval'); props.should.containEql('Date'); props.should.containEql('XMLHttpRequest'); }); }); describe('.globals()', function(){ it('should default to the known globals', function(){ runner.globals().length.should.be.above(16); }) it('should white-list globals', function(){ runner.globals(['foo', 'bar']); runner.globals().should.containEql('foo'); runner.globals().should.containEql('bar'); }) }) describe('.checkGlobals(test)', function(){ it('should allow variables that match a wildcard', function(done) { runner.globals(['foo*', 'giz*']); global.foo = 'baz'; global.gizmo = 'quux'; runner.checkGlobals(); delete global.foo; delete global.gizmo; done() }) it('should emit "fail" when a new global is introduced', function(done){ runner.checkGlobals(); global.foo = 'bar'; runner.on('fail', function(test, err){ test.should.equal('im a test'); err.message.should.equal('global leak detected: foo'); delete global.foo; done(); }); runner.checkGlobals('im a test'); }) it('should emit "fail" when a single new disallowed global is introduced after a single extra global is allowed', function(done) { var doneCalled = false; runner.globals('good'); global.bad = 1; runner.on('fail', function(test, err) { delete global.bad; done(); doneCalled = true; }); runner.checkGlobals('test'); if (!doneCalled) { done(Error("Expected test failure did not occur.")); } }); it ('should not fail when a new common global is introduced', function(){ // verify that the prop isn't enumerable delete global.XMLHttpRequest; global.propertyIsEnumerable('XMLHttpRequest').should.not.be.ok; // create a new runner and keep a reference to the test. var test = new Test('im a test about bears'); suite.addTest(test); var newRunner = new Runner(suite); // make the prop enumerable again. global.XMLHttpRequest = function() {}; global.propertyIsEnumerable('XMLHttpRequest').should.be.ok; // verify the test hasn't failed. newRunner.checkGlobals(test); test.should.not.have.key('state'); // clean up our global space. delete global.XMLHttpRequest; }); it('should pluralize the error message when several are introduced', function(done){ runner.checkGlobals(); global.foo = 'bar'; global.bar = 'baz'; runner.on('fail', function(test, err){ test.should.equal('im a test'); err.message.should.equal('global leaks detected: foo, bar'); delete global.foo; delete global.bar; done(); }); runner.checkGlobals('im a test'); }) it('should respect per test whitelisted globals', function() { var test = new Test('im a test about lions'); test.globals(['foo']); suite.addTest(test); var runner = new Runner(suite); global.foo = 'bar'; // verify the test hasn't failed. runner.checkGlobals(test); test.should.not.have.key('state'); delete global.foo; }) it('should respect per test whitelisted globals but still detect other leaks', function(done) { var test = new Test('im a test about lions'); test.globals(['foo']); suite.addTest(test); global.foo = 'bar'; global.bar = 'baz'; runner.on('fail', function(test, err){ test.title.should.equal('im a test about lions'); err.message.should.equal('global leak detected: bar'); delete global.foo; done(); }); runner.checkGlobals(test); }) }) describe('.fail(test, err)', function(){ it('should increment .failures', function(){ runner.failures.should.equal(0); runner.fail({}, {}); runner.failures.should.equal(1); runner.fail({}, {}); runner.failures.should.equal(2); }) it('should set test.state to "failed"', function(){ var test = {}; runner.fail(test, 'some error'); test.state.should.equal('failed'); }) it('should emit "fail"', function(done){ var test = {}, err = {}; runner.on('fail', function(test, err){ test.should.equal(test); err.should.equal(err); done(); }); runner.fail(test, err); }) }) describe('.failHook(hook, err)', function(){ it('should increment .failures', function(){ runner.failures.should.equal(0); runner.failHook({}, {}); runner.failures.should.equal(1); runner.failHook({}, {}); runner.failures.should.equal(2); }) it('should emit "fail"', function(done){ var hook = {}, err = {}; runner.on('fail', function(hook, err){ hook.should.equal(hook); err.should.equal(err); done(); }); runner.failHook(hook, err); }) it('should emit "end" if suite bail is true', function(done){ var hook = {}, err = {}; suite.bail(true); runner.on('end', done); runner.failHook(hook, err); }) it('should not emit "end" if suite bail is not true', function(done){ var hook = {}, err = {}; suite.bail(false); runner.on('end', function() { throw new Error('"end" was emit, but the bail is false'); }); runner.failHook(hook, err); done(); }) }) }) mocha-1.20.1/test/suite.js000066400000000000000000000274671234352070300153470ustar00rootroot00000000000000 var mocha = require('../') , Context = mocha.Context , Suite = mocha.Suite , Test = mocha.Test; describe('Suite', function(){ describe('.clone()', function(){ beforeEach(function(){ this.suite = new Suite('To be cloned'); this.suite._timeout = 3043; this.suite._slow = 101; this.suite._bail = true; this.suite.suites.push(1); this.suite.tests.push('hello'); this.suite._beforeEach.push(2); this.suite._beforeAll.push(3); this.suite._afterEach.push(4); this.suite._afterAll.push(5); }); it('should copy the title', function(){ this.suite.clone().title.should.equal('To be cloned'); }); it('should copy the timeout value', function(){ this.suite.clone().timeout().should.equal(3043); }); it('should copy the slow value', function(){ this.suite.clone().slow().should.equal(101); }); it('should copy the bail value', function(){ this.suite.clone().bail().should.be.true; }); it('should not copy the values from the suites array', function(){ this.suite.clone().suites.should.be.empty; }); it('should not copy the values from the tests array', function(){ this.suite.clone().tests.should.be.empty; }); it('should not copy the values from the _beforeEach array', function(){ this.suite.clone()._beforeEach.should.be.empty; }); it('should not copy the values from the _beforeAll array', function(){ this.suite.clone()._beforeAll.should.be.empty; }); it('should not copy the values from the _afterEach array', function(){ this.suite.clone()._afterEach.should.be.empty; }); it('should not copy the values from the _afterAll array', function(){ this.suite.clone()._afterAll.should.be.empty; }); }); describe('.timeout()', function(){ beforeEach(function(){ this.suite = new Suite('A Suite'); }); describe('when no argument is passed', function(){ it('should return the timeout value', function(){ this.suite.timeout().should.equal(2000); }); }); describe('when argument is passed', function(){ it('should return the Suite object', function(){ var newSuite = this.suite.timeout(5000); newSuite.timeout().should.equal(5000); }); }); }); describe('.slow()', function(){ beforeEach(function(){ this.suite = new Suite('A Suite'); }); describe('when given a string', function(){ it('should parse it', function(){ this.suite.slow('5 seconds'); this.suite.slow().should.equal(5000); }) }) describe('when no argument is passed', function(){ it('should return the slow value', function(){ this.suite.slow().should.equal(75); }); }); describe('when argument is passed', function(){ it('should return the Suite object', function(){ var newSuite = this.suite.slow(5000); newSuite.slow().should.equal(5000); }); }); }); describe('.bail()', function(){ beforeEach(function(){ this.suite = new Suite('A Suite'); this.suite._bail = true }); describe('when no argument is passed', function(){ it('should return the bail value', function(){ this.suite.bail().should.be.true; }); }); describe('when argument is passed', function(){ it('should return the Suite object', function(){ var newSuite = this.suite.bail(false); newSuite.bail().should.be.false; }); }); }); describe('.beforeAll()', function(){ beforeEach(function(){ this.suite = new Suite('A Suite'); }); describe('wraps the passed in function in a Hook', function(){ it('adds it to _beforeAll', function(){ var fn = function(){}; this.suite.beforeAll(fn); this.suite._beforeAll.should.have.length(1); var beforeAllItem = this.suite._beforeAll[0]; beforeAllItem.title.should.equal('"before all" hook'); beforeAllItem.fn.should.equal(fn); }); it('appends title to hook', function(){ var fn = function(){}; this.suite.beforeAll('test', fn); this.suite._beforeAll.should.have.length(1); var beforeAllItem = this.suite._beforeAll[0]; beforeAllItem.title.should.equal('"before all" hook: test'); beforeAllItem.fn.should.equal(fn); function namedFn(){} this.suite.beforeAll(namedFn); this.suite._beforeAll.should.have.length(2); beforeAllItem = this.suite._beforeAll[1]; beforeAllItem.title.should.equal('"before all" hook: namedFn'); beforeAllItem.fn.should.equal(namedFn); }); }); }); describe('.afterAll()', function(){ beforeEach(function(){ this.suite = new Suite('A Suite'); }); describe('wraps the passed in function in a Hook', function(){ it('adds it to _afterAll', function(){ var fn = function(){}; this.suite.afterAll(fn); this.suite._afterAll.should.have.length(1); var afterAllItem = this.suite._afterAll[0]; afterAllItem.title.should.equal('"after all" hook'); afterAllItem.fn.should.equal(fn); }); it('appends title to hook', function(){ var fn = function(){}; this.suite.afterAll('test', fn); this.suite._afterAll.should.have.length(1); var beforeAllItem = this.suite._afterAll[0]; beforeAllItem.title.should.equal('"after all" hook: test'); beforeAllItem.fn.should.equal(fn); function namedFn(){} this.suite.afterAll(namedFn); this.suite._afterAll.should.have.length(2); beforeAllItem = this.suite._afterAll[1]; beforeAllItem.title.should.equal('"after all" hook: namedFn'); beforeAllItem.fn.should.equal(namedFn); }); }); }); describe('.beforeEach()', function(){ beforeEach(function(){ this.suite = new Suite('A Suite'); }); describe('wraps the passed in function in a Hook', function(){ it('adds it to _beforeEach', function(){ var fn = function(){}; this.suite.beforeEach(fn); this.suite._beforeEach.should.have.length(1); var beforeEachItem = this.suite._beforeEach[0]; beforeEachItem.title.should.equal('"before each" hook'); beforeEachItem.fn.should.equal(fn); }); it('appends title to hook', function(){ var fn = function(){}; this.suite.beforeEach('test', fn); this.suite._beforeEach.should.have.length(1); var beforeAllItem = this.suite._beforeEach[0]; beforeAllItem.title.should.equal('"before each" hook: test'); beforeAllItem.fn.should.equal(fn); function namedFn(){} this.suite.beforeEach(namedFn); this.suite._beforeEach.should.have.length(2); beforeAllItem = this.suite._beforeEach[1]; beforeAllItem.title.should.equal('"before each" hook: namedFn'); beforeAllItem.fn.should.equal(namedFn); }); }); }); describe('.afterEach()', function(){ beforeEach(function(){ this.suite = new Suite('A Suite'); }); describe('wraps the passed in function in a Hook', function(){ it('adds it to _afterEach', function(){ var fn = function(){}; this.suite.afterEach(fn); this.suite._afterEach.should.have.length(1); var afterEachItem = this.suite._afterEach[0]; afterEachItem.title.should.equal('"after each" hook'); afterEachItem.fn.should.equal(fn); }); it('appends title to hook', function(){ var fn = function(){}; this.suite.afterEach('test', fn); this.suite._afterEach.should.have.length(1); var beforeAllItem = this.suite._afterEach[0]; beforeAllItem.title.should.equal('"after each" hook: test'); beforeAllItem.fn.should.equal(fn); function namedFn(){} this.suite.afterEach(namedFn); this.suite._afterEach.should.have.length(2); beforeAllItem = this.suite._afterEach[1]; beforeAllItem.title.should.equal('"after each" hook: namedFn'); beforeAllItem.fn.should.equal(namedFn); }); }); }); describe('.addSuite()', function(){ beforeEach(function(){ this.first = new Suite('First suite'); this.first.timeout(4002); this.first.slow(200); this.second = new Suite('Second suite'); this.first.addSuite(this.second); }); it('sets the parent on the added Suite', function(){ this.second.parent.should.equal(this.first); }); it('copies the timeout value', function(){ this.second.timeout().should.equal(4002); }); it('copies the slow value', function(){ this.second.slow().should.equal(200); }); it('adds the suite to the suites collection', function(){ this.first.suites.should.have.length(1); this.first.suites[0].should.equal(this.second); }); }); // describe('.addTest()', function(){ // beforeEach(function(){ // this.suite = new Suite('A Suite', new Context); // this.suite.timeout(4002); // this.test = new Test('test'); // this.suite.addTest(this.test); // }); // // it('sets the parent on the added test', function(){ // this.test.parent.should.equal(this.suite); // }); // // it('copies the timeout value', function(){ // this.test.timeout().should.equal(4002); // }); // // it('adds the test to the tests collection', function(){ // this.suite.tests.should.have.length(1); // this.suite.tests[0].should.equal(this.test); // }); // }); describe('.fullTitle()', function(){ beforeEach(function(){ this.suite = new Suite('A Suite'); }); describe('when there is no parent', function(){ it('returns the suite title', function(){ this.suite.fullTitle().should.equal('A Suite'); }); }); describe('when there is a parent', function(){ it('returns the combination of parent\'s and suite\'s title', function(){ var parentSuite = new Suite('I am a parent'); parentSuite.addSuite(this.suite); this.suite.fullTitle().should.equal('I am a parent A Suite'); }); }); }); describe('.total()', function(){ beforeEach(function(){ this.suite = new Suite('A Suite'); }); describe('when there are no nested suites or tests', function(){ it('should return 0', function(){ this.suite.total().should.equal(0); }); }); describe('when there are several tests in the suite', function(){ it('should return the number', function(){ this.suite.addTest(new Test('a child test')); this.suite.addTest(new Test('another child test')); this.suite.total().should.equal(2); }); }); }); describe('.eachTest(fn)', function(){ beforeEach(function(){ this.suite = new Suite('A Suite'); }); describe('when there are no nested suites or tests', function(){ it('should return 0', function(){ var n = 0; function fn(){ n++; } this.suite.eachTest(fn); n.should.equal(0); }); }); describe('when there are several tests in the suite', function(){ it('should return the number', function(){ this.suite.addTest(new Test('a child test')); this.suite.addTest(new Test('another child test')); var n = 0; function fn(){ n++; } this.suite.eachTest(fn); n.should.equal(2); }); }); describe('when there are several levels of nested suites', function(){ it('should return the number', function(){ this.suite.addTest(new Test('a child test')); var suite = new Suite('a child suite'); suite.addTest(new Test('a test in a child suite')); this.suite.addSuite(suite); var n = 0; function fn(){ n++; } this.suite.eachTest(fn); n.should.equal(2); }); }); }); }); mocha-1.20.1/test/utils.js000066400000000000000000000012061234352070300153350ustar00rootroot00000000000000 var mocha = require('..'); var utils = mocha.utils; var clean = utils.clean; describe('utils', function(){ describe('.clean()', function(){ it('should remove the wrapping function declaration', function(){ clean('function (one, two, three) {\n//code\n}').should.equal('//code'); }) it('should remove space character indentation from the function body', function(){ clean(' //line1\n //line2').should.equal('//line1\n //line2'); }) it('should remove tab character indentation from the function body', function(){ clean('\t//line1\n\t\t//line2').should.equal('//line1\n\t//line2'); }) }) })