Skip to content

Commit 3b34bdd

Browse files
authored
Merge pull request #33 from trurl-master/update-io
IO: Refactor mock, add multi-node methods
2 parents 8a90b10 + 7de5e3e commit 3b34bdd

File tree

6 files changed

+520
-125
lines changed

6 files changed

+520
-125
lines changed

README.md

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -89,16 +89,24 @@ Example, using `React Testing Library`:
8989
```jsx
9090
import { mockIntersectionObserver } from 'jsdom-testing-mocks';
9191

92-
const intersectionObserver = mockIntersectionObserver();
92+
const io = mockIntersectionObserver();
9393

94+
/*
95+
Assuming html:
96+
<div data-testid="container">
97+
<img src="..." alt="alt text" />
98+
</div>
99+
100+
And an IntersectionObserver, observing the container
101+
*/
94102
it('loads the image when the component is in the viewport', () => {
95103
const { container } = render(<TestComponent />);
96104

97105
expect(screen.queryByAltText('alt text')).not.toBeInTheDocument();
98106

99107
// when the component's observed node is in the viewport - show the image
100108
act(() => {
101-
intersectionObserver.enterNode(container.firstChild);
109+
io.enterNode(screen.getByTestId('container'));
102110
});
103111

104112
expect(screen.getByAltText('alt text')).toBeInTheDocument();
@@ -109,17 +117,40 @@ it('loads the image when the component is in the viewport', () => {
109117

110118
`mockIntersectionObserver` returns an object, that has several useful methods:
111119

112-
#### .enterNode(node, desc) and .leaveNode(node, desc)
120+
#### .enterNode(node, desc)
121+
122+
Triggers all IntersectionObservers observing the `node`, with `isIntersected` set to `true` and `intersectionRatio` set to `1`. Other `IntersectionObserverEntry` params can be passed as `desc` argument, you can override any parameter except `isIntersected`
123+
124+
#### .leaveNode(node, desc)
125+
126+
Triggers all IntersectionObservers observing the `node`, with `isIntersected` set to `false` and `intersectionRatio` set to `0`. Other `IntersectionObserverEntry` params can be passed as `desc` argument, you can override any parameter except `isIntersected`
127+
128+
#### .enterNodes(nodeDescriptions)
129+
130+
Triggers all IntersectionObservers observing the nodes in `nodeDescriptions` with multiple nodes entering at once. Each IntersectionObserver callback will receive only the nodes it's observing:
131+
132+
```js
133+
io.enterNodes([
134+
// you can pass multiple nodes each with its own state
135+
{ node: screen.getByText('First Node'), desc: { intersectionRatio: 0.5 } },
136+
// description is optional:
137+
{ node: screen.getByText('Second Node') },
138+
// or you can use a shorthand:
139+
screen.getByText('Third Node'),
140+
]);
141+
```
142+
143+
#### .leaveNodes(nodeDescriptions)
144+
145+
Triggers all IntersectionObservers observing the nodes in `nodeDescriptions` with multiple nodes leaving at once. Each IntersectionObserver callback will receive only the nodes it's observing.
146+
147+
#### .triggerNodes(nodeDescriptions)
113148

114-
Triggers the intersection observer callback with only one node
115-
and `isIntersected` set to `true` (for `enterNode`) or `false` (for `leaveNode`).
116-
Other `IntersectionObserverEntry` params can be passed as `desc` argument
149+
Triggers all IntersectionObservers observing the nodes in `nodeDescriptions` with multiple nodes at once with custom descriptions (`isIntersected` is not enforced). Each IntersectionObserver callback will receive only the nodes it's observing
117150

118151
#### .enterAll(desc) and .leaveAll(desc)
119152

120-
Triggers the intersection observer callback for all of the observed nodes
121-
and `isIntersected` set to `true` (for `enterAll`) or `false` (for `leaveAll`).
122-
Other `IntersectionObserverEntry` params can be passed as `desc` argument
153+
Triggers all IntersectionObservers for each of the observed nodes
123154

124155
## Mock ResizeObserver
125156

example/App.tsx

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from 'react';
2-
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
2+
import { BrowserRouter, Switch, Route } from 'react-router-dom';
33

44
import Nav from './Nav';
55

@@ -10,24 +10,19 @@ import CustomUseMedia from './viewport/custom-use-media/CustomUseMedia';
1010

1111
export default function App() {
1212
return (
13-
<Router>
13+
<BrowserRouter>
1414
<div>
1515
<Nav />
1616
<Switch>
17-
<Route path="/intersection-observer">
18-
<GlobalObserver />
19-
</Route>
20-
<Route path="/viewport">
21-
<CustomUseMedia />
22-
</Route>
23-
<Route path="/resize-observer/do-i-fit">
24-
<MeasureParent />
25-
</Route>
26-
<Route path="/resize-observer/print-my-size">
27-
<PrintMySize />
28-
</Route>
17+
<Route path="/intersection-observer" component={GlobalObserver} />
18+
<Route path="/viewport" component={CustomUseMedia} />
19+
<Route path="/resize-observer/do-i-fit" component={MeasureParent} />
20+
<Route
21+
path="/resize-observer/print-my-size"
22+
component={PrintMySize}
23+
/>
2924
</Switch>
3025
</div>
31-
</Router>
26+
</BrowserRouter>
3227
);
3328
}

example/intersection-observer/global-observer/GlobalObserver.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export const Section = ({
2626
);
2727
};
2828

29-
const App = (): ReactElement => {
29+
const App = () => {
3030
const sections = 10;
3131

3232
return (

src/mocks/DOMRect.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
export class MockedDOMRectReadOnly implements DOMRectReadOnly {
2+
readonly bottom: number = 0;
3+
readonly height: number = 0;
4+
readonly left: number = 0;
5+
readonly right: number = 0;
6+
readonly top: number = 0;
7+
readonly width: number = 0;
8+
readonly x: number = 0;
9+
readonly y: number = 0;
10+
11+
constructor(x = 0, y = 0, width = 0, height = 0) {
12+
this.x = x;
13+
this.y = y;
14+
this.width = width;
15+
this.height = height;
16+
}
17+
18+
toJSON() {
19+
return {
20+
bottom: this.bottom,
21+
height: this.height,
22+
left: this.left,
23+
right: this.right,
24+
top: this.top,
25+
width: this.width,
26+
x: this.x,
27+
y: this.y,
28+
};
29+
}
30+
}
31+
32+
if (typeof DOMRectReadOnly === 'undefined') {
33+
Object.defineProperty(window, 'DOMRectReadOnly', {
34+
writable: true,
35+
configurable: true,
36+
value: MockedDOMRectReadOnly,
37+
});
38+
}

0 commit comments

Comments
 (0)