¿Es posible simular el lienzo sin tener la implementación real ( canvas
/ canvas-prebuilt
)?
Me gustaría evitar que ocurra este error, ya que la funcionalidad del lienzo no es realmente importante para mí:
Not implemented: HTMLCanvasElement.prototype.getContext (without installing the canvas npm package)
En caso de que alguien necesite esto, así es como lo resolví:
const utils = require("jsdom/lib/jsdom/utils");
const canvasMock = require("canvas-mock");
function Canvas () {
canvasMock(this);
this.toDataURL = function() { return ""; }
}
utils.Canvas = Canvas;
Por favor, no hagas eso. Se romperá en una futura versión de parche. En su lugar, anule el método getContext (), es decir, window.HTMLCanvasElement.prototype.getContext = ...
¡Gracias @domenic !
@domenic No puedo hacer que eso funcione. No se llama a mi método anulado. Utilizo el archivo de script de configuración y broma de la siguiente manera:
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');
Lo siento por contaminar global en el nodo, pero esta es una base de código muy antigua y grande que intento migrar a Jest.
Versión de broma: 21.2.1
Versión de Jsdom: 9.12.0
Sería muy bueno si los documentos oficiales cubrieran la burla de lienzo (sin usar el paquete de lienzo, ya que no es compatible con Windows) y no solo como un comentario en un problema.
sin usar el paquete de lienzo ya que no es compatible con Windows
¿Por qué el lienzo preconstruido no es una opción para usted? Eso es lo que estamos usando en nuestro proyecto sin ningún problema (Win, Mac y Linux, aunque todo tiene que ser x64).
En general, no estamos planeando agregar documentos o ayudar con problemas de simulación únicos. Hemos cubierto esto en https://github.com/tmpvar/jsdom#intervening -before-parsing en general y cualquier problema específico estará relacionado con su base de código específica.
Aquí hay una forma sencilla de simular el lienzo que se me ocurrió:
//
// 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);
¡Muchas gracias! El paquete de lienzo prediseñado parece estar funcionando.
Hola @cattermo ,
He agregado un lienzo preconstruido a mis departamentos, ¿necesito cambiar mi configuración de broma? No puedo hacer que funcione, me da
Not implemented: HTMLCanvasElement.prototype.toBlob (without installing the canvas npm package)
@micabe
No realicé ningún cambio de configuración. Jsdom recogerá el lienzo precompilado si está presente en node_modules.
¿Quizás esa función específica no es compatible?
Está funcionando ahora después de yarn cache clean
Lo siento por molestarte! gracias @cattermo
Tal vez jest-canvas-mock pueda ayudar.
La solución es simple, simplemente instale canvas
como devDependency y vuelva a ejecutar sus pruebas de broma.
ref: https://github.com/jsdom/jsdom#canvas -support
Eso todavía no funciona debido a la forma en que jsdom verifica los módulos de lienzo en 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;
}
Hacer require ('lienzo') devuelve un Objeto que tiene la función Canvas. No devuelve la función Canvas de inmediato. ¿O me equivoco en este tema? Funcionó bien cuando estaba usando el módulo preconstruido de lienzo, pero parece que el módulo de lienzo tiene una API diferente. Estoy usando la última versión de canvas, 2.0.1.
Editar
Probé la versión principal anterior (1.6.x) y funciona bien, es un cambio de API que JSDOM no está tratando.
Puedes simplemente hacer:
HTMLCanvasElement.prototype.getContext = jest.fn()
si la implementación real no es importante para usted
Eso todavía no funciona debido a la forma en que jsdom verifica los módulos de lienzo en 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; }
Hacer require ('lienzo') devuelve un Objeto que tiene la función Canvas. No devuelve la función Canvas de inmediato. ¿O me equivoco en este tema? Funcionó bien cuando estaba usando el módulo preconstruido de lienzo, pero parece que el módulo de lienzo tiene una API diferente. Estoy usando la última versión de canvas, 2.0.1.
Editar
Probé la versión principal anterior (1.6.x) y funciona bien, es un cambio de API que JSDOM no está tratando.
Tengo el mismo problema. Parece que el problema no es con jsdom, ya que la solución se fusionó hace un tiempo en https://github.com/jsdom/jsdom/pull/1964 y está disponible desde la versión 13
.
Sin embargo, la versión jsdom
en jest-environment-jsdom
todavía está bloqueada en ^11.5.1
y creo que eso está causando el problema:
https://github.com/facebook/jest/blob/2e2d2c8dedb76e71c0dfa85ed36b81d1f89e0d87/packages/jest-environment-jsdom/package.json#L14
Sin instalar canvas , o canvas-prebuilt pudo deshacerse de los errores relacionados con HTMLCanvasElement, así como cualquier otro método de lienzo bien propuesto por @endel como un truco para solucionar este problema. Como propuso @hustcc , usé jest-canvas-mock para encontrar una solución bastante limpia. Para obtener detalles técnicos, eche un vistazo a este comentario .
Veía mensajes como "No se puede leer webkitBackingStorePixelRatio de null", así como "
No implementado: HTMLCanvasElement.prototype.getContext (sin instalar el paquete canvas npm) ", e instalar canvas (-prebuilt) no fue suficiente. Entré en package-lock.json, arreglé el jest-environment-jsdom para que apunte a jsdom 13 , tiró node_modules y volvió a ejecutar npm install. Los mensajes de error desaparecieron. Creo que @paradite tiene razón y abrió un ticket contra broma:
Recibí comentarios. Está relacionado con la broma que se atasca con versiones de nodos anteriores. Si necesita soporte para el último nodo, busque aquí: https://www.npmjs.com/package/jest-environment-jsdom-thirteen. Sin embargo, esto es específico de la broma, por lo que quizás un poco fuera de tema aquí. Compartiendo de todos modos para la posteridad.
@grtjn : verifiqué la dependencia jest-environment-jsdom-thirteen , pero en mi caso todavía tengo estos 2 exactamente los mismos errores
Error: Not implemented: HTMLCanvasElement.prototype.getContext (without installing the canvas npm package)
TypeError: Cannot read property 'fillRect' of null
Manteniendo mi solución mencionada anteriormente, sobre la versión de Node, no diría que 10.15 es una obsoleta, ya que tengo los problemas para dicho entorno
Angular CLI: 7.2.4
Node: 10.15.0
OS: win32 x64
Angular: 7.2.4
FYI: Tuve que agregar "testEnvironment": "jest-environment-jsdom-thirteen"
a mi configuración de jest e instalar el paquete canvas, así como el conjunto de herramientas del SO Cairo. canvas-prebuilt no pareció funcionar para mí. Estoy usando Vue.
¿Enlace a la dependencia del conjunto de herramientas del SO Cairo? No pude encontrar ese.
@danieldanielecki Consulte la página principal del paquete 'lienzo': https://www.npmjs.com/package/canvas#compiling
@grtjn gracias por ello, tal vez en algún momento lo aproveche. Me lo estaba perdiendo, pero parece más complicado que mi solución, por lo que mantengo el proyecto como está.
Perdón por necropost, pero la sugerencia de @grtjn de instalar jest-environment-jsdom-thirteen (usé catorce solo porque es más reciente) solucionó mi problema. Intenté usar jest-canvas-mock pero hicimos algunas cosas raras en las que falsificamos createImageBitmap usando node-canvas cuando OffscreenCanvas no está disponible, que no está en muchos navegadores, y jest-canvas-mock se confundió bastante con esto. Tal vez otro día lo haremos funcionar ... es una biblioteca simulada genial.
Comentario más útil
Aquí hay una forma sencilla de simular el lienzo que se me ocurrió: