├── .editorconfig ├── .eslintrc ├── .gitignore ├── .mailmap ├── .travis.yml ├── .versions ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── README.mocha.md ├── bin ├── .eslintrc ├── _mocha ├── mocha └── options.js ├── bower.json ├── component.json ├── editors └── JavaScript mocha.tmbundle │ ├── Snippets │ ├── bdd - after each.tmSnippet │ ├── bdd - after.tmSnippet │ ├── bdd - before each.tmSnippet │ ├── bdd - before.tmSnippet │ ├── bdd - describe.tmSnippet │ ├── bdd - it.tmSnippet │ ├── tdd - assert.tmSnippet │ ├── tdd - assert_deepEqual.tmSnippet │ ├── tdd - assert_equal.tmSnippet │ ├── tdd - assert_fail.tmSnippet │ ├── tdd - assert_isFunction.tmSnippet │ ├── tdd - setup.tmSnippet │ ├── tdd - suite.tmSnippet │ ├── tdd - teardown.tmSnippet │ └── tdd - test.tmSnippet │ └── info.plist ├── images ├── error.png └── ok.png ├── index.js ├── lib ├── browser │ ├── debug.js │ ├── events.js │ ├── progress.js │ └── tty.js ├── context.js ├── hook.js ├── interfaces │ ├── bdd.js │ ├── common.js │ ├── exports.js │ ├── index.js │ ├── qunit.js │ └── tdd.js ├── mocha.js ├── ms.js ├── pending.js ├── reporters │ ├── base.js │ ├── doc.js │ ├── dot.js │ ├── html-cov.js │ ├── html.js │ ├── index.js │ ├── json-cov.js │ ├── json-stream.js │ ├── json.js │ ├── landing.js │ ├── list.js │ ├── markdown.js │ ├── min.js │ ├── nyan.js │ ├── progress.js │ ├── spec.js │ ├── tap.js │ ├── templates │ │ ├── coverage.jade │ │ ├── menu.jade │ │ ├── script.html │ │ └── style.html │ └── xunit.js ├── runnable.js ├── runner.js ├── suite.js ├── template.html ├── test.js └── utils.js ├── media └── logo.svg ├── meteor ├── CHANGELOG.md ├── LICENSE.md ├── bin │ ├── install-meteor.sh │ └── test.sh ├── src │ ├── client │ │ └── mocha.html │ ├── index.js │ ├── lib │ │ ├── MochaRunner.coffee │ │ └── log.js │ ├── reporters │ │ ├── BaseReporter.coffee │ │ ├── ClientServerBaseReporter.coffee │ │ ├── ClientServerReporter.coffee │ │ ├── ConsoleReporter.coffee │ │ ├── HtmlReporter.coffee │ │ ├── JsonStreamReporter.coffee │ │ ├── MeteorPublishReporter.coffee │ │ ├── MirrorReporter.coffee │ │ ├── XunitReporter.coffee │ │ ├── html.js │ │ └── index.js │ ├── server │ │ └── autoupdate.js │ └── setup │ │ ├── index.js │ │ └── setupMochaClient.js ├── test-app │ ├── .meteor │ │ ├── .finished-upgraders │ │ ├── .gitignore │ │ ├── .id │ │ ├── packages │ │ ├── platforms │ │ ├── release │ │ └── versions │ ├── app.app-test.js │ ├── app.test.js │ ├── both-test.js │ ├── client │ │ ├── client-test.js │ │ ├── client.app-test.js │ │ ├── client.test.js │ │ ├── main.css │ │ ├── main.html │ │ └── main.js │ ├── globals-test.js │ ├── globals.app-test.js │ ├── globals.test.js │ ├── import │ │ └── collections │ │ │ └── TestCollection.js │ ├── package.json │ └── server │ │ ├── main.js │ │ ├── server-test.js │ │ ├── server.app-test.js │ │ └── server.test.js ├── test-package │ ├── TestCollection.coffee │ ├── mocha-globals-tests.js │ ├── mocha-tests.js │ ├── package.js │ └── server-tests.js └── tests │ ├── mocha-globals-test.coffee │ ├── mocha-import-test.coffee │ ├── phantomjs-test-script.js │ ├── test-app.html │ └── test-package.html ├── mocha.css ├── mocha.js ├── package.js ├── package.json ├── scripts └── ensure-compatible-npm.sh ├── support └── browser-entry.js └── test ├── .eslintrc ├── acceptance ├── context.js ├── duration.js ├── fs.js ├── glob │ ├── glob.js │ └── glob.sh ├── globals.js ├── http.js ├── interfaces │ ├── bdd.js │ ├── exports.js │ ├── qunit.js │ └── tdd.js ├── misc │ ├── exit.js │ ├── many.js │ ├── nontty.js │ └── only │ │ ├── bdd-require.js │ │ ├── bdd.js │ │ ├── qunit.js │ │ └── tdd.js ├── require │ ├── a.js │ ├── b.coffee │ ├── c.js │ ├── d.coffee │ └── require.js ├── required-tokens.js ├── root.js ├── test.coffee ├── test.foo ├── throw.js ├── timeout.js └── utils.js ├── browser ├── array.js ├── grep.html ├── grep.js ├── index.html ├── large.html ├── large.js ├── multiple-done.js ├── opts.html ├── opts.js ├── stack-trace.html ├── stack-trace.js ├── ui.html └── ui.js ├── color.js ├── compiler └── foo.js ├── grep.js ├── hook.async.js ├── hook.sync.js ├── hook.sync.nested.js ├── hook.timeout.js ├── http.meta.2.js ├── http.meta.js ├── integration ├── diffs.js ├── fixtures │ ├── cascade.js │ ├── diffs │ │ ├── diffs.css.in │ │ ├── diffs.css.out │ │ ├── diffs.js │ │ └── output │ ├── hooks │ │ ├── after.hook.async.error.js │ │ ├── after.hook.error.js │ │ ├── afterEach.hook.async.error.js │ │ ├── afterEach.hook.error.js │ │ ├── before.hook.async.error.js │ │ ├── before.hook.async.error.tip.js │ │ ├── before.hook.error.js │ │ ├── before.hook.error.tip.js │ │ ├── beforeEach.hook.async.error.js │ │ ├── beforeEach.hook.error.js │ │ ├── multiple.hook.async.error.js │ │ └── multiple.hook.error.js │ ├── multiple.done.before.js │ ├── multiple.done.beforeEach.js │ ├── multiple.done.js │ ├── multiple.done.specs.js │ ├── options │ │ ├── async-only.async.js │ │ ├── async-only.sync.js │ │ ├── bail.js │ │ ├── delay-fail.js │ │ ├── delay.js │ │ ├── grep.js │ │ ├── retries.js │ │ ├── sort.alpha.js │ │ └── sort.beta.js │ ├── passing.js │ ├── pending │ │ ├── skip.sync.before.js │ │ ├── skip.sync.beforeEach.js │ │ ├── skip.sync.spec.js │ │ └── spec.js │ ├── regression │ │ ├── 1794 │ │ │ ├── issue-1794.js │ │ │ └── simple-ui.js │ │ ├── issue-1327.js │ │ └── issue-1991.js │ ├── retries │ │ ├── async.js │ │ ├── early-pass.js │ │ ├── hooks.js │ │ └── nested.js │ ├── timeout.js │ ├── uncaught.hook.js │ └── uncaught.js ├── helpers.js ├── hook.err.js ├── hooks.js ├── multiple.done.js ├── options.js ├── pending.js ├── regression.js ├── reporters.js ├── retries.js ├── timeout.js └── uncaught.js ├── jsapi └── index.js ├── mocha.js ├── mocha.opts ├── ms.js ├── reporters ├── base.js ├── json.js └── nyan.js ├── runnable.js ├── runner.js ├── suite.js ├── test.js └── utils.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | end_of_line = lf 8 | charset = utf-8 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | indent_style = space 12 | indent_size = 2 13 | 14 | [Makefile] 15 | indent_style = tab 16 | 17 | [*.md] 18 | trim_trailing_whitespace = false 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | coverage.html 2 | lib-cov 3 | .DS_Store 4 | node_modules 5 | test-outputs 6 | *.sock 7 | testing 8 | _mocha.js 9 | my-reporter.js 10 | *.sw* 11 | lib/browser/diff.js 12 | .idea 13 | *.iml 14 | *.patch 15 | *.diff 16 | npm-debug.log* 17 | *.npm 18 | *.compare 19 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | TJ Holowaychuk 2 | Travis Jeffery 3 | Travis Jeffery Dr. Travis Jeffery 4 | Christopher Hiller Christopher Hiller 5 | David da Silva Contín David da Silva 6 | David da Silva Contín David da Silva 7 | Ariel Mashraki Ariel Mashraki 8 | Ariel Mashraki Ariel Mashraki 9 | Forbes Lindesay Forbes Lindesay 10 | Ben Bradley Ben Bradley <[ben.bradley@cigna.com|mailto:ben.bradley@cigna.com]> 11 | Glen Mailer Glen Mailer 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: node_js 4 | 5 | node_js: 6 | - "0.10.45" 7 | 8 | cache: 9 | directories: 10 | - $HOME/.meteor 11 | - $HOME/.npm 12 | 13 | notifications: 14 | slack: 15 | secure: Sp0XScJQvQJmAD842c3+NRfcz/kmY3t01vyqcqywGBp+AtpYrTCT8ZXWzxSsS5+0Zyxbw5qHo+cApjvaP3pWKRYYoCz8OQ41cJ5m7CauvRXhLNlGph9fzSk5f1s6Ut1efXlFRY/DQhFPuHw8OdsrahIrgoLSYoJvPU3oc2aBszo= 16 | 17 | before_install: 18 | - export PATH="$HOME/.meteor:$PATH" 19 | - export REPO_HOME="$TRAVIS_BUILD_DIR" 20 | - export PACKAGE_DIRS="$TRAVIS_BUILD_DIR/../" 21 | - "meteor/bin/install-meteor.sh" 22 | - "npm install -g spacejam" 23 | -------------------------------------------------------------------------------- /.versions: -------------------------------------------------------------------------------- 1 | allow-deny@1.0.5 2 | autoupdate@1.2.10 3 | babel-compiler@6.8.3 4 | babel-runtime@0.1.9_1 5 | base64@1.0.9 6 | binary-heap@1.0.9 7 | blaze@2.1.8 8 | blaze-tools@1.0.9 9 | boilerplate-generator@1.0.9 10 | caching-compiler@1.0.5_1 11 | caching-html-compiler@1.0.6 12 | callback-hook@1.0.9 13 | check@1.2.3 14 | coffeescript@1.1.2_1 15 | ddp@1.2.5 16 | ddp-client@1.2.8_1 17 | ddp-common@1.2.6 18 | ddp-server@1.2.8_1 19 | deps@1.0.12 20 | diff-sequence@1.0.6 21 | ecmascript@0.4.6_1 22 | ecmascript-runtime@0.2.11_1 23 | ejson@1.0.12 24 | geojson-utils@1.0.9 25 | html-tools@1.0.10 26 | htmljs@1.0.10 27 | http@1.1.7 28 | id-map@1.0.8 29 | jquery@1.11.9 30 | local-test:practicalmeteor:mocha@2.4.5_6 31 | logging@1.0.13_1 32 | meteor@1.1.15_1 33 | minifier-js@1.1.12_1 34 | minimongo@1.0.17 35 | modules@0.6.4 36 | modules-runtime@0.6.4_1 37 | mongo@1.1.9_1 38 | mongo-id@1.0.5 39 | npm-mongo@1.4.44_1 40 | observe-sequence@1.0.12 41 | ordered-dict@1.0.8 42 | practicalmeteor:chai@2.1.0_1 43 | practicalmeteor:loglevel@1.2.0_2 44 | practicalmeteor:mocha@2.4.5_6 45 | practicalmeteor:mocha-core@1.0.1 46 | practicalmeteor:sinon@1.14.1_2 47 | promise@0.7.2_1 48 | random@1.0.10 49 | reactive-var@1.0.10 50 | reload@1.1.10 51 | retry@1.0.8 52 | routepolicy@1.0.11 53 | spacebars@1.0.12 54 | spacebars-compiler@1.0.12 55 | templating@1.1.12_1 56 | templating-tools@1.0.4 57 | tinytest@1.0.11 58 | tmeasday:test-reporter-helpers@0.2.1 59 | tracker@1.0.14 60 | ui@1.0.11 61 | underscore@1.0.9 62 | url@1.0.10 63 | webapp@1.2.9_1 64 | webapp-hashing@1.0.9 65 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Mocha 2 | 3 | Hi! We could use your help. Let us help you help us. Or something. 4 | 5 | ## General 6 | 7 | 1. If you are looking for a place to begin, **please send PRs for bugfixes instead of new features**, and/or **look for issues labeled `PR PLEASE`.** 8 | 9 | 2. **Help with documentation and the wiki is always appreciated**. 10 | 11 | 3. Please **be courteous and constructive** when commenting on issues, commits, and pull requests. 12 | 13 | ## Bug Reports & Issues 14 | 15 | 1. When reporting a bug, please **provide steps to reproduce**. If possible, show code. 16 | 17 | 2. Please **show all code in JavaScript**. We don't all read ``. If you do not, you will be asked to. 18 | 19 | 3. Because Mocha works with many third-party libraries and tools, **ensure the bug you are reporting is actually within Mocha**. 20 | 21 | 4. If you report a bug, and it is inactive for a significant amount of time, it may be closed. **Please respond promptly to requests for more information**. 22 | 23 | ## Pull Requests 24 | 25 | 1. Before sending a large PR, it's recommended to **create an issue to propose the change**. Nobody wants to write a book of code and throw it away. 26 | 27 | 2. Because Mocha should be kept as maintainable as possible, its codebase must be kept slim. Historically, *most PRs for new features are not merged*. New features inevitably increase the size of the codebase, and thus reduce maintainability. Only features *deemed essential* are likely to be merged--this is at the discretion of the maintainer(s). If your PR for a feature is not merged, this doesn't necessarily mean your PR was a bad idea, wouldn't be used, or otherwise sucks. It just means **only essential PRs for new features are likely to be merged**. 28 | 29 | 3. Due to the above, before creating a PR for a new feature, **create an issue to propose the feature.** 30 | 31 | 4. Please **respect existing coding conventions**, whatever those may be. 32 | 33 | 5. If your PR has been waiting in limbo for some time, it's very helpful to **rebase against master**, which will make it easier to merge. 34 | 35 | 6. Please **add tests for new code**. 36 | 37 | 7. **Always run `npm test` before sending a PR.** If you break the tests, your PR will not be accepted until they are fixed. 38 | 39 | ## Source Control 40 | 41 | 1. Please **squash your commits** when sending a pull request. If you are unfamiliar with this process, see [this guide](https://help.github.com/articles/about-git-rebase/). If you have already pushed your changesets and are squashing thereafter, this may necessitate the use of a "force push". Please [read the docs](http://git-scm.com/docs/git-push) before you attempt this. 42 | 43 | 2. Please **follow the commit message conventions [outlined here](https://medium.com/code-adventures/git-conventions-a940ee20862d).** 44 | 45 | ## TL;DR 46 | 47 | **Be kind, be diligent, look before you leap into a PR, and follow common community conventions**. 48 | 49 | *- The Mocha Team* 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 LaVaina Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | mocha license 24 | ============= 25 | 26 | (The MIT License) 27 | 28 | Copyright (c) 2011-2016 TJ Holowaychuk 29 | 30 | Permission is hereby granted, free of charge, to any person obtaining 31 | a copy of this software and associated documentation files (the 32 | 'Software'), to deal in the Software without restriction, including 33 | without limitation the rights to use, copy, modify, merge, publish, 34 | distribute, sublicense, and/or sell copies of the Software, and to 35 | permit persons to whom the Software is furnished to do so, subject to 36 | the following conditions: 37 | 38 | The above copyright notice and this permission notice shall be 39 | included in all copies or substantial portions of the Software. 40 | 41 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 42 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 43 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 44 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 45 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 46 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 47 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 48 | -------------------------------------------------------------------------------- /bin/.eslintrc: -------------------------------------------------------------------------------- 1 | --- 2 | rules: 3 | no-process-exit: 0 4 | -------------------------------------------------------------------------------- /bin/mocha: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * This tiny wrapper file checks for known node flags and appends them 5 | * when found, before invoking the "real" _mocha(1) executable. 6 | */ 7 | 8 | var spawn = require('child_process').spawn, 9 | path = require('path'), 10 | fs = require('fs'), 11 | getOptions = require('./options'), 12 | args = [path.join(__dirname, '_mocha')]; 13 | 14 | // Load mocha.opts into process.argv 15 | // Must be loaded here to handle node-specific options 16 | getOptions(); 17 | 18 | process.argv.slice(2).forEach(function(arg){ 19 | var flag = arg.split('=')[0]; 20 | 21 | switch (flag) { 22 | case '-d': 23 | args.unshift('--debug'); 24 | args.push('--no-timeouts'); 25 | break; 26 | case 'debug': 27 | case '--debug': 28 | case '--debug-brk': 29 | args.unshift(arg); 30 | args.push('--no-timeouts'); 31 | break; 32 | case '-gc': 33 | case '--expose-gc': 34 | args.unshift('--expose-gc'); 35 | break; 36 | case '--gc-global': 37 | case '--es_staging': 38 | case '--no-deprecation': 39 | case '--prof': 40 | case '--log-timer-events': 41 | case '--throw-deprecation': 42 | case '--trace-deprecation': 43 | case '--use_strict': 44 | case '--allow-natives-syntax': 45 | case '--perf-basic-prof': 46 | args.unshift(arg); 47 | break; 48 | default: 49 | if (0 == arg.indexOf('--harmony')) args.unshift(arg); 50 | else if (0 == arg.indexOf('--trace')) args.unshift(arg); 51 | else if (0 == arg.indexOf('--max-old-space-size')) args.unshift(arg); 52 | else args.push(arg); 53 | break; 54 | } 55 | }); 56 | 57 | var proc = spawn(process.execPath, args, { stdio: 'inherit' }); 58 | proc.on('exit', function (code, signal) { 59 | process.on('exit', function(){ 60 | if (signal) { 61 | process.kill(process.pid, signal); 62 | } else { 63 | process.exit(code); 64 | } 65 | }); 66 | }); 67 | 68 | // terminate children. 69 | process.on('SIGINT', function () { 70 | proc.kill('SIGINT'); // calls runner.abort() 71 | proc.kill('SIGTERM'); // if that didn't work, we're probably in an infinite loop, so make it die. 72 | }); 73 | -------------------------------------------------------------------------------- /bin/options.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Dependencies. 3 | */ 4 | 5 | var fs = require('fs'); 6 | 7 | /** 8 | * Export `getOptions`. 9 | */ 10 | 11 | module.exports = getOptions; 12 | 13 | /** 14 | * Get options. 15 | */ 16 | 17 | function getOptions() { 18 | var optsPath = process.argv.indexOf('--opts') !== -1 19 | ? process.argv[process.argv.indexOf('--opts') + 1] 20 | : 'test/mocha.opts'; 21 | 22 | try { 23 | var opts = fs.readFileSync(optsPath, 'utf8') 24 | .replace(/\\\s/g, '%20') 25 | .split(/\s/) 26 | .filter(Boolean) 27 | .map(function(value) { 28 | return value.replace(/%20/g, ' '); 29 | }); 30 | 31 | process.argv = process.argv 32 | .slice(0, 2) 33 | .concat(opts.concat(process.argv.slice(2))); 34 | } catch (err) { 35 | // ignore 36 | } 37 | 38 | process.env.LOADED_MOCHA_OPTS = true; 39 | } 40 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mocha", 3 | "homepage": "http://mocha.github.io/mocha", 4 | "description": "simple, flexible, fun test framework", 5 | "authors": [ 6 | "TJ Holowaychuk ", 7 | "Joshua Appelman ", 8 | "Oleg Gaidarenko ", 9 | "Christoffer Hallas ", 10 | "Christopher Hiller ", 11 | "Travis Jeffery ", 12 | "Johnathan Ong ", 13 | "Guillermo Rauch " 14 | ], 15 | "repository": { 16 | "type": "git", 17 | "url": "git://github.com/mochajs/mocha.git" 18 | }, 19 | "main": [ 20 | "mocha.js", 21 | "mocha.css" 22 | ], 23 | "ignore": [ 24 | "bin", 25 | "editors", 26 | "images", 27 | "lib", 28 | "support", 29 | "test", 30 | ".gitignore", 31 | ".npmignore", 32 | ".travis.yml", 33 | "component.json", 34 | "index.js", 35 | "Makefile", 36 | "package.json" 37 | ], 38 | "keywords": [ 39 | "mocha", 40 | "test", 41 | "bdd", 42 | "tdd", 43 | "tap" 44 | ], 45 | "license": "MIT" 46 | } 47 | -------------------------------------------------------------------------------- /component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mocha", 3 | "version": "2.4.0", 4 | "repo": "mochajs/mocha", 5 | "description": "simple, flexible, fun test framework", 6 | "keywords": [ 7 | "mocha", 8 | "test", 9 | "bdd", 10 | "tdd", 11 | "tap" 12 | ], 13 | "main": "mocha.js", 14 | "scripts": [ 15 | "mocha.js" 16 | ], 17 | "styles": [ 18 | "mocha.css" 19 | ] 20 | } -------------------------------------------------------------------------------- /editors/JavaScript mocha.tmbundle/Snippets/bdd - after each.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | afterEach(function(){ 7 | $0 8 | }) 9 | name 10 | bdd - after each 11 | scope 12 | source.js 13 | tabTrigger 14 | ae 15 | uuid 16 | 7B4DA8F4-2064-468B-B252-054148419B4B 17 | 18 | 19 | -------------------------------------------------------------------------------- /editors/JavaScript mocha.tmbundle/Snippets/bdd - after.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | after(function(){ 7 | $0 8 | }) 9 | name 10 | bdd - after 11 | scope 12 | source.js 13 | tabTrigger 14 | a 15 | uuid 16 | A49A87F9-399E-4D74-A489-C535BB06D487 17 | 18 | 19 | -------------------------------------------------------------------------------- /editors/JavaScript mocha.tmbundle/Snippets/bdd - before each.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | beforeEach(function(){ 7 | $0 8 | }) 9 | name 10 | bdd - before each 11 | scope 12 | source.js 13 | tabTrigger 14 | be 15 | uuid 16 | 7AB064E3-EFBB-4FA7-98CA-9E87C10CC04E 17 | 18 | 19 | -------------------------------------------------------------------------------- /editors/JavaScript mocha.tmbundle/Snippets/bdd - before.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | before(function(){ 7 | $0 8 | }) 9 | name 10 | bdd - before 11 | scope 12 | source.js 13 | tabTrigger 14 | b 15 | uuid 16 | DF6F1F42-F80A-4A24-AF78-376F19070C4C 17 | 18 | 19 | -------------------------------------------------------------------------------- /editors/JavaScript mocha.tmbundle/Snippets/bdd - describe.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | describe('$1', function(){ 7 | $0 8 | }) 9 | name 10 | bdd - describe 11 | scope 12 | source.js 13 | tabTrigger 14 | des 15 | uuid 16 | 4AA1FB50-9BB9-400E-A140-D61C39BDFDF5 17 | 18 | 19 | -------------------------------------------------------------------------------- /editors/JavaScript mocha.tmbundle/Snippets/bdd - it.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | it('should $1', function(){ 7 | $0 8 | }) 9 | name 10 | bdd - it 11 | scope 12 | source.js 13 | tabTrigger 14 | it 15 | uuid 16 | 591AE071-95E4-4E1E-B0F3-A7DAF41595EE 17 | 18 | 19 | -------------------------------------------------------------------------------- /editors/JavaScript mocha.tmbundle/Snippets/tdd - assert.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | assert($0); 7 | name 8 | tdd - assert 9 | scope 10 | source.js 11 | tabTrigger 12 | as 13 | uuid 14 | 9D920EC2-6A72-4108-B5A0-591AFA61C740 15 | 16 | 17 | -------------------------------------------------------------------------------- /editors/JavaScript mocha.tmbundle/Snippets/tdd - assert_deepEqual.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | assert.deepEqual($1, $2); 7 | name 8 | tdd - assert.deepEqual 9 | scope 10 | source.js 11 | tabTrigger 12 | deq 13 | uuid 14 | 7D21FF16-E2E1-46BB-AD6B-82AD767A0822 15 | 16 | 17 | -------------------------------------------------------------------------------- /editors/JavaScript mocha.tmbundle/Snippets/tdd - assert_equal.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | assert.equal($1, $2); 7 | name 8 | tdd - assert.equal 9 | scope 10 | source.js 11 | tabTrigger 12 | eq 13 | uuid 14 | 4868D5C0-075D-44A8-B41B-A14E8350C0F8 15 | 16 | 17 | -------------------------------------------------------------------------------- /editors/JavaScript mocha.tmbundle/Snippets/tdd - assert_fail.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | assert.fail($0); 7 | name 8 | tdd - assert.fail 9 | scope 10 | source.js 11 | tabTrigger 12 | fail 13 | uuid 14 | 11756F3A-5F08-445C-B5B6-30605838BC6F 15 | 16 | 17 | -------------------------------------------------------------------------------- /editors/JavaScript mocha.tmbundle/Snippets/tdd - assert_isFunction.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | assert.isFunction($0); 7 | name 8 | tdd - assert.isFunction 9 | scope 10 | source.js 11 | tabTrigger 12 | isf 13 | uuid 14 | 83DFFD36-2C46-4C92-8950-64665D32DC8E 15 | 16 | 17 | -------------------------------------------------------------------------------- /editors/JavaScript mocha.tmbundle/Snippets/tdd - setup.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | setup(function() { 7 | $0 8 | }); 9 | name 10 | tdd - setup 11 | scope 12 | source.js 13 | tabTrigger 14 | setup 15 | uuid 16 | DCEE796A-900D-4922-BAF0-39C9B91A15E1 17 | 18 | 19 | -------------------------------------------------------------------------------- /editors/JavaScript mocha.tmbundle/Snippets/tdd - suite.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | suite('$1', function() { 7 | $0 8 | }); 9 | name 10 | tdd - suite 11 | scope 12 | source.js 13 | tabTrigger 14 | suite 15 | uuid 16 | 2E65C1BE-A568-4868-95BF-E8C958EA5BA5 17 | 18 | 19 | -------------------------------------------------------------------------------- /editors/JavaScript mocha.tmbundle/Snippets/tdd - teardown.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | teardown(function() { 7 | $0 8 | }); 9 | name 10 | tdd - teardown 11 | scope 12 | source.js 13 | tabTrigger 14 | teardown 15 | uuid 16 | 9472B167-BEC1-45FD-BA1C-68A99961D8FF 17 | 18 | 19 | -------------------------------------------------------------------------------- /editors/JavaScript mocha.tmbundle/Snippets/tdd - test.tmSnippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | content 6 | test('$1', function() { 7 | $0 8 | }); 9 | name 10 | tdd - test 11 | scope 12 | source.js 13 | tabTrigger 14 | test 15 | uuid 16 | F6E3DF27-3458-4ADD-91A3-B6EF11E1D81E 17 | 18 | 19 | -------------------------------------------------------------------------------- /editors/JavaScript mocha.tmbundle/info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | JavaScript mocha 7 | ordering 8 | 9 | 4AA1FB50-9BB9-400E-A140-D61C39BDFDF5 10 | 591AE071-95E4-4E1E-B0F3-A7DAF41595EE 11 | DF6F1F42-F80A-4A24-AF78-376F19070C4C 12 | A49A87F9-399E-4D74-A489-C535BB06D487 13 | 7AB064E3-EFBB-4FA7-98CA-9E87C10CC04E 14 | 7B4DA8F4-2064-468B-B252-054148419B4B 15 | 16 | uuid 17 | 094ACE33-0C0E-422A-B3F7-5B919F5B1239 18 | 19 | 20 | -------------------------------------------------------------------------------- /images/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/practicalmeteor/meteor-mocha/9a06c82aed7e3015014875602ed1499dc321cb51/images/error.png -------------------------------------------------------------------------------- /images/ok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/practicalmeteor/meteor-mocha/9a06c82aed7e3015014875602ed1499dc321cb51/images/ok.png -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = process.env.COV 2 | ? require('./lib-cov/mocha') 3 | : require('./lib/mocha'); 4 | -------------------------------------------------------------------------------- /lib/browser/debug.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | module.exports = function(type) { 3 | return function() {}; 4 | }; 5 | -------------------------------------------------------------------------------- /lib/browser/progress.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Expose `Progress`. 3 | */ 4 | 5 | module.exports = Progress; 6 | 7 | /** 8 | * Initialize a new `Progress` indicator. 9 | */ 10 | function Progress() { 11 | this.percent = 0; 12 | this.size(0); 13 | this.fontSize(11); 14 | this.font('helvetica, arial, sans-serif'); 15 | } 16 | 17 | /** 18 | * Set progress size to `size`. 19 | * 20 | * @api public 21 | * @param {number} size 22 | * @return {Progress} Progress instance. 23 | */ 24 | Progress.prototype.size = function(size) { 25 | this._size = size; 26 | return this; 27 | }; 28 | 29 | /** 30 | * Set text to `text`. 31 | * 32 | * @api public 33 | * @param {string} text 34 | * @return {Progress} Progress instance. 35 | */ 36 | Progress.prototype.text = function(text) { 37 | this._text = text; 38 | return this; 39 | }; 40 | 41 | /** 42 | * Set font size to `size`. 43 | * 44 | * @api public 45 | * @param {number} size 46 | * @return {Progress} Progress instance. 47 | */ 48 | Progress.prototype.fontSize = function(size) { 49 | this._fontSize = size; 50 | return this; 51 | }; 52 | 53 | /** 54 | * Set font to `family`. 55 | * 56 | * @param {string} family 57 | * @return {Progress} Progress instance. 58 | */ 59 | Progress.prototype.font = function(family) { 60 | this._font = family; 61 | return this; 62 | }; 63 | 64 | /** 65 | * Update percentage to `n`. 66 | * 67 | * @param {number} n 68 | * @return {Progress} Progress instance. 69 | */ 70 | Progress.prototype.update = function(n) { 71 | this.percent = n; 72 | return this; 73 | }; 74 | 75 | /** 76 | * Draw on `ctx`. 77 | * 78 | * @param {CanvasRenderingContext2d} ctx 79 | * @return {Progress} Progress instance. 80 | */ 81 | Progress.prototype.draw = function(ctx) { 82 | try { 83 | var percent = Math.min(this.percent, 100); 84 | var size = this._size; 85 | var half = size / 2; 86 | var x = half; 87 | var y = half; 88 | var rad = half - 1; 89 | var fontSize = this._fontSize; 90 | 91 | ctx.font = fontSize + 'px ' + this._font; 92 | 93 | var angle = Math.PI * 2 * (percent / 100); 94 | ctx.clearRect(0, 0, size, size); 95 | 96 | // outer circle 97 | ctx.strokeStyle = '#9f9f9f'; 98 | ctx.beginPath(); 99 | ctx.arc(x, y, rad, 0, angle, false); 100 | ctx.stroke(); 101 | 102 | // inner circle 103 | ctx.strokeStyle = '#eee'; 104 | ctx.beginPath(); 105 | ctx.arc(x, y, rad - 1, 0, angle, true); 106 | ctx.stroke(); 107 | 108 | // text 109 | var text = this._text || (percent | 0) + '%'; 110 | var w = ctx.measureText(text).width; 111 | 112 | ctx.fillText(text, x - w / 2 + 1, y + fontSize / 2 - 1); 113 | } catch (err) { 114 | // don't fail if we can't render progress 115 | } 116 | return this; 117 | }; 118 | -------------------------------------------------------------------------------- /lib/browser/tty.js: -------------------------------------------------------------------------------- 1 | exports.isatty = function isatty() { 2 | return true; 3 | }; 4 | 5 | exports.getWindowSize = function getWindowSize() { 6 | if ('innerHeight' in global) { 7 | return [global.innerHeight, global.innerWidth]; 8 | } 9 | // In a Web Worker, the DOM Window is not available. 10 | return [640, 480]; 11 | }; 12 | -------------------------------------------------------------------------------- /lib/context.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Expose `Context`. 3 | */ 4 | 5 | module.exports = Context; 6 | 7 | /** 8 | * Initialize a new `Context`. 9 | * 10 | * @api private 11 | */ 12 | function Context() {} 13 | 14 | /** 15 | * Set or get the context `Runnable` to `runnable`. 16 | * 17 | * @api private 18 | * @param {Runnable} runnable 19 | * @return {Context} 20 | */ 21 | Context.prototype.runnable = function(runnable) { 22 | if (!arguments.length) { 23 | return this._runnable; 24 | } 25 | this.test = this._runnable = runnable; 26 | return this; 27 | }; 28 | 29 | /** 30 | * Set test timeout `ms`. 31 | * 32 | * @api private 33 | * @param {number} ms 34 | * @return {Context} self 35 | */ 36 | Context.prototype.timeout = function(ms) { 37 | if (!arguments.length) { 38 | return this.runnable().timeout(); 39 | } 40 | this.runnable().timeout(ms); 41 | return this; 42 | }; 43 | 44 | /** 45 | * Set test timeout `enabled`. 46 | * 47 | * @api private 48 | * @param {boolean} enabled 49 | * @return {Context} self 50 | */ 51 | Context.prototype.enableTimeouts = function(enabled) { 52 | this.runnable().enableTimeouts(enabled); 53 | return this; 54 | }; 55 | 56 | /** 57 | * Set test slowness threshold `ms`. 58 | * 59 | * @api private 60 | * @param {number} ms 61 | * @return {Context} self 62 | */ 63 | Context.prototype.slow = function(ms) { 64 | this.runnable().slow(ms); 65 | return this; 66 | }; 67 | 68 | /** 69 | * Mark a test as skipped. 70 | * 71 | * @api private 72 | * @return {Context} self 73 | */ 74 | Context.prototype.skip = function() { 75 | this.runnable().skip(); 76 | return this; 77 | }; 78 | 79 | /** 80 | * Allow a number of retries on failed tests 81 | * 82 | * @api private 83 | * @param {number} n 84 | * @return {Context} self 85 | */ 86 | Context.prototype.retries = function(n) { 87 | if (!arguments.length) { 88 | return this.runnable().retries(); 89 | } 90 | this.runnable().retries(n); 91 | return this; 92 | }; 93 | 94 | /** 95 | * Inspect the context void of `._runnable`. 96 | * 97 | * @api private 98 | * @return {string} 99 | */ 100 | Context.prototype.inspect = function() { 101 | return JSON.stringify(this, function(key, val) { 102 | return key === 'runnable' || key === 'test' ? undefined : val; 103 | }, 2); 104 | }; 105 | -------------------------------------------------------------------------------- /lib/hook.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var Runnable = require('./runnable'); 6 | var inherits = require('./utils').inherits; 7 | 8 | /** 9 | * Expose `Hook`. 10 | */ 11 | 12 | module.exports = Hook; 13 | 14 | /** 15 | * Initialize a new `Hook` with the given `title` and callback `fn`. 16 | * 17 | * @param {String} title 18 | * @param {Function} fn 19 | * @api private 20 | */ 21 | function Hook(title, fn) { 22 | Runnable.call(this, title, fn); 23 | this.type = 'hook'; 24 | } 25 | 26 | /** 27 | * Inherit from `Runnable.prototype`. 28 | */ 29 | inherits(Hook, Runnable); 30 | 31 | /** 32 | * Get or set the test `err`. 33 | * 34 | * @param {Error} err 35 | * @return {Error} 36 | * @api public 37 | */ 38 | Hook.prototype.error = function(err) { 39 | if (!arguments.length) { 40 | err = this._error; 41 | this._error = null; 42 | return err; 43 | } 44 | 45 | this._error = err; 46 | }; 47 | -------------------------------------------------------------------------------- /lib/interfaces/common.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Functions common to more than one interface. 5 | * 6 | * @param {Suite[]} suites 7 | * @param {Context} context 8 | * @return {Object} An object containing common functions. 9 | */ 10 | module.exports = function(suites, context) { 11 | return { 12 | /** 13 | * This is only present if flag --delay is passed into Mocha. It triggers 14 | * root suite execution. 15 | * 16 | * @param {Suite} suite The root wuite. 17 | * @return {Function} A function which runs the root suite 18 | */ 19 | runWithSuite: function runWithSuite(suite) { 20 | return function run() { 21 | suite.run(); 22 | }; 23 | }, 24 | 25 | /** 26 | * Execute before running tests. 27 | * 28 | * @param {string} name 29 | * @param {Function} fn 30 | */ 31 | before: function(name, fn) { 32 | suites[0].beforeAll(name, fn); 33 | }, 34 | 35 | /** 36 | * Execute after running tests. 37 | * 38 | * @param {string} name 39 | * @param {Function} fn 40 | */ 41 | after: function(name, fn) { 42 | suites[0].afterAll(name, fn); 43 | }, 44 | 45 | /** 46 | * Execute before each test case. 47 | * 48 | * @param {string} name 49 | * @param {Function} fn 50 | */ 51 | beforeEach: function(name, fn) { 52 | suites[0].beforeEach(name, fn); 53 | }, 54 | 55 | /** 56 | * Execute after each test case. 57 | * 58 | * @param {string} name 59 | * @param {Function} fn 60 | */ 61 | afterEach: function(name, fn) { 62 | suites[0].afterEach(name, fn); 63 | }, 64 | 65 | test: { 66 | /** 67 | * Pending test case. 68 | * 69 | * @param {string} title 70 | */ 71 | skip: function(title) { 72 | context.test(title); 73 | }, 74 | 75 | /** 76 | * Number of retry attempts 77 | * 78 | * @param {string} n 79 | */ 80 | retries: function(n) { 81 | context.retries(n); 82 | } 83 | } 84 | }; 85 | }; 86 | -------------------------------------------------------------------------------- /lib/interfaces/exports.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var Suite = require('../suite'); 6 | var Test = require('../test'); 7 | 8 | /** 9 | * TDD-style interface: 10 | * 11 | * exports.Array = { 12 | * '#indexOf()': { 13 | * 'should return -1 when the value is not present': function() { 14 | * 15 | * }, 16 | * 17 | * 'should return the correct index when the value is present': function() { 18 | * 19 | * } 20 | * } 21 | * }; 22 | * 23 | * @param {Suite} suite Root suite. 24 | */ 25 | module.exports = function(suite) { 26 | var suites = [suite]; 27 | 28 | suite.on('require', visit); 29 | 30 | function visit(obj, file) { 31 | var suite; 32 | for (var key in obj) { 33 | if (typeof obj[key] === 'function') { 34 | var fn = obj[key]; 35 | switch (key) { 36 | case 'before': 37 | suites[0].beforeAll(fn); 38 | break; 39 | case 'after': 40 | suites[0].afterAll(fn); 41 | break; 42 | case 'beforeEach': 43 | suites[0].beforeEach(fn); 44 | break; 45 | case 'afterEach': 46 | suites[0].afterEach(fn); 47 | break; 48 | default: 49 | var test = new Test(key, fn); 50 | test.file = file; 51 | suites[0].addTest(test); 52 | } 53 | } else { 54 | suite = Suite.create(suites[0], key); 55 | suites.unshift(suite); 56 | visit(obj[key], file); 57 | suites.shift(); 58 | } 59 | } 60 | } 61 | }; 62 | -------------------------------------------------------------------------------- /lib/interfaces/index.js: -------------------------------------------------------------------------------- 1 | exports.bdd = require('./bdd'); 2 | exports.tdd = require('./tdd'); 3 | exports.qunit = require('./qunit'); 4 | exports.exports = require('./exports'); 5 | -------------------------------------------------------------------------------- /lib/interfaces/qunit.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var Suite = require('../suite'); 6 | var Test = require('../test'); 7 | var escapeRe = require('escape-string-regexp'); 8 | 9 | /** 10 | * QUnit-style interface: 11 | * 12 | * suite('Array'); 13 | * 14 | * test('#length', function() { 15 | * var arr = [1,2,3]; 16 | * ok(arr.length == 3); 17 | * }); 18 | * 19 | * test('#indexOf()', function() { 20 | * var arr = [1,2,3]; 21 | * ok(arr.indexOf(1) == 0); 22 | * ok(arr.indexOf(2) == 1); 23 | * ok(arr.indexOf(3) == 2); 24 | * }); 25 | * 26 | * suite('String'); 27 | * 28 | * test('#length', function() { 29 | * ok('foo'.length == 3); 30 | * }); 31 | * 32 | * @param {Suite} suite Root suite. 33 | */ 34 | module.exports = function(suite) { 35 | var suites = [suite]; 36 | 37 | suite.on('pre-require', function(context, file, mocha) { 38 | var common = require('./common')(suites, context); 39 | 40 | context.before = common.before; 41 | context.after = common.after; 42 | context.beforeEach = common.beforeEach; 43 | context.afterEach = common.afterEach; 44 | context.run = mocha.options.delay && common.runWithSuite(suite); 45 | /** 46 | * Describe a "suite" with the given `title`. 47 | */ 48 | 49 | context.suite = function(title) { 50 | if (suites.length > 1) { 51 | suites.shift(); 52 | } 53 | var suite = Suite.create(suites[0], title); 54 | suite.file = file; 55 | suites.unshift(suite); 56 | return suite; 57 | }; 58 | 59 | /** 60 | * Exclusive test-case. 61 | */ 62 | 63 | context.suite.only = function(title, fn) { 64 | var suite = context.suite(title, fn); 65 | mocha.grep(suite.fullTitle()); 66 | }; 67 | 68 | /** 69 | * Describe a specification or test-case 70 | * with the given `title` and callback `fn` 71 | * acting as a thunk. 72 | */ 73 | 74 | context.test = function(title, fn) { 75 | var test = new Test(title, fn); 76 | test.file = file; 77 | suites[0].addTest(test); 78 | return test; 79 | }; 80 | 81 | /** 82 | * Exclusive test-case. 83 | */ 84 | 85 | context.test.only = function(title, fn) { 86 | var test = context.test(title, fn); 87 | var reString = '^' + escapeRe(test.fullTitle()) + '$'; 88 | mocha.grep(new RegExp(reString)); 89 | }; 90 | 91 | context.test.skip = common.test.skip; 92 | context.test.retries = common.test.retries; 93 | }); 94 | }; 95 | -------------------------------------------------------------------------------- /lib/interfaces/tdd.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var Suite = require('../suite'); 6 | var Test = require('../test'); 7 | var escapeRe = require('escape-string-regexp'); 8 | 9 | /** 10 | * TDD-style interface: 11 | * 12 | * suite('Array', function() { 13 | * suite('#indexOf()', function() { 14 | * suiteSetup(function() { 15 | * 16 | * }); 17 | * 18 | * test('should return -1 when not present', function() { 19 | * 20 | * }); 21 | * 22 | * test('should return the index when present', function() { 23 | * 24 | * }); 25 | * 26 | * suiteTeardown(function() { 27 | * 28 | * }); 29 | * }); 30 | * }); 31 | * 32 | * @param {Suite} suite Root suite. 33 | */ 34 | module.exports = function(suite) { 35 | var suites = [suite]; 36 | 37 | suite.on('pre-require', function(context, file, mocha) { 38 | var common = require('./common')(suites, context); 39 | 40 | context.setup = common.beforeEach; 41 | context.teardown = common.afterEach; 42 | context.suiteSetup = common.before; 43 | context.suiteTeardown = common.after; 44 | context.run = mocha.options.delay && common.runWithSuite(suite); 45 | 46 | /** 47 | * Describe a "suite" with the given `title` and callback `fn` containing 48 | * nested suites and/or tests. 49 | */ 50 | context.suite = function(title, fn) { 51 | var suite = Suite.create(suites[0], title); 52 | suite.file = file; 53 | suites.unshift(suite); 54 | fn.call(suite); 55 | suites.shift(); 56 | return suite; 57 | }; 58 | 59 | /** 60 | * Pending suite. 61 | */ 62 | context.suite.skip = function(title, fn) { 63 | var suite = Suite.create(suites[0], title); 64 | suite.pending = true; 65 | suites.unshift(suite); 66 | fn.call(suite); 67 | suites.shift(); 68 | }; 69 | 70 | /** 71 | * Exclusive test-case. 72 | */ 73 | context.suite.only = function(title, fn) { 74 | var suite = context.suite(title, fn); 75 | mocha.grep(suite.fullTitle()); 76 | }; 77 | 78 | /** 79 | * Describe a specification or test-case with the given `title` and 80 | * callback `fn` acting as a thunk. 81 | */ 82 | context.test = function(title, fn) { 83 | var suite = suites[0]; 84 | if (suite.pending) { 85 | fn = null; 86 | } 87 | var test = new Test(title, fn); 88 | test.file = file; 89 | suite.addTest(test); 90 | return test; 91 | }; 92 | 93 | /** 94 | * Exclusive test-case. 95 | */ 96 | 97 | context.test.only = function(title, fn) { 98 | var test = context.test(title, fn); 99 | var reString = '^' + escapeRe(test.fullTitle()) + '$'; 100 | mocha.grep(new RegExp(reString)); 101 | }; 102 | 103 | context.test.skip = common.test.skip; 104 | context.test.retries = common.test.retries; 105 | }); 106 | }; 107 | -------------------------------------------------------------------------------- /lib/ms.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Helpers. 3 | */ 4 | 5 | var s = 1000; 6 | var m = s * 60; 7 | var h = m * 60; 8 | var d = h * 24; 9 | var y = d * 365.25; 10 | 11 | /** 12 | * Parse or format the given `val`. 13 | * 14 | * Options: 15 | * 16 | * - `long` verbose formatting [false] 17 | * 18 | * @api public 19 | * @param {string|number} val 20 | * @param {Object} options 21 | * @return {string|number} 22 | */ 23 | module.exports = function(val, options) { 24 | options = options || {}; 25 | if (typeof val === 'string') { 26 | return parse(val); 27 | } 28 | // https://github.com/mochajs/mocha/pull/1035 29 | return options['long'] ? longFormat(val) : shortFormat(val); 30 | }; 31 | 32 | /** 33 | * Parse the given `str` and return milliseconds. 34 | * 35 | * @api private 36 | * @param {string} str 37 | * @return {number} 38 | */ 39 | function parse(str) { 40 | var match = (/^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i).exec(str); 41 | if (!match) { 42 | return; 43 | } 44 | var n = parseFloat(match[1]); 45 | var type = (match[2] || 'ms').toLowerCase(); 46 | switch (type) { 47 | case 'years': 48 | case 'year': 49 | case 'y': 50 | return n * y; 51 | case 'days': 52 | case 'day': 53 | case 'd': 54 | return n * d; 55 | case 'hours': 56 | case 'hour': 57 | case 'h': 58 | return n * h; 59 | case 'minutes': 60 | case 'minute': 61 | case 'm': 62 | return n * m; 63 | case 'seconds': 64 | case 'second': 65 | case 's': 66 | return n * s; 67 | case 'ms': 68 | return n; 69 | default: 70 | // No default case 71 | } 72 | } 73 | 74 | /** 75 | * Short format for `ms`. 76 | * 77 | * @api private 78 | * @param {number} ms 79 | * @return {string} 80 | */ 81 | function shortFormat(ms) { 82 | if (ms >= d) { 83 | return Math.round(ms / d) + 'd'; 84 | } 85 | if (ms >= h) { 86 | return Math.round(ms / h) + 'h'; 87 | } 88 | if (ms >= m) { 89 | return Math.round(ms / m) + 'm'; 90 | } 91 | if (ms >= s) { 92 | return Math.round(ms / s) + 's'; 93 | } 94 | return ms + 'ms'; 95 | } 96 | 97 | /** 98 | * Long format for `ms`. 99 | * 100 | * @api private 101 | * @param {number} ms 102 | * @return {string} 103 | */ 104 | function longFormat(ms) { 105 | return plural(ms, d, 'day') 106 | || plural(ms, h, 'hour') 107 | || plural(ms, m, 'minute') 108 | || plural(ms, s, 'second') 109 | || ms + ' ms'; 110 | } 111 | 112 | /** 113 | * Pluralization helper. 114 | * 115 | * @api private 116 | * @param {number} ms 117 | * @param {number} n 118 | * @param {string} name 119 | */ 120 | function plural(ms, n, name) { 121 | if (ms < n) { 122 | return; 123 | } 124 | if (ms < n * 1.5) { 125 | return Math.floor(ms / n) + ' ' + name; 126 | } 127 | return Math.ceil(ms / n) + ' ' + name + 's'; 128 | } 129 | -------------------------------------------------------------------------------- /lib/pending.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Expose `Pending`. 4 | */ 5 | 6 | module.exports = Pending; 7 | 8 | /** 9 | * Initialize a new `Pending` error with the given message. 10 | * 11 | * @param {string} message 12 | */ 13 | function Pending(message) { 14 | this.message = message; 15 | } 16 | -------------------------------------------------------------------------------- /lib/reporters/doc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var Base = require('./base'); 6 | var utils = require('../utils'); 7 | 8 | /** 9 | * Expose `Doc`. 10 | */ 11 | 12 | exports = module.exports = Doc; 13 | 14 | /** 15 | * Initialize a new `Doc` reporter. 16 | * 17 | * @param {Runner} runner 18 | * @api public 19 | */ 20 | function Doc(runner) { 21 | Base.call(this, runner); 22 | 23 | var indents = 2; 24 | 25 | function indent() { 26 | return Array(indents).join(' '); 27 | } 28 | 29 | runner.on('suite', function(suite) { 30 | if (suite.root) { 31 | return; 32 | } 33 | ++indents; 34 | console.log('%s
', indent()); 35 | ++indents; 36 | console.log('%s

%s

', indent(), utils.escape(suite.title)); 37 | console.log('%s
', indent()); 38 | }); 39 | 40 | runner.on('suite end', function(suite) { 41 | if (suite.root) { 42 | return; 43 | } 44 | console.log('%s
', indent()); 45 | --indents; 46 | console.log('%s
', indent()); 47 | --indents; 48 | }); 49 | 50 | runner.on('pass', function(test) { 51 | console.log('%s
%s
', indent(), utils.escape(test.title)); 52 | var code = utils.escape(utils.clean(test.body)); 53 | console.log('%s
%s
', indent(), code); 54 | }); 55 | 56 | runner.on('fail', function(test, err) { 57 | console.log('%s
%s
', indent(), utils.escape(test.title)); 58 | var code = utils.escape(utils.clean(test.fn.body)); 59 | console.log('%s
%s
', indent(), code); 60 | console.log('%s
%s
', indent(), utils.escape(err)); 61 | }); 62 | } 63 | -------------------------------------------------------------------------------- /lib/reporters/dot.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var Base = require('./base'); 6 | var inherits = require('../utils').inherits; 7 | var color = Base.color; 8 | 9 | /** 10 | * Expose `Dot`. 11 | */ 12 | 13 | exports = module.exports = Dot; 14 | 15 | /** 16 | * Initialize a new `Dot` matrix test reporter. 17 | * 18 | * @api public 19 | * @param {Runner} runner 20 | */ 21 | function Dot(runner) { 22 | Base.call(this, runner); 23 | 24 | var self = this; 25 | var width = Base.window.width * .75 | 0; 26 | var n = -1; 27 | 28 | runner.on('start', function() { 29 | process.stdout.write('\n'); 30 | }); 31 | 32 | runner.on('pending', function() { 33 | if (++n % width === 0) { 34 | process.stdout.write('\n '); 35 | } 36 | process.stdout.write(color('pending', Base.symbols.dot)); 37 | }); 38 | 39 | runner.on('pass', function(test) { 40 | if (++n % width === 0) { 41 | process.stdout.write('\n '); 42 | } 43 | if (test.speed === 'slow') { 44 | process.stdout.write(color('bright yellow', Base.symbols.dot)); 45 | } else { 46 | process.stdout.write(color(test.speed, Base.symbols.dot)); 47 | } 48 | }); 49 | 50 | runner.on('fail', function() { 51 | if (++n % width === 0) { 52 | process.stdout.write('\n '); 53 | } 54 | process.stdout.write(color('fail', Base.symbols.dot)); 55 | }); 56 | 57 | runner.on('end', function() { 58 | console.log(); 59 | self.epilogue(); 60 | }); 61 | } 62 | 63 | /** 64 | * Inherit from `Base.prototype`. 65 | */ 66 | inherits(Dot, Base); 67 | -------------------------------------------------------------------------------- /lib/reporters/html-cov.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var JSONCov = require('./json-cov'); 6 | var readFileSync = require('fs').readFileSync; 7 | var join = require('path').join; 8 | 9 | /** 10 | * Expose `HTMLCov`. 11 | */ 12 | 13 | exports = module.exports = HTMLCov; 14 | 15 | /** 16 | * Initialize a new `JsCoverage` reporter. 17 | * 18 | * @api public 19 | * @param {Runner} runner 20 | */ 21 | function HTMLCov(runner) { 22 | var jade = require('jade'); 23 | var file = join(__dirname, '/templates/coverage.jade'); 24 | var str = readFileSync(file, 'utf8'); 25 | var fn = jade.compile(str, { filename: file }); 26 | var self = this; 27 | 28 | JSONCov.call(this, runner, false); 29 | 30 | runner.on('end', function() { 31 | process.stdout.write(fn({ 32 | cov: self.cov, 33 | coverageClass: coverageClass 34 | })); 35 | }); 36 | } 37 | 38 | /** 39 | * Return coverage class for a given coverage percentage. 40 | * 41 | * @api private 42 | * @param {number} coveragePctg 43 | * @return {string} 44 | */ 45 | function coverageClass(coveragePctg) { 46 | if (coveragePctg >= 75) { 47 | return 'high'; 48 | } 49 | if (coveragePctg >= 50) { 50 | return 'medium'; 51 | } 52 | if (coveragePctg >= 25) { 53 | return 'low'; 54 | } 55 | return 'terrible'; 56 | } 57 | -------------------------------------------------------------------------------- /lib/reporters/index.js: -------------------------------------------------------------------------------- 1 | // Alias exports to a their normalized format Mocha#reporter to prevent a need 2 | // for dynamic (try/catch) requires, which Browserify doesn't handle. 3 | exports.Base = exports.base = require('./base'); 4 | // exports.Dot = exports.dot = require('./dot'); 5 | // exports.Doc = exports.doc = require('./doc'); 6 | // exports.TAP = exports.tap = require('./tap'); 7 | // exports.JSON = exports.json = require('./json'); 8 | // exports.HTML = exports.html = require('./html'); 9 | // exports.List = exports.list = require('./list'); 10 | // exports.Min = exports.min = require('./min'); 11 | exports.Spec = exports.spec = require('./spec'); 12 | // exports.Nyan = exports.nyan = require('./nyan'); 13 | // exports.XUnit = exports.xunit = require('./xunit'); 14 | // exports.Markdown = exports.markdown = require('./markdown'); 15 | // exports.Progress = exports.progress = require('./progress'); 16 | // exports.Landing = exports.landing = require('./landing'); 17 | // exports.JSONCov = exports['json-cov'] = require('./json-cov'); 18 | // exports.HTMLCov = exports['html-cov'] = require('./html-cov'); 19 | // exports.JSONStream = exports['json-stream'] = require('./json-stream'); 20 | -------------------------------------------------------------------------------- /lib/reporters/json-stream.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var Base = require('./base'); 6 | 7 | /** 8 | * Expose `List`. 9 | */ 10 | 11 | exports = module.exports = List; 12 | 13 | /** 14 | * Initialize a new `List` test reporter. 15 | * 16 | * @api public 17 | * @param {Runner} runner 18 | */ 19 | function List(runner) { 20 | Base.call(this, runner); 21 | 22 | var self = this; 23 | var total = runner.total; 24 | 25 | runner.on('start', function() { 26 | console.log(JSON.stringify(['start', { total: total }])); 27 | }); 28 | 29 | runner.on('pass', function(test) { 30 | console.log(JSON.stringify(['pass', clean(test)])); 31 | }); 32 | 33 | runner.on('fail', function(test, err) { 34 | test = clean(test); 35 | test.err = err.message; 36 | test.stack = err.stack || null; 37 | console.log(JSON.stringify(['fail', test])); 38 | }); 39 | 40 | runner.on('end', function() { 41 | process.stdout.write(JSON.stringify(['end', self.stats])); 42 | }); 43 | } 44 | 45 | /** 46 | * Return a plain-object representation of `test` 47 | * free of cyclic properties etc. 48 | * 49 | * @api private 50 | * @param {Object} test 51 | * @return {Object} 52 | */ 53 | function clean(test) { 54 | return { 55 | title: test.title, 56 | fullTitle: test.fullTitle(), 57 | duration: test.duration, 58 | currentRetry: test.currentRetry() 59 | }; 60 | } 61 | -------------------------------------------------------------------------------- /lib/reporters/json.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var Base = require('./base'); 6 | 7 | /** 8 | * Expose `JSON`. 9 | */ 10 | 11 | exports = module.exports = JSONReporter; 12 | 13 | /** 14 | * Initialize a new `JSON` reporter. 15 | * 16 | * @api public 17 | * @param {Runner} runner 18 | */ 19 | function JSONReporter(runner) { 20 | Base.call(this, runner); 21 | 22 | var self = this; 23 | var tests = []; 24 | var pending = []; 25 | var failures = []; 26 | var passes = []; 27 | 28 | runner.on('test end', function(test) { 29 | tests.push(test); 30 | }); 31 | 32 | runner.on('pass', function(test) { 33 | passes.push(test); 34 | }); 35 | 36 | runner.on('fail', function(test) { 37 | failures.push(test); 38 | }); 39 | 40 | runner.on('pending', function(test) { 41 | pending.push(test); 42 | }); 43 | 44 | runner.on('end', function() { 45 | var obj = { 46 | stats: self.stats, 47 | tests: tests.map(clean), 48 | pending: pending.map(clean), 49 | failures: failures.map(clean), 50 | passes: passes.map(clean) 51 | }; 52 | 53 | runner.testResults = obj; 54 | 55 | process.stdout.write(JSON.stringify(obj, null, 2)); 56 | }); 57 | } 58 | 59 | /** 60 | * Return a plain-object representation of `test` 61 | * free of cyclic properties etc. 62 | * 63 | * @api private 64 | * @param {Object} test 65 | * @return {Object} 66 | */ 67 | function clean(test) { 68 | return { 69 | title: test.title, 70 | fullTitle: test.fullTitle(), 71 | duration: test.duration, 72 | currentRetry: test.currentRetry(), 73 | err: errorJSON(test.err || {}) 74 | }; 75 | } 76 | 77 | /** 78 | * Transform `error` into a JSON object. 79 | * 80 | * @api private 81 | * @param {Error} err 82 | * @return {Object} 83 | */ 84 | function errorJSON(err) { 85 | var res = {}; 86 | Object.getOwnPropertyNames(err).forEach(function(key) { 87 | res[key] = err[key]; 88 | }, err); 89 | return res; 90 | } 91 | -------------------------------------------------------------------------------- /lib/reporters/landing.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var Base = require('./base'); 6 | var inherits = require('../utils').inherits; 7 | var cursor = Base.cursor; 8 | var color = Base.color; 9 | 10 | /** 11 | * Expose `Landing`. 12 | */ 13 | 14 | exports = module.exports = Landing; 15 | 16 | /** 17 | * Airplane color. 18 | */ 19 | 20 | Base.colors.plane = 0; 21 | 22 | /** 23 | * Airplane crash color. 24 | */ 25 | 26 | Base.colors['plane crash'] = 31; 27 | 28 | /** 29 | * Runway color. 30 | */ 31 | 32 | Base.colors.runway = 90; 33 | 34 | /** 35 | * Initialize a new `Landing` reporter. 36 | * 37 | * @api public 38 | * @param {Runner} runner 39 | */ 40 | function Landing(runner) { 41 | Base.call(this, runner); 42 | 43 | var self = this; 44 | var width = Base.window.width * .75 | 0; 45 | var total = runner.total; 46 | var stream = process.stdout; 47 | var plane = color('plane', '✈'); 48 | var crashed = -1; 49 | var n = 0; 50 | 51 | function runway() { 52 | var buf = Array(width).join('-'); 53 | return ' ' + color('runway', buf); 54 | } 55 | 56 | runner.on('start', function() { 57 | stream.write('\n\n\n '); 58 | cursor.hide(); 59 | }); 60 | 61 | runner.on('test end', function(test) { 62 | // check if the plane crashed 63 | var col = crashed === -1 ? width * ++n / total | 0 : crashed; 64 | 65 | // show the crash 66 | if (test.state === 'failed') { 67 | plane = color('plane crash', '✈'); 68 | crashed = col; 69 | } 70 | 71 | // render landing strip 72 | stream.write('\u001b[' + (width + 1) + 'D\u001b[2A'); 73 | stream.write(runway()); 74 | stream.write('\n '); 75 | stream.write(color('runway', Array(col).join('⋅'))); 76 | stream.write(plane); 77 | stream.write(color('runway', Array(width - col).join('⋅') + '\n')); 78 | stream.write(runway()); 79 | stream.write('\u001b[0m'); 80 | }); 81 | 82 | runner.on('end', function() { 83 | cursor.show(); 84 | console.log(); 85 | self.epilogue(); 86 | }); 87 | } 88 | 89 | /** 90 | * Inherit from `Base.prototype`. 91 | */ 92 | inherits(Landing, Base); 93 | -------------------------------------------------------------------------------- /lib/reporters/list.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var Base = require('./base'); 6 | var inherits = require('../utils').inherits; 7 | var color = Base.color; 8 | var cursor = Base.cursor; 9 | 10 | /** 11 | * Expose `List`. 12 | */ 13 | 14 | exports = module.exports = List; 15 | 16 | /** 17 | * Initialize a new `List` test reporter. 18 | * 19 | * @api public 20 | * @param {Runner} runner 21 | */ 22 | function List(runner) { 23 | Base.call(this, runner); 24 | 25 | var self = this; 26 | var n = 0; 27 | 28 | runner.on('start', function() { 29 | console.log(); 30 | }); 31 | 32 | runner.on('test', function(test) { 33 | process.stdout.write(color('pass', ' ' + test.fullTitle() + ': ')); 34 | }); 35 | 36 | runner.on('pending', function(test) { 37 | var fmt = color('checkmark', ' -') 38 | + color('pending', ' %s'); 39 | console.log(fmt, test.fullTitle()); 40 | }); 41 | 42 | runner.on('pass', function(test) { 43 | var fmt = color('checkmark', ' ' + Base.symbols.dot) 44 | + color('pass', ' %s: ') 45 | + color(test.speed, '%dms'); 46 | cursor.CR(); 47 | console.log(fmt, test.fullTitle(), test.duration); 48 | }); 49 | 50 | runner.on('fail', function(test) { 51 | cursor.CR(); 52 | console.log(color('fail', ' %d) %s'), ++n, test.fullTitle()); 53 | }); 54 | 55 | runner.on('end', self.epilogue.bind(self)); 56 | } 57 | 58 | /** 59 | * Inherit from `Base.prototype`. 60 | */ 61 | inherits(List, Base); 62 | -------------------------------------------------------------------------------- /lib/reporters/markdown.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var Base = require('./base'); 6 | var utils = require('../utils'); 7 | 8 | /** 9 | * Constants 10 | */ 11 | 12 | var SUITE_PREFIX = '$'; 13 | 14 | /** 15 | * Expose `Markdown`. 16 | */ 17 | 18 | exports = module.exports = Markdown; 19 | 20 | /** 21 | * Initialize a new `Markdown` reporter. 22 | * 23 | * @api public 24 | * @param {Runner} runner 25 | */ 26 | function Markdown(runner) { 27 | Base.call(this, runner); 28 | 29 | var level = 0; 30 | var buf = ''; 31 | 32 | function title(str) { 33 | return Array(level).join('#') + ' ' + str; 34 | } 35 | 36 | function mapTOC(suite, obj) { 37 | var ret = obj; 38 | var key = SUITE_PREFIX + suite.title; 39 | 40 | obj = obj[key] = obj[key] || { suite: suite }; 41 | suite.suites.forEach(function(suite) { 42 | mapTOC(suite, obj); 43 | }); 44 | 45 | return ret; 46 | } 47 | 48 | function stringifyTOC(obj, level) { 49 | ++level; 50 | var buf = ''; 51 | var link; 52 | for (var key in obj) { 53 | if (key === 'suite') { 54 | continue; 55 | } 56 | if (key !== SUITE_PREFIX) { 57 | link = ' - [' + key.substring(1) + ']'; 58 | link += '(#' + utils.slug(obj[key].suite.fullTitle()) + ')\n'; 59 | buf += Array(level).join(' ') + link; 60 | } 61 | buf += stringifyTOC(obj[key], level); 62 | } 63 | return buf; 64 | } 65 | 66 | function generateTOC(suite) { 67 | var obj = mapTOC(suite, {}); 68 | return stringifyTOC(obj, 0); 69 | } 70 | 71 | generateTOC(runner.suite); 72 | 73 | runner.on('suite', function(suite) { 74 | ++level; 75 | var slug = utils.slug(suite.fullTitle()); 76 | buf += '' + '\n'; 77 | buf += title(suite.title) + '\n'; 78 | }); 79 | 80 | runner.on('suite end', function() { 81 | --level; 82 | }); 83 | 84 | runner.on('pass', function(test) { 85 | var code = utils.clean(test.body); 86 | buf += test.title + '.\n'; 87 | buf += '\n```js\n'; 88 | buf += code + '\n'; 89 | buf += '```\n\n'; 90 | }); 91 | 92 | runner.on('end', function() { 93 | process.stdout.write('# TOC\n'); 94 | process.stdout.write(generateTOC(runner.suite)); 95 | process.stdout.write(buf); 96 | }); 97 | } 98 | -------------------------------------------------------------------------------- /lib/reporters/min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var Base = require('./base'); 6 | var inherits = require('../utils').inherits; 7 | 8 | /** 9 | * Expose `Min`. 10 | */ 11 | 12 | exports = module.exports = Min; 13 | 14 | /** 15 | * Initialize a new `Min` minimal test reporter (best used with --watch). 16 | * 17 | * @api public 18 | * @param {Runner} runner 19 | */ 20 | function Min(runner) { 21 | Base.call(this, runner); 22 | 23 | runner.on('start', function() { 24 | // clear screen 25 | process.stdout.write('\u001b[2J'); 26 | // set cursor position 27 | process.stdout.write('\u001b[1;3H'); 28 | }); 29 | 30 | runner.on('end', this.epilogue.bind(this)); 31 | } 32 | 33 | /** 34 | * Inherit from `Base.prototype`. 35 | */ 36 | inherits(Min, Base); 37 | -------------------------------------------------------------------------------- /lib/reporters/progress.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var Base = require('./base'); 6 | var inherits = require('../utils').inherits; 7 | var color = Base.color; 8 | var cursor = Base.cursor; 9 | 10 | /** 11 | * Expose `Progress`. 12 | */ 13 | 14 | exports = module.exports = Progress; 15 | 16 | /** 17 | * General progress bar color. 18 | */ 19 | 20 | Base.colors.progress = 90; 21 | 22 | /** 23 | * Initialize a new `Progress` bar test reporter. 24 | * 25 | * @api public 26 | * @param {Runner} runner 27 | * @param {Object} options 28 | */ 29 | function Progress(runner, options) { 30 | Base.call(this, runner); 31 | 32 | var self = this; 33 | var width = Base.window.width * .50 | 0; 34 | var total = runner.total; 35 | var complete = 0; 36 | var lastN = -1; 37 | 38 | // default chars 39 | options = options || {}; 40 | options.open = options.open || '['; 41 | options.complete = options.complete || '▬'; 42 | options.incomplete = options.incomplete || Base.symbols.dot; 43 | options.close = options.close || ']'; 44 | options.verbose = false; 45 | 46 | // tests started 47 | runner.on('start', function() { 48 | console.log(); 49 | cursor.hide(); 50 | }); 51 | 52 | // tests complete 53 | runner.on('test end', function() { 54 | complete++; 55 | 56 | var percent = complete / total; 57 | var n = width * percent | 0; 58 | var i = width - n; 59 | 60 | if (n === lastN && !options.verbose) { 61 | // Don't re-render the line if it hasn't changed 62 | return; 63 | } 64 | lastN = n; 65 | 66 | cursor.CR(); 67 | process.stdout.write('\u001b[J'); 68 | process.stdout.write(color('progress', ' ' + options.open)); 69 | process.stdout.write(Array(n).join(options.complete)); 70 | process.stdout.write(Array(i).join(options.incomplete)); 71 | process.stdout.write(color('progress', options.close)); 72 | if (options.verbose) { 73 | process.stdout.write(color('progress', ' ' + complete + ' of ' + total)); 74 | } 75 | }); 76 | 77 | // tests are complete, output some stats 78 | // and the failures if any 79 | runner.on('end', function() { 80 | cursor.show(); 81 | console.log(); 82 | self.epilogue(); 83 | }); 84 | } 85 | 86 | /** 87 | * Inherit from `Base.prototype`. 88 | */ 89 | inherits(Progress, Base); 90 | -------------------------------------------------------------------------------- /lib/reporters/spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var Base = require('./base'); 6 | var inherits = require('../utils').inherits; 7 | var color = Base.color; 8 | var cursor = Base.cursor; 9 | 10 | /** 11 | * Expose `Spec`. 12 | */ 13 | 14 | exports = module.exports = Spec; 15 | 16 | /** 17 | * Initialize a new `Spec` test reporter. 18 | * 19 | * @api public 20 | * @param {Runner} runner 21 | */ 22 | function Spec(runner) { 23 | Base.call(this, runner); 24 | 25 | var self = this; 26 | var indents = 0; 27 | var n = 0; 28 | 29 | function indent() { 30 | return Array(indents).join(' '); 31 | } 32 | 33 | runner.on('start', function() { 34 | console.log(); 35 | }); 36 | 37 | runner.on('suite', function(suite) { 38 | ++indents; 39 | console.log(color('suite', '%s%s'), indent(), suite.title); 40 | }); 41 | 42 | runner.on('suite end', function() { 43 | --indents; 44 | if (indents === 1) { 45 | console.log(); 46 | } 47 | }); 48 | 49 | runner.on('pending', function(test) { 50 | var fmt = indent() + color('pending', ' - %s'); 51 | console.log(fmt, test.title); 52 | }); 53 | 54 | runner.on('pass', function(test) { 55 | var fmt; 56 | if (test.speed === 'fast') { 57 | fmt = indent() 58 | + color('checkmark', ' ' + Base.symbols.ok) 59 | + color('pass', ' %s'); 60 | cursor.CR(); 61 | console.log(fmt, test.title); 62 | } else { 63 | fmt = indent() 64 | + color('checkmark', ' ' + Base.symbols.ok) 65 | + color('pass', ' %s') 66 | + color(test.speed, ' (%dms)'); 67 | cursor.CR(); 68 | console.log(fmt, test.title, test.duration); 69 | } 70 | }); 71 | 72 | runner.on('fail', function(test) { 73 | cursor.CR(); 74 | console.log(indent() + color('fail', ' %d) %s'), ++n, test.title); 75 | }); 76 | 77 | runner.on('end', self.epilogue.bind(self)); 78 | } 79 | 80 | /** 81 | * Inherit from `Base.prototype`. 82 | */ 83 | inherits(Spec, Base); 84 | -------------------------------------------------------------------------------- /lib/reporters/tap.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var Base = require('./base'); 6 | 7 | /** 8 | * Expose `TAP`. 9 | */ 10 | 11 | exports = module.exports = TAP; 12 | 13 | /** 14 | * Initialize a new `TAP` reporter. 15 | * 16 | * @api public 17 | * @param {Runner} runner 18 | */ 19 | function TAP(runner) { 20 | Base.call(this, runner); 21 | 22 | var n = 1; 23 | var passes = 0; 24 | var failures = 0; 25 | 26 | runner.on('start', function() { 27 | var total = runner.grepTotal(runner.suite); 28 | console.log('%d..%d', 1, total); 29 | }); 30 | 31 | runner.on('test end', function() { 32 | ++n; 33 | }); 34 | 35 | runner.on('pending', function(test) { 36 | console.log('ok %d %s # SKIP -', n, title(test)); 37 | }); 38 | 39 | runner.on('pass', function(test) { 40 | passes++; 41 | console.log('ok %d %s', n, title(test)); 42 | }); 43 | 44 | runner.on('fail', function(test, err) { 45 | failures++; 46 | console.log('not ok %d %s', n, title(test)); 47 | if (err.stack) { 48 | console.log(err.stack.replace(/^/gm, ' ')); 49 | } 50 | }); 51 | 52 | runner.on('end', function() { 53 | console.log('# tests ' + (passes + failures)); 54 | console.log('# pass ' + passes); 55 | console.log('# fail ' + failures); 56 | }); 57 | } 58 | 59 | /** 60 | * Return a TAP-safe title of `test` 61 | * 62 | * @api private 63 | * @param {Object} test 64 | * @return {String} 65 | */ 66 | function title(test) { 67 | return test.fullTitle().replace(/#/g, ''); 68 | } 69 | -------------------------------------------------------------------------------- /lib/reporters/templates/coverage.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title Coverage 5 | meta(charset='utf-8') 6 | include script.html 7 | include style.html 8 | body 9 | #coverage 10 | h1#overview Coverage 11 | include menu 12 | 13 | #stats(class=coverageClass(cov.coverage)) 14 | .percentage #{cov.coverage | 0}% 15 | .sloc= cov.sloc 16 | .hits= cov.hits 17 | .misses= cov.misses 18 | 19 | #files 20 | for file in cov.files 21 | .file 22 | h2(id=file.filename)= file.filename 23 | #stats(class=coverageClass(file.coverage)) 24 | .percentage #{file.coverage | 0}% 25 | .sloc= file.sloc 26 | .hits= file.hits 27 | .misses= file.misses 28 | 29 | table#source 30 | thead 31 | tr 32 | th Line 33 | th Hits 34 | th Source 35 | tbody 36 | for line, number in file.source 37 | if line.coverage > 0 38 | tr.hit 39 | td.line= number 40 | td.hits= line.coverage 41 | td.source= line.source 42 | else if 0 === line.coverage 43 | tr.miss 44 | td.line= number 45 | td.hits 0 46 | td.source= line.source 47 | else 48 | tr 49 | td.line= number 50 | td.hits 51 | td.source= line.source || ' ' 52 | -------------------------------------------------------------------------------- /lib/reporters/templates/menu.jade: -------------------------------------------------------------------------------- 1 | #menu 2 | li 3 | a(href='#overview') overview 4 | for file in cov.files 5 | li 6 | span.cov(class=coverageClass(file.coverage)) #{file.coverage | 0} 7 | a(href='##{file.filename}') 8 | segments = file.filename.split('/') 9 | basename = segments.pop() 10 | if segments.length 11 | span.dirname= segments.join('/') + '/' 12 | span.basename= basename 13 | a#logo(href='http://mochajs.org/') m 14 | -------------------------------------------------------------------------------- /lib/reporters/templates/script.html: -------------------------------------------------------------------------------- 1 | 35 | -------------------------------------------------------------------------------- /lib/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Mocha 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /lib/test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var Runnable = require('./runnable'); 6 | var inherits = require('./utils').inherits; 7 | 8 | /** 9 | * Expose `Test`. 10 | */ 11 | 12 | module.exports = Test; 13 | 14 | /** 15 | * Initialize a new `Test` with the given `title` and callback `fn`. 16 | * 17 | * @api private 18 | * @param {String} title 19 | * @param {Function} fn 20 | */ 21 | function Test(title, fn) { 22 | Runnable.call(this, title, fn); 23 | this.pending = !fn; 24 | this.type = 'test'; 25 | this.body = (fn || '').toString(); 26 | } 27 | 28 | /** 29 | * Inherit from `Runnable.prototype`. 30 | */ 31 | inherits(Test, Runnable); 32 | 33 | Test.prototype.clone = function() { 34 | var test = new Test(this.title, this.fn); 35 | test.timeout(this.timeout()); 36 | test.slow(this.slow()); 37 | test.enableTimeouts(this.enableTimeouts()); 38 | test.retries(this.retries()); 39 | test.currentRetry(this.currentRetry()); 40 | test.globals(this.globals()); 41 | test.parent = this.parent; 42 | test.file = this.file; 43 | test.ctx = this.ctx; 44 | return test; 45 | }; 46 | -------------------------------------------------------------------------------- /media/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | mocha 7 | 8 | -------------------------------------------------------------------------------- /meteor/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 2.4.5_6 2 | 3 | - Add `ConsoleReporter` and `XunitReporter` more details in how to run then [HERE](). 4 | - Run rests on `runTests` functions. Fixes [#59](https://github.com/practicalmeteor/meteor-mocha/issues/51) 5 | 6 | # 2.4.5_5 7 | 8 | - Fix bug when running on linux. [More details](https://github.com/practicalmeteor/meteor-mocha/issues/51) 9 | 10 | # 2.4.5_4 11 | 12 | - Fix bug related to firing 'end all' mocha runner event. [More details](https://github.com/practicalmeteor/meteor-mocha-console-runner/issues/6) 13 | 14 | # 2.4.5_3 15 | 16 | - Bug fixes (more details below) - [#42](https://github.com/practicalmeteor/meteor-mocha/issues/42), [#44](https://github.com/practicalmeteor/meteor-mocha/issues/44), [#45](https://github.com/practicalmeteor/meteor-mocha/issues/45), 17 | 18 | - Add an acceptance test that includes most mocha test scenarios by verifying that the actual html produced by the reporter matches the expected one. The acceptance test runs both `meteor test`, `meteor test --full-app` and `meteor test-packages` and runs in ci. 19 | 20 | - Move dependency on mocha to mocha-core, and depend on mocha's npm 21 | package, instead of the forked source code - fixes [#23](https://github.com/practicalmeteor/meteor-mocha/issues/23) - conflict with dispatch:mocha-phantomjs 22 | 23 | - Properly support promises returned from mocha functions - fixes [#44](https://github.com/practicalmeteor/meteor-mocha/issues/44) 24 | 25 | - Only use meteor's node stubs client side - fixes [#45](https://github.com/practicalmeteor/meteor-mocha/issues/45) 26 | 27 | - Wrap the server test results publication's added function with fibers support - fixes [#42](https://github.com/practicalmeteor/meteor-mocha/issues/42) 28 | -------------------------------------------------------------------------------- /meteor/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2015 LaVaina Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | [mocha](https://github.com/mochajs/mocha) - [MIT](https://github.com/mochajs/mocha/blob/master/LICENSE) 24 | 25 | [mike:mocha](https://atmospherejs.com/mike/mocha) - [MIT](https://github.com/mad-eye/meteor-mocha-web/blob/master/LICENSE) 26 | -------------------------------------------------------------------------------- /meteor/bin/install-meteor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -ex 2 | 3 | if [ ! -e "$HOME/.meteor/meteor" ]; then 4 | curl https://install.meteor.com/ | sh 5 | else 6 | echo "meteor already exists in Travis CI cache, not installing it." 7 | fi 8 | 9 | # Making sure correct version of meteor is downloaded 10 | meteor --release 1.3.3.1 --version 11 | -------------------------------------------------------------------------------- /meteor/bin/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -x 2 | 3 | cd $REPO_HOME 4 | spacejam test-packages ./ 5 | 6 | EXIT_STATUS="$?" 7 | export TEST_FILE="$REPO_HOME/meteor/tests/test-app.html" 8 | function createCompareFile { 9 | 10 | EXIT_STATUS="$2" 11 | if [ "$1" -ne "0" ] 12 | then 13 | if [ -n "${TRAVIS_BUILD_DIR}" ] 14 | then 15 | echo "Test failed printing compare file." 16 | cat "$TEST_FILE.compare" 17 | echo "End compare file." 18 | else 19 | cat "$TEST_FILE.compare" >> "$(dirname $TEST_FILE)/$3.compare.html" 20 | fi 21 | rm -rf "$TEST_FILE.compare" 22 | EXIT_STATUS="$1" 23 | fi 24 | return ${EXIT_STATUS} 25 | } 26 | 27 | export TEST_FILE="$REPO_HOME/meteor/tests/test-app.html" 28 | 29 | cd "$REPO_HOME/meteor/test-app" 30 | spacejam test --phantomjs-script "$REPO_HOME/meteor/tests/phantomjs-test-script.js" --driver-package practicalmeteor:mocha 31 | createCompareFile "$?" "$EXIT_STATUS" "test-app-parallel" 32 | EXIT_STATUS="$?" 33 | 34 | 35 | cd "$REPO_HOME/meteor/test-app" 36 | MOCHA_RUN_ORDER='serial' 37 | spacejam test --phantomjs-script "$REPO_HOME/meteor/tests/phantomjs-test-script.js" --driver-package practicalmeteor:mocha 38 | createCompareFile "$?" "$EXIT_STATUS" "test-app-serial" 39 | EXIT_STATUS="$?" 40 | 41 | 42 | cd "$REPO_HOME/meteor/test-app" 43 | MOCHA_RUN_ORDER='parallel' 44 | spacejam test --full-app --phantomjs-script "$REPO_HOME/meteor/tests/phantomjs-test-script.js" --driver-package practicalmeteor:mocha 45 | createCompareFile "$?" "$EXIT_STATUS" "test-full-app-parallel" 46 | EXIT_STATUS="$?" 47 | 48 | 49 | cd "$REPO_HOME/meteor/test-app" 50 | MOCHA_RUN_ORDER='serial' 51 | spacejam test --full-app --phantomjs-script "$REPO_HOME/meteor/tests/phantomjs-test-script.js" --driver-package practicalmeteor:mocha 52 | createCompareFile "$?" "$EXIT_STATUS" "test-full-app-serial" 53 | EXIT_STATUS="$?" 54 | 55 | 56 | export TEST_FILE="$REPO_HOME/meteor/tests/test-package.html" 57 | 58 | cd "$REPO_HOME/meteor/test-package" 59 | MOCHA_RUN_ORDER='parallel' 60 | spacejam test-packages --phantomjs-script "$REPO_HOME/meteor/tests/phantomjs-test-script.js" --driver-package practicalmeteor:mocha ./ 61 | createCompareFile "$?" "$EXIT_STATUS" "test-package-parallel" 62 | EXIT_STATUS="$?" 63 | 64 | 65 | cd "$REPO_HOME/meteor/test-package" 66 | MOCHA_RUN_ORDER='serial' 67 | spacejam test-packages --phantomjs-script "$REPO_HOME/meteor/tests/phantomjs-test-script.js" --driver-package practicalmeteor:mocha ./ 68 | createCompareFile "$?" "$EXIT_STATUS" "test-package-serial" 69 | EXIT_STATUS="$?" 70 | 71 | exit $EXIT_STATUS -------------------------------------------------------------------------------- /meteor/src/client/mocha.html: -------------------------------------------------------------------------------- 1 | 2 | Mocha 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /meteor/src/index.js: -------------------------------------------------------------------------------- 1 | import "./setup" 2 | import MochaRunner from "./lib/MochaRunner" 3 | import BaseReporter from "./reporters/BaseReporter" 4 | import ClientServerBaseReporter from "./reporters/ClientServerBaseReporter" 5 | import HtmlReporter from "./reporters/HtmlReporter" 6 | import {hideOtherCSS, hideApp} from 'meteor/tmeasday:test-reporter-helpers'; 7 | 8 | export const runTests = () => { 9 | hideApp('.mocha-wrapper'); 10 | hideOtherCSS(); 11 | MochaRunner.runEverywhere() 12 | }; 13 | 14 | let { before, after, beforeEach, afterEach, 15 | describe, xdescribe, it, xit, specify, 16 | xspecify, xcontext, context } = global; 17 | 18 | export {MochaRunner} 19 | export {BaseReporter, ClientServerBaseReporter, HtmlReporter} 20 | export { before, after, beforeEach, afterEach, 21 | describe, xdescribe, it, xit, specify, 22 | xspecify, xcontext, context }; 23 | -------------------------------------------------------------------------------- /meteor/src/lib/log.js: -------------------------------------------------------------------------------- 1 | log = loglevel.createPackageLogger('practicalmeteor:mocha', 'debug'); 2 | -------------------------------------------------------------------------------- /meteor/src/reporters/BaseReporter.coffee: -------------------------------------------------------------------------------- 1 | #/** 2 | # * Initialize a new `Base` reporter. 3 | # * 4 | # * All other reporters generally 5 | # * inherit from this reporter, providing 6 | # * stats such as test duration, number 7 | # * of tests passed / failed etc. 8 | #* 9 | #* @param {Runner} runner 10 | #* @api public 11 | #*/ 12 | 13 | class BaseReporter 14 | 15 | constructor: (@runner, @options)-> 16 | expect(@runner).to.be.an 'object' 17 | expect(@options).to.be.an 'object' 18 | @stats = { total: @runner.total, suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 } 19 | @failures = [] 20 | 21 | @runner.stats = @stats 22 | 23 | @runner.on 'start', => 24 | @stats.start = new Date 25 | 26 | @runner.on 'suite', (suite)=> 27 | @stats.suites++ if not suite.root 28 | 29 | @runner.on 'test end', (test)=> 30 | @stats.tests++ 31 | 32 | @runner.on 'pass', (test)=> 33 | medium = test.slow() / 2 34 | if test.duration > test.slow() 35 | test.speed = 'slow' 36 | else if test.duration > medium 37 | test.speed = 'medium' 38 | else 39 | test.speed = 'fast' 40 | @stats.passes++ 41 | 42 | @runner.on 'fail', (test, err)=> 43 | @stats.failures++; 44 | test.err = err 45 | @failures.push(test) 46 | 47 | @runner.on 'end', => 48 | @stats.end = new Date 49 | @stats.duration = @stats.end - @stats.start 50 | 51 | @runner.on 'pending', => 52 | @stats.pending++ 53 | 54 | 55 | module.exports = BaseReporter 56 | -------------------------------------------------------------------------------- /meteor/src/reporters/HtmlReporter.coffee: -------------------------------------------------------------------------------- 1 | {ObjectLogger} = require("meteor/practicalmeteor:loglevel") 2 | MochaHtmlReporter = require("./html") 3 | ClientServerBaseReporter = require("./ClientServerBaseReporter") 4 | MochaRunner = require("../lib/MochaRunner") 5 | 6 | log = new ObjectLogger('HtmlReporter', 'info') 7 | 8 | class HtmlReporter extends ClientServerBaseReporter 9 | 10 | constructor: (@clientRunner, @serverRunner, @options = {})-> 11 | try 12 | log.enter('constructor') 13 | @addReporterHtml() 14 | 15 | @reporter = new MochaHtmlReporter(@clientRunner) 16 | @serverReporter = new MochaHtmlReporter(@serverRunner, { 17 | elementIdPrefix: 'server-' 18 | }) 19 | super(@clientRunner, @serverRunner, @options) 20 | finally 21 | log.return() 22 | 23 | ### 24 | Adds the html required by the mocha HTML reporter to the body of the html 25 | document. We modified the mocha HTML reporter to be able to display 2 reporters 26 | at the same time, one for client tests and one for server tests. 27 | TODO: Create a single meteor reactive reporter. 28 | ### 29 | addReporterHtml: ()=> 30 | try 31 | log.enter("addReporterHtml") 32 | div = document.createElement('div') 33 | div.className = 'mocha-wrapper' 34 | 35 | div.innerHTML = '
36 |
37 |

Client tests

38 | 39 |
40 |
41 | 42 |
43 | 44 |
45 |

Server tests

46 | 47 |
48 |
49 |
' 50 | 51 | document.body.appendChild(div) 52 | finally 53 | log.return() 54 | 55 | 56 | 57 | module.exports = HtmlReporter 58 | -------------------------------------------------------------------------------- /meteor/src/reporters/JsonStreamReporter.coffee: -------------------------------------------------------------------------------- 1 | BaseReporter = require("./BaseReporter") 2 | 3 | class JsonStreamReporter extends BaseReporter 4 | 5 | constructor: (runner, options)-> 6 | super(runner, options) 7 | 8 | @runner.on 'start', (total)=> 9 | console.log(JSON.stringify(['start', { total: @stats.total }])) 10 | 11 | @runner.on 'pass', (test)=> 12 | console.log(JSON.stringify(['pass', @clean(test)])) 13 | 14 | @runner.on 'fail', (test, err)=> 15 | test = @clean(test) 16 | test.err = err.message 17 | console.log(JSON.stringify(['fail', test])) 18 | 19 | @runner.on 'end', => 20 | console.log(JSON.stringify(['end', @stats])) 21 | 22 | #/** 23 | # * Return a plain-object representation of `test` 24 | # * free of cyclic properties etc. 25 | # * 26 | # * @param {Object} test 27 | # * @return {Object} 28 | # * @api private 29 | # */ 30 | 31 | clean: (test)-> 32 | return { 33 | title: test.title 34 | fullTitle: test.fullTitle() 35 | duration: test.duration 36 | } 37 | 38 | module.exports = JsonStreamReporter 39 | -------------------------------------------------------------------------------- /meteor/src/reporters/MirrorReporter.coffee: -------------------------------------------------------------------------------- 1 | {ObjectLogger} = require("meteor/practicalmeteor:loglevel") 2 | log = new ObjectLogger('MirrorReporter', 'info') 3 | 4 | class MirrorReporter 5 | 6 | constructor:(@mochaReporter, options)-> 7 | 8 | clientRunner = options.reporterOptions?.clientRunner 9 | expect(clientRunner, "clientRunner").to.be.ok 10 | 11 | # The in order to calculate the progress 12 | clientRunner.total = @mochaReporter.total 13 | 14 | @mochaReporter.on 'start', => 15 | try 16 | log.enter 'onStart', arguments 17 | clientRunner.emit.call(clientRunner, 'start') 18 | finally 19 | log.return() 20 | 21 | @mochaReporter.on 'suite', (suite)=> 22 | try 23 | log.enter 'onSuite', arguments 24 | clientRunner.emit.call(clientRunner, 'suite',suite) 25 | finally 26 | log.return() 27 | 28 | @mochaReporter.on 'suite end', (suite)=> 29 | try 30 | log.enter 'onSuiteEnd', arguments 31 | clientRunner.emit.call(clientRunner, 'suite end',suite) 32 | finally 33 | log.return() 34 | 35 | @mochaReporter.on 'test end', (test)=> 36 | try 37 | log.enter 'onTestEnd', arguments 38 | clientRunner.emit.call(clientRunner, 'test end', test) 39 | finally 40 | log.return() 41 | 42 | @mochaReporter.on 'pass', (test)=> 43 | try 44 | log.enter 'onPass', arguments 45 | clientRunner.emit.call(clientRunner, 'pass', test) 46 | finally 47 | log.return() 48 | 49 | @mochaReporter.on 'fail', (test, error)=> 50 | try 51 | log.enter 'onFail', arguments 52 | clientRunner.emit.call(clientRunner, 'fail', test, error) 53 | finally 54 | log.return() 55 | 56 | @mochaReporter.on 'end', => 57 | try 58 | log.enter 'onEnd', arguments 59 | clientRunner.emit.call(clientRunner, 'end') 60 | finally 61 | log.return() 62 | 63 | @mochaReporter.on 'pending', (test)=> 64 | try 65 | log.enter 'onPending', arguments 66 | clientRunner.emit.call(clientRunner, 'pending', test) 67 | 68 | finally 69 | log.return() 70 | 71 | 72 | module.exports = MirrorReporter 73 | -------------------------------------------------------------------------------- /meteor/src/reporters/index.js: -------------------------------------------------------------------------------- 1 | import ConsoleReporter from "./ConsoleReporter" 2 | import XunitReporter from "./XunitReporter" 3 | import HtmlReporter from "./HtmlReporter" 4 | 5 | 6 | export const HTML_REPORTER = 'html'; 7 | export const CONSOLE_REPORTER = 'console'; 8 | export const XUNIT_REPORTER = 'xunit'; 9 | export const REPORTERS = [HTML_REPORTER, CONSOLE_REPORTER, XUNIT_REPORTER]; 10 | let reporters = { }; 11 | reporters[HTML_REPORTER] = HtmlReporter; 12 | reporters[CONSOLE_REPORTER] = ConsoleReporter; 13 | reporters[XUNIT_REPORTER] = XunitReporter; 14 | export { reporters } 15 | -------------------------------------------------------------------------------- /meteor/src/server/autoupdate.js: -------------------------------------------------------------------------------- 1 | import {Autoupdate} from "meteor/autoupdate" 2 | import {Random} from "meteor/random" 3 | // autoupdate normally won't reload on server-only changes, but when 4 | // running tests in the browser it's nice to have server changes cause 5 | // the tests to reload. Setting the auto update version to a 6 | // different value when the server restarts accomplishes this. 7 | Autoupdate.autoupdateVersion = Random.id(); 8 | -------------------------------------------------------------------------------- /meteor/src/setup/index.js: -------------------------------------------------------------------------------- 1 | import { mochaInstance } from "meteor/practicalmeteor:mocha-core" 2 | import setupMochaClient from "./setupMochaClient" 3 | 4 | if(Meteor.isClient){ 5 | setupMochaClient() 6 | } 7 | if (Meteor.isServer){ 8 | global.mocha = mochaInstance; 9 | } -------------------------------------------------------------------------------- /meteor/src/setup/setupMochaClient.js: -------------------------------------------------------------------------------- 1 | import {meteorInstall} from "meteor/modules" 2 | 3 | // Here we are creating stubs packages to be availabe on the client side. 4 | // This must be called before require('mocha') 5 | // See an example from https://goo.gl/us9YVR 6 | 7 | export default ()=>{ 8 | 9 | process.browser = true; 10 | 11 | require("meteor-node-stubs"); 12 | 13 | meteorInstall({ 14 | node_modules: { 15 | "tty.js": function (r, e, module) { 16 | module.exports = { isatty: ()=>{ return false}} 17 | } 18 | } 19 | }); 20 | 21 | meteorInstall({ 22 | node_modules: { 23 | "constants.js": function (r, e, module) { 24 | module.exports = { 25 | test: {'test':'test'} 26 | } 27 | } 28 | } 29 | }); 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /meteor/test-app/.meteor/.finished-upgraders: -------------------------------------------------------------------------------- 1 | # This file contains information which helps Meteor properly upgrade your 2 | # app when you run 'meteor update'. You should check it into version control 3 | # with your project. 4 | 5 | notices-for-0.9.0 6 | notices-for-0.9.1 7 | 0.9.4-platform-file 8 | notices-for-facebook-graph-api-2 9 | 1.2.0-standard-minifiers-package 10 | 1.2.0-meteor-platform-split 11 | 1.2.0-cordova-changes 12 | 1.2.0-breaking-changes 13 | 1.3.0-split-minifiers-package 14 | -------------------------------------------------------------------------------- /meteor/test-app/.meteor/.gitignore: -------------------------------------------------------------------------------- 1 | local 2 | -------------------------------------------------------------------------------- /meteor/test-app/.meteor/.id: -------------------------------------------------------------------------------- 1 | # This file contains a token that is unique to your project. 2 | # Check it into your repository along with the rest of this directory. 3 | # It can be used for purposes such as: 4 | # - ensuring you don't accidentally deploy one app on top of another 5 | # - providing package authors with aggregated statistics 6 | 7 | 1fl3h7o1w0mo9n5z98 8 | -------------------------------------------------------------------------------- /meteor/test-app/.meteor/packages: -------------------------------------------------------------------------------- 1 | # Meteor packages used by this project, one per line. 2 | # Check this file (and the other files in this directory) into your repository. 3 | # 4 | # 'meteor add' and 'meteor remove' will edit this file for you, 5 | # but you can also edit it by hand. 6 | 7 | meteor-base # Packages every Meteor app needs to have 8 | mobile-experience # Packages for a great mobile UX 9 | mongo # The database Meteor supports right now 10 | blaze-html-templates # Compile .html files into Meteor Blaze views 11 | reactive-var # Reactive variable for tracker 12 | jquery # Helpful client-side library 13 | tracker # Meteor's client-side reactive programming library 14 | 15 | standard-minifier-css # CSS minifier run for production mode 16 | standard-minifier-js # JS minifier run for production mode 17 | es5-shim # ECMAScript 5 compatibility for older browsers. 18 | ecmascript # Enable ECMAScript2015+ syntax in app code 19 | 20 | autopublish # Publish all data to the clients (for prototyping) 21 | insecure # Allow all DB writes from clients (for prototyping) 22 | practicalmeteor:mocha@=2.4.5_6 23 | practicalmeteor:chai 24 | practicalmeteor:loglevel 25 | -------------------------------------------------------------------------------- /meteor/test-app/.meteor/platforms: -------------------------------------------------------------------------------- 1 | server 2 | browser 3 | -------------------------------------------------------------------------------- /meteor/test-app/.meteor/release: -------------------------------------------------------------------------------- 1 | METEOR@1.3.3.1 2 | -------------------------------------------------------------------------------- /meteor/test-app/.meteor/versions: -------------------------------------------------------------------------------- 1 | allow-deny@1.0.5 2 | autopublish@1.0.7 3 | autoupdate@1.2.10 4 | babel-compiler@6.8.2 5 | babel-runtime@0.1.9 6 | base64@1.0.9 7 | binary-heap@1.0.9 8 | blaze@2.1.8 9 | blaze-html-templates@1.0.4 10 | blaze-tools@1.0.9 11 | boilerplate-generator@1.0.9 12 | caching-compiler@1.0.5 13 | caching-html-compiler@1.0.6 14 | callback-hook@1.0.9 15 | check@1.2.3 16 | coffeescript@1.1.1 17 | ddp@1.2.5 18 | ddp-client@1.2.8 19 | ddp-common@1.2.6 20 | ddp-server@1.2.8 21 | deps@1.0.12 22 | diff-sequence@1.0.6 23 | ecmascript@0.4.5 24 | ecmascript-runtime@0.2.11 25 | ejson@1.0.12 26 | es5-shim@4.5.12 27 | fastclick@1.0.12 28 | geojson-utils@1.0.9 29 | hot-code-push@1.0.4 30 | html-tools@1.0.10 31 | htmljs@1.0.10 32 | http@1.1.6 33 | id-map@1.0.8 34 | insecure@1.0.7 35 | jquery@1.11.9 36 | launch-screen@1.0.12 37 | livedata@1.0.18 38 | logging@1.0.13 39 | meteor@1.1.15 40 | meteor-base@1.0.4 41 | minifier-css@1.1.12 42 | minifier-js@1.1.12 43 | minimongo@1.0.17 44 | mobile-experience@1.0.4 45 | mobile-status-bar@1.0.12 46 | modules@0.6.3 47 | modules-runtime@0.6.4 48 | mongo@1.1.9 49 | mongo-id@1.0.5 50 | npm-mongo@1.4.44 51 | observe-sequence@1.0.12 52 | ordered-dict@1.0.8 53 | practicalmeteor:chai@2.1.0_1 54 | practicalmeteor:loglevel@1.2.0_2 55 | practicalmeteor:mocha@2.4.5_6 56 | practicalmeteor:mocha-core@1.0.1 57 | practicalmeteor:sinon@1.14.1_2 58 | promise@0.7.2 59 | random@1.0.10 60 | reactive-var@1.0.10 61 | reload@1.1.9 62 | retry@1.0.8 63 | routepolicy@1.0.11 64 | spacebars@1.0.12 65 | spacebars-compiler@1.0.12 66 | standard-minifier-css@1.0.7 67 | standard-minifier-js@1.0.7 68 | templating@1.1.11 69 | templating-tools@1.0.4 70 | tmeasday:test-reporter-helpers@0.2.1 71 | tracker@1.0.14 72 | ui@1.0.11 73 | underscore@1.0.9 74 | url@1.0.10 75 | webapp@1.2.9 76 | webapp-hashing@1.0.9 77 | -------------------------------------------------------------------------------- /meteor/test-app/app.app-test.js: -------------------------------------------------------------------------------- 1 | import addTests from "./both-test" 2 | 3 | addTests("Full app: "); -------------------------------------------------------------------------------- /meteor/test-app/app.test.js: -------------------------------------------------------------------------------- 1 | import addTests from "./both-test" 2 | 3 | addTests(); -------------------------------------------------------------------------------- /meteor/test-app/client/client-test.js: -------------------------------------------------------------------------------- 1 | import {MochaRunner, describe, it, before, after, beforeEach, afterEach, xdescribe, xit, specify, xspecify, context, xcontext} from "meteor/practicalmeteor:mocha" 2 | import {expect} from "meteor/practicalmeteor:chai" 3 | 4 | export default () =>{ 5 | 6 | describe("Client Test", function(){ 7 | 8 | it("this test is client side only", function(){ 9 | expect(Meteor.isClient).to.be.true 10 | expect(Meteor.isServer).to.be.false 11 | }) 12 | }); 13 | 14 | } -------------------------------------------------------------------------------- /meteor/test-app/client/client.app-test.js: -------------------------------------------------------------------------------- 1 | import addTests from "./client-test" 2 | 3 | addTests("Full app: "); -------------------------------------------------------------------------------- /meteor/test-app/client/client.test.js: -------------------------------------------------------------------------------- 1 | import addTests from "./client-test" 2 | 3 | addTests(); -------------------------------------------------------------------------------- /meteor/test-app/client/main.css: -------------------------------------------------------------------------------- 1 | /* CSS declarations go here */ 2 | -------------------------------------------------------------------------------- /meteor/test-app/client/main.html: -------------------------------------------------------------------------------- 1 | 2 | simple 3 | 4 | 5 | 6 |

Welcome to Meteor!

7 | 8 | {{> hello}} 9 | {{> info}} 10 | 11 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /meteor/test-app/client/main.js: -------------------------------------------------------------------------------- 1 | import { Template } from 'meteor/templating'; 2 | import { ReactiveVar } from 'meteor/reactive-var'; 3 | 4 | import './main.html'; 5 | 6 | Template.hello.onCreated(function helloOnCreated() { 7 | // counter starts at 0 8 | this.counter = new ReactiveVar(0); 9 | }); 10 | 11 | Template.hello.helpers({ 12 | counter() { 13 | return Template.instance().counter.get(); 14 | }, 15 | }); 16 | 17 | Template.hello.events({ 18 | 'click button'(event, instance) { 19 | // increment the counter when button is clicked 20 | instance.counter.set(instance.counter.get() + 1); 21 | }, 22 | }); 23 | -------------------------------------------------------------------------------- /meteor/test-app/globals-test.js: -------------------------------------------------------------------------------- 1 | import {expect} from "meteor/practicalmeteor:chai" 2 | 3 | export default () =>{ 4 | 5 | describe('Globals', function() { 6 | 7 | before(function() { 8 | return console.log('before'); 9 | }); 10 | after(function() { 11 | return console.log('after'); 12 | }); 13 | beforeEach(function() { 14 | return console.log('beforeEach'); 15 | }); 16 | afterEach(function() { 17 | return console.log('afterEach'); 18 | }); 19 | it('passing', function() { 20 | return expect(true).to.be["true"]; 21 | }); 22 | it('throwing', function() { 23 | return expect(false).to.be["true"]; 24 | }); 25 | 26 | specify("it works", function () { 27 | expect(true).to.be.true; 28 | }); 29 | 30 | xspecify("Skip: This won't run (xspecify)", function () { 31 | throw new Error("This won't run") 32 | }); 33 | 34 | xdescribe('Skip suite (xdescribe)', function() { 35 | return it("this won't run", function() { 36 | throw new Error("This is an error"); 37 | }); 38 | }); 39 | 40 | context("Context test", function () { 41 | it("it works", function () { 42 | expect(true).to.be.true; 43 | }); 44 | }); 45 | 46 | xcontext("Skip suite (xcontext)", function () { 47 | 48 | it("This won't run", function () { 49 | throw new Error("This won't run") 50 | }) 51 | }) 52 | 53 | }); 54 | 55 | } -------------------------------------------------------------------------------- /meteor/test-app/globals.app-test.js: -------------------------------------------------------------------------------- 1 | import {expect} from "meteor/practicalmeteor:chai" 2 | import addTests from "./globals-test" 3 | 4 | addTests("Full app"); 5 | -------------------------------------------------------------------------------- /meteor/test-app/globals.test.js: -------------------------------------------------------------------------------- 1 | import {expect} from "meteor/practicalmeteor:chai" 2 | import addTests from "./globals-test" 3 | 4 | addTests(); 5 | -------------------------------------------------------------------------------- /meteor/test-app/import/collections/TestCollection.js: -------------------------------------------------------------------------------- 1 | import {Mongo} from "meteor/mongo"; 2 | 3 | export default TestCollection = new Mongo.Collection("TestCollection"); 4 | -------------------------------------------------------------------------------- /meteor/test-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test-app", 3 | "private": true, 4 | "scripts": { 5 | "start": "meteor run" 6 | }, 7 | "dependencies": { 8 | "meteor-node-stubs": "~0.2.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /meteor/test-app/server/main.js: -------------------------------------------------------------------------------- 1 | import { Meteor } from 'meteor/meteor'; 2 | 3 | Meteor.startup(() => { 4 | // code to run on server at startup 5 | }); 6 | -------------------------------------------------------------------------------- /meteor/test-app/server/server-test.js: -------------------------------------------------------------------------------- 1 | import {MochaRunner, describe, it, before, after, beforeEach, afterEach, xdescribe, xit, specify, xspecify, context, xcontext} from "meteor/practicalmeteor:mocha" 2 | import {expect} from "meteor/practicalmeteor:chai" 3 | 4 | export default () =>{ 5 | 6 | describe("Server Test", function(){ 7 | 8 | it("this test is server side only", function(){ 9 | expect(Meteor.isServer).to.be.true 10 | expect(Meteor.isClient).to.be.false 11 | }); 12 | 13 | it("require('fs) === to Npm.require('fs')", function() { 14 | expect(require('fs')).to.equal(Npm.require('fs')) 15 | }); 16 | 17 | }); 18 | } -------------------------------------------------------------------------------- /meteor/test-app/server/server.app-test.js: -------------------------------------------------------------------------------- 1 | import addTests from "./server-test" 2 | 3 | addTests("Full app: "); 4 | 5 | -------------------------------------------------------------------------------- /meteor/test-app/server/server.test.js: -------------------------------------------------------------------------------- 1 | import addTests from "./server-test" 2 | 3 | addTests(); 4 | 5 | -------------------------------------------------------------------------------- /meteor/test-package/TestCollection.coffee: -------------------------------------------------------------------------------- 1 | {Mongo} = require("meteor/mongo") 2 | 3 | TestCollection = new Mongo.Collection('test.collection') 4 | module.exports = TestCollection 5 | 6 | #if Meteor.isClient 7 | # throw new Error 'Uncaught client side error before tests.' 8 | -------------------------------------------------------------------------------- /meteor/test-package/mocha-globals-tests.js: -------------------------------------------------------------------------------- 1 | import {expect} from "meteor/practicalmeteor:chai" 2 | 3 | describe('Globals', function() { 4 | 5 | before(function() { 6 | return console.log('before'); 7 | }); 8 | after(function() { 9 | return console.log('after'); 10 | }); 11 | beforeEach(function() { 12 | return console.log('beforeEach'); 13 | }); 14 | afterEach(function() { 15 | return console.log('afterEach'); 16 | }); 17 | it('passing', function() { 18 | return expect(true).to.be["true"]; 19 | }); 20 | it('throwing', function() { 21 | return expect(false).to.be["true"]; 22 | }); 23 | 24 | specify("it works", function () { 25 | expect(true).to.be.true; 26 | }); 27 | 28 | xspecify("Skip: This won't run (xspecify)", function () { 29 | throw new Error("This won't run") 30 | }); 31 | 32 | xdescribe('Skip suite (xdescribe)', function() { 33 | return it("this won't run", function() { 34 | throw new Error("This is an error"); 35 | }); 36 | }); 37 | 38 | context("Context test", function () { 39 | it("it works", function () { 40 | expect(true).to.be.true; 41 | }); 42 | }); 43 | 44 | xcontext("Skip suite (xcontext)", function () { 45 | 46 | it("This won't run", function () { 47 | throw new Error("This won't run") 48 | }) 49 | }) 50 | 51 | }); 52 | -------------------------------------------------------------------------------- /meteor/test-package/package.js: -------------------------------------------------------------------------------- 1 | // Using the "wrapper package" version format 2 | Package.describe({ 3 | name: "test-package", 4 | summary: "Test package for the mocha package" 5 | }); 6 | 7 | 8 | Package.onUse(function (api) { 9 | api.versionsFrom('1.3'); 10 | 11 | api.use([ 12 | 'meteor', 13 | 'mongo', 14 | 'coffeescript', 15 | 'practicalmeteor:loglevel', 16 | 'practicalmeteor:chai', 17 | "ecmascript" 18 | ]); 19 | 20 | }); 21 | 22 | Package.onTest(function (api) { 23 | api.use([ 24 | 'coffeescript', 25 | 'practicalmeteor:loglevel', 26 | 'practicalmeteor:chai', 27 | 'practicalmeteor:mocha@=2.4.5_6', 28 | 'ecmascript', 29 | 'test-package' 30 | ]); 31 | 32 | api.addFiles('mocha-tests.js'); 33 | api.addFiles('server-tests.js', 'server'); 34 | api.addFiles('mocha-globals-tests.js'); 35 | }); 36 | -------------------------------------------------------------------------------- /meteor/test-package/server-tests.js: -------------------------------------------------------------------------------- 1 | import {describe, it } from "meteor/practicalmeteor:mocha" 2 | import {expect} from "meteor/practicalmeteor:chai" 3 | 4 | describe("Server Test", function(){ 5 | 6 | it("this test is server side only", function(){ 7 | expect(Meteor.isServer).to.be.true 8 | expect(Meteor.isClient).to.be.false 9 | }); 10 | 11 | it("require('fs) === to Npm.require('fs')", function() { 12 | expect(require('fs')).to.equal(Npm.require('fs')) 13 | }) 14 | }); 15 | -------------------------------------------------------------------------------- /meteor/tests/mocha-globals-test.coffee: -------------------------------------------------------------------------------- 1 | Tinytest.add 'mocha should exist', (test)-> 2 | expect(mocha).to.be.an 'object' 3 | 4 | Tinytest.add 'mocha.run should exist', (test)-> 5 | expect(mocha.run).to.be.a 'function' 6 | 7 | Tinytest.add 'describe should exist', (test)-> 8 | expect(describe).to.be.a 'function' 9 | 10 | Tinytest.add 'it should exist', (test)-> 11 | expect(it).to.be.a 'function' 12 | 13 | Tinytest.add 'before should exist', (test)-> 14 | expect(before).to.be.a 'function' 15 | 16 | Tinytest.add 'after should exist', (test)-> 17 | expect(after).to.be.a 'function' 18 | 19 | Tinytest.add 'beforeEach should exist', (test)-> 20 | expect(beforeEach).to.be.a 'function' 21 | 22 | Tinytest.add 'afterEach should exist', (test)-> 23 | expect(afterEach).to.be.a 'function' 24 | 25 | Tinytest.add 'xdescribe should exist', (test)-> 26 | expect(xdescribe).to.be.a 'function' 27 | 28 | Tinytest.add 'xit should exist', (test)-> 29 | expect(xit).to.be.a 'function' 30 | 31 | Tinytest.add 'specify should exist', (test)-> 32 | expect(specify).to.be.a 'function' 33 | 34 | Tinytest.add 'xspecify should exist', (test)-> 35 | expect(xspecify).to.be.a 'function' 36 | 37 | Tinytest.add 'context should exist', (test)-> 38 | expect(context).to.be.a 'function' 39 | 40 | Tinytest.add 'xcontext should exist', (test)-> 41 | expect(xcontext).to.be.a 'function' 42 | -------------------------------------------------------------------------------- /meteor/tests/mocha-import-test.coffee: -------------------------------------------------------------------------------- 1 | {describe, it, before, after, beforeEach, afterEach, xdescribe, xit, specify, xspecify, context, xcontext} = require("meteor/practicalmeteor:mocha") 2 | 3 | 4 | Tinytest.add 'import - describe should exist', (test)-> 5 | expect(describe).to.be.a 'function' 6 | 7 | Tinytest.add 'import - it should exist', (test)-> 8 | expect(it).to.be.a 'function' 9 | 10 | Tinytest.add 'import - before should exist', (test)-> 11 | expect(before).to.be.a 'function' 12 | 13 | Tinytest.add 'import - after should exist', (test)-> 14 | expect(after).to.be.a 'function' 15 | 16 | Tinytest.add 'import - beforeEach should exist', (test)-> 17 | expect(beforeEach).to.be.a 'function' 18 | 19 | Tinytest.add 'import - afterEach should exist', (test)-> 20 | expect(afterEach).to.be.a 'function' 21 | 22 | Tinytest.add 'import - xdescribe should exist', (test)-> 23 | expect(xdescribe).to.be.a 'function' 24 | 25 | Tinytest.add 'import - xit should exist', (test)-> 26 | expect(xit).to.be.a 'function' 27 | 28 | Tinytest.add 'import - specify should exist', (test)-> 29 | expect(specify).to.be.a 'function' 30 | 31 | Tinytest.add 'import - xspecify should exist', (test)-> 32 | expect(xspecify).to.be.a 'function' 33 | 34 | Tinytest.add 'import - context should exist', (test)-> 35 | expect(context).to.be.a 'function' 36 | 37 | Tinytest.add 'import - xcontext should exist', (test)-> 38 | expect(xcontext).to.be.a 'function' 39 | 40 | -------------------------------------------------------------------------------- /meteor/tests/phantomjs-test-script.js: -------------------------------------------------------------------------------- 1 | var page, system; 2 | 3 | page = require('webpage').create(); 4 | var fs = require('fs'); 5 | system = require('system'); 6 | console.log("phantomjs: Using file " + system.env.TEST_FILE + " to compare."); 7 | var compare = fs.read(system.env.TEST_FILE); 8 | console.log("phantomjs: Running tests at " + system.env.ROOT_URL); 9 | 10 | page.onConsoleMessage = function (message) { 11 | console.log(message); 12 | }; 13 | 14 | page.open(system.env.ROOT_URL, function(status) {console.log("status:", status)}); 15 | 16 | page.onError = function (msg, trace) { 17 | var mochaIsRunning; 18 | mochaIsRunning = page.evaluate(function () { 19 | return window.mochaIsRunning; 20 | }); 21 | if (mochaIsRunning) { 22 | return; 23 | } 24 | console.log("phantomjs: " + msg); 25 | trace.forEach(function (item) { 26 | console.log(" " + item.file + ": " + item.line); 27 | }); 28 | phantom.exit(6); 29 | }; 30 | 31 | setInterval(function () { 32 | var done, failures; 33 | done = page.evaluate(function () { 34 | if (typeof TEST_STATUS !== "undefined" && TEST_STATUS !== null) { 35 | return TEST_STATUS.DONE; 36 | } 37 | if (typeof DONE !== "undefined" && DONE !== null) { 38 | return DONE; 39 | } 40 | return false; 41 | }); 42 | if (done) { 43 | var html = page.evaluate(function () { 44 | // We don't care about the duration of tests. We make them '0' 45 | var duration = document.querySelectorAll(".duration"); 46 | for(var i = 0; i < duration.length; i++){ 47 | duration[i].innerHTML = "0"; 48 | } 49 | // Cleanup slow fast medium classes 50 | var tests = document.querySelectorAll(".test"); 51 | for (var i = 0; i < tests.length; i++) { 52 | var test = tests[i]; 53 | test.classList.remove("fast"); 54 | test.classList.remove("medium"); 55 | test.classList.remove("slow"); 56 | 57 | test.classList.add("fast") 58 | } 59 | 60 | return document.querySelector(".mocha-wrapper").innerHTML; 61 | }); 62 | // Remove changing strings 63 | var regex = new RegExp("/local\\?", "g"); 64 | html = html.replace(regex, "/?"); 65 | 66 | regex = new RegExp("http://localhost:3000", "g"); 67 | compare = compare.replace(regex, system.env.ROOT_URL); 68 | 69 | regex = new RegExp("hash=[^\\n|^<]*", "g"); 70 | html = html.replace(regex, "hash=a"); 71 | 72 | regex = new RegExp("meteor-test-[^\/]*", "g"); 73 | html = html.replace(regex, "meteor-test-123"); 74 | 75 | regex = new RegExp("meteor-test-[^\/]*", "g"); 76 | html = html.replace(regex, "meteor-test-123"); 77 | 78 | regex = /\/home\/.*\/.meteor\/.*\)/g 79 | html = html.replace(regex, "/home/test/.meteor/promise/core.js:1:1)"); 80 | 81 | 82 | var equal = (compare == html); 83 | if (!equal){ 84 | fs.write(system.env.TEST_FILE+".compare", html, 'w'); 85 | } 86 | return phantom.exit( !equal); 87 | } 88 | }, 500); 89 | 90 | // --- 91 | // generated by coffee-script 1.9.2 -------------------------------------------------------------------------------- /package.js: -------------------------------------------------------------------------------- 1 | // Using the "wrapper package" version format 2 | Package.describe({ 3 | name: "practicalmeteor:mocha", 4 | summary: "Write package tests with mocha and run them in the browser or from the command line with spacejam.", 5 | git: "https://github.com/practicalmeteor/meteor-mocha.git", 6 | version: '2.4.5_6', 7 | testOnly: true 8 | }); 9 | 10 | // This will remove 'Unable to resolve some modules' warnings. See https://goo.gl/YB44Km 11 | Npm.depends({ 12 | "diff": "1.4.0", 13 | "debug": "2.2.0", 14 | "glob": "3.2.3", 15 | "growl": "1.8.1", 16 | "util": "0.10.3", 17 | "events":"1.1.0", 18 | "assert":"1.3.0", 19 | "escape-string-regexp": "1.0.2", 20 | "supports-color": "1.2.0", 21 | "path": "0.12.7", 22 | "meteor-node-stubs": "0.2.1", 23 | "underscore": "1.8.3", 24 | mocha: '2.4.5' 25 | }); 26 | 27 | Package.onUse(function (api) { 28 | api.versionsFrom("1.3"); 29 | 30 | api.use('tmeasday:test-reporter-helpers@0.2.1'); 31 | api.use('coffeescript'); 32 | api.use('reload'); 33 | api.use('ddp'); 34 | api.use('random'); 35 | api.use('mongo'); 36 | api.use('autoupdate'); 37 | api.use('ecmascript'); 38 | api.use('check'); 39 | 40 | // If we use a reactive reporter such as meteor's test-in-browser one, 41 | // we'll need all of this. 42 | api.use(['blaze', 'templating', 'spacebars', 'tracker'], 'client'); 43 | 44 | api.use([ 45 | 'practicalmeteor:mocha-core@1.0.1', 46 | 'practicalmeteor:loglevel@1.2.0_2', 47 | 'practicalmeteor:chai@2.1.0_1', 48 | 'practicalmeteor:sinon@1.14.1_2' 49 | ]); 50 | 51 | api.imply([ 52 | 'practicalmeteor:mocha-core@1.0.1', 53 | 'practicalmeteor:loglevel@1.2.0_2', 54 | 'practicalmeteor:chai@2.1.0_1', 55 | 'practicalmeteor:sinon@1.14.1_2' 56 | ]); 57 | 58 | // So meteor-web-driver will be available from the command line 59 | // api.imply(['practicalmeteor:mocha-web-driver@0.9.0-rc0']); 60 | 61 | // Uncomment once we upgrade to loglevel v2 62 | //api.addFiles('src/lib/log.js'); 63 | 64 | api.addFiles([ 65 | 'meteor/src/server/autoupdate.js' 66 | ], 'server'); 67 | 68 | 69 | api.addFiles([ 70 | 'meteor/src/client/mocha.html', 71 | 'mocha.css' 72 | ], 'client'); 73 | 74 | 75 | api.mainModule('meteor/src/index.js'); 76 | api.export('runTests'); 77 | }); 78 | 79 | 80 | Package.onTest(function (api) { 81 | api.use([ 82 | 'coffeescript', 83 | 'ecmascript', 84 | 'practicalmeteor:chai', 85 | 'practicalmeteor:mocha', 86 | 'tinytest']); 87 | 88 | api.addFiles('meteor/tests/mocha-globals-test.coffee'); 89 | api.addFiles('meteor/tests/mocha-import-test.coffee'); 90 | }); 91 | -------------------------------------------------------------------------------- /scripts/ensure-compatible-npm.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | set -o nounset 4 | set -o errexit 5 | 6 | npm install semver 7 | if node -e "process.exit(require('semver').lt(process.argv[1], '1.3.7') ? 0 : 1)" $(npm -v); then 8 | npm install -g npm@2 9 | npm install -g npm 10 | fi 11 | npm uninstall semver 12 | -------------------------------------------------------------------------------- /test/.eslintrc: -------------------------------------------------------------------------------- 1 | --- 2 | env: 3 | mocha: true 4 | -------------------------------------------------------------------------------- /test/acceptance/context.js: -------------------------------------------------------------------------------- 1 | describe('Context', function(){ 2 | beforeEach(function(){ 3 | this.calls = ['before']; 4 | }) 5 | 6 | describe('nested', function(){ 7 | beforeEach(function(){ 8 | this.calls.push('before two'); 9 | }) 10 | 11 | it('should work', function(){ 12 | this.calls.should.eql(['before', 'before two']); 13 | this.calls.push('test'); 14 | }) 15 | 16 | after(function(){ 17 | this.calls.should.eql(['before', 'before two', 'test']); 18 | this.calls.push('after two'); 19 | }) 20 | }) 21 | 22 | after(function(){ 23 | this.calls.should.eql(['before', 'before two', 'test', 'after two']); 24 | }) 25 | }) 26 | 27 | describe('Context Siblings', function(){ 28 | beforeEach(function(){ 29 | this.calls = ['before']; 30 | }) 31 | 32 | describe('sequestered sibling', function(){ 33 | beforeEach(function(){ 34 | this.calls.push('before two'); 35 | this.hiddenFromSibling = 'This should be hidden'; 36 | }) 37 | 38 | it('should work', function(){ 39 | this.hiddenFromSibling.should.eql('This should be hidden') 40 | }) 41 | }) 42 | 43 | describe('sibling verifiction', function(){ 44 | beforeEach(function(){ 45 | this.calls.push('before sibling'); 46 | }) 47 | 48 | it('should not have value set within a sibling describe', function(){ 49 | 'This should be hidden'.should.not.eql(this.hiddenFromSibling); 50 | this.visibleFromTestSibling = 'Visible from test sibling'; 51 | }) 52 | 53 | it('should allow test siblings to modify shared context', function(){ 54 | 'Visible from test sibling'.should.eql(this.visibleFromTestSibling); 55 | }) 56 | 57 | it('should have reset this.calls before describe', function(){ 58 | this.calls.should.eql(['before', 'before sibling']); 59 | }) 60 | }) 61 | 62 | after(function(){ 63 | this.calls.should.eql(['before', 'before sibling']); 64 | }) 65 | 66 | }) 67 | 68 | describe('timeout()', function(){ 69 | it('should return the timeout', function(){ 70 | this.timeout().should.equal(200); 71 | }); 72 | }); 73 | -------------------------------------------------------------------------------- /test/acceptance/duration.js: -------------------------------------------------------------------------------- 1 | describe('durations', function(){ 2 | describe('when slow', function(){ 3 | it('should highlight in red', function(done){ 4 | setTimeout(function(){ 5 | done(); 6 | }, 100); 7 | }) 8 | }) 9 | 10 | describe('when reasonable', function(){ 11 | it('should highlight in yellow', function(done){ 12 | setTimeout(function(){ 13 | done(); 14 | }, 50); 15 | }) 16 | }) 17 | 18 | describe('when fast', function(){ 19 | it('should highlight in green', function(done){ 20 | setTimeout(function(){ 21 | done(); 22 | }, 10); 23 | }) 24 | }) 25 | }) 26 | -------------------------------------------------------------------------------- /test/acceptance/fs.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | 3 | describe('fs.readFile()', function(){ 4 | describe('when the file exists', function(){ 5 | it('should succeed', function(done){ 6 | fs.writeFile('/tmp/mocha', 'wahoo', done) 7 | }) 8 | }) 9 | 10 | describe('when the file does not exist', function(){ 11 | it('should fail', function(done){ 12 | // uncomment 13 | // fs.readFile('/tmp/does-not-exist', done); 14 | done(); 15 | }) 16 | }) 17 | }) 18 | -------------------------------------------------------------------------------- /test/acceptance/glob/glob.js: -------------------------------------------------------------------------------- 1 | describe('globbing test', function(){ 2 | it('should find this test', function(){ 3 | // see glob.sh for details 4 | }) 5 | }); 6 | -------------------------------------------------------------------------------- /test/acceptance/glob/glob.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | REL_SCRIPT_DIR="`dirname \"$0\"`" 3 | SCRIPT_DIR="`( cd \"$REL_SCRIPT_DIR\" && pwd )`" 4 | 5 | cd $SCRIPT_DIR || { 6 | echo Could not cd to $SCRIPT_DIR from `pwd` 7 | exit 1 8 | } 9 | 10 | ../../../bin/mocha -R json-stream ./*.js > /tmp/mocha-glob.txt || { 11 | echo Globbing ./*.js in `pwd` failed. 12 | exit 1 13 | } 14 | 15 | cat /tmp/mocha-glob.txt | grep -q -F '["end",{"suites":1,"tests":1,"passes":1,"pending":0,"failures":0,' || { 16 | echo Globbing ./*.js in `pwd` should match glob.js with one test inside. 17 | exit 1 18 | } 19 | 20 | ../../../bin/mocha -R json-stream ./*-none.js 2> /tmp/mocha-glob.txt && { 21 | echo Globbing './*-none.js' in `pwd` failed. 22 | exit 1 23 | } 24 | 25 | cat /tmp/mocha-glob.txt | grep -q -F 'cannot resolve path' || { 26 | echo Globbing './*-none.js' in `pwd` should match no files and run no tests. 27 | exit 1 28 | } 29 | 30 | # Globbing in windows command-shell differs completely from unix-style globbing. 31 | # In bash, the shell expands globs and passes the result to executables. 32 | # In windows, the shell passes globs unexpanded, executables do expansion if they support it. 33 | # Adding single-quotes around the glob below makes bash pass glob unexpanded, 34 | # allowing us to test windows-style globbing in bash. 35 | ../../../bin/mocha -R json-stream './*.js' > /tmp/mocha-glob.txt || { 36 | echo Globbing './*.js' in `pwd` failed. 37 | exit 1 38 | } 39 | 40 | cat /tmp/mocha-glob.txt | grep -q -F '["end",{"suites":1,"tests":1,"passes":1,"pending":0,"failures":0,' || { 41 | echo Globbing './*.js' in `pwd` should match glob.js with one test inside. 42 | exit 1 43 | } 44 | 45 | ../../../bin/mocha -R json-stream './*-none.js' 2> /tmp/mocha-glob.txt && { 46 | echo Globbing './*-none.js' in `pwd` failed. 47 | exit 1 48 | } 49 | 50 | cat /tmp/mocha-glob.txt | grep -q -F 'cannot resolve path' || { 51 | echo Globbing './*-none.js' in `pwd` should match no files and run no tests. 52 | exit 1 53 | } 54 | 55 | echo Glob-test passed. 56 | -------------------------------------------------------------------------------- /test/acceptance/globals.js: -------------------------------------------------------------------------------- 1 | describe('global leaks', function(){ 2 | before(function(){ 3 | // uncomment to test 4 | // foo = 'hey'; 5 | // bar = 'hey'; 6 | }) 7 | 8 | beforeEach(function(){ 9 | // uncomment to test 10 | // foo = 'bar' 11 | }); 12 | 13 | it('should cause tests to fail', function(){ 14 | // uncomment to test 15 | // foo = 'bar'; 16 | // bar = 'baz'; 17 | // baz = 'raz'; 18 | }); 19 | 20 | it('should pass when accepted', function(){ 21 | global.okGlobalA = 1; 22 | global.okGlobalB = 1; 23 | global.okGlobalC = 1; 24 | }) 25 | 26 | it('should pass with wildcard', function(){ 27 | global.callback123 = 'foo'; 28 | global.callback345 = 'bar'; 29 | }); 30 | 31 | it('should pass when prefixed "mocha-"', function(){ 32 | // Opera and IE do this for HTML element IDs anyway 33 | // but to sure we can assert this in any browser, simulate it. 34 | global['mocha-example'] = { nodeType: 1 }; 35 | }); 36 | 37 | afterEach(function(){ 38 | // uncomment to test 39 | // foo = 'bar' 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /test/acceptance/http.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | 3 | var server = http.createServer(function(req, res){ 4 | res.end('Hello World\n'); 5 | }) 6 | 7 | server.listen(8888); 8 | 9 | describe('http', function(){ 10 | it('should provide an example', function(done){ 11 | http.get({ path: '/', port: 8888 }, function(res){ 12 | res.should.have.property('statusCode', 200); 13 | done(); 14 | }) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /test/acceptance/interfaces/bdd.js: -------------------------------------------------------------------------------- 1 | describe('Array', function(){ 2 | describe('#indexOf()', function(){ 3 | it('should return -1 when the value is not present', function(){ 4 | [1,2,3].indexOf(5).should.equal(-1); 5 | [1,2,3].indexOf(0).should.equal(-1); 6 | }) 7 | 8 | it('should return the correct index when the value is present', function(){ 9 | [1,2,3].indexOf(1).should.equal(0); 10 | [1,2,3].indexOf(2).should.equal(1); 11 | [1,2,3].indexOf(3).should.equal(2); 12 | }) 13 | }) 14 | }) 15 | 16 | describe('Array', function(){ 17 | describe('#pop()', function(){ 18 | it('should remove and return the last value', function(){ 19 | var arr = [1,2,3]; 20 | arr.pop().should.equal(3); 21 | arr.should.eql([1,2]); 22 | }) 23 | }) 24 | }) 25 | 26 | context('Array', function(){ 27 | beforeEach(function(){ 28 | this.arr = [1,2,3]; 29 | }) 30 | 31 | specify('has a length property', function(){ 32 | this.arr.length.should.equal(3); 33 | }) 34 | }) 35 | -------------------------------------------------------------------------------- /test/acceptance/interfaces/exports.js: -------------------------------------------------------------------------------- 1 | var calls = []; 2 | 3 | exports.Array = { 4 | before: function(){ 5 | calls.push('before'); 6 | }, 7 | 8 | after: function(){ 9 | calls.push('after'); 10 | calls.should.eql([ 11 | 'before' 12 | , 'before each' 13 | , 'one' 14 | , 'after each' 15 | , 'before each' 16 | , 'two' 17 | , 'after each' 18 | , 'after']); 19 | }, 20 | 21 | '#indexOf()': { 22 | beforeEach: function(){ 23 | calls.push('before each'); 24 | }, 25 | 26 | afterEach: function(){ 27 | calls.push('after each'); 28 | }, 29 | 30 | 'should return -1 when the value is not present': function(){ 31 | calls.push('one'); 32 | [1,2,3].indexOf(5).should.equal(-1); 33 | [1,2,3].indexOf(0).should.equal(-1); 34 | }, 35 | 36 | 'should return the correct index when the value is present': function(){ 37 | calls.push('two'); 38 | [1,2,3].indexOf(1).should.equal(0); 39 | [1,2,3].indexOf(2).should.equal(1); 40 | [1,2,3].indexOf(3).should.equal(2); 41 | } 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /test/acceptance/interfaces/qunit.js: -------------------------------------------------------------------------------- 1 | function ok(expr, msg) { 2 | if (!expr) throw new Error(msg); 3 | } 4 | 5 | suite('Array'); 6 | 7 | test('#length', function(){ 8 | var arr = [1,2,3]; 9 | ok(arr.length == 3); 10 | }); 11 | 12 | test('#indexOf()', function(){ 13 | var arr = [1,2,3]; 14 | ok(arr.indexOf(1) == 0); 15 | ok(arr.indexOf(2) == 1); 16 | ok(arr.indexOf(3) == 2); 17 | }); 18 | 19 | suite('String'); 20 | 21 | test('#length', function(){ 22 | ok('foo'.length == 3); 23 | }); 24 | -------------------------------------------------------------------------------- /test/acceptance/interfaces/tdd.js: -------------------------------------------------------------------------------- 1 | suite('Array', function(){ 2 | suite('#indexOf()', function(){ 3 | var initialValue = 32; 4 | 5 | suiteSetup(function(done){ 6 | initialValue.should.eql(32); 7 | initialValue = 42; 8 | done(); 9 | }); 10 | 11 | test('should return -1 when the value is not present', function(){ 12 | initialValue.should.eql(42); 13 | [1,2,3].indexOf(5).should.equal(-1); 14 | [1,2,3].indexOf(0).should.equal(-1); 15 | }); 16 | 17 | test('should return the correct index when the value is present', function(){ 18 | initialValue.should.eql(42); 19 | [1,2,3].indexOf(1).should.equal(0); 20 | [1,2,3].indexOf(2).should.equal(1); 21 | [1,2,3].indexOf(3).should.equal(2); 22 | }); 23 | 24 | test.skip('should skip this test', function(){ 25 | var zero = 0; 26 | zero.should.equal(1, 'this test should have been skipped'); 27 | }); 28 | 29 | suite.skip('should skip this suite', function(){ 30 | test('should skip this test', function(){ 31 | var zero = 0; 32 | zero.should.equal(1, 'this test should have been skipped'); 33 | }); 34 | }); 35 | 36 | suiteTeardown(function(done){ 37 | initialValue.should.eql(42); 38 | done(); 39 | }); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /test/acceptance/misc/exit.js: -------------------------------------------------------------------------------- 1 | describe('exit', function(){ 2 | //note --bail works nicely in that it still allows an 'early exit' in an error scenario 3 | it('should not exit even in error scenario if called with --no-exit', function(done){ 4 | done(new Error('failure')); 5 | }) 6 | 7 | it('should take a long time to exit if called with --no-exit', function(done){ 8 | done(); 9 | setTimeout(function() { 10 | console.log('all done'); 11 | }, 2500) 12 | }) 13 | 14 | it('should kill all processes when SIGINT received', function () { 15 | // uncomment to test 16 | //while (true) {} 17 | }); 18 | }) 19 | -------------------------------------------------------------------------------- /test/acceptance/misc/many.js: -------------------------------------------------------------------------------- 1 | // Useful for testing SIGINT handler 2 | // use env.big_number to tune iterations so that you have time to ctrl+c 3 | 4 | describe('a load of tests', function(){ 5 | it('should fail the first test', function(){ 6 | throw new Error('this should appear in the summary'); 7 | }) 8 | 9 | var iterations = (process.env.big_number || 1e7); 10 | function work() { 11 | var a = 0; 12 | for(var i=0; i 5 | it 'should work', -> 6 | obj.should.eql foo: 'bar' 7 | -------------------------------------------------------------------------------- /test/acceptance/test.foo: -------------------------------------------------------------------------------- 1 | 1 2 | -------------------------------------------------------------------------------- /test/acceptance/timeout.js: -------------------------------------------------------------------------------- 1 | describe('timeouts', function(){ 2 | beforeEach(function(done){ 3 | // uncomment 4 | // setTimeout(done, 3000); 5 | done(); 6 | }) 7 | 8 | it('should error on timeout', function(done){ 9 | // uncomment 10 | // setTimeout(done, 3000); 11 | done(); 12 | }) 13 | 14 | it('should allow overriding per-test', function(done){ 15 | this.timeout(1000); 16 | setTimeout(function(){ 17 | done(); 18 | }, 300); 19 | }) 20 | 21 | describe('disabling', function(){ 22 | it('should allow overriding per-test', function(done){ 23 | this.enableTimeouts(false); 24 | this.timeout(1); 25 | setTimeout(done, 2); 26 | }); 27 | 28 | it('should work with timeout(0)', function(done) { 29 | this.timeout(0); 30 | setTimeout(done, 1); 31 | }) 32 | 33 | describe('using beforeEach', function() { 34 | beforeEach(function () { 35 | this.timeout(0); 36 | }) 37 | 38 | it('should work with timeout(0)', function(done) { 39 | setTimeout(done, 1); 40 | }) 41 | }) 42 | 43 | describe('using before', function() { 44 | before(function () { 45 | this.timeout(0); 46 | }) 47 | 48 | it('should work with timeout(0)', function(done) { 49 | setTimeout(done, 1); 50 | }) 51 | }) 52 | 53 | describe('using enableTimeouts(false)', function() { 54 | this.timeout(4); 55 | 56 | it('should suppress timeout(4)', function(done) { 57 | // The test is in the before() call. 58 | this.enableTimeouts(false); 59 | setTimeout(done, 50); 60 | }) 61 | }) 62 | 63 | describe('suite-level', function() { 64 | this.timeout(0); 65 | 66 | it('should work with timeout(0)', function(done) { 67 | setTimeout(done, 1); 68 | }) 69 | 70 | describe('nested suite', function () { 71 | it('should work with timeout(0)', function(done) { 72 | setTimeout(done, 1); 73 | }) 74 | 75 | }) 76 | }) 77 | }); 78 | 79 | }) 80 | -------------------------------------------------------------------------------- /test/browser/array.js: -------------------------------------------------------------------------------- 1 | describe('Array', function(){ 2 | describe('#push()', function(){ 3 | it('should append a value', function(){ 4 | foo = 'asdf' 5 | var arr = []; 6 | arr.push('foo'); 7 | arr.push('bar'); 8 | arr.push('baz'); 9 | assert('foo' == arr[0]); // to test indentation 10 | assert('bar' == arr[1]); 11 | assert('baz' == arr[2]); 12 | }) 13 | 14 | it('should return the length', function(){ 15 | var arr = []; 16 | assert(1 == arr.push('foo')); 17 | assert(2 == arr.push('bar')); 18 | assert(3 == arr.push('baz')); 19 | }) 20 | }) 21 | }) 22 | 23 | describe('Array', function(){ 24 | describe('#pop()', function(){ 25 | it('should remove and return the last value', function(){ 26 | var arr = [1,2,3]; 27 | assert(arr.pop() == 3); 28 | assert(arr.pop() == 2); 29 | assert(arr.pop() == -1); 30 | }) 31 | 32 | it('should adjust .length', function(){ 33 | var arr = [1,2,3]; 34 | arr.pop(); 35 | assert(arr.length == 2); 36 | }) 37 | }) 38 | }) 39 | -------------------------------------------------------------------------------- /test/browser/grep.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Mocha 4 | 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 | 17 |
18 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /test/browser/grep.js: -------------------------------------------------------------------------------- 1 | // numbers 2 | describe('21', function() { 3 | it('1', function() { 4 | assert(true); 5 | }); 6 | it('2', function() { 7 | assert(true); 8 | }); 9 | }); 10 | // symbols 11 | describe('@Array', function() { 12 | it('.pop()', function() { 13 | assert(true); 14 | }); 15 | it('.push()', function() { 16 | assert(true); 17 | }); 18 | it('.length', function() { 19 | assert(true); 20 | }); 21 | }); 22 | 23 | describe('@Function', function() { 24 | it('.call()', function() { 25 | assert(true); 26 | }); 27 | it('.apply()', function() { 28 | assert(true); 29 | }); 30 | it('.length', function() { 31 | assert(true); 32 | }); 33 | it('.name', function() { 34 | assert(true); 35 | }); 36 | it('.prototype', function() { 37 | assert(true); 38 | }); 39 | }); 40 | 41 | //url with hashtags 42 | describe('#Services',function() { 43 | describe('#http', function() { 44 | it('.createClient()', function() { 45 | assert(true); 46 | }); 47 | it('.Server()', function() { 48 | assert(true); 49 | }); 50 | }); 51 | describe('#crypto', function() { 52 | it('.randomBytes()', function() { 53 | assert(true); 54 | }); 55 | it('.Hmac()', function() { 56 | assert(true); 57 | }); 58 | }); 59 | }); 60 | 61 | // Uppercase 62 | describe('CONSTANTS', function() { 63 | it('.STATUS_CODES', function() { 64 | assert(true); 65 | }); 66 | }); 67 | 68 | // Dates 69 | describe('Date:', function() { 70 | it('01/02/2015', function() { 71 | assert(true); 72 | }); 73 | it('01/03/2015', function() { 74 | assert(true); 75 | }); 76 | it('01/06/2015', function() { 77 | assert(true); 78 | }); 79 | }); 80 | 81 | // etc.. 82 | describe('booking/summary', function() { 83 | it('should be run last', function() { 84 | assert(true); 85 | }); 86 | }); 87 | 88 | describe('component/booking/summary', function() { 89 | it('should be run second', function() { 90 | assert(true); 91 | }); 92 | }); 93 | 94 | describe('component/booking/intro', function() { 95 | it('should be run first', function() { 96 | assert(true); 97 | }); 98 | }); 99 | 100 | describe('contains numbers', function() { 101 | it('should run if the number 92 matching', function() { 102 | assert(true); 103 | }); 104 | 105 | it('should run if the number 8 matching', function() { 106 | assert(true); 107 | }); 108 | }); -------------------------------------------------------------------------------- /test/browser/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Mocha 4 | 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 | 17 | 18 | 29 | 30 | 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /test/browser/large.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Mocha 4 | 5 | 6 | 7 | 8 | 9 | 14 | 15 | 20 | 21 | 22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /test/browser/large.js: -------------------------------------------------------------------------------- 1 | var n = 30; 2 | while (n--) { 3 | describe('Array ' + n, function(){ 4 | var arr; 5 | 6 | beforeEach(function(){ 7 | arr = [1,2,3]; 8 | }) 9 | 10 | describe('#indexOf()', function(){ 11 | it('should return -1 when the value is not present', function(){ 12 | assert(-1 == arr.indexOf(5)); 13 | }) 14 | 15 | it('should return the correct index when the value is present', function(done){ 16 | assert(0 == arr.indexOf(1)); 17 | assert(1 == arr.indexOf(2)); 18 | done(); 19 | }) 20 | }) 21 | }) 22 | } 23 | 24 | describe('something', function(){ 25 | it('should provide a useful error', function(done){ 26 | setTimeout(function(){ 27 | throw new Error('boom'); 28 | done(); 29 | }, 1); 30 | }) 31 | 32 | it('should provide an even better error on phantomjs', function(done){ 33 | setTimeout(function(){ 34 | var AssertionError = function(message, actual, expected) { 35 | this.message = message; 36 | this.actual = actual; 37 | this.expected = expected; 38 | this.showDiff = true; 39 | }; 40 | AssertionError.prototype = Object.create(Error.prototype); 41 | AssertionError.prototype.name = 'AssertionError'; 42 | AssertionError.prototype.constructor = AssertionError; 43 | 44 | mocha.throwError(new AssertionError('kabooom', 'text with a typo', 'text without a typo')); 45 | done(); 46 | }, 1); 47 | }) 48 | }) 49 | -------------------------------------------------------------------------------- /test/browser/multiple-done.js: -------------------------------------------------------------------------------- 1 | describe('Multiple Done calls', function(){ 2 | it('should report an error if done was called more than once', function(done){ 3 | done(); 4 | done(); 5 | }) 6 | 7 | it('should report an error if an exception happened async after done was called', function (done) { 8 | done(); 9 | setTimeout(done, 50); 10 | }) 11 | 12 | it('should report an error if an exception happened after done was called', function(done){ 13 | done(); 14 | throw new Error("thrown error"); 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /test/browser/opts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Mocha 4 | 5 | 6 | 7 | 8 | 14 | 19 | 20 | 21 | 26 | 27 | 28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /test/browser/opts.js: -------------------------------------------------------------------------------- 1 | describe('Options', function() { 2 | it('should set timeout value', function() { 3 | assert(this.test._timeout === 1500); 4 | }); 5 | }) 6 | -------------------------------------------------------------------------------- /test/browser/stack-trace.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Mocha 4 | 5 | 6 | 7 | 8 | 9 | 14 | 15 | 20 | 21 | 22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /test/browser/stack-trace.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | describe('Stack trace', function() { 3 | it('should prettify the stack-trace', function() { 4 | var err = new Error(); 5 | // We do this fake stack-trace because we under development, 6 | // and our root isn't `node_modules`, `bower` or `components` 7 | err.stack = ['Error: failed' 8 | , 'at assert (stack-trace.html:11:30)' 9 | , 'at Context. (stack-trace.js:5:5)' 10 | , 'at callFn (http://localhost:63342/node_modules/mocha.js:4546:21)' 11 | , 'at Test.require.register.Runnable.run (http://localhost:63342/node_modules/mocha.js:4539:7)' 12 | , 'at Runner.require.register.Runner.runTest (http://localhost:63342/node_modules/mocha.js:4958:10)' 13 | , 'at http://localhost:63342/bower_components/mocha.js:5041:12' 14 | , 'at next (http://localhost:63342/bower_components/mocha.js:4883:14)' 15 | , 'at http://localhost:63342/bower_components/mocha.js:4893:7' 16 | , 'at next (http://localhost:63342/bower_components/mocha.js:4828:23)' 17 | , 'at http://localhost:63342/bower_components/mocha.js:4860:5'].join('\n'); 18 | assert(false, err); 19 | }); 20 | }); -------------------------------------------------------------------------------- /test/browser/ui.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Mocha 4 | 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 | 17 |
18 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /test/browser/ui.js: -------------------------------------------------------------------------------- 1 | // test titles containing regex-conflicting characters 2 | 3 | // leading $ 4 | describe('$.jQuery', function() { 5 | // parens 6 | describe('.on()', function () { 7 | it('should set an event', function() { 8 | assert(true); 9 | }); 10 | }); 11 | 12 | describe('.off()', function () { 13 | it('should remove an event', function () { 14 | 15 | }); 16 | }); 17 | }); 18 | 19 | // another generic describe block to verify it is absent 20 | // when greeping on $.jQuery 21 | describe('@Array', function() { 22 | it('.pop()', function() { 23 | assert(true); 24 | }); 25 | it('.push()', function() { 26 | assert(true); 27 | }); 28 | it('.length', function() { 29 | assert(true); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/color.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var child_process = require('child_process'); 3 | 4 | describe('Mocha', function() { 5 | this.timeout(1000); 6 | 7 | it('should not output colors to pipe', function(cb) { 8 | var command = 'bin/mocha --grep missing-test'; 9 | child_process.exec(command, function(err, stdout, stderr) { 10 | if (err) return cb(err); 11 | 12 | assert(stdout.indexOf('[90m') === -1); 13 | 14 | cb(null); 15 | }); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/compiler/foo.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | require.extensions['.foo'] = function(module, filename) { 3 | var content; 4 | content = fs.readFileSync(filename, 'utf8'); 5 | var test = 'describe("custom compiler",function(){ it("should work",function() { ' 6 | + content + '.should.eql(1); }); });'; 7 | return module._compile(test, filename); 8 | }; 9 | -------------------------------------------------------------------------------- /test/grep.js: -------------------------------------------------------------------------------- 1 | var Mocha = require('../'); 2 | 3 | describe('Mocha', function(){ 4 | describe('"grep" option', function(){ 5 | it('should add a RegExp to the mocha.options object', function(){ 6 | var mocha = new Mocha({ grep: /foo.*/ }); 7 | mocha.options.grep.toString().should.equal('/foo.*/'); 8 | }) 9 | 10 | it('should convert string to a RegExp', function(){ 11 | var mocha = new Mocha({ grep: 'foo.*' }); 12 | mocha.options.grep.toString().should.equal('/foo.*/'); 13 | }) 14 | }) 15 | 16 | describe('"fgrep" option', function(){ 17 | it('should escape and convert string to a RegExp', function(){ 18 | var mocha = new Mocha({ fgrep: 'foo.*' }); 19 | mocha.options.grep.toString().should.equal('/foo\\.\\*/'); 20 | }) 21 | }) 22 | 23 | describe('.grep()', function(){ 24 | it('should add a RegExp to the mocha.options object', function(){ 25 | var mocha = new Mocha; 26 | mocha.grep(/foo/); 27 | mocha.options.grep.toString().should.equal('/foo/'); 28 | }) 29 | 30 | it('should convert grep string to a RegExp', function(){ 31 | var mocha = new Mocha; 32 | mocha.grep('foo'); 33 | mocha.options.grep.toString().should.equal('/foo/'); 34 | }) 35 | 36 | it('should return it\'s parent Mocha object for chainability', function(){ 37 | var mocha = new Mocha; 38 | mocha.grep().should.equal(mocha); 39 | }) 40 | }) 41 | 42 | describe('"invert" option', function(){ 43 | it('should add a Boolean to the mocha.options object', function(){ 44 | var mocha = new Mocha({ invert: true }); 45 | mocha.options.invert.should.be.ok(); 46 | }) 47 | }) 48 | }) 49 | -------------------------------------------------------------------------------- /test/hook.sync.js: -------------------------------------------------------------------------------- 1 | describe('serial', function(){ 2 | var calls = []; 3 | 4 | beforeEach(function(){ 5 | calls.push('parent before'); 6 | }) 7 | 8 | afterEach(function(){ 9 | calls.push('parent after'); 10 | }) 11 | 12 | describe('hooks', function(){ 13 | beforeEach(function(){ 14 | calls.push('before'); 15 | if (this.currentTest) { 16 | calls.push('before test ' + this.currentTest.title); 17 | } 18 | }) 19 | 20 | it('one', function(){ 21 | calls.should.eql([ 22 | 'parent before' 23 | , 'before' 24 | , 'before test one']); 25 | calls.push('one'); 26 | }) 27 | 28 | it('two', function(){ 29 | calls.should.eql([ 30 | 'parent before' 31 | , 'before' 32 | , 'before test one' 33 | , 'one' 34 | , 'after' 35 | , 'after test one passed' 36 | , 'parent after' 37 | , 'parent before' 38 | , 'before' 39 | , 'before test two']); 40 | calls.push('two'); 41 | }) 42 | 43 | it('three', function(){ 44 | calls.should.eql([ 45 | 'parent before' 46 | , 'before' 47 | , 'before test one' 48 | , 'one' 49 | , 'after' 50 | , 'after test one passed' 51 | , 'parent after' 52 | , 'parent before' 53 | , 'before' 54 | , 'before test two' 55 | , 'two' 56 | , 'after' 57 | , 'after test two passed' 58 | , 'parent after' 59 | , 'parent before' 60 | , 'before' 61 | , 'before test three']); 62 | calls.push('three'); 63 | }) 64 | 65 | afterEach(function(){ 66 | calls.push('after'); 67 | if (this.currentTest) { 68 | calls.push('after test ' + this.currentTest.title + ' ' + this.currentTest.state); 69 | } 70 | }) 71 | 72 | after(function(){ 73 | calls.should.eql([ 74 | 'parent before' 75 | , 'before' 76 | , 'before test one' 77 | , 'one' 78 | , 'after' 79 | , 'after test one passed' 80 | , 'parent after' 81 | , 'parent before' 82 | , 'before' 83 | , 'before test two' 84 | , 'two' 85 | , 'after' 86 | , 'after test two passed' 87 | , 'parent after' 88 | , 'parent before' 89 | , 'before' 90 | , 'before test three' 91 | , 'three' 92 | , 'after' 93 | , 'after test three passed' 94 | , 'parent after']); 95 | }) 96 | }) 97 | }) 98 | -------------------------------------------------------------------------------- /test/hook.sync.nested.js: -------------------------------------------------------------------------------- 1 | describe('serial', function(){ 2 | describe('nested', function(){ 3 | var calls = []; 4 | 5 | beforeEach(function(){ 6 | calls.push('parent before'); 7 | if (this.currentTest) { 8 | calls.push('parent before test ' + this.currentTest.title); 9 | } 10 | }) 11 | 12 | afterEach(function(){ 13 | calls.push('parent after'); 14 | if (this.currentTest) { 15 | calls.push('parent after test ' + this.currentTest.title + ' ' + this.currentTest.state); 16 | } 17 | }); 18 | 19 | it('foo', function(){ 20 | calls.should.eql([ 21 | 'parent before' 22 | , 'parent before test foo']); 23 | calls.push('foo'); 24 | }) 25 | 26 | it('bar', function(){ 27 | calls.should.eql([ 28 | 'parent before' 29 | , 'parent before test foo' 30 | , 'foo' 31 | , 'parent after' 32 | , 'parent after test foo passed' 33 | , 'parent before' 34 | , 'parent before test bar']); 35 | }) 36 | 37 | describe('hooks', function(){ 38 | beforeEach(function(){ 39 | calls.push('before'); 40 | if (this.currentTest) { 41 | calls.push('before test ' + this.currentTest.title); 42 | } 43 | }) 44 | 45 | it('one', function(){ 46 | calls.should.eql([ 47 | 'parent before' 48 | , 'parent before test foo' 49 | , 'foo' 50 | , 'parent after' 51 | , 'parent after test foo passed' 52 | , 'parent before' 53 | , 'parent before test bar' 54 | , 'parent after' 55 | , 'parent after test bar passed' 56 | , 'parent before' 57 | , 'parent before test one' 58 | , 'before' 59 | , 'before test one']); 60 | calls.push('one'); 61 | }) 62 | 63 | it('two', function(){ 64 | calls.should.eql([ 65 | 'parent before' 66 | , 'parent before test foo' 67 | , 'foo' 68 | , 'parent after' 69 | , 'parent after test foo passed' 70 | , 'parent before' 71 | , 'parent before test bar' 72 | , 'parent after' 73 | , 'parent after test bar passed' 74 | , 'parent before' 75 | , 'parent before test one' 76 | , 'before' 77 | , 'before test one' 78 | , 'one' 79 | , 'after' 80 | , 'after test one passed' 81 | , 'parent after' 82 | , 'parent after test one passed' 83 | , 'parent before' 84 | , 'parent before test two' 85 | , 'before' 86 | , 'before test two']); 87 | calls.push('two'); 88 | }); 89 | 90 | afterEach(function(){ 91 | calls.push('after'); 92 | if (this.currentTest) { 93 | calls.push('after test ' + this.currentTest.title + ' ' + this.currentTest.state); 94 | } 95 | }) 96 | }) 97 | }) 98 | }) 99 | -------------------------------------------------------------------------------- /test/hook.timeout.js: -------------------------------------------------------------------------------- 1 | before(function(done){ 2 | this.timeout(100); 3 | setTimeout(done, 50); 4 | }) 5 | 6 | it('should work', function(done) { 7 | done(); 8 | }); 9 | -------------------------------------------------------------------------------- /test/http.meta.2.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | 3 | var PORT = 8899; 4 | 5 | var server = http.createServer(function(req, res){ 6 | var accept = req.headers.accept || '' 7 | , json = ~accept.indexOf('json'); 8 | 9 | switch (req.url) { 10 | case '/': 11 | res.end('hello'); 12 | break; 13 | case '/users': 14 | if (json) { 15 | res.end('["tobi","loki","jane"]'); 16 | } else { 17 | res.end('tobi, loki, jane'); 18 | } 19 | break; 20 | } 21 | }) 22 | 23 | function get(url) { 24 | var fields 25 | , expected 26 | , header = {}; 27 | 28 | function request(done) { 29 | http.get({ path: url, port: PORT, headers: header }, function(res){ 30 | var buf = ''; 31 | res.should.have.property('statusCode', 200); 32 | res.setEncoding('utf8'); 33 | res.on('data', function(chunk){ buf += chunk }); 34 | res.on('end', function(){ 35 | buf.should.equal(expected); 36 | done(); 37 | }); 38 | }) 39 | } 40 | 41 | return { 42 | set: function(field, val){ 43 | header[field] = val; 44 | return this; 45 | }, 46 | 47 | should: { 48 | respond: function(body){ 49 | fields = Object.keys(header).map(function(field){ 50 | return field + ': ' + header[field]; 51 | }).join(', '); 52 | 53 | expected = body; 54 | describe('GET ' + url, function(){ 55 | this.timeout(500); 56 | if (fields) { 57 | describe('when given ' + fields, function(){ 58 | it('should respond with "' + body + '"', request); 59 | }); 60 | } else { 61 | it('should respond with "' + body + '"', request); 62 | } 63 | }); 64 | } 65 | } 66 | }; 67 | } 68 | 69 | describe('http server', function(){ 70 | 71 | before(function(done) { 72 | server.listen(PORT, done); 73 | }); 74 | 75 | after(function() { 76 | server.close(); 77 | }); 78 | 79 | get('/') 80 | .should 81 | .respond('hello') 82 | 83 | get('/users') 84 | .should 85 | .respond('tobi, loki, jane') 86 | 87 | get('/users') 88 | .set('Accept', 'application/json') 89 | .should 90 | .respond('["tobi","loki","jane"]') 91 | }) 92 | -------------------------------------------------------------------------------- /test/http.meta.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | 3 | var PORT = 8889; 4 | 5 | var server = http.createServer(function(req, res){ 6 | var accept = req.headers.accept || '' 7 | , json = ~accept.indexOf('json'); 8 | 9 | switch (req.url) { 10 | case '/': 11 | res.end('hello'); 12 | break; 13 | case '/users': 14 | if (json) { 15 | res.end('["tobi","loki","jane"]'); 16 | } else { 17 | res.end('tobi, loki, jane'); 18 | } 19 | break; 20 | } 21 | }); 22 | 23 | 24 | function get(url, body, header) { 25 | return function(done){ 26 | http.get({ path: url, port: PORT, headers: header || {}}, function(res){ 27 | var buf = ''; 28 | res.should.have.property('statusCode', 200); 29 | res.setEncoding('utf8'); 30 | res.on('data', function(chunk){ buf += chunk }); 31 | res.on('end', function(){ 32 | buf.should.equal(body); 33 | done(); 34 | }); 35 | }) 36 | } 37 | } 38 | 39 | describe('http requests', function () { 40 | 41 | before(function(done) { 42 | server.listen(PORT, done); 43 | }); 44 | 45 | after(function() { 46 | server.close(); 47 | }); 48 | 49 | describe('GET /', function () { 50 | it('should respond with hello', 51 | get('/', 'hello')) 52 | }) 53 | 54 | describe('GET /users', function(){ 55 | it('should respond with users', 56 | get('/users', 'tobi, loki, jane')) 57 | 58 | it('should respond with users', 59 | get('/users', '["tobi","loki","jane"]', { Accept: 'application/json' })) 60 | }) 61 | }) 62 | -------------------------------------------------------------------------------- /test/integration/diffs.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var helpers = require('./helpers'); 3 | var run = helpers.runMocha; 4 | var fs = require('fs'); 5 | var getDiffs = helpers.getDiffs; 6 | 7 | function getExpectedOutput() { 8 | var output = fs.readFileSync('test/integration/fixtures/diffs/output', 'UTF8'); 9 | 10 | // Diffs are delimited in file by "// DIFF" 11 | return output.split(/\s*\/\/ DIFF/).slice(1).map(function(diff) { 12 | return diff.split('\n').filter(Boolean).join('\n'); 13 | }); 14 | } 15 | 16 | describe('diffs', function() { 17 | var diffs, expected; 18 | this.timeout(1000); 19 | 20 | before(function(done) { 21 | run('diffs/diffs.js', ['-C'], function(err, res) { 22 | expected = getExpectedOutput(); 23 | diffs = getDiffs(res.output); 24 | done(err); 25 | }); 26 | }); 27 | 28 | [ 29 | 'should display a diff for small strings', 30 | 'should display a diff of canonicalized objects', 31 | 'should display a diff for medium strings', 32 | 'should display a diff for entire object dumps', 33 | 'should display a diff for multi-line strings', 34 | 'should display a diff for entire object dumps', 35 | 'should display a full-comparison with escaped special characters', 36 | 'should display a word diff for large strings', 37 | 'should work with objects', 38 | 'should show value diffs and not be affected by commas', 39 | 'should display diff by data and not like an objects' 40 | ].forEach(function(title, i) { 41 | it(title, function() { 42 | assert.equal(diffs[i], expected[i]); 43 | }); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /test/integration/fixtures/cascade.js: -------------------------------------------------------------------------------- 1 | describe('one', function() { 2 | before(function() { 3 | console.log('before one'); 4 | }); 5 | 6 | after(function() { 7 | console.log('after one'); 8 | }); 9 | 10 | beforeEach(function() { 11 | console.log(' before each one'); 12 | }); 13 | 14 | afterEach(function() { 15 | console.log(' after each one'); 16 | }); 17 | 18 | describe('two', function() { 19 | before(function() { 20 | console.log(' before two'); 21 | }); 22 | 23 | after(function() { 24 | console.log(' after two'); 25 | }); 26 | 27 | beforeEach(function() { 28 | console.log(' before each two'); 29 | }); 30 | 31 | afterEach(function() { 32 | console.log(' after each two'); 33 | }); 34 | 35 | describe('three', function() { 36 | before(function() { 37 | console.log(' before three'); 38 | }); 39 | 40 | after(function() { 41 | console.log(' after three'); 42 | }); 43 | 44 | beforeEach(function() { 45 | console.log(' before each three'); 46 | }); 47 | 48 | afterEach(function() { 49 | console.log(' after each three'); 50 | }); 51 | 52 | it('should three', function() { 53 | console.log(' TEST three'); 54 | }); 55 | }); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /test/integration/fixtures/diffs/diffs.css.in: -------------------------------------------------------------------------------- 1 | body { 2 | font: "Helvetica Neue", Helvetica, arial, sans-serif; 3 | background: black; 4 | color: white; 5 | } 6 | 7 | a { 8 | color: blue 9 | } 10 | -------------------------------------------------------------------------------- /test/integration/fixtures/diffs/diffs.css.out: -------------------------------------------------------------------------------- 1 | body { 2 | font: "Helvetica Neue", Helvetica, arial, sans-serif; 3 | background: black; 4 | color: #fff; 5 | } 6 | 7 | a { 8 | color: blue; 9 | } 10 | 11 | foo { 12 | bar: 'baz'; 13 | } 14 | -------------------------------------------------------------------------------- /test/integration/fixtures/diffs/diffs.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var assert = require('assert'); 3 | var cssin = fs.readFileSync('test/integration/fixtures/diffs/diffs.css.in', 'ascii'); 4 | var cssout = fs.readFileSync('test/integration/fixtures/diffs/diffs.css.out', 'ascii'); 5 | 6 | describe('diffs', function() { 7 | var actual, expected; 8 | 9 | it('should display a diff for small strings', function() { 10 | actual = 'foo rar baz'; 11 | expected = 'foo bar baz'; 12 | actual.should.equal(expected); 13 | }); 14 | 15 | it('should display a diff of canonicalized objects', function() { 16 | actual = { name: 'travis j', age: 23 }; 17 | expected = { age: 23, name: 'travis' }; 18 | actual.should.equal(expected); 19 | }); 20 | 21 | it('should display a diff for medium strings', function() { 22 | actual = 'foo bar baz\nfoo rar baz\nfoo bar raz'; 23 | expected = 'foo bar baz\nfoo bar baz\nfoo bar baz'; 24 | actual.should.equal(expected); 25 | }); 26 | 27 | it('should display a diff for entire object dumps', function() { 28 | actual = { name: 'joel', age: 30, address: {city: 'new york', country: 'usa' }}; 29 | expected = { name: 'joe', age: 30, address: {city: 'new york', country: 'us' }}; 30 | actual.should.equal(expected); 31 | }); 32 | 33 | it('should display a diff for multi-line strings', function() { 34 | actual = 'one two three\nfour zzzz six\nseven eight nine'; 35 | expected = 'one two three\nfour five six\nseven eight nine'; 36 | actual.should.equal(expected); 37 | }); 38 | 39 | it('should display a diff for entire object dumps', function() { 40 | actual = { name: 'joel', age: 30, address: {city: 'new york', country: 'usa' }}; 41 | expected = { name: 'joe', age: 30, address: {city: 'new york', country: 'us' }} 42 | actual.should.equal(expected); 43 | }); 44 | 45 | it('should display a full-comparison with escaped special characters', function() { 46 | actual = 'one\ttab\ntwo\t\t\ttabs'; 47 | expected = 'one\ttab\ntwo\t\ttabs'; 48 | actual.should.equal(expected); 49 | }); 50 | 51 | it('should display a word diff for large strings', function() { 52 | cssin.should.equal(cssout); 53 | }); 54 | 55 | it('should work with objects', function() { 56 | actual = { 57 | name: 'tobi', 58 | species: 'ferret', 59 | color: 'white', 60 | age: 2 61 | }; 62 | 63 | expected = { 64 | name: 'loki', 65 | species: 'ferret', 66 | color: 'brown', 67 | age: 2 68 | }; 69 | 70 | actual.should.eql(expected); 71 | }); 72 | 73 | it('should show value diffs and not be affected by commas', function() { 74 | actual = { a: 123 }; 75 | expected = { a: 123, b: 456 }; 76 | actual.should.equal(expected); 77 | }); 78 | 79 | it('should display diff by data and not like an objects', function() { 80 | actual = new Buffer([0x01]); 81 | expected = new Buffer([0x02]); 82 | actual.should.equal(expected); 83 | }); 84 | }); 85 | -------------------------------------------------------------------------------- /test/integration/fixtures/diffs/output: -------------------------------------------------------------------------------- 1 | // DIFF 2 | -foo rar baz 3 | +foo bar baz 4 | 5 | // DIFF 6 | { 7 | "age": 23 8 | - "name": "travis j" 9 | + "name": "travis" 10 | } 11 | 12 | // DIFF 13 | foo bar baz 14 | -foo rar baz 15 | -foo bar raz 16 | +foo bar baz 17 | +foo bar baz 18 | 19 | // DIFF 20 | { 21 | "address": { 22 | "city": "new york" 23 | - "country": "usa" 24 | + "country": "us" 25 | } 26 | "age": 30 27 | - "name": "joel" 28 | + "name": "joe" 29 | } 30 | 31 | // DIFF 32 | one two three 33 | -four zzzz six 34 | +four five six 35 | seven eight nine 36 | 37 | // DIFF 38 | { 39 | "address": { 40 | "city": "new york" 41 | - "country": "usa" 42 | + "country": "us" 43 | } 44 | "age": 30 45 | - "name": "joel" 46 | + "name": "joe" 47 | } 48 | 49 | // DIFF 50 | one tab 51 | -two tabs 52 | +two tabs 53 | 54 | // DIFF 55 | body { 56 | font: "Helvetica Neue", Helvetica, arial, sans-serif; 57 | background: black; 58 | - color: white; 59 | + color: #fff; 60 | } 61 | 62 | a { 63 | - color: blue 64 | + color: blue; 65 | } 66 | + 67 | +foo { 68 | + bar: 'baz'; 69 | +} 70 | 71 | // DIFF 72 | { 73 | "age": 2 74 | - "color": "white" 75 | - "name": "tobi" 76 | + "color": "brown" 77 | + "name": "loki" 78 | "species": "ferret" 79 | } 80 | 81 | // DIFF 82 | { 83 | "a": 123 84 | + "b": 456 85 | } 86 | 87 | // DIFF 88 | [ 89 | - 1 90 | + 2 91 | ] 92 | -------------------------------------------------------------------------------- /test/integration/fixtures/hooks/after.hook.async.error.js: -------------------------------------------------------------------------------- 1 | describe('spec 1', function () { 2 | after(function (done) { 3 | console.log('after'); 4 | process.nextTick(function () { 5 | throw new Error('after hook error'); 6 | }); 7 | }); 8 | it('should be called because error is in after hook', function () { 9 | console.log('test 1'); 10 | }); 11 | it('should be called because error is in after hook', function () { 12 | console.log('test 2'); 13 | }); 14 | }); 15 | describe('spec 2', function () { 16 | it('should be called, because hook error was in a sibling suite', function () { 17 | console.log('test 3'); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/integration/fixtures/hooks/after.hook.error.js: -------------------------------------------------------------------------------- 1 | describe('spec 1', function () { 2 | after(function () { 3 | console.log('after'); 4 | throw new Error('after hook error'); 5 | }); 6 | it('should be called because error is in after hook', function () { 7 | console.log('test 1'); 8 | }); 9 | it('should be called because error is in after hook', function () { 10 | console.log('test 2'); 11 | }); 12 | }); 13 | describe('spec 2', function () { 14 | it('should be called, because hook error was in a sibling suite', function () { 15 | console.log('test 3'); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/integration/fixtures/hooks/afterEach.hook.async.error.js: -------------------------------------------------------------------------------- 1 | describe('spec 1', function () { 2 | afterEach(function (done) { 3 | console.log('after'); 4 | process.nextTick(function () { 5 | throw new Error('after each hook error'); 6 | }); 7 | }); 8 | it('should be called because error is in after each hook', function () { 9 | console.log('test 1'); 10 | }); 11 | it('should not be called', function () { 12 | console.log('test 2'); 13 | }); 14 | }); 15 | describe('spec 2', function () { 16 | it('should be called, because hook error was in a sibling suite', function () { 17 | console.log('test 3'); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/integration/fixtures/hooks/afterEach.hook.error.js: -------------------------------------------------------------------------------- 1 | describe('spec 1', function () { 2 | afterEach(function () { 3 | console.log('after'); 4 | throw new Error('after each hook error'); 5 | }); 6 | it('should be called because error is in after each hook', function () { 7 | console.log('test 1'); 8 | }); 9 | it('should not be called', function () { 10 | console.log('test 2'); 11 | }); 12 | }); 13 | describe('spec 2', function () { 14 | it('should be called, because hook error was in a sibling suite', function () { 15 | console.log('test 3'); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/integration/fixtures/hooks/before.hook.async.error.js: -------------------------------------------------------------------------------- 1 | describe('spec 1', function () { 2 | before(function (done) { 3 | console.log('before'); 4 | process.nextTick(function () { 5 | throw new Error('before hook error'); 6 | }); 7 | }); 8 | it('should not be called because of error in before hook', function () { 9 | console.log('test 1'); 10 | }); 11 | it('should not be called because of error in before hook', function () { 12 | console.log('test 2'); 13 | }); 14 | }); 15 | describe('spec 2', function () { 16 | it('should be called, because hook error was in a sibling suite', function () { 17 | console.log('test 3'); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/integration/fixtures/hooks/before.hook.async.error.tip.js: -------------------------------------------------------------------------------- 1 | describe('spec 1', function() { 2 | it('should not blame me', function() { }); 3 | }); 4 | describe('spec 2', function() { 5 | before(function(done) { 6 | process.nextTick(function () { 7 | throw new Error('before hook error'); 8 | }); 9 | }); 10 | it('skipped'); 11 | }); 12 | -------------------------------------------------------------------------------- /test/integration/fixtures/hooks/before.hook.error.js: -------------------------------------------------------------------------------- 1 | describe('spec 1', function () { 2 | before(function () { 3 | console.log('before'); 4 | throw new Error('before hook error'); 5 | }); 6 | it('should not be called because of error in before hook', function () { 7 | console.log('test 1'); 8 | }); 9 | it('should not be called because of error in before hook', function () { 10 | console.log('test 2'); 11 | }); 12 | }); 13 | describe('spec 2', function () { 14 | it('should be called, because hook error was in a sibling suite', function () { 15 | console.log('test 3'); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/integration/fixtures/hooks/before.hook.error.tip.js: -------------------------------------------------------------------------------- 1 | describe('spec 1', function() { 2 | it('should not blame me', function() { }); 3 | }); 4 | describe('spec 2', function() { 5 | before(function() { 6 | throw new Error('before hook error'); 7 | }); 8 | it('skipped'); 9 | }); 10 | -------------------------------------------------------------------------------- /test/integration/fixtures/hooks/beforeEach.hook.async.error.js: -------------------------------------------------------------------------------- 1 | describe('spec 1', function () { 2 | beforeEach(function (done) { 3 | console.log('before'); 4 | process.nextTick(function () { 5 | throw new Error('before each hook error'); 6 | }); 7 | }); 8 | it('should not be called because of error in before each hook', function () { 9 | console.log('test 1'); 10 | }); 11 | it('should not be called because of error in before each hook', function () { 12 | console.log('test 2'); 13 | }); 14 | }); 15 | describe('spec 2', function () { 16 | it('should be called, because hook error was in a sibling suite', function () { 17 | console.log('test 3'); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/integration/fixtures/hooks/beforeEach.hook.error.js: -------------------------------------------------------------------------------- 1 | describe('spec 1', function () { 2 | beforeEach(function () { 3 | console.log('before'); 4 | throw new Error('before each hook error'); 5 | }); 6 | it('should not be called because of error in before each hook', function () { 7 | console.log('test 1'); 8 | }); 9 | it('should not be called because of error in before each hook', function () { 10 | console.log('test 2'); 11 | }); 12 | }); 13 | describe('spec 2', function () { 14 | it('should be called, because hook error was in a sibling suite', function () { 15 | console.log('test 3'); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/integration/fixtures/multiple.done.before.js: -------------------------------------------------------------------------------- 1 | describe('suite', function() { 2 | before(function(done) { 3 | setTimeout(done, 10); 4 | setTimeout(done, 30); 5 | }); 6 | 7 | it('test1', function(done) { 8 | setTimeout(done, 50); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/integration/fixtures/multiple.done.beforeEach.js: -------------------------------------------------------------------------------- 1 | describe('suite', function() { 2 | beforeEach(function(done) { 3 | setTimeout(done, 10); 4 | setTimeout(done, 20); 5 | }); 6 | 7 | it('test1', function(done) { 8 | setTimeout(done, 50); 9 | }); 10 | 11 | it('test2', function(done) { 12 | setTimeout(done, 50); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/integration/fixtures/multiple.done.js: -------------------------------------------------------------------------------- 1 | // The suite below should result in an additional error, but does 2 | // not. Uncomment once this bug is resolved. 3 | 4 | // describe('suite', function() { 5 | // beforeEach(function(done) { 6 | // done(); 7 | // done(); 8 | // }); 9 | 10 | // it('test', function() {}); 11 | // }); 12 | 13 | it('should fail in a test-case', function(done) { 14 | process.nextTick(function(){ 15 | done(); 16 | done(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /test/integration/fixtures/multiple.done.specs.js: -------------------------------------------------------------------------------- 1 | describe('suite', function() { 2 | it('test1', function(done) { 3 | done(); 4 | setTimeout(done, 10); 5 | }); 6 | 7 | it('test2', function(done) { 8 | setTimeout(done, 20); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/integration/fixtures/options/async-only.async.js: -------------------------------------------------------------------------------- 1 | it('should pass', function(done){ 2 | done(); 3 | }); 4 | -------------------------------------------------------------------------------- /test/integration/fixtures/options/async-only.sync.js: -------------------------------------------------------------------------------- 1 | it('throws an error', function() {}); 2 | -------------------------------------------------------------------------------- /test/integration/fixtures/options/bail.js: -------------------------------------------------------------------------------- 1 | describe('suite1', function() { 2 | it('should display this spec', function() {}); 3 | 4 | it('should only display this error', function(done) { 5 | throw new Error('this should be displayed'); 6 | }); 7 | 8 | it('should not display this error', function(done) { 9 | throw new Error('this should not be displayed'); 10 | }); 11 | }); 12 | 13 | describe('suite2', function() { 14 | before(function(done) { 15 | throw new Error('this hook should not be displayed'); 16 | }); 17 | 18 | it('should not display this error', function(done) { 19 | throw new Error('this should not be displayed'); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/integration/fixtures/options/delay-fail.js: -------------------------------------------------------------------------------- 1 | setTimeout(function() { 2 | throw new Error('oops'); 3 | it('test', function() {}); 4 | run(); 5 | }, 100); 6 | -------------------------------------------------------------------------------- /test/integration/fixtures/options/delay.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var delay = 500; 3 | var start = new Date().getTime(); 4 | 5 | setTimeout(function() { 6 | describe('delayed execution', function() { 7 | it('should have waited ' + delay + 'ms to run this suite', function() { 8 | assert(new Date().getTime() - delay >= start); 9 | }); 10 | 11 | it('should have no effect if attempted twice in the same suite', function() { 12 | assert(true); 13 | run(); 14 | assert(true); 15 | }); 16 | }); 17 | 18 | run(); 19 | }, delay); 20 | -------------------------------------------------------------------------------- /test/integration/fixtures/options/grep.js: -------------------------------------------------------------------------------- 1 | describe('grep', function() { 2 | describe('match', function() { 3 | it('should run', function(){}); 4 | it('should also run', function() {}); 5 | }); 6 | 7 | describe('fail', function(){ 8 | it('should not be ran', function() { 9 | throw new Error('Spec should not run'); 10 | }); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test/integration/fixtures/options/retries.js: -------------------------------------------------------------------------------- 1 | describe('retries', function() { 2 | it('should fail', function () { 3 | throw new Error('retry failure'); 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /test/integration/fixtures/options/sort.alpha.js: -------------------------------------------------------------------------------- 1 | describe('alpha', function(){ 2 | it('should be executed first', function(){ 3 | if (global.beta) { 4 | throw new Error('alpha was not executed first'); 5 | } 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /test/integration/fixtures/options/sort.beta.js: -------------------------------------------------------------------------------- 1 | describe('beta', function(){ 2 | it('should be executed second', function(){ 3 | global.beta = 1; 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /test/integration/fixtures/passing.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | 3 | describe('suite', function() { 4 | it('test1', function() { 5 | assert(true); 6 | }); 7 | 8 | it('test2', function() { 9 | assert(true); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /test/integration/fixtures/pending/skip.sync.before.js: -------------------------------------------------------------------------------- 1 | describe('skip in before', function() { 2 | before(function() { 3 | this.skip(); 4 | }); 5 | 6 | it('should never run this test', function() { 7 | throw new Error('never thrown'); 8 | }); 9 | 10 | it('should never run this test', function() { 11 | throw new Error('never thrown'); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /test/integration/fixtures/pending/skip.sync.beforeEach.js: -------------------------------------------------------------------------------- 1 | describe('skip in beforeEach', function() { 2 | beforeEach(function() { 3 | this.skip(); 4 | }); 5 | 6 | it('should never run this test', function() { 7 | throw new Error('never thrown'); 8 | }); 9 | 10 | it('should never run this test', function() { 11 | throw new Error('never thrown'); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /test/integration/fixtures/pending/skip.sync.spec.js: -------------------------------------------------------------------------------- 1 | describe('skip in test', function() { 2 | it('should skip immediately', function() { 3 | this.skip(); 4 | throw new Error('never thrown'); 5 | }); 6 | 7 | it('should run other tests in the suite', function() { 8 | // Do nothing 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/integration/fixtures/pending/spec.js: -------------------------------------------------------------------------------- 1 | describe('suite', function() { 2 | it('pending spec'); 3 | }); 4 | -------------------------------------------------------------------------------- /test/integration/fixtures/regression/1794/issue-1794.js: -------------------------------------------------------------------------------- 1 | test('pass', function() { 2 | // pass 3 | }); 4 | -------------------------------------------------------------------------------- /test/integration/fixtures/regression/1794/simple-ui.js: -------------------------------------------------------------------------------- 1 | var path = '../../../../../lib/', 2 | Mocha = require(path + 'mocha'); 3 | Suite = require(path + 'suite'), 4 | Test = require(path + 'test'); 5 | 6 | /** 7 | * A simple UI that only exposes a single function: test 8 | */ 9 | module.exports = Mocha.interfaces['simple-ui'] = function(suite) { 10 | suite.on('pre-require', function(context, file, mocha) { 11 | var common = require(path + 'interfaces/common')([suite], context); 12 | 13 | context.run = mocha.options.delay && common.runWithSuite(suite); 14 | 15 | /** 16 | * Describes a specification or test-case with the given `title` 17 | * and callback `fn` acting as a thunk. 18 | */ 19 | context.test = function(title, fn) { 20 | var test = new Test(title, fn); 21 | test.file = file; 22 | suite.addTest(test); 23 | 24 | return test; 25 | }; 26 | }); 27 | }; 28 | -------------------------------------------------------------------------------- /test/integration/fixtures/regression/issue-1327.js: -------------------------------------------------------------------------------- 1 | it('test 1', function() { 2 | console.log('testbody1'); 3 | process.nextTick(function() { 4 | throw 'Too bad'; 5 | }); 6 | }); 7 | 8 | it('test 2', function() { 9 | console.log('testbody2'); 10 | }); 11 | 12 | it('test 3', function() { 13 | console.log('testbody3'); 14 | throw new Error('OUCH'); 15 | }); 16 | -------------------------------------------------------------------------------- /test/integration/fixtures/regression/issue-1991.js: -------------------------------------------------------------------------------- 1 | function MemoryLeak() { 2 | this.myArr = []; 3 | for (var i = 0; i < 1000000; i++) { 4 | this.myArr.push(i) 5 | } 6 | } 7 | 8 | var numOfTests = 300; 9 | for (var i = 0; i < numOfTests; i += 1) { 10 | /* 11 | * This Test suite will crash V8 due to: 12 | * 'FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory' 13 | * if all the deferred functions references have not been cleared 14 | */ 15 | describe('Memory Leak Suite #' + i, function () { 16 | 17 | // The variable will be accessed by the test below. 18 | // As long as those test's functions are 19 | // referenced in memory, the closure variable may not be garbage collected 20 | // as it is still referenced. 21 | // * In a chrome heap snapshot it will appear under "system / Context" (a scope) 22 | var closureVar; 23 | 24 | before(function () { 25 | var x = closureVar ? 1 : 2 26 | }); 27 | 28 | after(function () { 29 | var x = closureVar[0] 30 | }); 31 | 32 | beforeEach(function () { 33 | var x = closureVar ? 1 : 2 34 | }); 35 | 36 | afterEach(function () { 37 | var x = closureVar[0] 38 | }); 39 | 40 | it('access a variable via a closure', function () { 41 | // slow performance on older node.js versions 42 | this.timeout(1000); 43 | closureVar = new MemoryLeak(); 44 | }); 45 | 46 | }); 47 | } 48 | -------------------------------------------------------------------------------- /test/integration/fixtures/retries/async.js: -------------------------------------------------------------------------------- 1 | describe('retries', function() { 2 | var times = 0; 3 | before(function () { 4 | console.log('before'); 5 | }); 6 | 7 | after(function () { 8 | console.log('after'); 9 | }); 10 | 11 | beforeEach(function() { 12 | console.log('before each', times); 13 | }); 14 | 15 | afterEach(function () { 16 | console.log('after each', times); 17 | }); 18 | 19 | it('should allow override and run appropriate hooks', function (done) { 20 | this.timeout(200); 21 | this.retries(2); 22 | console.log('TEST', times); 23 | if (++times < 3) { 24 | return setTimeout(done, 300); 25 | } 26 | setTimeout(done, 50); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/integration/fixtures/retries/early-pass.js: -------------------------------------------------------------------------------- 1 | describe('retries', function() { 2 | this.retries(1); 3 | var times = 0; 4 | 5 | it('should pass after 1 retry', function() { 6 | times++; 7 | if (times !== 2) { 8 | throw new Error('retry error ' + times); 9 | } 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /test/integration/fixtures/retries/hooks.js: -------------------------------------------------------------------------------- 1 | describe('retries', function() { 2 | var times = 0; 3 | before(function () { 4 | console.log('before'); 5 | }); 6 | 7 | after(function () { 8 | console.log('after'); 9 | }); 10 | 11 | beforeEach(function() { 12 | console.log('before each', times); 13 | }); 14 | 15 | afterEach(function () { 16 | console.log('after each', times); 17 | }); 18 | 19 | it('should allow override and run appropriate hooks', function(){ 20 | this.retries(4); 21 | console.log('TEST', times); 22 | times++; 23 | throw new Error('retry error'); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /test/integration/fixtures/retries/nested.js: -------------------------------------------------------------------------------- 1 | describe('retries', function() { 2 | this.retries(3); 3 | describe('nested', function () { 4 | it('should fail after only 1 retry', function(){ 5 | this.retries(1); 6 | throw new Error('retry error'); 7 | }); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /test/integration/fixtures/timeout.js: -------------------------------------------------------------------------------- 1 | describe('timeout', function(){ 2 | this.timeout(1); 3 | 4 | it('should be honored with sync suites', function() { 5 | sleep(2); 6 | }); 7 | 8 | it('should be honored with async suites', function(done) { 9 | sleep(2); 10 | done(); 11 | }); 12 | 13 | function sleep(ms) { 14 | var start = Date.now(); 15 | while (start + ms > Date.now()); 16 | } 17 | }); 18 | -------------------------------------------------------------------------------- /test/integration/fixtures/uncaught.hook.js: -------------------------------------------------------------------------------- 1 | describe('uncaught', function() { 2 | beforeEach(function(done) { 3 | process.nextTick(function() { 4 | throw new Error('oh noes'); 5 | done(); 6 | }); 7 | }); 8 | 9 | it('test', function(done) { 10 | process.nextTick(function() { 11 | throw new Error("I'm uncaught!"); 12 | done(); 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/integration/fixtures/uncaught.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * This file should only generate one failure per spec despite the fact that 5 | * Mocha is capable of detecting two distinct exceptions during test execution. 6 | */ 7 | 8 | it('fails exactly once when a global error is thrown first', function(done) { 9 | setTimeout(function() { 10 | throw new Error('global error'); 11 | 12 | setTimeout(function() { 13 | done(new Error('test error')); 14 | }, 0); 15 | }, 0); 16 | }); 17 | 18 | it('fails exactly once when a global error is thrown second', function(done) { 19 | setTimeout(function() { 20 | done(new Error('test error')); 21 | }, 0); 22 | 23 | setTimeout(function() { 24 | throw new Error('global error'); 25 | }, 0); 26 | }); 27 | -------------------------------------------------------------------------------- /test/integration/hooks.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var run = require('./helpers').runMocha; 3 | var args = []; 4 | 5 | describe('hooks', function() { 6 | this.timeout(1000); 7 | 8 | it('are ran in correct order', function(done) { 9 | run('cascade.js', args, function(err, res) { 10 | var lines, expected; 11 | 12 | assert(!err); 13 | 14 | lines = res.output.split(/[\n․]+/).map(function(line) { 15 | return line.trim(); 16 | }).filter(function(line) { 17 | return line.length; 18 | }).slice(0, -1); 19 | 20 | expected = [ 21 | 'before one', 22 | 'before two', 23 | 'before three', 24 | 'before each one', 25 | 'before each two', 26 | 'before each three', 27 | 'TEST three', 28 | 'after each three', 29 | 'after each two', 30 | 'after each one', 31 | 'after three', 32 | 'after two', 33 | 'after one' 34 | ]; 35 | 36 | expected.forEach(function(line, i) { 37 | assert.equal(lines[i], line); 38 | }); 39 | 40 | assert.equal(res.code, 0); 41 | done(); 42 | }); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /test/integration/pending.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var run = require('./helpers').runMochaJSON; 3 | var args = []; 4 | 5 | describe('pending', function() { 6 | describe('pending specs', function() { 7 | this.timeout(1000); 8 | 9 | it('should be created by omitting a function', function(done) { 10 | run('pending/spec.js', args, function(err, res) { 11 | assert(!err); 12 | assert.equal(res.stats.pending, 1); 13 | assert.equal(res.stats.passes, 0); 14 | assert.equal(res.stats.failures, 0); 15 | assert.equal(res.code, 0); 16 | done(); 17 | }); 18 | }); 19 | }); 20 | 21 | describe('synchronous skip()', function() { 22 | this.timeout(1000); 23 | 24 | describe('in spec', function() { 25 | it('should immediately skip the spec and run all others', function(done) { 26 | run('pending/skip.sync.spec.js', args, function(err, res) { 27 | assert(!err); 28 | assert.equal(res.stats.pending, 1); 29 | assert.equal(res.stats.passes, 1); 30 | assert.equal(res.stats.failures, 0); 31 | assert.equal(res.code, 0); 32 | done(); 33 | }); 34 | }); 35 | }); 36 | 37 | describe('in before', function() { 38 | it('should skip all suite specs', function(done) { 39 | run('pending/skip.sync.before.js', args, function(err, res) { 40 | assert(!err); 41 | assert.equal(res.stats.pending, 2); 42 | assert.equal(res.stats.passes, 0); 43 | assert.equal(res.stats.failures, 0); 44 | assert.equal(res.code, 0); 45 | done(); 46 | }); 47 | }); 48 | }); 49 | 50 | describe('in beforeEach', function() { 51 | it('should skip all suite specs', function(done) { 52 | run('pending/skip.sync.beforeEach.js', args, function(err, res) { 53 | assert(!err); 54 | assert.equal(res.stats.pending, 2); 55 | assert.equal(res.stats.passes, 0); 56 | assert.equal(res.stats.failures, 0); 57 | assert.equal(res.code, 0); 58 | done(); 59 | }); 60 | }); 61 | }); 62 | }); 63 | }); 64 | -------------------------------------------------------------------------------- /test/integration/regression.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var fs = require('fs'); 3 | var path = require('path'); 4 | var run = require('./helpers').runMocha; 5 | 6 | describe('regressions', function() { 7 | this.timeout(1000); 8 | 9 | it('issue-1327: should run all 3 specs exactly once', function(done) { 10 | var args = []; 11 | run('regression/issue-1327.js', args, function(err, res) { 12 | var occurences = function(str) { 13 | var pattern = new RegExp(str, 'g'); 14 | return (res.output.match(pattern) || []).length; 15 | }; 16 | 17 | assert(!err); 18 | assert.equal(occurences('testbody1'), 1); 19 | assert.equal(occurences('testbody2'), 1); 20 | assert.equal(occurences('testbody3'), 1); 21 | 22 | assert.equal(res.code, 1); 23 | done(); 24 | }); 25 | }); 26 | 27 | it('should not duplicate mocha.opts args in process.argv', function() { 28 | var processArgv = process.argv.join(''); 29 | var mochaOpts = fs.readFileSync(path.join(__dirname, '..', 'mocha.opts'), 'utf-8').split(/[\s]+/).join(''); 30 | assert.notEqual(processArgv.indexOf(mochaOpts), -1, 'process.argv missing mocha.opts'); 31 | assert.equal(processArgv.indexOf(mochaOpts), processArgv.lastIndexOf(mochaOpts), 'process.argv contains duplicated mocha.opts'); 32 | }); 33 | 34 | it('issue-1794: Can\'t --require custom UI and use it', function(done) { 35 | var simpleUiPath = path.join(__dirname, 'fixtures', 'regression', '1794', 'simple-ui.js'); 36 | var args = ['--require', simpleUiPath, '--ui', 'simple-ui']; 37 | run('regression/1794/issue-1794.js', args, function(err, res) { 38 | assert.equal(res.code, 0, 'Custom UI should be loaded'); 39 | done(); 40 | }); 41 | }); 42 | 43 | it('issue-1991: Declarations do not get cleaned up unless you set them to `null` - Memory Leak', function(done) { 44 | // on a modern MBP takes ±5 seconds on node 4.0, but on older laptops with node 0.12 ±40 seconds. 45 | // Could easily take longer on even weaker machines (Travis-CI containers for example). 46 | this.timeout(120000); 47 | run('regression/issue-1991.js', [], function(err, res) { 48 | assert.equal(/process out of memory/.test(res.output), false, 'fixture\'s process out of memory!'); 49 | assert.equal(res.code, 0, 'Runnable fn (it/before[Each]/after[Each]) references should be deleted to avoid memory leaks'); 50 | done(); 51 | }); 52 | }) 53 | }); 54 | -------------------------------------------------------------------------------- /test/integration/reporters.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var os = require('os'); 3 | var fs = require('fs'); 4 | var crypto = require('crypto'); 5 | var path = require('path'); 6 | var run = require('./helpers').runMocha; 7 | 8 | describe('reporters', function() { 9 | this.timeout(3000); 10 | 11 | describe('markdown', function() { 12 | var res; 13 | 14 | before(function(done) { 15 | run('passing.js', ['--reporter', 'markdown'], function(err, result) { 16 | res = result; 17 | done(err); 18 | }); 19 | }); 20 | 21 | it('does not exceed maximum callstack (issue: 1875)', function() { 22 | assert(res.output.indexOf('RangeError') === -1, 'Threw RangeError'); 23 | }); 24 | 25 | it('contains spec src', function() { 26 | var src = [ 27 | '```js', 28 | 'assert(true);', 29 | '```' 30 | ].join('\n'); 31 | 32 | assert(res.output.indexOf(src) !== -1, 'No assert found'); 33 | }); 34 | }); 35 | 36 | describe('xunit', function() { 37 | it('prints test cases with --reporter-options output (issue: 1864)', function(done) { 38 | var randomStr = crypto.randomBytes(8).toString('hex'); 39 | var tmpDir = os.tmpDir().replace(new RegExp(path.sep + '$'), ''); 40 | var tmpFile = tmpDir + path.sep + 'test-issue-1864-' + randomStr + '.xml'; 41 | 42 | var args = ['--reporter=xunit', '--reporter-options', 'output=' + tmpFile]; 43 | var expectedOutput = [ 44 | '