vis.js is a dynamic, browser-based visualization library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
4.7 KiB

  1. /**
  2. * Set up mock 2D context, for usage in unit tests.
  3. *
  4. * Adapted from: https://github.com/Cristy94/canvas-mock
  5. */
  6. var jsdom = require('jsdom');
  7. var jsdom_global = require('jsdom-global');
  8. var canvasMock; // Use one canvas instance for all calls to createElement('canvas');
  9. function replaceCanvasContext (el) {
  10. el.getContext = function() {
  11. return {
  12. fillRect: function() {},
  13. clearRect: function(){},
  14. getImageData: function(x, y, w, h) {
  15. return {
  16. data: new Array(w*h*4)
  17. };
  18. },
  19. putImageData: function() {},
  20. createImageData: function(){ return []},
  21. setTransform: function(){},
  22. drawImage: function(){},
  23. save: function(){},
  24. text: function(){},
  25. fillText: function(){},
  26. restore: function(){},
  27. beginPath: function(){},
  28. moveTo: function(){},
  29. lineTo: function(){},
  30. closePath: function(){},
  31. stroke: function(){},
  32. translate: function(){},
  33. scale: function(){},
  34. rotate: function(){},
  35. circle: function(){},
  36. arc: function(){},
  37. fill: function(){},
  38. //
  39. // Following added for vis.js unit tests
  40. //
  41. measureText: function(text) {
  42. return {
  43. width: 12*text.length,
  44. height: 14
  45. };
  46. }
  47. };
  48. }
  49. }
  50. /**
  51. * Overrides document.createElement(), in order to supply a custom canvas element.
  52. *
  53. * In the canvas element, getContext() is overridden in order to supply a simple
  54. * mock object for the 2D context. For all other elements, the call functions unchanged.
  55. *
  56. * The override is only done if there is no 2D context already present.
  57. * This allows for normal running in a browser, and for node.js the usage of 'canvas'.
  58. *
  59. * @param {object} window - current global window object. This can possibly come from module 'jsdom',
  60. * when running under node.js.
  61. * @private
  62. */
  63. function overrideCreateElement(window) {
  64. var d = window.document;
  65. var f = window.document.createElement;
  66. // Check if 2D context already present. That happens either when running in a browser,
  67. // or this is node.js with 'canvas' installed.
  68. var ctx = d.createElement('canvas').getContext('2d');
  69. if (ctx !== null && ctx !== undefined) {
  70. //console.log('2D context is present, no need to override');
  71. return;
  72. }
  73. window.document.createElement = function(param) {
  74. if (param === 'canvas') {
  75. if (canvasMock === undefined) {
  76. canvasMock = f.call(d, 'canvas');
  77. replaceCanvasContext(canvasMock);
  78. }
  79. return canvasMock;
  80. } else {
  81. return f.call(d, param);
  82. }
  83. };
  84. }
  85. /**
  86. * The override is only done if there is no 2D context already present.
  87. * This allows for normal running in a browser, and for node.js the usage of 'style'
  88. * property on a newly created svg element.
  89. *
  90. * @param {object} window - current global window object. This can possibly come from module 'jsdom',
  91. * when running under node.js.
  92. * @private
  93. */
  94. function overrideCreateElementNS(window) {
  95. var d = window.document;
  96. var f = window.document.createElementNS;
  97. window.document.createElementNS = function(namespaceURI, qualifiedName) {
  98. if (namespaceURI === 'http://www.w3.org/2000/svg') {
  99. var result = f.call(d, namespaceURI, qualifiedName);
  100. if (result.style == undefined) {
  101. result.style = {};
  102. return result;
  103. }
  104. }
  105. };
  106. }
  107. /**
  108. * Initialize the mock, jsdom and jsdom_global for unit test usage.
  109. *
  110. * Suppresses a warning from `jsdom` on usage of `getContext()`. A mock definition is added for
  111. * it, so the message is not relevant.
  112. *
  113. * @param {string} [html=''] html definitions which should be added to the jsdom definition
  114. * @returns {function} function to call in after(), to clean up for `jsdom_global`
  115. */
  116. function mockify(html = '') {
  117. // Start of message that we want to suppress.
  118. let msg = 'Error: Not implemented: HTMLCanvasElement.prototype.getContext'
  119. + ' (without installing the canvas npm package)';
  120. // Override default virtual console of jsdom
  121. const virtualConsole = new jsdom.VirtualConsole();
  122. // Set up a simple 'mock' console output. Only 'error' needs to be overridden
  123. let myConsole = {
  124. error: (msg) => {
  125. if (msg.indexOf(msg) === 0) {
  126. //console.error('all is well');
  127. } else {
  128. // All other messages pass through
  129. console.error(msg);
  130. }
  131. }
  132. };
  133. // Using the global catch instead of specific event handler, because I couldn't get them to work
  134. virtualConsole.sendTo(myConsole);
  135. let cleanupFunction = jsdom_global(
  136. html,
  137. { skipWindowCheck: true, virtualConsole: virtualConsole}
  138. );
  139. overrideCreateElement(window); // The actual initialization of canvas-mock
  140. overrideCreateElementNS(window);
  141. return cleanupFunction;
  142. }
  143. module.exports = mockify;