@gitlab/ui
Version:
GitLab UI Components
97 lines (78 loc) • 2.38 kB
JavaScript
/* global jest, beforeEach, afterEach */
/* eslint-disable class-methods-use-this, max-classes-per-file, camelcase */
import isMatch from 'lodash/isMatch';
/**
* This class gives us a JSDom friendly DOM observer which we can manually trigger in tests
*
* Use this in place of MutationObserver or IntersectionObserver
*
* This class is largely influenced from [a test helper][1] in the main GitLab project
*
* [1]: https://gitlab.com/gitlab-org/gitlab/blob/a123813c63147392b95cd03c4744ae9db0575b0f/spec/frontend/helpers/mock_dom_observer.js#L95
*/
class MockObserver {
constructor(cb) {
this.$_cb = cb;
this.$_observers = [];
}
observe(node, options = {}) {
this.$_observers.push([node, options]);
}
disconnect() {
this.$_observers = [];
}
takeRecords() {}
// eslint-disable-next-line camelcase
$_triggerObserve(nodeParam, { entry = {}, options = {} } = {}) {
const nodes = this.$_getNodesFromParam(nodeParam);
nodes.forEach((node) => {
if (this.$_hasObserver(node, options)) {
this.$_cb([{ target: node, ...entry }]);
}
});
}
// eslint-disable-next-line camelcase
$_hasObserver(node, options = {}) {
return this.$_observers.some(
([obvNode, obvOptions]) => node === obvNode && isMatch(options, obvOptions)
);
}
$_getNodesFromParam(nodeParam) {
if (!nodeParam) {
return this.$_observers.map(([node]) => node);
}
if (!Array.isArray(nodeParam)) {
return [nodeParam];
}
return nodeParam;
}
}
class MockIntersectionObserver extends MockObserver {
unobserve(node) {
this.$_observers = this.$_observers.filter(([obvNode]) => node !== obvNode);
}
}
export const useMockIntersectionObserver = () => {
let instances;
let origObserver;
beforeEach(() => {
instances = [];
origObserver = global.IntersectionObserver;
global.IntersectionObserver = jest.fn().mockImplementation((...args) => {
const mockObserver = new MockIntersectionObserver(...args);
instances.push(mockObserver);
return mockObserver;
});
});
afterEach(() => {
instances = [];
global.IntersectionObserver = origObserver;
});
const trigger = (observer, ...args) => {
observer.$_triggerObserve(...args);
};
const getInstances = () => {
return instances;
};
return { getInstances, trigger };
};