/**
|
|
* Set up mock 2D context, for usage in unit tests.
|
|
*
|
|
* Adapted from: https://github.com/Cristy94/canvas-mock
|
|
*/
|
|
var jsdom = require('jsdom');
|
|
var jsdom_global = require('jsdom-global');
|
|
|
|
var canvasMock; // Use one canvas instance for all calls to createElement('canvas');
|
|
|
|
|
|
function replaceCanvasContext (el) {
|
|
el.getContext = function() {
|
|
return {
|
|
fillRect: function() {},
|
|
clearRect: function(){},
|
|
getImageData: function(x, y, w, h) {
|
|
return {
|
|
data: new Array(w*h*4)
|
|
};
|
|
},
|
|
putImageData: function() {},
|
|
createImageData: function(){ return []},
|
|
setTransform: function(){},
|
|
drawImage: function(){},
|
|
save: function(){},
|
|
text: function(){},
|
|
fillText: function(){},
|
|
restore: function(){},
|
|
beginPath: function(){},
|
|
moveTo: function(){},
|
|
lineTo: function(){},
|
|
closePath: function(){},
|
|
stroke: function(){},
|
|
translate: function(){},
|
|
scale: function(){},
|
|
rotate: function(){},
|
|
circle: function(){},
|
|
arc: function(){},
|
|
fill: function(){},
|
|
|
|
//
|
|
// Following added for vis.js unit tests
|
|
//
|
|
|
|
measureText: function(text) {
|
|
return {
|
|
width: 12*text.length,
|
|
height: 14
|
|
};
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Overrides document.createElement(), in order to supply a custom canvas element.
|
|
*
|
|
* In the canvas element, getContext() is overridden in order to supply a simple
|
|
* mock object for the 2D context. For all other elements, the call functions unchanged.
|
|
*
|
|
* The override is only done if there is no 2D context already present.
|
|
* This allows for normal running in a browser, and for node.js the usage of 'canvas'.
|
|
*
|
|
* @param {object} window - current global window object. This can possibly come from module 'jsdom',
|
|
* when running under node.js.
|
|
* @private
|
|
*/
|
|
function overrideCreateElement(window) {
|
|
var d = window.document;
|
|
var f = window.document.createElement;
|
|
|
|
// Check if 2D context already present. That happens either when running in a browser,
|
|
// or this is node.js with 'canvas' installed.
|
|
var ctx = d.createElement('canvas').getContext('2d');
|
|
if (ctx !== null && ctx !== undefined) {
|
|
//console.log('2D context is present, no need to override');
|
|
return;
|
|
}
|
|
|
|
window.document.createElement = function(param) {
|
|
if (param === 'canvas') {
|
|
if (canvasMock === undefined) {
|
|
canvasMock = f.call(d, 'canvas');
|
|
replaceCanvasContext(canvasMock);
|
|
}
|
|
return canvasMock;
|
|
} else {
|
|
return f.call(d, param);
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* The override is only done if there is no 2D context already present.
|
|
* This allows for normal running in a browser, and for node.js the usage of 'style'
|
|
* property on a newly created svg element.
|
|
*
|
|
* @param {object} window - current global window object. This can possibly come from module 'jsdom',
|
|
* when running under node.js.
|
|
* @private
|
|
*/
|
|
function overrideCreateElementNS(window) {
|
|
var d = window.document;
|
|
var f = window.document.createElementNS;
|
|
|
|
window.document.createElementNS = function(namespaceURI, qualifiedName) {
|
|
if (namespaceURI === 'http://www.w3.org/2000/svg') {
|
|
var result = f.call(d, namespaceURI, qualifiedName);
|
|
if (result.style == undefined) {
|
|
result.style = {};
|
|
return result;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Initialize the mock, jsdom and jsdom_global for unit test usage.
|
|
*
|
|
* Suppresses a warning from `jsdom` on usage of `getContext()`. A mock definition is added for
|
|
* it, so the message is not relevant.
|
|
*
|
|
* @param {string} [html=''] html definitions which should be added to the jsdom definition
|
|
* @returns {function} function to call in after(), to clean up for `jsdom_global`
|
|
*/
|
|
function mockify(html = '') {
|
|
// Start of message that we want to suppress.
|
|
let msg = 'Error: Not implemented: HTMLCanvasElement.prototype.getContext'
|
|
+ ' (without installing the canvas npm package)';
|
|
|
|
// Override default virtual console of jsdom
|
|
const virtualConsole = new jsdom.VirtualConsole();
|
|
|
|
// Set up a simple 'mock' console output. Only 'error' needs to be overridden
|
|
let myConsole = {
|
|
error: (msg) => {
|
|
if (msg.indexOf(msg) === 0) {
|
|
//console.error('all is well');
|
|
} else {
|
|
// All other messages pass through
|
|
console.error(msg);
|
|
}
|
|
}
|
|
};
|
|
|
|
// Using the global catch instead of specific event handler, because I couldn't get them to work
|
|
virtualConsole.sendTo(myConsole);
|
|
|
|
let cleanupFunction = jsdom_global(
|
|
html,
|
|
{ skipWindowCheck: true, virtualConsole: virtualConsole}
|
|
);
|
|
|
|
overrideCreateElement(window); // The actual initialization of canvas-mock
|
|
|
|
overrideCreateElementNS(window);
|
|
|
|
return cleanupFunction;
|
|
}
|
|
|
|
|
|
module.exports = mockify;
|