From e2204c10815a2f1ea12a3f614b1296a055fde7ca Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Wed, 31 Oct 2018 21:59:07 -0500 Subject: [PATCH 01/39] feat(Growl): Check notification support _before_ use! Added (minorly brittle) means to verify prerequisite software is installed. Migrated Growl support code to its own file. This implementation's checks are required to enable Growl; failure will write notice to `stderr`. Other modifications based on discussion from Chad Rickman's PR #3311. This also checks for errors from Growl callback. Fixes #3111 Signed-off-by: Paul Roebuck --- lib/growl.js | 153 ++++++++++++++++++++++++++++++++++++++++ lib/mocha.js | 79 ++++++++++----------- test/unit/mocha.spec.js | 24 +++++-- 3 files changed, 211 insertions(+), 45 deletions(-) create mode 100644 lib/growl.js diff --git a/lib/growl.js b/lib/growl.js new file mode 100644 index 0000000000..4c87d1798e --- /dev/null +++ b/lib/growl.js @@ -0,0 +1,153 @@ +'use strict'; +/** + * @module Growl + */ + +/** + * Module dependencies. + */ +var fs = require('fs'); +var os = require('os'); +var path = require('path'); + +/** + * @summary + * Checks if Growl support seems likely. + * + * @description + * Glosses over the distinction between an unsupported platform + * and one that lacks prerequisite software installations. + * Autofails when run in browser. + * + * @public + * @see {@link https://github.com/tj/node-growl/blob/master/README.md|Prerequisite Installs} + * @see {@link Mocha#growl} + * @return {boolean} whether Growl support can be expected + */ +exports.isCapable = function() { + return !process.browser && which(getSupportBinaries()) !== ''; +}; + +/** + * Implements desktop notifications as a pseudo-reporter. + * + * @private + * @see {@link Mocha#_growl} + * @param {Object} runner - Runner instance. + */ +exports.notify = function(runner) { + var sendNotification = function() { + var growl = require('growl'); + var stats = runner.stats; + var msg; + var options; + + if (stats.failures) { + msg = stats.failures + ' of ' + runner.total + ' tests failed'; + options = { + name: 'mocha', + title: 'Failed', + image: image('error') + }; + } else { + msg = stats.passes + ' tests passed in ' + stats.duration + 'ms'; + options = { + name: 'mocha', + title: 'Passed', + image: image('ok') + }; + } + growl(msg, options, onCompletion); + }; + + /** + * Callback for result of attempted Growl notification. + * + * @callback Growl~growlCB + * @param {*} err - Error object, or null if successful. + * @param {string} stdout - stdout from notification delivery + * process. + * @param {string} stderr - stderr from notification delivery + * process. It will include timestamp and executed command with arguments. + */ + + function onCompletion(err, stdout, stderr) { + if (err) { + if (err.code === 'ENOENT') { + console.error( + 'Growl notification support not installed... listener removed!' + ); + runner.removeListener('end', sendNotification); + } else { + console.error('growl: ', err.message); + } + } + } + + // :TBD: should this be `.once`? + runner.on('end', sendNotification); +}; + +/** + * Returns Growl image `name` path. + * + * @private + * @param {string} name - Basename of associated Growl image. + * @return {string} Pathname to Growl image + */ +function image(name) { + return path.join(__dirname, '..', 'assets', 'growl', name + '.png'); +} + +/** + * @summary + * Locate a binary in the user's `PATH`. + * + * @description + * Takes a list of command names and searches the path for each executable + * file that would be run had these commands actually been invoked. + * + * @private + * @param {string[]} binaries - Names of binary files to search for. + * @return {string} absolute path of first binary found, or empty string if none + */ +function which(binaries) { + var paths = process.env.PATH.split(path.delimiter); + var exists = fs.existsSync || path.existsSync; + + for (var n = 0, blen = binaries.length; n < blen; n++) { + var binary = binaries[n]; + var loc; + for (var i = 0, plen = paths.length; i < plen; i++) { + loc = path.join(paths[i], binary); + if (exists(loc)) { + return loc; + } + } + } + return ''; +} + +/** + * @summary + * Get platform-specific Growl support binaries. + * + * @description + * Somewhat brittle dependency on `growl` package implementation, but it + * rarely changes. + * + * @private + * @see {@link https://github.com/tj/node-growl/blob/master/lib/growl.js#L28-L126|setupCmd} + * @return {string[]} names of Growl support binaries + */ +function getSupportBinaries() { + switch (os.type()) { + case 'Darwin': + return ['terminal-notifier', 'growlnotify']; + case 'Linux': + return ['notify-send', 'growl']; + case 'Windows_NT': + return ['growlnotify']; + } + return []; +} diff --git a/lib/mocha.js b/lib/mocha.js index 1700fe9ca7..f81b3973c5 100644 --- a/lib/mocha.js +++ b/lib/mocha.js @@ -9,6 +9,7 @@ var escapeRe = require('escape-string-regexp'); var path = require('path'); var builtinReporters = require('./reporters'); +var growl = require('./growl'); var utils = require('./utils'); exports = module.exports = Mocha; @@ -49,17 +50,6 @@ exports.Suite = require('./suite'); exports.Hook = require('./hook'); exports.Test = require('./test'); -/** - * Returns Growl image `name` path. - * - * @private - * @param {string} name - Basename of associated Growl image. - * @return {string} Pathname to Growl image - */ -function image(name) { - return path.join(__dirname, '..', 'assets', 'growl', name + '.png'); -} - /** * Constructs a new Mocha instance with `options`. * @@ -104,6 +94,9 @@ function Mocha(options) { this.suite = new exports.Suite('', new exports.Context()); this.ui(options.ui); this.bail(options.bail); + if (options.growl) { + this.growl(); + } this.reporter(options.reporter, options.reporterOptions); if (typeof options.timeout !== 'undefined' && options.timeout !== null) { this.timeout(options.timeout); @@ -290,32 +283,6 @@ Mocha.prototype.loadFiles = function(fn) { fn && fn(); }; -/** - * Implements desktop notifications using a pseudo-reporter. - * - * @private - * @see {@link Mocha#growl} - * @param {Object} runner - Runner instance. - * @param {Object} reporter - Reporter instance. - */ -Mocha.prototype._growl = function(runner, reporter) { - var notify = require('growl'); - - runner.on('end', function() { - var stats = reporter.stats; - if (stats.failures) { - var msg = stats.failures + ' of ' + runner.total + ' tests failed'; - notify(msg, {name: 'mocha', title: 'Failed', image: image('error')}); - } else { - notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', { - name: 'mocha', - title: 'Passed', - image: image('ok') - }); - } - }); -}; - /** * Sets `grep` filter after escaping RegExp special characters. * @@ -440,18 +407,50 @@ Mocha.prototype.fullTrace = function() { }; /** - * Enables desktop notification support. + * @summary + * Enables desktop notification support if prerequisite software installed. * * @public + * @see {@link Mocha#isGrowlCapable} * @see {@link Mocha#_growl} * @return {Mocha} this * @chainable */ Mocha.prototype.growl = function() { - this.options.growl = true; + this.options.growl = this.isGrowlCapable(); + if (!this.options.growl) { + var detail = process.browser + ? 'Growl notification support not available in browser... cannot enable!' + : 'Growl notification support not installed... cannot enable!'; + console.error(detail); + } return this; }; +/** + * @summary + * Determines if Growl support seems likely. + * + * @description + * Not available when run in browser. + * + * @private + * @see {@link Growl#isCapable} + * @see {@link Mocha#growl} + * @return {boolean} whether Growl support can be expected + */ +Mocha.prototype.isGrowlCapable = growl.isCapable; + +/** + * Implements desktop notifications using a pseudo-reporter. + * + * @private + * @see {@link Mocha#growl} + * @see {@link Growl#notify} + * @param {Object} runner - Runner instance. + */ +Mocha.prototype._growl = growl.notify; + /** * Specifies whitelist of variable names to be expected in global scope. * @@ -721,7 +720,7 @@ Mocha.prototype.run = function(fn) { runner.globals(options.globals); } if (options.growl) { - this._growl(runner, reporter); + this._growl(runner); } if (options.useColors !== undefined) { exports.reporters.Base.useColors = options.useColors; diff --git a/test/unit/mocha.spec.js b/test/unit/mocha.spec.js index 3f7145834c..6146afdfbe 100644 --- a/test/unit/mocha.spec.js +++ b/test/unit/mocha.spec.js @@ -110,12 +110,26 @@ describe('Mocha', function() { }); describe('.growl()', function() { - it('should set the growl option to true', function() { - var mocha = new Mocha(blankOpts); - mocha.growl(); - expect(mocha.options.growl, 'to be', true); + context('if Growl capable', function() { + it('should set the growl option to true', function() { + var mocha = new Mocha(blankOpts); + mocha.isGrowlCapable = function() { + return true; + }; + mocha.growl(); + expect(mocha.options.growl, 'to be', true); + }); + }); + context('if not Growl capable', function() { + it('should set the growl option to false', function() { + var mocha = new Mocha(blankOpts); + mocha.isGrowlCapable = function() { + return false; + }; + mocha.growl(); + expect(mocha.options.growl, 'to be', false); + }); }); - it('should be chainable', function() { var mocha = new Mocha(blankOpts); expect(mocha.growl(), 'to be', mocha); From b9e557fcc251bc5c3d1bcce04a18197d4aa2bf87 Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Wed, 31 Oct 2018 22:32:28 -0500 Subject: [PATCH 02/39] docs(growl.js): Correct access level of `notify` method [skip ci] --- lib/growl.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/growl.js b/lib/growl.js index 4c87d1798e..8406a80f45 100644 --- a/lib/growl.js +++ b/lib/growl.js @@ -31,7 +31,7 @@ exports.isCapable = function() { /** * Implements desktop notifications as a pseudo-reporter. * - * @private + * @public * @see {@link Mocha#_growl} * @param {Object} runner - Runner instance. */ From 190202386e470059286679df90e5c60dee603ca7 Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Wed, 31 Oct 2018 22:49:01 -0500 Subject: [PATCH 03/39] docs(growl.js,mocha.js): Minor changes to improve specificity [skip ci] --- lib/growl.js | 10 ++++------ lib/mocha.js | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/growl.js b/lib/growl.js index 8406a80f45..8c8c06857a 100644 --- a/lib/growl.js +++ b/lib/growl.js @@ -3,9 +3,6 @@ * @module Growl */ -/** - * Module dependencies. - */ var fs = require('fs'); var os = require('os'); var path = require('path'); @@ -22,6 +19,7 @@ var path = require('path'); * @public * @see {@link https://github.com/tj/node-growl/blob/master/README.md|Prerequisite Installs} * @see {@link Mocha#growl} + * @see {@link Mocha#isGrowlCapable} * @return {boolean} whether Growl support can be expected */ exports.isCapable = function() { @@ -33,7 +31,7 @@ exports.isCapable = function() { * * @public * @see {@link Mocha#_growl} - * @param {Object} runner - Runner instance. + * @param {Runner} runner - Runner instance. */ exports.notify = function(runner) { var sendNotification = function() { @@ -101,7 +99,7 @@ function image(name) { /** * @summary - * Locate a binary in the user's `PATH`. + * Locates a binary in the user's `PATH`. * * @description * Takes a list of command names and searches the path for each executable @@ -130,7 +128,7 @@ function which(binaries) { /** * @summary - * Get platform-specific Growl support binaries. + * Gets platform-specific Growl support binaries. * * @description * Somewhat brittle dependency on `growl` package implementation, but it diff --git a/lib/mocha.js b/lib/mocha.js index f81b3973c5..456a7bc6c7 100644 --- a/lib/mocha.js +++ b/lib/mocha.js @@ -447,7 +447,7 @@ Mocha.prototype.isGrowlCapable = growl.isCapable; * @private * @see {@link Mocha#growl} * @see {@link Growl#notify} - * @param {Object} runner - Runner instance. + * @param {Runner} runner - Runner instance. */ Mocha.prototype._growl = growl.notify; From 08ec0a829493828e65866d2442122ae6f3384066 Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Wed, 31 Oct 2018 23:34:57 -0500 Subject: [PATCH 04/39] docs(mocha.js): Remove unneeded JSDoc tag [skip ci] --- lib/mocha.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/mocha.js b/lib/mocha.js index 456a7bc6c7..dabea27e00 100644 --- a/lib/mocha.js +++ b/lib/mocha.js @@ -407,7 +407,6 @@ Mocha.prototype.fullTrace = function() { }; /** - * @summary * Enables desktop notification support if prerequisite software installed. * * @public From ddeca7e1667a37ea59e9e5b822f7055f0059ec9f Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Thu, 1 Nov 2018 06:01:20 -0500 Subject: [PATCH 05/39] refactor(growl.js): Simplify completion callback error reporting --- lib/growl.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/lib/growl.js b/lib/growl.js index 8c8c06857a..06b1f1f910 100644 --- a/lib/growl.js +++ b/lib/growl.js @@ -71,14 +71,9 @@ exports.notify = function(runner) { function onCompletion(err, stdout, stderr) { if (err) { - if (err.code === 'ENOENT') { - console.error( - 'Growl notification support not installed... listener removed!' - ); - runner.removeListener('end', sendNotification); - } else { - console.error('growl: ', err.message); - } + var detail = + err.code === 'ENOENT' ? 'prerequisite software not found' : err.message; + console.error('Growl notification error:', detail); } } From 9b0907aafca2c1cc9ed6655700fb73a0b0f581b8 Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Thu, 1 Nov 2018 08:56:57 -0500 Subject: [PATCH 06/39] refactor(growl.js): Change event listener style Convert listener from `.on` to `.once`. --- lib/growl.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/growl.js b/lib/growl.js index 06b1f1f910..a271a37d6b 100644 --- a/lib/growl.js +++ b/lib/growl.js @@ -59,8 +59,13 @@ exports.notify = function(runner) { }; /** + * @summary * Callback for result of attempted Growl notification. * + * @description + * Despite its appearance, this is not an Error-first + * callback -- all parameters are populated regardless of success. + * * @callback Growl~growlCB * @param {*} err - Error object, or null if successful. * @param {string} stdout - stdout from notification delivery @@ -77,8 +82,7 @@ exports.notify = function(runner) { } } - // :TBD: should this be `.once`? - runner.on('end', sendNotification); + runner.once('end', sendNotification); }; /** From 64c09eb2d817baa63a3843c4b3bffbbe08f44a39 Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Sun, 4 Nov 2018 01:25:15 -0500 Subject: [PATCH 07/39] test(unit/mocha.spec.js): Convert `context` to `describe` --- test/unit/mocha.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/mocha.spec.js b/test/unit/mocha.spec.js index 6146afdfbe..4bd654915f 100644 --- a/test/unit/mocha.spec.js +++ b/test/unit/mocha.spec.js @@ -110,7 +110,7 @@ describe('Mocha', function() { }); describe('.growl()', function() { - context('if Growl capable', function() { + describe('if Growl capable', function() { it('should set the growl option to true', function() { var mocha = new Mocha(blankOpts); mocha.isGrowlCapable = function() { @@ -120,7 +120,7 @@ describe('Mocha', function() { expect(mocha.options.growl, 'to be', true); }); }); - context('if not Growl capable', function() { + describe('if not Growl capable', function() { it('should set the growl option to false', function() { var mocha = new Mocha(blankOpts); mocha.isGrowlCapable = function() { From 4773475c4e91b41689e745ddf3289637a217e009 Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Sun, 4 Nov 2018 01:49:38 -0500 Subject: [PATCH 08/39] refactor(lib/growl.js): Convert `switch` to KV lookup --- lib/growl.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/lib/growl.js b/lib/growl.js index a271a37d6b..e890e669f1 100644 --- a/lib/growl.js +++ b/lib/growl.js @@ -138,13 +138,10 @@ function which(binaries) { * @return {string[]} names of Growl support binaries */ function getSupportBinaries() { - switch (os.type()) { - case 'Darwin': - return ['terminal-notifier', 'growlnotify']; - case 'Linux': - return ['notify-send', 'growl']; - case 'Windows_NT': - return ['growlnotify']; - } - return []; + var binaries = { + Darwin: ['terminal-notifier', 'growlnotify'], + Linux: ['notify-send', 'growl'], + Windows_NT: ['growlnotify'] + }; + return binaries[os.type()] || []; } From 8a16c9a37208dc4de2fa7928388e5946ed3e3bed Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Sun, 4 Nov 2018 01:31:46 -0600 Subject: [PATCH 09/39] refactor(lib/growl.js): Remove `path.exists` anachronism Hey, my Coveralls score _should_ improve! --- lib/growl.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/growl.js b/lib/growl.js index e890e669f1..e140d6fceb 100644 --- a/lib/growl.js +++ b/lib/growl.js @@ -98,7 +98,7 @@ function image(name) { /** * @summary - * Locates a binary in the user's `PATH`. + * Locates a binary in the user's `PATH` environment variable. * * @description * Takes a list of command names and searches the path for each executable @@ -110,14 +110,13 @@ function image(name) { */ function which(binaries) { var paths = process.env.PATH.split(path.delimiter); - var exists = fs.existsSync || path.existsSync; for (var n = 0, blen = binaries.length; n < blen; n++) { var binary = binaries[n]; var loc; for (var i = 0, plen = paths.length; i < plen; i++) { loc = path.join(paths[i], binary); - if (exists(loc)) { + if (fs.existsSync(loc)) { return loc; } } From da252058cb342884483b15f979599ee1d450a9eb Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Sat, 10 Nov 2018 11:18:44 -0600 Subject: [PATCH 10/39] docs(docs/index.md): Add Growl section to user guide [skip travis][skip appveyor] --- docs/index.md | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/docs/index.md b/docs/index.md index 5fae36b634..2dcf2a237a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -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 notifications](#desktop-notification-support) - [reports test durations](#test-duration) - [highlights slow tests](#dot-matrix) - [file watcher support](#min) @@ -70,6 +70,7 @@ 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) - [`mocha.opts`](#mochaopts) - [The `test/` Directory](#the-test-directory) - [Editor Plugins](#editor-plugins) @@ -788,7 +789,7 @@ Mocha supports the `err.expected` and `err.actual` properties of any thrown `Ass -A, --async-only force all tests to take a callback (async) or return a promise -c, --colors force enabling of colors -C, --no-colors force disabling of colors - -G, --growl enable growl notification support + -G, --growl enable Growl notification support -O, --reporter-options reporter-specific options -R, --reporter specify the reporter to use (default: spec) -S, --sort sort test files @@ -1293,6 +1294,30 @@ 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. + +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](https://github.com/mochajs/mocha/wiki/Growl-Notifications). + +Enable Mocha's desktop notifications as follows: + +```bash +$ mocha --growl +``` + +When the root suite completes test execution, a desktop notification should +appear informing you whether your tests passed or not. + ## `mocha.opts` Back on the server, Mocha will attempt to load `"./test/mocha.opts"` as a @@ -1319,11 +1344,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 ``` ## The `test/` Directory @@ -1414,3 +1439,12 @@ $ REPORTER=nyan npm test ## More Information In addition to chatting with us on [Gitter](https://gitter.im/mochajs/mocha), 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). + + +[//]: # (Cross reference section) + +[Growl]: http://growl.info/ +[Growl-install]: https://github.com/mochajs/mocha/wiki/Growl-Notifications +[Mocha-gitter]: https://gitter.im/mochajs/mocha +[Mocha-website]: https://mochajs.org/ + From a5df7919460bf157238303ae05d42c9310da40d3 Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Sat, 10 Nov 2018 12:19:10 -0600 Subject: [PATCH 11/39] docs(docs/index.md): Make markdownlint happy Why a blank line bothers the linter is beyond me... --- docs/index.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/index.md b/docs/index.md index 2dcf2a237a..066ee691ae 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1440,11 +1440,9 @@ $ REPORTER=nyan npm test In addition to chatting with us on [Gitter](https://gitter.im/mochajs/mocha), 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). - [//]: # (Cross reference section) [Growl]: http://growl.info/ [Growl-install]: https://github.com/mochajs/mocha/wiki/Growl-Notifications [Mocha-gitter]: https://gitter.im/mochajs/mocha [Mocha-website]: https://mochajs.org/ - From 1271f8b3db44e0d2df19fd6c0a9be5bace7c1362 Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Sun, 18 Nov 2018 16:13:59 -0600 Subject: [PATCH 12/39] test(unit/mocha.spec.js): Minor tweaks to Growl-related tests --- test/unit/mocha.spec.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/unit/mocha.spec.js b/test/unit/mocha.spec.js index 13e5a6db02..6fd7c64ce9 100644 --- a/test/unit/mocha.spec.js +++ b/test/unit/mocha.spec.js @@ -120,20 +120,20 @@ describe('Mocha', function() { }); describe('.growl()', function() { - describe('if Growl capable', function() { + describe('if capable of notifications', function() { it('should set the growl option to true', function() { var mocha = new Mocha(blankOpts); - mocha.isGrowlCapable = function() { + mocha.isGrowlCapable = function forceEnable() { return true; }; mocha.growl(); expect(mocha.options.growl, 'to be', true); }); }); - describe('if not Growl capable', function() { + describe('if not capable of notifications', function() { it('should set the growl option to false', function() { var mocha = new Mocha(blankOpts); - mocha.isGrowlCapable = function() { + mocha.isGrowlCapable = function forceDisable() { return false; }; mocha.growl(); From c303f634ab9f30e94910a0cbddb42285a2ec76b1 Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Sun, 18 Nov 2018 16:18:40 -0600 Subject: [PATCH 13/39] docs(docs/index.md): Updates to user guide for desktop notification support Added documentation for web notification support. --- docs/index.md | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/docs/index.md b/docs/index.md index 67376c4a35..d4a7db9571 100644 --- a/docs/index.md +++ b/docs/index.md @@ -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 notifications](#desktop-notification-support) +- [Growl support](#desktop-notification-support) - [reports test durations](#test-duration) - [highlights slow tests](#dot-matrix) - [file watcher support](#min) @@ -1303,6 +1303,11 @@ 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](https://github.com/mochajs/mocha/wiki/Growl-Notifications). @@ -1313,8 +1318,42 @@ Enable Mocha's desktop notifications as follows: $ mocha --growl ``` -When the root suite completes test execution, a desktop notification should -appear informing you whether your tests passed or not. +### 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 `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="mocha.css" /> + </head> + <body> + <div id="mocha"></div> + <script src="mocha.js"></script> + <script> + mocha.setup('bdd'); + mocha.growl(); // <-- activate web notifications + </script> + <script src="tests.js"></script> + <script> + mocha.run(); + </script> + </body> +</html> +``` ## `mocha.opts` From 20dddf0ccd8a3badd1155721b4d782f88dd54b6b Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Sun, 18 Nov 2018 16:23:52 -0600 Subject: [PATCH 14/39] feat(lib/browser/growl.js): Added web notification support for `Mocha#growl` Replaced the existing noop stub with an implementation using browser notifications as the Mocha `growl` pseudo-reporter (when run in browser). --- lib/browser/growl.js | 212 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 210 insertions(+), 2 deletions(-) diff --git a/lib/browser/growl.js b/lib/browser/growl.js index 28c62efbec..a6a3bd9a8d 100644 --- a/lib/browser/growl.js +++ b/lib/browser/growl.js @@ -1,5 +1,213 @@ 'use strict'; -// just stub out growl +/** + * @module Growl + * + * Browser implementation. + */ -module.exports = require('../utils').noop; +/** + * @summary + * 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} promise determining if browser notification + * permissible when fulfilled. + */ +function isPermitted() { + var permitted = { + granted: Promise.resolve(true), + denied: Promise.resolve(false), + default: (function ask() { + Notification.requestPermission().then(function(permission) { + return Promise.resolve(permission === 'granted'); + }); + })() + }; + + return permitted[Notification.permission]; +} + +/** + * A promise determining if notification can proceed. + * + * @promise Growl~CanNotifyPromise + * @fulfill {boolean} Notification allowed (true). + * @reject {Error} Notification denied (or request unacknowledged) by user. + */ + +/** + * @summary + * Determines if notification should proceed. + * + * @description + * Notification should not proceed unless `value` is true. + * + * `value` will equal one of: + *
    + *
  • true (from `isPermitted`)
  • + *
  • false (from `isPermitted`)
  • + *
  • undefined (from `Promise.race`)
  • + *
+ * + * @private + * @param {Promise} value - Determines if browser + * notification permissible when fulfilled. + * @returns {Growl~CanNotifyPromise} Should notification 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(true); +} + +/** + * Displays the notification. + * + * @param {Runner} runner - Runner instance. + * @private + */ +function display(runner) { + var stats = runner.stats; + var symbol = { + cross: '\u274C', + tick: '\u2705' + }; + var logo = require('../../package').logo; + var lang = 'en-US'; + 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, + icon: logo, + lang: lang, + name: 'mocha', + requireInteraction: false, + tag: generateTag(), + 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); +} + +/** + * Used to help distinguish notifications within a root suite run. + * @type {number} + */ +var ntags = 0; + +/** + * @summary + * Generates a datestamped, run-unique tag for each notification. + * + * @description + * Use of a tag allows notifications that represent the same conceptual event + * to specify as much. This implementation doesn't really bother. + * + * @private + * @returns {string} tag unique within a root suite execution + * @example + * + * generateTag(); + * // => "mocha_results-20181117-1" + */ +function generateTag() { + return ['mocha_results', datestamp(), ++ntags].join('-'); +} + +/** + * Generates a datestamp. + * + * @private + * @returns {string} tag in YYYYMMDD format + * @example + * + * datestamp(); + * // => "20181117" + */ +function datestamp() { + var now = new Date(Date.now()); + var year = now.getFullYear(); + var month = now.getMonth() + 1; + var day = now.getDate(); + + return '' + year + (month < 10 ? '0' : '') + month + day; +} From f1c81afaba9f375ecdf307d732b1c22c1b138e19 Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Sun, 18 Nov 2018 16:34:19 -0600 Subject: [PATCH 15/39] feat(lib/growl.js): Updated notification appearance Updated previous submmission with changes to minimize differences between the Node and browser versions. Changed implementation to use Mocha logo as its image icon and appended unicode marks to displayed message. This was done to make Node and web notifications more similar visually. --- lib/growl.js | 124 +++++++++++++++++++++++++++++---------------------- 1 file changed, 70 insertions(+), 54 deletions(-) diff --git a/lib/growl.js b/lib/growl.js index e140d6fceb..af02b97168 100644 --- a/lib/growl.js +++ b/lib/growl.js @@ -1,6 +1,9 @@ 'use strict'; + /** * @module Growl + * + * Node implementation. */ var fs = require('fs'); @@ -9,18 +12,17 @@ var path = require('path'); /** * @summary - * Checks if Growl support seems likely. + * Checks if Growl notification support seems likely. * * @description * Glosses over the distinction between an unsupported platform * and one that lacks prerequisite software installations. - * Autofails when run in browser. * * @public * @see {@link https://github.com/tj/node-growl/blob/master/README.md|Prerequisite Installs} * @see {@link Mocha#growl} * @see {@link Mocha#isGrowlCapable} - * @return {boolean} whether Growl support can be expected + * @return {boolean} whether Growl notification support can be expected */ exports.isCapable = function() { return !process.browser && which(getSupportBinaries()) !== ''; @@ -35,65 +37,80 @@ exports.isCapable = function() { */ exports.notify = function(runner) { var sendNotification = function() { - var growl = require('growl'); - var stats = runner.stats; - var msg; - var options; - - if (stats.failures) { - msg = stats.failures + ' of ' + runner.total + ' tests failed'; - options = { - name: 'mocha', - title: 'Failed', - image: image('error') - }; - } else { - msg = stats.passes + ' tests passed in ' + stats.duration + 'ms'; - options = { - name: 'mocha', - title: 'Passed', - image: image('ok') - }; - } - growl(msg, options, onCompletion); + display(runner); }; + runner.once('end', sendNotification); +}; - /** - * @summary - * Callback for result of attempted Growl notification. - * - * @description - * Despite its appearance, this is not an Error-first - * callback -- all parameters are populated regardless of success. - * - * @callback Growl~growlCB - * @param {*} err - Error object, or null if successful. - * @param {string} stdout - stdout from notification delivery - * process. - * @param {string} stderr - stderr from notification delivery - * process. It will include timestamp and executed command with arguments. - */ +/** + * Displays the notification. + * + * @private + * @param {Runner} runner - Runner instance. + */ +function display(runner) { + var growl = require('growl'); + var stats = runner.stats; + var symbol = { + cross: '\u274C', + tick: '\u2705' + }; + var _message; + var message; + var title; - function onCompletion(err, stdout, stderr) { - if (err) { - var detail = - err.code === 'ENOENT' ? 'prerequisite software not found' : err.message; - console.error('Growl notification error:', detail); - } + 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'; } - runner.once('end', sendNotification); -}; + // Send notification + var options = { + image: logo(), + name: 'mocha', + title: title + }; + growl(message, options, onCompletion); +} + +/** + * @summary + * Callback for result of attempted Growl notification. + * + * @description + * Despite its appearance, this is not an Error-first + * callback -- all parameters are populated regardless of success. + * + * @private + * @callback Growl~growlCB + * @param {*} err - Error object, or null if successful. + * @param {string} stdout - stdout from notification delivery + * process. + * @param {string} stderr - stderr from notification delivery + * process. It will include timestamp and executed command with arguments. + */ +function onCompletion(err, stdout, stderr) { + if (err) { + // As notifications are tangential to our purpose, just log the error. + var message = + err.code === 'ENOENT' ? 'prerequisite software not found' : err.message; + console.error('notification error:', message); + } +} /** - * Returns Growl image `name` path. + * Returns Mocha logo image path. * * @private - * @param {string} name - Basename of associated Growl image. - * @return {string} Pathname to Growl image + * @return {string} Pathname of Mocha logo */ -function image(name) { - return path.join(__dirname, '..', 'assets', 'growl', name + '.png'); +function logo() { + return path.join(__dirname, '..', 'assets', 'mocha-logo-64.png'); } /** @@ -113,9 +130,8 @@ function which(binaries) { for (var n = 0, blen = binaries.length; n < blen; n++) { var binary = binaries[n]; - var loc; for (var i = 0, plen = paths.length; i < plen; i++) { - loc = path.join(paths[i], binary); + var loc = path.join(paths[i], binary); if (fs.existsSync(loc)) { return loc; } From fb9b696e466b4335f68fb714e6dda80c8c7caa21 Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Sun, 18 Nov 2018 16:37:11 -0600 Subject: [PATCH 16/39] refactor(lib/mocha.js): Change `Mocha#growl` notification support error message --- lib/mocha.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/mocha.js b/lib/mocha.js index 3fd8d6cafa..b7a9300bcc 100644 --- a/lib/mocha.js +++ b/lib/mocha.js @@ -419,9 +419,9 @@ Mocha.prototype.growl = function() { this.options.growl = this.isGrowlCapable(); if (!this.options.growl) { var detail = process.browser - ? 'Growl notification support not available in browser... cannot enable!' - : 'Growl notification support not installed... cannot enable!'; - console.error(detail); + ? 'notification support not available in this browser...' + : 'notification support prerequisites not installed...'; + console.error(detail + ' cannot enable!'); } return this; }; From c9a8d9ba0edce1d7d1c646b804cbb7124e58caac Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Sun, 18 Nov 2018 16:48:16 -0600 Subject: [PATCH 17/39] build(browserify): Updated browserify settings to bundle web notification support Replaced previous commit's transform package; it now uses a different package and a script that allows more flexibility. Bundled web notification support when run in browser. --- package-scripts.js | 2 +- package.json | 8 ++++---- scripts/package-json-minify.js | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 scripts/package-json-minify.js diff --git a/package-scripts.js b/package-scripts.js index 3824e7d373..7c69d694e3 100644 --- a/package-scripts.js +++ b/package-scripts.js @@ -20,7 +20,7 @@ function test(testName, mochaParams) { module.exports = { scripts: { build: { - script: `browserify ./browser-entry --plugin ./scripts/dedefine --ignore 'fs' --ignore 'glob' --ignore 'path' --ignore 'supports-color' > mocha.js`, + script: `browserify -e browser-entry.js --plugin './scripts/dedefine' --ignore 'fs' --ignore 'glob' --ignore 'path' --ignore 'supports-color' -o mocha.js`, description: 'Build browser bundle' }, lint: { diff --git a/package.json b/package.json index 7b1938ffa1..639528c6da 100644 --- a/package.json +++ b/package.json @@ -485,6 +485,7 @@ "@mocha/docdash": "^1.0.1", "assetgraph-builder": "^5.9.1", "browserify": "^16.2.2", + "browserify-package-json": "^1.0.1", "chai": "^4.1.2", "coffee-script": "^1.10.0", "coveralls": "^3.0.1", @@ -511,7 +512,6 @@ "markdownlint-cli": "^0.9.0", "nps": "^5.7.1", "nyc": "^11.7.3", - "package-json-versionify": "^1.0.4", "prettier-eslint-cli": "^4.7.1", "rimraf": "^2.5.2", "svgo": "^0.7.2", @@ -530,13 +530,13 @@ ], "browserify": { "transform": [ - "package-json-versionify" + "./scripts/package-json-minify" ] }, "browser": { - "growl": "./lib/browser/growl.js", - "tty": "./lib/browser/tty.js", "./index.js": "./browser-entry.js", + "./lib/growl.js": "./lib/browser/growl.js", + "tty": "./lib/browser/tty.js", "fs": false, "glob": false, "path": false, diff --git a/scripts/package-json-minify.js b/scripts/package-json-minify.js new file mode 100644 index 0000000000..32413f413b --- /dev/null +++ b/scripts/package-json-minify.js @@ -0,0 +1,17 @@ +'use strict'; + +/** + * This is a transform stream used to minify "package.json" results + * when our source is transformed for our Browserify bundle. + * + * Based on Nolan Lawson's "package-json-versionify" package. + */ + +const browserifyPackageJSON = require('browserify-package-json'); + +module.exports = function(filename, options) { + const fieldsToKeep = ['name', 'version', 'homepage', 'logo']; + const bpjOptions = Object.assign(options || {}, {only: fieldsToKeep}); + + return browserifyPackageJSON(filename, bpjOptions); +}; From 519f2cdf41bbd9463a8bb819b96d9831e08c2999 Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Mon, 19 Nov 2018 07:44:37 -0600 Subject: [PATCH 18/39] docs(growl): Fix JSDoc module header --- lib/browser/growl.js | 3 +-- lib/growl.js | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/browser/growl.js b/lib/browser/growl.js index a6a3bd9a8d..3437791c17 100644 --- a/lib/browser/growl.js +++ b/lib/browser/growl.js @@ -1,9 +1,8 @@ 'use strict'; /** + * Web Notifications module. * @module Growl - * - * Browser implementation. */ /** diff --git a/lib/growl.js b/lib/growl.js index af02b97168..3849f7a58a 100644 --- a/lib/growl.js +++ b/lib/growl.js @@ -1,9 +1,8 @@ 'use strict'; /** + * Desktop Notifications module. * @module Growl - * - * Node implementation. */ var fs = require('fs'); From b4ea1de6f925aee727ab15c91c852bb71316074c Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Mon, 19 Nov 2018 07:55:24 -0600 Subject: [PATCH 19/39] docs(docs/index.md): Unescape left tag delimmiters in HTML codefence Had assumed the HTML might be interpolated if not escaped. --- docs/index.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/index.md b/docs/index.md index d4a7db9571..45ab3b1e6e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1332,27 +1332,27 @@ client-side mocha HTML. Add `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="mocha.css" /> - </head> - <body> - <div id="mocha"></div> - <script src="mocha.js"></script> - <script> + + + + Mocha + + + + + +
+ + + + + + ``` ## `mocha.opts` From 7e7a67c3c0aa0aed0b8279347e79b80788bc378e Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Mon, 19 Nov 2018 08:26:17 -0600 Subject: [PATCH 20/39] docs(user guide): Minor wordsmithing [skip travis][skip appveyor] --- docs/index.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/index.md b/docs/index.md index 45ab3b1e6e..cb1f9341a3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1328,8 +1328,8 @@ 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 `mocha.growl()` prior to running your tests as -shown below: +client-side mocha HTML. Add a call to `mocha.growl()` prior to running your +tests as shown below: ```html @@ -1343,12 +1343,12 @@ shown below:
- - From 528437a79e70065f1115952e5c7ac37cff81ce82 Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Mon, 19 Nov 2018 08:55:23 -0600 Subject: [PATCH 21/39] docs(user guide): Make HTML examples more similar Added placeholder npm package version URLs to web notification example. Added class names to browser-use HTML example script tags to help identify their purpose. --- docs/index.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/index.md b/docs/index.md index cb1f9341a3..49b719199d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1240,12 +1240,14 @@ A typical setup might look something like the following, where we call `mocha.se - + - @@ -1338,17 +1340,17 @@ tests as shown below: Mocha - +
- + - From a1dce650f8a88875c0cb8f41f0793a6f823a6f66 Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Fri, 23 Nov 2018 12:22:43 -0600 Subject: [PATCH 22/39] ci(appveyor.yml): Change URL for GrowlForWindows (GfW) Developer retired commercial site. Use GitHub URL instead. --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index e9f8eba0c0..81e2fa9617 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,7 +22,7 @@ install: ## Manual Growl install - ps: Add-AppveyorMessage "Installing Growl..." - ps: $exePath = "$($env:USERPROFILE)\GrowlInstaller.exe" - - ps: (New-Object Net.WebClient).DownloadFile('http://www.growlforwindows.com/gfw/downloads/GrowlInstaller.exe', $exePath) + - ps: (New-Object Net.WebClient).DownloadFile('https://github.com/briandunnington/growl-for-windows/releases/download/final/GrowlInstaller.exe', $exePath) - ps: mkdir C:\GrowlInstaller | out-null - ps: 7z x $exePath -oC:\GrowlInstaller | out-null - ps: cmd /c start /wait msiexec /i C:\GrowlInstaller\Growl_v2.0.msi /quiet From 63ca4501b59f137276288efd8a46b2ec098cad27 Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Thu, 6 Dec 2018 12:42:26 -0600 Subject: [PATCH 23/39] build(scripts/package-json-cullify.js): Renamed browserify-related script (ci skip) Previous usage of "minify" term (while correct) could cause confusion over exactly what the transformation had done. Renamed file more discernably. --- package.json | 2 +- scripts/{package-json-minify.js => package-json-cullify.js} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename scripts/{package-json-minify.js => package-json-cullify.js} (87%) diff --git a/package.json b/package.json index 639528c6da..cfc011bb30 100644 --- a/package.json +++ b/package.json @@ -530,7 +530,7 @@ ], "browserify": { "transform": [ - "./scripts/package-json-minify" + "./scripts/package-json-cullify" ] }, "browser": { diff --git a/scripts/package-json-minify.js b/scripts/package-json-cullify.js similarity index 87% rename from scripts/package-json-minify.js rename to scripts/package-json-cullify.js index 32413f413b..6118decbc0 100644 --- a/scripts/package-json-minify.js +++ b/scripts/package-json-cullify.js @@ -1,7 +1,7 @@ 'use strict'; /** - * This is a transform stream used to minify "package.json" results + * This is a transform stream used to cull "package.json" results * when our source is transformed for our Browserify bundle. * * Based on Nolan Lawson's "package-json-versionify" package. From 52b3f0388b545a6060fb478c2c3ab35e51dc3c2e Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Thu, 6 Dec 2018 13:00:49 -0600 Subject: [PATCH 24/39] refactor(browser/growl.js): Adapt code to recommendations following review Modified `canNotify()` to use `Promise.resolve()` without a value. Updated `CanNotifyPromise` documentation to match. Modified `isPermitted()` to remove the IIFE used to test something then not removed. Now its `permitted` object always returns a function returning a promise, and that function is executed as return value of `isPermitted()`. --- lib/browser/growl.js | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/browser/growl.js b/lib/browser/growl.js index 3437791c17..57f64467ac 100644 --- a/lib/browser/growl.js +++ b/lib/browser/growl.js @@ -63,23 +63,29 @@ exports.notify = function(runner) { */ function isPermitted() { var permitted = { - granted: Promise.resolve(true), - denied: Promise.resolve(false), - default: (function ask() { - Notification.requestPermission().then(function(permission) { - return Promise.resolve(permission === 'granted'); + granted: function allow() { + return Promise.resolve(true); + }, + denied: function deny() { + return Promise.resolve(false); + }, + default: function ask() { + return new Promise(function(resolve, reject) { + Notification.requestPermission().then(function(permission) { + return resolve(permission === 'granted'); + }); }); - })() + } }; - return permitted[Notification.permission]; + return permitted[Notification.permission](); } /** * A promise determining if notification can proceed. * * @promise Growl~CanNotifyPromise - * @fulfill {boolean} Notification allowed (true). + * @fulfill {undefined} Notification allowed. * @reject {Error} Notification denied (or request unacknowledged) by user. */ @@ -108,7 +114,7 @@ function canNotify(value) { var reason = 'not permitted by user (' + why + ')'; return Promise.reject(new Error(reason)); } - return Promise.resolve(true); + return Promise.resolve(); } /** From 2d73c2a9c1bf694e3f6b6a09946d4779b71b984b Mon Sep 17 00:00:00 2001 From: Paul Roebuck Date: Thu, 6 Dec 2018 16:01:16 -0600 Subject: [PATCH 25/39] docs(docs/index.md): Update browser usage links to reference upcoming major release Changed "unpkg.com" links to reference the mocha "6.0.0" release. --- docs/index.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/index.md b/docs/index.md index b915021f03..a8b71e6e04 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1236,13 +1236,13 @@ A typical setup might look something like the following, where we call `mocha.se Mocha Tests - +
- + + - + +