Stencil, Leaflet, компонент модульного тестирования, дает TypeError: Невозможно прочитать свойство 'deviceXDPI' из неопределенного
Поэтому мы разрабатываем компонент Stenciljs, который оборачивает карту листовки и добавляет некоторые дополнительные функции.
Теперь очевидно, что мы не хотим или не должны тестировать Leaflet, а вместо этого - только части в наших компонентах-оболочках.
Итак, используя тестовые примеры, мы создаем наши тесты,
import { LeMap } from "./le-map";
describe("Map component tests", () => {
it("Should build the map component", async () => {
const map = new LeMap();
expect(map).not.toBeNull();
});
});
попробуйте загрузить компоненты и протестировать публичные функции, но мы получим
TypeError: Cannot read property 'deviceXDPI' of undefined
> 1 | import {Component, Element, Listen, Method, Prop, Watch} from
'@stencil/core';
> 2 | import L from 'leaflet';
| ^
3 |
4 | @Component({
5 | shadow: false,
Мы полагаем, что это сообщение связано с тем, что тест пытается отобразить листовку, и поскольку это не настоящий браузер, он не может обнаружить представление, поэтому выбрасывает эту ошибку, поэтому мы попытались смоделировать листовку в тестах, но все же получаем та же проблема.
Мы пытаемся смоделировать модуль листовки с помощью шутки
jest.genMockFromModule('leaflet');
но это не сделало никакой разницы
Единственная идея, которая у меня была, - это отделить логику от компонентов, но это неправильно, так как мы будем делать это только для целей тестирования.
Используются следующие версии: листовка: 1.3.4, @stencil: 0.15.2, шутка: 23.4.2
Любые другие предложения?
Дальнейшее расследование, благодаря предложениям @skyboyer, приводит меня к этой строке файла ядра листовки browser.js
приводит меня к этой строке файла ядра листовки browser.js
export var retina = (window.devicePixelRatio || (window.screen.deviceXDPI/window.screen.logicalXDPI)) > 1;
Но я не могу смоделировать свойство экрана окна, поскольку я получаю следующую ошибку
[ts] Cannot assign to 'screen' because it is a constant or a read-only property,
поэтому я пробую следующее.
const screen = {
deviceXDPI:0,
logicalXDPI:0
}
Object.defineProperty(window, 'screen', screen);
Object.defineProperty(window, 'devicePixelRatio', 0);
Та же ошибка, полностью игнорирует это, поэтому я пытаюсь перебрать экспорт.
jest.spyOn(L.Browser,'retina').mockImplementation(() => false);
Радости тоже нет, поэтому попробовал
L.Browser.retina = jest.fn(() => false);
но получить это говорит мне, что это константа и не может быть изменена (все же статистика импликации var так ¯_(ツ)_/¯)
Что-нибудь еще я могу попробовать?
Дальнейшее обновление, мне удалось издеваться над окном, но это, к сожалению, не решает.
const screenMock = {
deviceXDPI: 0,
logicalXDPI: 0
}
const windowMock = {
value: {
'devicePixelRatio': 0,
'screen': screenMock
}
}
Object.defineProperty(global, 'window', windowMock);
Если я консоль журнала, я получаю правильные свойства, но как только я тестирую создание экземпляра компонента, он не с
TypeError: Cannot read property 'deviceXDPI' of undefined
Читая вокруг, кажется, что Leaflet не проверяет DOM и просто пытается выполнить рендеринг, в любом случае, я не вижу ничего вокруг, я видел пакет без заголовка, но я не знаю, как я мог бы поменять их только для тестирование.
Думаю, мне нужно будет взглянуть на другую стратегию тестирования, вероятно, транспортир.
1 ответ
Нашел решение, еще не полностью протестированное, но тесты пройдены. Я сделал это, создав
__mocks__
каталог на том же уровне, что и каталог node_modules. создал файл с именем leaflet.js. Это простой файл, который он содержит.
'use strict';
const leaflet = jest.fn();
module.exports = leaflet;
затем в моем тестовом файле (le-map.spec.ts) я просто добавил
jest.mock('leaflet')
до импорта
и теперь мой тест проходит.
Я пытался сделать это в самом тесте, но это просто дало мне ту же ошибку, это должно быть что-то в последовательности загрузки, что означает, что его нужно предварительно вручную смоделировать.
Надеюсь, что это помогает другим, это сводит меня с ума в течение нескольких недель.