Jsdom: Kanvas tiruan

Dibuat pada 22 Mar 2017  ·  25Komentar  ·  Sumber: jsdom/jsdom

Apakah mungkin untuk mengejek kanvas tanpa memiliki implementasi yang sebenarnya ( canvas / canvas-prebuilt )?

Saya ingin mencegah kesalahan ini terjadi, karena fungsi kanvas tidak terlalu penting bagi saya:

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

Komentar yang paling membantu

Inilah cara sederhana untuk mengejek kanvas yang saya buat:

//
// 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);

Semua 25 komentar

Jika ada yang membutuhkan ini, inilah cara saya menyelesaikannya:

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

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

Tolong jangan lakukan itu. Ini akan pecah dalam rilis patch mendatang. Sebagai gantinya, timpa metode getContext(), yaitu window.HTMLCanvasElement.prototype.getContext = ...

Terima kasih @domenic !

@domenic Saya tidak bisa

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');

Maaf telah mencemari global dalam simpul tetapi ini adalah basis kode yang sangat lama dan besar yang saya coba migrasikan ke Jest.
Versi lelucon: 21.2.1
Versi Jsdom: 9.12.0

Akan sangat bagus jika mengejek kanvas (tanpa menggunakan paket kanvas karena tidak didukung di Windows) dicakup oleh dokumen resmi dan tidak hanya sebagai komentar dalam suatu masalah.

tanpa menggunakan paket kanvas karena tidak didukung di Windows

Mengapa kanvas-prebuilt bukan pilihan untuk Anda? Itulah yang kami gunakan dalam proyek kami tanpa masalah (Win, Mac dan Linux, meskipun semuanya harus x64).

Secara umum kami tidak berencana untuk menambahkan dokumen atau membantu dengan masalah ejekan satu kali. Kami telah membahas ini di https://github.com/tmpvar/jsdom#intervening -before-parsing secara umum dan masalah spesifik apa pun akan terkait dengan basis kode spesifik Anda.

Inilah cara sederhana untuk mengejek kanvas yang saya buat:

//
// 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);

Terima kasih banyak! Paket bawaan kanvas tampaknya berfungsi.

Halo @cattermo ,
Saya telah menambahkan canvas-prebuilt ke deps saya, apakah saya perlu mengubah konfigurasi lelucon saya? Saya tidak bisa membuatnya bekerja itu memberi saya
Not implemented: HTMLCanvasElement.prototype.toBlob (without installing the canvas npm package)

@micabe
Saya tidak membuat perubahan konfigurasi apa pun. Jsdom akan mengambil kanvas prebuilt jika ada di node_modules.

Mungkin fungsi spesifik itu tidak didukung?

Ini berfungsi sekarang setelah yarn cache clean Maaf mengganggu Anda! terima kasih @cattermo

Mungkin jest-canvas-mock bisa membantu.

Solusinya sederhana, cukup instal canvas sebagai devDependency dan jalankan kembali tes lelucon Anda.

ref: https://github.com/jsdom/jsdom#canvas -support

Itu masih tidak berfungsi karena cara jsdom memeriksa modul kanvas di 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;
  }

Melakukan require('canvas') mengembalikan Objek yang memiliki fungsi Canvas. Itu tidak langsung mengembalikan fungsi Canvas. Atau apakah saya salah dalam masalah ini? Ini bekerja dengan baik ketika saya menggunakan modul canvas-prebuilt, tetapi tampaknya modul canvas memiliki API yang berbeda. Saya menggunakan versi terbaru kanvas, 2.0.1.
Sunting
Saya menguji versi utama sebelumnya (1.6.x) dan berfungsi dengan baik, ini adalah perubahan API yang tidak ditangani oleh JSDOM.

Anda hanya dapat melakukan:

HTMLCanvasElement.prototype.getContext = jest.fn()

jika implementasi aktual tidak penting bagi Anda

Itu masih tidak berfungsi karena cara jsdom memeriksa modul kanvas di 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;
  }

Melakukan require('canvas') mengembalikan Objek yang memiliki fungsi Canvas. Itu tidak langsung mengembalikan fungsi Canvas. Atau apakah saya salah dalam masalah ini? Ini bekerja dengan baik ketika saya menggunakan modul canvas-prebuilt, tetapi tampaknya modul canvas memiliki API yang berbeda. Saya menggunakan versi terbaru kanvas, 2.0.1.
Sunting
Saya menguji versi utama sebelumnya (1.6.x) dan berfungsi dengan baik, ini adalah perubahan API yang tidak ditangani oleh JSDOM.

Saya memiliki masalah yang sama. Sepertinya masalahnya bukan pada jsdom karena perbaikannya digabungkan beberapa waktu lalu di https://github.com/jsdom/jsdom/pull/1964 dan tersedia sejak versi 13 .
Namun, versi jsdom di jest-environment-jsdom masih macet di ^11.5.1 dan saya yakin itu yang menyebabkan masalah:
https://github.com/facebook/jest/blob/2e2d2c8dedb76e71c0dfa85ed36b81d1f89e0d87/packages/jest-environment-jsdom/package.json#L14

Tanpa menginstal canvas , atau canvas-prebuilt dapat menghilangkan kesalahan yang terkait dengan HTMLCanvasElement, serta metode kanvas lainnya yang diusulkan dengan baik oleh @endel sebagai peretasan untuk mengatasi masalah ini. Seperti yang diusulkan @hustcc , gunakan jest-canvas-mock dengan menemukan solusi yang cukup bersih. Untuk detail teknis silakan lihat di komentar ini .

Saya melihat pesan seperti "Tidak dapat membaca webkitBackingStorePixelRatio of null", serta "
Tidak diimplementasikan: HTMLCanvasElement.prototype.getContext (tanpa menginstal paket canvas npm)", dan menginstal canvas(-prebuilt) tidak cukup. Saya masuk ke dalam package-lock.json, memperbaiki jest-environment-jsdom untuk menunjuk ke jsdom 13 , membuang node_modules, dan menjalankan ulang npm install. Pesan kesalahan hilang. Saya pikir @paradite benar, dan membuka tiket melawan lelucon:

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

Mendapat umpan balik. Ini terkait dengan lelucon yang terjebak dengan versi simpul yang lebih lama. Jika Anda memerlukan dukungan untuk simpul terbaru, lihat di sini: https://www.npmjs.com/package/jest-environment-jsdom-thirteen. Ini hanya lelucon, jadi mungkin sedikit di luar topik di sini. Berbagi apapun untuk anak cucu..

@grtjn - memeriksa ketergantungan lelucon-lingkungan-jsdom-tiga belas , tetapi dalam kasus saya, saya masih mendapatkan 2 kesalahan yang sama persis ini

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

Menjaga solusi saya disebutkan sebelumnya, tentang versi Node saya tidak akan mengatakan 10.15 adalah yang sudah usang, karena saya mendapat masalah untuk lingkungan seperti itu

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

FYI: Saya harus menambahkan "testEnvironment": "jest-environment-jsdom-thirteen" ke konfigurasi lelucon saya, dan menginstal paket kanvas, serta perangkat OS Kairo. canvas-prebuilt sepertinya tidak berfungsi untuk saya. Saya menggunakan Vue.

Tautan ke ketergantungan perangkat OS Kairo? Tidak dapat menemukan yang itu.

@danieldanielecki Lihat halaman utama paket 'kanvas': https://www.npmjs.com/package/canvas#compiling

@grtjn terima kasih untuk itu - mungkin suatu saat akan memanfaatkannya. Saya melewatkannya, tetapi terlihat lebih rumit daripada solusi saya sehingga menjaga proyek apa adanya.

Maaf necropost tapi saran @grtjn untuk menginstal jest-environment-jsdom-thirteen (saya menggunakan empat belas hanya karena lebih baru) memperbaiki masalah saya. Saya mencoba menggunakan jest-canvas-mock tetapi kami melakukan beberapa hal aneh di mana kami memalsukan createImageBitmap menggunakan node-canvas ketika OffscreenCanvas tidak tersedia, yang tidak ada di banyak browser, dan jest-canvas-mock menjadi sangat bingung dengan ini. Mungkin lain hari kita akan membuatnya berfungsi ... itu adalah perpustakaan tiruan yang keren.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat