main
js 150 lines 3.56 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 */
8
9 const intersectionObserverMock = {callback: null, observedTargets: []};
10
11 /**
12 * This is a broken polyfill.
13 * It is only intended to provide bare minimum test coverage.
14 * More meaningful tests will require the use of fixtures.
15 */
16 export function mockIntersectionObserver() {
17 intersectionObserverMock.callback = null;
18 intersectionObserverMock.observedTargets = [];
19
20 class IntersectionObserver {
21 constructor() {
22 intersectionObserverMock.callback = arguments[0];
23 }
24
25 disconnect() {
26 intersectionObserverMock.callback = null;
27 intersectionObserverMock.observedTargets.splice(0);
28 }
29
30 observe(target) {
31 intersectionObserverMock.observedTargets.push(target);
32 }
33
34 unobserve(target) {
35 const index = intersectionObserverMock.observedTargets.indexOf(target);
36 if (index >= 0) {
37 intersectionObserverMock.observedTargets.splice(index, 1);
38 }
39 }
40 }
41
42 window.IntersectionObserver = IntersectionObserver;
43
44 return intersectionObserverMock;
45 }
46
47 export function simulateIntersection(...entries) {
48 intersectionObserverMock.callback(
49 entries.map(([target, rect, ratio]) => ({
50 boundingClientRect: {
51 top: rect.y,
52 left: rect.x,
53 width: rect.width,
54 height: rect.height,
55 },
56 intersectionRatio: ratio,
57 target,
58 })),
59 );
60 }
61
62 /**
63 * Stub out getBoundingClientRect for the specified target.
64 * This API is required by the test selectors but it isn't implemented by jsdom.
65 */
66 export function setBoundingClientRect(target, {x, y, width, height}) {
67 target.getBoundingClientRect = function () {
68 return {
69 width,
70 height,
71 left: x,
72 right: x + width,
73 top: y,
74 bottom: y + height,
75 };
76 };
77 }
78
79 /**
80 * Stub out getClientRects for the specified target.
81 */
82 export function setClientRects(target, rects) {
83 target.getClientRects = function () {
84 return rects.map(({x, y, width, height}) => ({
85 width,
86 height,
87 left: x,
88 right: x + width,
89 top: y,
90 bottom: y + height,
91 x,
92 y,
93 }));
94 };
95 }
96
97 /**
98 * Mock Range.prototype.getClientRects and getBoundingClientRect since jsdom doesn't implement them.
99 * Call this in beforeEach to set up the mock.
100 */
101 export function mockRangeClientRects(
102 rects = [{x: 0, y: 0, width: 100, height: 20}],
103 ) {
104 const originalCreateRange = document.createRange;
105 document.createRange = function () {
106 const range = originalCreateRange.call(document);
107 range.getClientRects = function () {
108 return rects.map(({x, y, width, height}) => ({
109 width,
110 height,
111 left: x,
112 right: x + width,
113 top: y,
114 bottom: y + height,
115 x,
116 y,
117 }));
118 };
119 range.getBoundingClientRect = function () {
120 // Return the bounding rect that encompasses all rects
121 if (rects.length === 0) {
122 return {
123 width: 0,
124 height: 0,
125 left: 0,
126 right: 0,
127 top: 0,
128 bottom: 0,
129 x: 0,
130 y: 0,
131 };
132 }
133 const first = rects[0];
134 return {
135 width: first.width,
136 height: first.height,
137 left: first.x,
138 right: first.x + first.width,
139 top: first.y,
140 bottom: first.y + first.height,
141 x: first.x,
142 y: first.y,
143 };
144 };
145 return range;
146 };
147 return function restore() {
148 document.createRange = originalCreateRange;
149 };
150 }