Spaces:
Running
Running
; | |
/** | |
* Desktop Notifications module. | |
* @module Growl | |
*/ | |
const os = require('os'); | |
const path = require('path'); | |
const {sync: which} = require('which'); | |
const {EVENT_RUN_END} = require('../runner').constants; | |
const {isBrowser} = require('../utils'); | |
/** | |
* @summary | |
* Checks if Growl notification support seems likely. | |
* | |
* @description | |
* Glosses over the distinction between an unsupported platform | |
* and one that lacks prerequisite software installations. | |
* | |
* @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 notification support can be expected | |
*/ | |
exports.isCapable = () => { | |
if (!isBrowser()) { | |
return getSupportBinaries().reduce( | |
(acc, binary) => acc || Boolean(which(binary, {nothrow: true})), | |
false | |
); | |
} | |
return false; | |
}; | |
/** | |
* Implements desktop notifications as a pseudo-reporter. | |
* | |
* @public | |
* @see {@link Mocha#_growl} | |
* @param {Runner} runner - Runner instance. | |
*/ | |
exports.notify = runner => { | |
runner.once(EVENT_RUN_END, () => { | |
display(runner); | |
}); | |
}; | |
/** | |
* Displays the notification. | |
* | |
* @private | |
* @param {Runner} runner - Runner instance. | |
*/ | |
const display = runner => { | |
const growl = require('growl'); | |
const stats = runner.stats; | |
const symbol = { | |
cross: '\u274C', | |
tick: '\u2705' | |
}; | |
let _message; | |
let message; | |
let title; | |
if (stats.failures) { | |
_message = `${stats.failures} of ${stats.tests} 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 | |
const options = { | |
image: logo(), | |
name: 'mocha', | |
title | |
}; | |
growl(message, options, onCompletion); | |
}; | |
/** | |
* @summary | |
* Callback for result of attempted Growl notification. | |
* | |
* @description | |
* Despite its appearance, this is <strong>not</strong> an Error-first | |
* callback -- all parameters are populated regardless of success. | |
* | |
* @private | |
* @callback Growl~growlCB | |
* @param {*} err - Error object, or <code>null</code> if successful. | |
*/ | |
function onCompletion(err) { | |
if (err) { | |
// As notifications are tangential to our purpose, just log the error. | |
const message = | |
err.code === 'ENOENT' ? 'prerequisite software not found' : err.message; | |
console.error('notification error:', message); | |
} | |
} | |
/** | |
* Returns Mocha logo image path. | |
* | |
* @private | |
* @return {string} Pathname of Mocha logo | |
*/ | |
const logo = () => { | |
return path.join(__dirname, '..', 'assets', 'mocha-logo-96.png'); | |
}; | |
/** | |
* @summary | |
* Gets 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 | |
*/ | |
const getSupportBinaries = () => { | |
const binaries = { | |
Darwin: ['terminal-notifier', 'growlnotify'], | |
Linux: ['notify-send', 'growl'], | |
Windows_NT: ['growlnotify.exe'] | |
}; | |
return binaries[os.type()] || []; | |
}; | |