Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More general way of adding getContext() to a mock canvas object. #2

Open
wimrijnders opened this issue Oct 3, 2017 · 1 comment
Open

Comments

@wimrijnders
Copy link

wimrijnders commented Oct 3, 2017

The issue with the current way of doing it, is that the change is not global; i.e. the mock canvas object is reset during regular usage by any component. This makes it kind of useless for unit tests.

The following works for me, I hope you can adapt something similar:

var myHackedInCanvas;    // Use one global canvas instance for all calls to createElement('canvas');

function replaceCanvasContext (el) {
  // The previous export
}

/**
 * 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 possibly 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 (myHackedInCanvas === undefined) {
        myHackedInCanvas = f.call(d, 'canvas');
        replaceCanvasContext(myHackedInCanvas);
      }
      return myHackedInCanvas;
    } else {
      return f.call(d, param);
    }
  };
}

module.exports = mockify;

This does change the object to pass in, so in a sense breaking. I personally do not care, but you may think different. Perhaps you know a better way.

@hustcc
Copy link

hustcc commented Dec 26, 2017

For testcase of echarts-for-react, we should mock echarts which is a chart library based on canvas.

So do something by a jest mock plugin: jest-canvas-mock, and use it to test echarts, works fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants