我已经阅读了有关此主题的所有相关问题,并且我意识到这可能会被标记为重复项,但是我一生都无法弄清楚如何使它正常工作。
我有一个简单的函数,可以延迟加载元素:
export default function lazyLoad(targets, onIntersection) {
const observer = new IntersectionObserver((entries, self) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
onIntersection(entry.target);
self.unobserve(entry.target);
}
});
});
document.querySelectorAll(targets).forEach((target) => observer.observe(target));
return observer;
}
用法示例:
lazyLoad('.lazy-img', (img) => {
const pictureElement = img.parentElement;
const source = pictureElement.querySelector('.lazy-source');
source.srcset = source.getAttribute('data-srcset');
img.src = img.getAttribute('data-src');
});
现在,我正在尝试使用玩笑来测试lazyLoad
函数,但是由于它是浏览器API,而不是本机JavaScript,因此我显然需要模拟IntersectionObserver。
以下用于测试observe
方法的工作:
let observe;
let unobserve;
beforeEach(() => {
observe = jest.fn();
unobserve = jest.fn();
window.IntersectionObserver = jest.fn(() => ({
observe,
unobserve,
}));
});
describe('lazyLoad utility', () => {
it('calls observe on each target', () => {
for (let i = 0; i < 3; i++) {
const target = document.createElement('img');
target.className = 'lazy-img';
document.body.appendChild(target);
}
lazyLoad(
'.lazy-img',
jest.fn(() => {})
);
expect(observe).toHaveBeenCalledTimes(3);
});
});
但是我也想测试.isIntersecting
逻辑,在该逻辑上触发回调……除非我不知道该怎么做。如何测试带有笑话的路口?
答案 0 :(得分:2)
当您将其作为参数传递时,模拟的东西非常简单:
export default function lazyLoad(targets, onIntersection, observerClass = IntersectionObserver) {
const observer = new observerClass(...)
...
}
// test file
let entries = [];
const observeFn = jest.fn();
const unobserveFn = jest.fn()
class MockObserver {
constructor(fn) {
fn(entries,this);
}
observe() { observeFn() }
unobserve() { unobserveFn() }
}
test('...',() => {
// set `entries` to be something so you can mock it
entries = ...something
lazyLoad('something',jest.fn(),MockObserver);
});
答案 1 :(得分:1)
另一种选择是使用上面提到的 mockObserver 并在窗口中模拟。
window.IntersetionObserver = mockObserver
而且你不需要在组件 props 中传递观察者。
测试条目是否为Intesecting的重点是将IntersectionObserver模拟为如上所述的类。