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

до импорта

и теперь мой тест проходит.

Я пытался сделать это в самом тесте, но это просто дало мне ту же ошибку, это должно быть что-то в последовательности загрузки, что означает, что его нужно предварительно вручную смоделировать.

Надеюсь, что это помогает другим, это сводит меня с ума в течение нескольких недель.

Другие вопросы по тегам