UNPKG

d2-ui

Version:
180 lines (148 loc) 4.09 kB
var extend = require('util')._extend var Path = require('path') /* * store original global keys */ var blacklist = Object.keys(global) blacklist.push('constructor') /* * default config */ var defaults = { globalize: true, console: true, useEach: false, skipWindowCheck: false, html: "<!doctype html><html><head><meta charset='utf-8'></head>" + '<body></body></html>' } /* * simple jsdom integration. * You can pass jsdom options in, too: * * require('./support/jsdom')({ * src: [ jquery ] * }) */ module.exports = function (_options) { var options = extend(extend({}, defaults), _options) var keys = [] var before = options.useEach ? global.beforeEach : global.before var after = options.useEach ? global.afterEach : global.after /* * register jsdom before the entire test suite */ before(function (next) { if (global.window && !options.skipWindowCheck) { throw new Error( 'mocha-jsdom: already a browser environment, or mocha-jsdom invoked ' + "twice. use 'skipWindowCheck' to disable this check.") } require('jsdom').env( extend(extend({}, options), { done: done })) function done (errors, window) { if (options.globalize) { propagateToGlobal(window) } else { global.window = window } if (options.console) { window.console = global.console } if (errors) { return next(getError(errors)) } next(null) } }) /* * undo keys from being propagated to global after the test suite */ after(function () { if (options.globalize) { keys.forEach(function (key) { delete global[key] }) } else { delete global.window } }) /* * propagate keys from `window` to `global` */ function propagateToGlobal (window) { for (var key in window) { if (!window.hasOwnProperty(key)) continue if (~blacklist.indexOf(key)) continue if (global[key]) { if (process.env.JSDOM_VERBOSE) { console.warn("[jsdom] Warning: skipping cleanup of global['" + key + "']") } continue } keys.push(key) global[key] = window[key] } } /* * re-throws jsdom errors */ function getError (errors) { var data = errors[0].data var err = data.error err.message = err.message + ' [jsdom]' // clean up stack trace if (err.stack) { err.stack = err.stack.split('\n') .reduce(function (list, line) { if (line.match(/node_modules.+(jsdom|mocha)/)) { return list } line = line .replace(/file:\/\/.*<script>/g, '<script>') .replace(/:undefined:undefined/g, '') list.push(line) return list }, []).join('\n') } return err } } module.exports.rerequire = rerequire /** * Requires a module via `require()`, but invalidates the cache so it may be * called again in the future. Useful for `mocha --watch`. * * var rerequire = require('mocha-jsdom').rerequire * var $ = rerequire('jquery') */ function rerequire (module) { if (module[0] === '.') { module = Path.join(Path.dirname(getCaller()), module) } var oldkeys = Object.keys(require.cache) var result = require(module) var newkeys = Object.keys(require.cache) newkeys.forEach(function (newkey) { if (!~oldkeys.indexOf(newkey)) { delete require.cache[newkey] } }) return result } /** * Internal: gets the filename of the caller function. The `offset` defines how * many hops away it's expected to be from in the stack trace. * * See: http://stackoverflow.com/questions/16697791/nodejs-get-filename-of-caller-function */ function getCaller (offset) { /* eslint-disable handle-callback-err */ if (typeof offset !== 'number') offset = 1 var old = Error.prepareStackTrace var err = new Error() Error.prepareStackTrace = function (err, stack) { return stack } var fname = err.stack[1 + offset].getFileName() Error.prepareStackTrace = old return fname }