Трафарет, Leaflet, компонент модульного тестирования, дает TypeError: Невозможно прочитать свойство 'deviceXDPI' из неопределенного - PullRequest
0 голосов
/ 04 декабря 2018

Итак, мы разрабатываем компонент 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, приводит меня кЕго строка из файла leaflet core browser.js

приводит меня к этой строке файла leaflet core 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 Ответ

0 голосов
/ 17 декабря 2018

Нашел решение, еще не полностью протестированное, но тесты пройдены.Я сделал это, создав каталог

__mocks__ 

на том же уровне, что и каталог node_modules.создал файл с именем leaflet.js.Это простой файл, который он содержит.

'use strict';

const leaflet = jest.fn();

module.exports = leaflet;

, затем в моем тестовом файле (le-map.spec.ts) я только что добавил

jest.mock('leaflet')

перед импортом

и теперь мой тест успешно пройден.

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

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

...