Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into issue/2755
Browse files Browse the repository at this point in the history
  • Loading branch information
juergba committed Jan 3, 2019
2 parents 6ec6c83 + 1f325e7 commit 82faa1b
Show file tree
Hide file tree
Showing 44 changed files with 2,608 additions and 1,412 deletions.
1 change: 1 addition & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ overrides:
- bin/*
- lib/cli/**/*.js
- test/node-unit/**/*.js
- lib/growl.js
parserOptions:
ecmaVersion: 6
env:
Expand Down
6 changes: 3 additions & 3 deletions .wallaby.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ module.exports = () => {
},
'package.json',
'test/opts/mocha.opts',
'mocharc.yml'
'mocharc.yml',
'!lib/browser/**/*.js',
],
filesWithNoCoverageCalculated: [
'test/**/*.fixture.js',
Expand Down Expand Up @@ -52,7 +53,6 @@ module.exports = () => {
return execFile.apply(this, arguments);
};
require('./test/setup');
},
debug: true
}
};
};
1,633 changes: 633 additions & 1,000 deletions CHANGELOG.md

Large diffs are not rendered by default.

Binary file added assets/mocha-logo-96.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
116 changes: 105 additions & 11 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Mocha is a feature-rich JavaScript test framework running on [Node.js](https://n
- [async test timeout support](#delayed-root-suite)
- [test retry support](#retry-tests)
- [test-specific timeouts](#test-level)
- [growl notification support](#mochaopts)
- [Growl support](#desktop-notification-support)
- [reports test durations](#test-duration)
- [highlights slow tests](#dot-matrix)
- [file watcher support](#min)
Expand Down Expand Up @@ -70,9 +70,11 @@ Mocha is a feature-rich JavaScript test framework running on [Node.js](https://n
- [Interfaces](#interfaces)
- [Reporters](#reporters)
- [Running Mocha in the Browser](#running-mocha-in-the-browser)
- [Desktop Notification Support](#desktop-notification-support)
- [Configuring Mocha (Node.js)](#configuring-mocha-nodejs)
- [`mocha.opts`](#mochaopts)
- [The `test/` Directory](#the-test-directory)
- [Error Codes](#error-codes)
- [Editor Plugins](#editor-plugins)
- [Examples](#examples)
- [Testing Mocha](#testing-mocha)
Expand Down Expand Up @@ -748,7 +750,7 @@ To tweak what's considered "slow", you can use the `slow()` method:

```js
describe('something slow', function() {
this.slow(10000);
this.slow(300000); // five minutes

it('should take long enough for me to go make a sandwich', function() {
// ...
Expand Down Expand Up @@ -1487,20 +1489,22 @@ A typical setup might look something like the following, where we call `mocha.se
<head>
<meta charset="utf-8">
<title>Mocha Tests</title>
<link href="https://unpkg.com/mocha@5.2.0/mocha.css" rel="stylesheet" />
<link rel="stylesheet" href="https://unpkg.com/mocha/mocha.css" />
</head>
<body>
<div id="mocha"></div>

<script src="https://unpkg.com/chai/chai.js"></script>
<script src="https://unpkg.com/mocha@5.2.0/mocha.js"></script>
<script src="https://unpkg.com/mocha/mocha.js"></script>

<script>mocha.setup('bdd')</script>
<script class="mocha-init">
mocha.setup('bdd');
mocha.checkLeaks();
</script>
<script src="test.array.js"></script>
<script src="test.object.js"></script>
<script src="test.xhr.js"></script>
<script>
mocha.checkLeaks();
<script class="mocha-exec">
mocha.run();
</script>
</body>
Expand Down Expand Up @@ -1547,6 +1551,69 @@ The "HTML" reporter is what you see when running Mocha in the browser. It looks

[Mochawesome](https://www.npmjs.com/package/mochawesome) is a great alternative to the default HTML reporter.

## Desktop Notification Support

Desktop notifications allow asynchronous communication of events without
forcing you to react to a notification immediately. Their appearance
and specific functionality vary across platforms. They typically disappear
automatically after a short delay, but their content is often stored in some
manner that allows you to access past notifications.

[Growl][] was an early notification system implementation for OS X and Windows,
hence, the name of Mocha's `--growl` option.

Once enabled, when your root suite completes test execution, a desktop
notification should appear informing you whether your tests passed or failed.

### Node-based notifications

In order to use desktop notifications with the command-line interface (CLI),
you **must** first install some platform-specific prerequisite software.
Instructions for doing so can be found [here][Growl-install].

Enable Mocha's desktop notifications as follows:

```sh
$ mocha --growl
```

### Browser-based notifications

Web notification support is being made available for current versions of
modern browsers. Ensure your browser version supports both
[promises](https://caniuse.com/#feat=promises) and
[web notifications](https://caniuse.com/#feat=notifications). As the
Notification API evolved over time, **do not expect** the minimum possible
browser version to necessarily work.

Enable Mocha's web notifications with a slight modification to your
client-side mocha HTML. Add a call to `mocha.growl()` prior to running your
tests as shown below:

```html
<!DOCTYPE html>
<html>
<head>
<title>Mocha</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/mocha/mocha.css" />
</head>
<body>
<div id="mocha"></div>
<script src="https://unpkg.com/mocha/mocha.js"></script>
<script class="mocha-init">
mocha.setup('bdd');
mocha.growl(); // <-- Enables web notifications
</script>
<script src="tests.js"></script>
<script class="mocha-exec">
mocha.run();
</script>
</body>
</html>
```

## Configuring Mocha (Node.js)

> *New in v6.0.0*
Expand Down Expand Up @@ -1631,11 +1698,11 @@ For example, suppose you have the following `mocha.opts` file:

The settings above will default the reporter to `dot`, require the `should`
library, and use `bdd` as the interface. With this, you may then invoke `mocha`
with additional arguments, here enabling [Growl](http://growl.info/) support,
and changing the reporter to `list`:
with additional arguments, here changing the reporter to `list` and setting the
slow threshold to half a second:

```sh
$ mocha --reporter list --growl
$ mocha --reporter list --slow 500
```

To ignore your `mocha.opts`, use the `--no-opts` option.
Expand All @@ -1658,6 +1725,20 @@ $ mocha "./spec/**/*.js"

*Note*: Double quotes around the glob are recommended for portability.

## Error Codes

List of codes associated with Errors thrown inside Mocha. Following NodeJS practices.

| Code | Meaning |
| ------------- | ------------- |
| ERR_MOCHA_INVALID_ARG_TYPE | argument of the wrong type was passed to Mocha's API |
| ERR_MOCHA_INVALID_ARG_VALUE | invalid or unsupported value was passed for a given argument |
| ERR_MOCHA_INVALID_INTERFACE | interface specified in options not found |
| ERR_MOCHA_INVALID_REPORTER | reporter specified in options not found |
| ERR_MOCHA_NO_FILES_MATCH_PATTERN | file/s of test could not be found |
| ERR_MOCHA_NOT_SUPPORTED | type of output specified was not supported |
| ERR_MOCHA_UNDEFINED_ERROR | an error was thrown but no details were specified |

## Editor Plugins

The following editor-related packages are available:
Expand Down Expand Up @@ -1727,7 +1808,20 @@ $ REPORTER=nyan npm test

## More Information

In addition to chatting with us on [Gitter], for additional information such as using spies, mocking, and shared behaviours be sure to check out the [Mocha Wiki](https://github.com/mochajs/mocha/wiki) on GitHub. For discussions join the [Google Group](https://groups.google.com/group/mochajs). For a running example of Mocha, view [example/tests.html](example/tests.html). For the JavaScript API, view the [API documentation](api/) or the [source](https://github.com/mochajs/mocha/blob/master/lib/mocha.js#L51).
In addition to chatting with us on [Gitter][Gitter-mocha], for additional information such as using
spies, mocking, and shared behaviours be sure to check out the [Mocha Wiki][Mocha-wiki] on GitHub.
For discussions join the [Google Group][Google-mocha]. For a running example of Mocha, view
[example/tests.html](example/tests.html). For the JavaScript API, view the [API documentation](api/)
or the [source](https://github.com/mochajs/mocha/blob/master/lib/mocha.js).

[//]: # (Cross reference section)

[Gitter-mocha]: https://gitter.im/mochajs/mocha
[Google-mocha]: https://groups.google.com/group/mochajs
[Growl]: http://growl.info/
[Growl-install]: https://github.com/mochajs/mocha/wiki/Growl-Notifications
[Mocha-website]: https://mochajs.org/
[Mocha-wiki]: https://github.com/mochajs/mocha/wiki

<!-- AUTO-GENERATED-CONTENT:START (manifest:template=[Gitter]: ${gitter}) -->
[Gitter]: https://gitter.im/mochajs/mocha
Expand Down
166 changes: 164 additions & 2 deletions lib/browser/growl.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,167 @@
'use strict';

// just stub out growl
/**
* Web Notifications module.
* @module Growl
*/

module.exports = require('../utils').noop;
/**
* Save timer references to avoid Sinon interfering (see GH-237).
*/
var Date = global.Date;
var setTimeout = global.setTimeout;

/**
* Checks if browser notification support exists.
*
* @public
* @see {@link https://caniuse.com/#feat=notifications|Browser support (notifications)}
* @see {@link https://caniuse.com/#feat=promises|Browser support (promises)}
* @see {@link Mocha#growl}
* @see {@link Mocha#isGrowlCapable}
* @return {boolean} whether browser notification support exists
*/
exports.isCapable = function() {
var hasNotificationSupport = 'Notification' in window;
var hasPromiseSupport = typeof Promise === 'function';
return process.browser && hasNotificationSupport && hasPromiseSupport;
};

/**
* Implements browser notifications as a pseudo-reporter.
*
* @public
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/notification|Notification API}
* @see {@link https://developers.google.com/web/fundamentals/push-notifications/display-a-notification|Displaying a Notification}
* @see {@link Growl#isPermitted}
* @see {@link Mocha#_growl}
* @param {Runner} runner - Runner instance.
*/
exports.notify = function(runner) {
var promise = isPermitted();

/**
* Attempt notification.
*/
var sendNotification = function() {
// If user hasn't responded yet... "No notification for you!" (Seinfeld)
Promise.race([promise, Promise.resolve(undefined)])
.then(canNotify)
.then(function() {
display(runner);
})
.catch(notPermitted);
};

runner.once('end', sendNotification);
};

/**
* Checks if browser notification is permitted by user.
*
* @private
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Notification/permission|Notification.permission}
* @see {@link Mocha#growl}
* @see {@link Mocha#isGrowlPermitted}
* @returns {Promise<boolean>} promise determining if browser notification
* permissible when fulfilled.
*/
function isPermitted() {
var permitted = {
granted: function allow() {
return Promise.resolve(true);
},
denied: function deny() {
return Promise.resolve(false);
},
default: function ask() {
return Notification.requestPermission().then(function(permission) {
return permission === 'granted';
});
}
};

return permitted[Notification.permission]();
}

/**
* @summary
* Determines if notification should proceed.
*
* @description
* Notification shall <strong>not</strong> proceed unless `value` is true.
*
* `value` will equal one of:
* <ul>
* <li><code>true</code> (from `isPermitted`)</li>
* <li><code>false</code> (from `isPermitted`)</li>
* <li><code>undefined</code> (from `Promise.race`)</li>
* </ul>
*
* @private
* @param {boolean|undefined} value - Determines if notification permissible.
* @returns {Promise<undefined>} Notification can proceed
*/
function canNotify(value) {
if (!value) {
var why = value === false ? 'blocked' : 'unacknowledged';
var reason = 'not permitted by user (' + why + ')';
return Promise.reject(new Error(reason));
}
return Promise.resolve();
}

/**
* Displays the notification.
*
* @private
* @param {Runner} runner - Runner instance.
*/
function display(runner) {
var stats = runner.stats;
var symbol = {
cross: '\u274C',
tick: '\u2705'
};
var logo = require('../../package').notifyLogo;
var _message;
var message;
var title;

if (stats.failures) {
_message = stats.failures + ' of ' + runner.total + ' tests failed';
message = symbol.cross + ' ' + _message;
title = 'Failed';
} else {
_message = stats.passes + ' tests passed in ' + stats.duration + 'ms';
message = symbol.tick + ' ' + _message;
title = 'Passed';
}

// Send notification
var options = {
badge: logo,
body: message,
dir: 'ltr',
icon: logo,
lang: 'en-US',
name: 'mocha',
requireInteraction: false,
timestamp: Date.now()
};
var notification = new Notification(title, options);

// Autoclose after brief delay (makes various browsers act same)
var FORCE_DURATION = 4000;
setTimeout(notification.close.bind(notification), FORCE_DURATION);
}

/**
* As notifications are tangential to our purpose, just log the error.
*
* @private
* @param {Error} err - Why notification didn't happen.
*/
function notPermitted(err) {
console.error('notification error:', err.message);
}
6 changes: 2 additions & 4 deletions lib/cli/run-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,8 @@ exports.handleFiles = ({
try {
newFiles = utils.lookupFiles(arg, extension, recursive);
} catch (err) {
if (err.message.indexOf('cannot resolve path') === 0) {
console.error(
`Warning: Could not find any test files matching pattern: ${arg}`
);
if (err.code === 'ERR_MOCHA_NO_FILES_MATCH_PATTERN') {
console.warn('Warning: %s: %O', err.message, err.pattern);
return;
}

Expand Down

0 comments on commit 82faa1b

Please sign in to comment.