Jsdom: モックキャンバス

作成日 2017年03月22日  ·  25コメント  ·  ソース: jsdom/jsdom

実際の実装( canvas / canvas-prebuilt )なしでキャンバスをモックすることは可能ですか?

キャンバスの機能は私にとってそれほど重要ではないため、このエラーが発生しないようにしたいと思います。

Not implemented: HTMLCanvasElement.prototype.getContext (without installing the canvas npm package)

最も参考になるコメント

これが私が思いついたキャンバスをモックする簡単な方法です:

//
// Mock Canvas / Context2D calls
//
function mockCanvas (window) {
    window.HTMLCanvasElement.prototype.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(){},
            measureText: function(){
                return { width: 0 };
            },
            transform: function(){},
            rect: function(){},
            clip: function(){},
        };
    }

    window.HTMLCanvasElement.prototype.toDataURL = function () {
        return "";
    }
}
const document = jsdom.jsdom(undefined, {
  virtualConsole: jsdom.createVirtualConsole().sendTo(console)
});

const window = document.defaultView;
mockCanvas(window);

全てのコメント25件

誰かがこれを必要とする場合に備えて、これが私がそれを解決した方法です:

const utils = require("jsdom/lib/jsdom/utils");
const canvasMock = require("canvas-mock");

function Canvas () {
    canvasMock(this);
    this.toDataURL = function() { return ""; }
}
utils.Canvas = Canvas;

しないでください。 将来のパッチリリースで壊れます。 代わりに、getContext()メソッド、つまりwindow.HTMLCanvasElement.prototype.getContext = ..をオーバーライドします。

ありがとう@domenic

@domenicそれを機能させることができません。 オーバーライドされたメソッドが呼び出されません。 私は次のようにjestとセットアップスクリプトファイルを使用します。

import { jsdom } from 'jsdom';
import mockLocalStorage from './mockLocalStorage';
import jQuery from 'jquery';
import Backbone from 'backbone';
import moment from 'moment';

const dom = jsdom('<!doctype html><html><body></body></html>');
const { window } = dom.defaultView;

function copyProps(src, target) {
    const props = Object.getOwnPropertyNames(src)
        .filter(prop => typeof target[prop] === 'undefined')
        .map(prop => Object.getOwnPropertyDescriptor(src, prop));
    Object.defineProperties(target, props);
}

//Mock canvas (used by qtip)
window.HTMLCanvasElement.prototype.getContext = () => {
    return {};
};

global.window = window;
global.document = window.document;
global.navigator = {
    userAgent: 'node.js',
};
global.localStorage = mockLocalStorage;
global.jQuery = jQuery;
global.$ = jQuery;
global.fetch = () => Promise.resolve();
Backbone.$ = jQuery;
copyProps(window, global);

//Mock Mousetrap (only works in browser)
jest.mock('mousetrap', () => { return { bind: () => {}}});

//Set moment locale for all tests
moment.locale('sv');

ノード内のグローバルを汚染して申し訳ありませんが、これは非常に古くて大きなコードベースであり、Jestに移行しようとしています。
ジェストバージョン:21.2.1
Jsdomバージョン:9.12.0

キャンバスのモック(Windowsではサポートされていないためキャンバスパッケージを使用しない)が、問題のコメントとしてだけでなく、公式ドキュメントでカバーされていれば非常に便利です。

Windowsではサポートされていないため、canvasパッケージを使用しません

なぜcanvas-prebuiltオプションがないのですか? これが私たちのプロジェクトで問題なく使用しているものです(Win、Mac、Linux、ただしすべてがx64である必要があります)。

一般的に、ドキュメントを追加したり、1回限りのモックの問題を支援したりする予定はありません。 これについては、 https: //github.com/tmpvar/jsdom#intervening -before-parsingで一般的に説明しており、特定の問題は特定のコードベースに関連しています。

これが私が思いついたキャンバスをモックする簡単な方法です:

//
// Mock Canvas / Context2D calls
//
function mockCanvas (window) {
    window.HTMLCanvasElement.prototype.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(){},
            measureText: function(){
                return { width: 0 };
            },
            transform: function(){},
            rect: function(){},
            clip: function(){},
        };
    }

    window.HTMLCanvasElement.prototype.toDataURL = function () {
        return "";
    }
}
const document = jsdom.jsdom(undefined, {
  virtualConsole: jsdom.createVirtualConsole().sendTo(console)
});

const window = document.defaultView;
mockCanvas(window);

どうもありがとう! キャンバスのビルド済みパッケージが機能しているようです。

こんにちは@cattermo
depsにcanvas-prebuiltを追加しましたが、jestの構成を変更する必要がありますか? 私はそれが私に与える仕事にそれを作ることができません
Not implemented: HTMLCanvasElement.prototype.toBlob (without installing the canvas npm package)

@micabe
構成を変更しませんでした。 Jsdomは、node_modulesに存在する場合、ビルド済みのキャンバスを取得します。

たぶん、その特定の機能はサポートされていませんか?

yarn cache clean後で動作しています。ご迷惑をおかけして申し訳ありません。 ありがとう@cattermo

たぶん、 jest-canvas-mockが役立つでしょう。

解決策は簡単です。devDependencyとしてcanvasをインストールし、jestテストを再実行するだけです。

参照: https

jsdomがlib / jsdom / utils.jsでキャンバスモジュールをチェックする方法のため、これはまだ機能していません。

  exports.Canvas = require(moduleName);
  if (typeof exports.Canvas !== "function") {
    // In browserify, the require will succeed but return an empty object
    exports.Canvas = null;
  }

require( 'canvas')を実行すると、Canvas関数を持つオブジェクトが返されます。 Canvas関数をすぐに返すわけではありません。 それとも私はこの問題について間違っていますか? 私がcanvas-prebuiltモジュールを使用していたときはうまく機能しましたが、canvasモジュールには別のAPIがあるようです。 私はcanvasの最新バージョン2.0.1を使用しています。
編集
以前のメジャーバージョン(1.6.x)をテストしましたが、正常に動作します。これは、JSDOMが処理していないAPIの変更です。

あなたはただすることができます:

HTMLCanvasElement.prototype.getContext = jest.fn()

実際の実装が重要でない場合

jsdomがlib / jsdom / utils.jsでキャンバスモジュールをチェックする方法のため、これはまだ機能していません。

  exports.Canvas = require(moduleName);
  if (typeof exports.Canvas !== "function") {
    // In browserify, the require will succeed but return an empty object
    exports.Canvas = null;
  }

require( 'canvas')を実行すると、Canvas関数を持つオブジェクトが返されます。 Canvas関数をすぐに返すわけではありません。 それとも私はこの問題について間違っていますか? 私がcanvas-prebuiltモジュールを使用していたときはうまく機能しましたが、canvasモジュールには別のAPIがあるようです。 私はcanvasの最新バージョン2.0.1を使用しています。
編集
以前のメジャーバージョン(1.6.x)をテストしましたが、正常に動作します。これは、JSDOMが処理していないAPIの変更です。

私は同じ問題を抱えています。 修正はしばらく前にhttps://github.com/jsdom/jsdom/pull/1964でマージされ、バージョン13以降で利用可能であるため、問題はjsdomにないようです。
ただし、 jest-environment-jsdomjsdomバージョンはまだ^11.5.1あり、それが問題の原因であると思います。
https://github.com/facebook/jest/blob/2e2d2c8dedb76e71c0dfa85ed36b81d1f89e0d87/packages/jest-environment-jsdom/package.json#L14

canvasをインストールせずに、またはcanvas-prebuiltは、HTMLCanvasElementに関連するエラーや、この問題を回避するためのハックとして@endelによってうまく提案された他のcanvasメソッドを取り除くことができました。 @hustccが提案したように、 jest-canvas-mockを使用して、非常にクリーンなソリューションを見つけました。 技術的な詳細については、このコメントをご覧ください。

「nullのwebkitBackingStorePixelRatioを読み取れません」や「
実装されていません:HTMLCanvasElement.prototype.getContext(canvas npmパッケージをインストールせずに)」、canvas(-prebuilt)をインストールするだけでは不十分でした。package-lock.json内に入り、jsdom13を指すようにjest-environment-jsdomを修正しました。 、node_modulesを破棄し、npm installを再実行しました。エラーメッセージは消えました。 @ paraditeは正しいと思い、jestに対するチケットを開きました。

https://github.com/facebook/jest/issues/8016

フィードバックを得ました。 これは、jestが古いバージョンのノードでスタックしていることに関連しています。 最新のノードのサポートが必要な場合は、 https

@ grtjn - jest-environment-jsdom-thirteenの依存関係を確認しましたが、私の場合でも、これら2つのまったく同じエラーが発生しました

Error: Not implemented: HTMLCanvasElement.prototype.getContext (without installing the canvas npm package)
TypeError: Cannot read property 'fillRect' of null

前述のソリューションを維持しますが、ノードバージョンについては、このような環境で問題が発生したため、10.15が非推奨であるとは言えません。

Angular CLI: 7.2.4
Node: 10.15.0
OS: win32 x64
Angular: 7.2.4

参考: "testEnvironment": "jest-environment-jsdom-thirteen"をjest構成に追加し、canvasパッケージとCairoOSツールセットをインストールする必要がありました。 キャンバスプリビルドは私にはうまくいかなかったようです。 私はVueを使用しています。

Cairo OSツールセットの依存関係へのリンク? それが見つかりませんでした。

@danieldanielecki 「canvas」パッケージのメインページを参照してください: https//www.npmjs.com/package/canvas#compiling

@grtjnありがとういつかそれを利用するでしょう。 私はそれを見逃していましたが、私のソリューションよりも複雑に見えるので、プロジェクトをそのまま維持します。

necropostに申し訳ありませんが、jest-environment-jsdom-thirteenをインストールするという@grtjnの提案(最近なので14を使用しました)で問題が修正されました。 jest-canvas-mockを使用してみましたが、OffscreenCanvasが利用できないときにnode-canvasを使用してcreateImageBitmapを偽造するという奇妙なことを行いました。これは多くのブラウザーにはなく、jest-canvas-mockはこれによってかなり混乱しました。 たぶん、別の日にそれが機能するようになるでしょう...それはクールなモックライブラリです。

このページは役に立ちましたか?
0 / 5 - 0 評価