所以我们正在开发一个 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 模拟来模拟传单模块
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;
但是当我收到以下错误时,我无法模拟 window 的屏幕属性
[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);
但得到它告诉我它是一个常数,不能改变(但含义 stats 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并且只是尝试渲染,无论如何我都看不到这个,我看到了一个leaflet-headless包,但我不知道我怎么能把它们换掉测试。
我想我需要看看另一种测试策略,可能是量角器。