Можно ли смоделировать холст без реальной реализации ( canvas
/ canvas-prebuilt
)?
Я бы хотел, чтобы эта ошибка не возникла, так как функциональность холста для меня не очень важна:
Not implemented: HTMLCanvasElement.prototype.getContext (without installing the canvas npm package)
Если кому-то это нужно, вот как я это решил:
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.
Версия Jest: 21.2.1
Версия Jsdom: 9.12.0
Было бы очень хорошо, если бы имитация холста (без использования пакета холста, поскольку он не поддерживается в Windows) охватывалась официальной документацией, а не только как комментарий к проблеме.
без использования пакета холста, так как не поддерживается в Windows
Почему вам не подходит вариант с
Как правило, мы не планируем добавлять документы или помогать с одноразовыми издевательствами. Мы рассмотрели это в 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!
Я добавил предварительную сборку Canvas в свой deps, мне нужно изменить конфигурацию jest? Я не могу заставить его работать, это дает мне
Not implemented: HTMLCanvasElement.prototype.toBlob (without installing the canvas npm package)
@micabe
Я не вносил никаких изменений в конфигурацию. Jsdom подберет предварительно собранный холст, если он присутствует в node_modules.
Может быть, эта конкретная функция не поддерживается?
Теперь он работает после yarn cache clean
Извините за беспокойство! спасибо @cattermo
Может быть, шутка-холст-издевательство может помочь.
Решение простое: просто установите canvas
как devDependency и повторно запустите свои шутливые тесты.
ссылка: https://github.com/jsdom/jsdom#canvas -support
Это все еще не работает, потому что 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, но, похоже, модуль Canvas имеет другой API. Я использую последнюю версию Canvas, 2.0.1.
Редактировать
Я тестировал предыдущую основную версию (1.6.x), и она отлично работает, это изменение API, которое JSDOM не обрабатывает.
Вы можете просто сделать:
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, но, похоже, модуль Canvas имеет другой API. Я использую последнюю версию Canvas, 2.0.1.
Редактировать
Я тестировал предыдущую основную версию (1.6.x), и она отлично работает, это изменение API, которое JSDOM не обрабатывает.
У меня точно такая же проблема. Похоже, проблема не в jsdom, поскольку исправление было объединено некоторое время назад в https://github.com/jsdom/jsdom/pull/1964 и доступно с версии 13
.
Однако версия jsdom
в jest-environment-jsdom
по-прежнему застревает на ^11.5.1
и я считаю, что это вызывает проблему:
https://github.com/facebook/jest/blob/2e2d2c8dedb76e71c0dfa85ed36b81d1f89e0d87/packages/jest-environment-jsdom/package.json#L14
Без установки холста , или холст-прекомпилированное был в состоянии избавиться от ошибок , связанных с HTMLCanvasElement, а также любые другие холст методы красиво предложенный @endel как взломать , чтобы обойти эту проблему. Как предложил @hustcc , использовал jest-canvas-mock с поиском довольно чистого решения. Для технических подробностей, пожалуйста, посмотрите этот комментарий .
Я видел такие сообщения, как "Не могу прочитать webkitBackingStorePixelRatio of null", а также "
Не реализовано: HTMLCanvasElement.prototype.getContext (без установки пакета canvas npm) ", и установки Canvas (-prebuilt) было недостаточно. Я зашел внутрь package-lock.json, исправил jest-environment-jsdom, чтобы он указывал на jsdom 13 , выбросил node_modules и повторно запустил npm install. Сообщения об ошибках исчезли. Я думаю, что @paradite прав, и открыл тикет против шутки:
Получил обратную связь. Это связано с застреванием шутки в старых версиях узлов. Если вам нужна поддержка для последней версии узла, посмотрите здесь: https://www.npmjs.com/package/jest-environment-jsdom-thirteen. Хотя это шутка специфическая, так что, возможно, здесь немного не по теме. Делиться так или иначе для потомков ..
@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
Сохраняя мое решение, упомянутое ранее, о версии Node я бы не сказал, что 10.15 является устаревшим, поскольку у меня есть проблемы для такой среды.
Angular CLI: 7.2.4
Node: 10.15.0
OS: win32 x64
Angular: 7.2.4
К вашему сведению: мне пришлось добавить "testEnvironment": "jest-environment-jsdom-thirteen"
в мою конфигурацию jest и установить пакет холста, а также набор инструментов Cairo OS. Canvas-prebuilt, похоже, не сработал для меня. Я использую Vue.
Ссылка на зависимость набора инструментов Cairo OS? Не могу найти того.
@danieldanielecki См. главную страницу пакета 'canvas': https://www.npmjs.com/package/canvas#compiling
@grtjn спасибо за это - может быть, в какой-то момент этим воспользуются. Мне его не хватало, но он выглядит сложнее, чем мое решение, поэтому сохраните проект как есть.
Извините за necropost, но предложение @grtjn об установке jest-environment-jsdom-thirteen (я использовал четырнадцать только с тех пор, как оно появилось позже) устранило мою проблему. Я пробовал использовать jest-canvas-mock, но мы сделали несколько странных вещей, где мы подделали createImageBitmap с помощью node-canvas, когда OffscreenCanvas недоступен, чего нет во многих браузерах, и jest-canvas-mock из-за этого довольно запутался. Может быть, в другой день мы получим эту работу ... это классная имитация библиотеки.
Самый полезный комментарий
Вот простой способ имитировать холст, который я придумал: