Skip to content
This repository has been archived by the owner on Jul 29, 2019. It is now read-only.

Use mock canvas object replacing canvas #3518

Merged
merged 4 commits into from
Oct 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ Link via cdnjs: http://cdnjs.com
Or download the library from the github project:
[https://github.com/almende/vis.git](https://github.com/almende/vis.git).


### Installing module `canvas`

Module `canvas` is only required if you need to run `vis.js` on `node.js` and require actual output. It is not required for regular usage in a browser.

Currently, the unit tests use a mock object for canvas which has limited but adequate functionality. If `canvas` is installed, that will be used silently in place of the mock object.

The issue with `canvas` is that it has an external dependency to `cairo`. This needs to be installed outside of the regular install as done by `npm`. Please consult [`node-canvas` github page](https://github.com/Automattic/node-canvas/wiki#desktop) for the correct installation procecure your platform


## Load

To use a component, include the javascript and css files of vis in your web page:
Expand Down Expand Up @@ -322,6 +332,9 @@ module: {

There is also an [demo-project](https://github.com/mojoaxel/vis-webpack-demo) showing the integration of vis.js using webpack.




## Test

To test the library, install the project dependencies once:
Expand Down
11 changes: 5 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,29 +34,28 @@
},
"dependencies": {
"emitter-component": "^1.1.1",
"moment": "^2.18.1",
"propagating-hammerjs": "^1.4.6",
"hammerjs": "^2.0.8",
"keycharm": "^0.2.0"
"keycharm": "^0.2.0",
"moment": "^2.18.1",
"propagating-hammerjs": "^1.4.6"
},
"devDependencies": {
"async": "^2.5.0",
"babel-core": "^6.25.0",
"babel-loader": "^7.1.1",
"babel-polyfill": "^6.23.0",
"babel-plugin-transform-es3-member-expression-literals": "^6.22.0",
"babel-plugin-transform-es3-property-literals": "^6.22.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.23.0",
"babel-preset-es2015": "^6.24.1",
"babel-runtime": "^6.23.0",
"babelify": "^7.3.0",
"canvas": "^1.6.5",
"clean-css": "^4.1.7",
"eslint": "^4.3.0",
"gulp": "^3.9.1",
"gulp-eslint": "^4.0.0",
"gulp-clean-css": "^3.7.0",
"gulp-concat": "^2.6.1",
"gulp-eslint": "^4.0.0",
"gulp-rename": "^1.2.2",
"gulp-util": "^3.0.8",
"jsdom": "9.12.0",
Expand Down
2 changes: 2 additions & 0 deletions test/Graph3d.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ var assert = require('assert');
var vis = require('../dist/vis');
var Graph3d = vis.Graph3d;
var jsdom_global = require('jsdom-global');
var canvasMockify = require('./canvas-mock');
var stdout = require('test-console').stdout;
var Validator = require("./../lib/shared/Validator").default;
//var {printStyle} = require('./../lib/shared/Validator');
Expand All @@ -16,6 +17,7 @@ describe('Graph3d', function () {
"<div id='mygraph'></div>",
{ skipWindowCheck: true}
);
canvasMockify(window);
this.container = document.getElementById('mygraph');
});

Expand Down
2 changes: 2 additions & 0 deletions test/Label.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ var Label = require('../lib/network/modules/components/shared/Label').default;
var NodesHandler = require('../lib/network/modules/NodesHandler').default;
var util = require('../lib/util');
var jsdom_global = require('jsdom-global');
var canvasMockify = require('./canvas-mock');
var vis = require('../dist/vis');
var Network = vis.network;

Expand Down Expand Up @@ -324,6 +325,7 @@ describe('Network Label', function() {
"<div id='mynetwork'></div>",
{ skipWindowCheck: true}
);
canvasMockify(window);
this.container = document.getElementById('mynetwork');
});

Expand Down
8 changes: 6 additions & 2 deletions test/Network.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ var fs = require('fs');
var assert = require('assert');
var vis = require('../dist/vis');
var Network = vis.network;
var jsdom_global = require('jsdom-global');
var stdout = require('test-console').stdout;
var Validator = require("./../lib/shared/Validator").default;
var jsdom_global = require('jsdom-global');
var canvasMockify = require('./canvas-mock');
var {allOptions, configureOptions} = require('./../lib/network/options.js');
//var {printStyle} = require('./../lib/shared/Validator');

Expand Down Expand Up @@ -222,13 +223,16 @@ function checkFontProperties(fontItem, checkStrict = true) {





describe('Network', function () {

before(function() {
this.jsdom_global = jsdom_global(
"<div id='mynetwork'></div>",
{ skipWindowCheck: true}
);
canvasMockify(window);
this.container = document.getElementById('mynetwork');
});

Expand Down Expand Up @@ -324,6 +328,7 @@ describe('Network', function () {
* The real deterrent is eslint rule 'guard-for-in`.
*/
it('can deal with added fields in Array.prototype', function (done) {
var canvas = window.document.createElement('canvas');
Array.prototype.foo = 1; // Just add anything to the prototype
Object.prototype.bar = 2; // Let's screw up hashes as well

Expand Down Expand Up @@ -615,7 +620,6 @@ describe('Edge', function () {

describe('Clustering', function () {


it('properly handles options allowSingleNodeCluster', function() {
var [network, data, numNodes, numEdges] = createSampleNetwork();
data.edges.update({from: 1, to: 11,});
Expand Down
90 changes: 90 additions & 0 deletions test/canvas-mock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/**
* Set up mock 2D context, for usage in unit tests.
*
* Adapted from: https://github.com/Cristy94/canvas-mock
*/

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(){},
fillText: function(){},
restore: function(){},
beginPath: function(){},
moveTo: function(){},
lineTo: function(){},
closePath: function(){},
stroke: function(){},
translate: function(){},
scale: function(){},
rotate: function(){},
arc: function(){},
fill: function(){},

//
// Following added for vis.js unit tests
//

measureText: function(text) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spacing looks off

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, this code is a module which I took from here and adapted it to own needs when I realized it wasn't completely fit for the purpose.

If think you mean this spacing?

      measureText: function(text) {
        return {
          width:>>  <<12*text.length,
          height: 14
        };
      },
};

Otherwise, I don't know what you mean. I have a habit of aligning related stuff, but indeed it's not needed here with only two lines.


Ah wait, there's tabs there. That's probably what you mean. Ah, right, that's from the original. I'll change it to spaces.

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} the current global window object. This can possible come from module 'jsdom',
* when running under node.js.
*/
function mockify(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);
}
};
}

module.exports = mockify;