blob: 82621f6ee65df17df15ee7246b27f98a40116fb3 [file] [log] [blame]
Adrià Vilanova Martínezc50fa962024-10-19 15:55:15 +02001import { beforeAll, describe, expect, it, jest } from '@jest/globals';
2import { waitFor } from '@testing-library/dom';
3import { NodeWatcherAdapter } from './NodeWatcher.adapter';
4import {
5 NodeMutationType,
6 NodeWatcherHandler,
7} from '../../../presentation/nodeWatcher/NodeWatcherHandler';
8
9describe('NodeWatcherAdapter', () => {
10 beforeAll(() => {
11 jest.resetAllMocks();
12 });
13
14 const createFakeHandler = () => {
15 return {
16 nodeFilter: jest.fn<NodeWatcherHandler['nodeFilter']>(),
17 onMutatedNode: jest.fn<NodeWatcherHandler['onMutatedNode']>(),
18 };
19 };
20
21 describe('Regarding start', () => {
22 it('should not throw an error when calling start', () => {
23 const sut = new NodeWatcherAdapter();
24
25 expect(() => sut.start()).not.toThrow();
26 });
27
28 it('should only call MutationObserver.prototype.observe 1 time after calling start 2 times', () => {
29 const sut = new NodeWatcherAdapter();
30
31 const observeSpy = jest.spyOn(MutationObserver.prototype, 'observe');
32
33 sut.start();
34 sut.start();
35
36 expect(observeSpy).toHaveBeenCalledTimes(1);
37 });
38 });
39
40 describe('Regarding setHandler', () => {
41 it('should not throw an error when setting a handler', () => {
42 const sut = new NodeWatcherAdapter();
43
44 const key = 'handler';
45 const handler = createFakeHandler();
46 expect(() => sut.setHandler(key, handler)).not.toThrow();
47 });
48
49 it('should call onMutatedNode when watching the node for initial discovery and it already exists in the DOM when the handler is set', async () => {
50 const nodeTestId = 'test-node';
51
52 const key = 'handler';
53 const handler = {
54 ...createFakeHandler(),
55 initialDiscoverySelector: '[data-testid="test-node"]',
56 };
57 handler.nodeFilter.mockImplementation((nodeMutation) => {
58 return (
59 nodeMutation.node instanceof HTMLElement &&
60 nodeMutation.type === NodeMutationType.InitialDiscovery &&
61 nodeMutation.node.getAttribute('data-testid') === nodeTestId
62 );
63 });
64
65 const newNode = document.createElement('div');
66 newNode.setAttribute('data-testid', nodeTestId);
67 document.body.append(newNode);
68
69 const sut = new NodeWatcherAdapter();
70 sut.setHandler(key, handler);
71
72 await waitFor(() => {
73 expect(handler.onMutatedNode).toHaveBeenCalledTimes(1);
74 });
75 });
76
77 it('should call onMutatedNode when watching for node creation and the watched node is created', async () => {
78 const nodeTestId = 'new-node';
79
80 const key = 'handler';
81 const handler = createFakeHandler();
82 handler.nodeFilter.mockImplementation((nodeMutation) => {
83 return (
84 nodeMutation.node instanceof HTMLElement &&
85 nodeMutation.type === NodeMutationType.NewNode &&
86 nodeMutation.node.getAttribute('data-testid') === nodeTestId
87 );
88 });
89
90 const sut = new NodeWatcherAdapter();
91 sut.setHandler(key, handler);
92
93 const newNode = document.createElement('div');
94 newNode.setAttribute('data-testid', nodeTestId);
95 document.body.append(newNode);
96
97 await waitFor(() => {
98 expect(handler.onMutatedNode).toHaveBeenCalledTimes(1);
99 });
100 });
101
102 it('should call onMutatedNode when watching for node removal and the watched node is removed', async () => {
103 const nodeTestId = 'will-not-last-very-long';
104
105 const key = 'handler';
106 const handler = createFakeHandler();
107 handler.nodeFilter.mockImplementation((nodeMutation) => {
108 return (
109 nodeMutation.node instanceof HTMLElement &&
110 nodeMutation.type === NodeMutationType.RemovedNode &&
111 nodeMutation.node.getAttribute('data-testid') === nodeTestId
112 );
113 });
114
115 const node = document.createElement('div');
116 node.setAttribute('data-testid', nodeTestId);
117 document.body.append(node);
118
119 const sut = new NodeWatcherAdapter();
120 sut.setHandler(key, handler);
121
122 node.remove();
123
124 await waitFor(() => {
125 expect(handler.onMutatedNode).toHaveBeenCalledTimes(1);
126 });
127 });
128
129 it('should not call nodeFilter when a mutation other than a node being added or removed is fired', async () => {
130 const nodeTestId = 'test-node';
131
132 const key = 'handler';
133 const handler = createFakeHandler();
134 handler.nodeFilter.mockImplementation((nodeMutation) => {
135 return (
136 nodeMutation.node instanceof HTMLElement &&
137 nodeMutation.type === NodeMutationType.RemovedNode &&
138 nodeMutation.node.getAttribute('data-testid') === nodeTestId
139 );
140 });
141
142 const node = document.createElement('div');
143 node.setAttribute('data-testid', nodeTestId);
144 document.body.append(node);
145
146 const sut = new NodeWatcherAdapter();
147 sut.setHandler(key, handler);
148
149 node.setAttribute('data-someattribute', 'random-value');
150
151 await waitFor(() => {
152 expect(handler.nodeFilter).toHaveBeenCalledTimes(0);
153 });
154 });
155 });
156
157 describe('Regarding removeHandler', () => {
158 it('should not call nodeFilter nor onMutatedNode when a node changes but the handler has been removed', async () => {
159 const nodeTestId = 'test-node';
160
161 const key = 'handler';
162 const handler = createFakeHandler();
163 handler.nodeFilter.mockReturnValue(true);
164
165 const sut = new NodeWatcherAdapter();
166 sut.setHandler(key, handler);
167 sut.removeHandler(key);
168
169 const node = document.createElement('div');
170 node.setAttribute('data-testid', nodeTestId);
171 document.body.append(node);
172
173 await waitFor(() => {
174 expect(handler.nodeFilter).toHaveBeenCalledTimes(0);
175 expect(handler.onMutatedNode).toHaveBeenCalledTimes(0);
176 });
177 });
178 });
179
180 describe('Regarding pause', () => {
181 it('should not call nodeFilter nor onMutatedNode when a node changes but the NodeWatcher has been paused', async () => {
182 const nodeTestId = 'test-node';
183
184 const key = 'handler';
185 const handler = createFakeHandler();
186 handler.nodeFilter.mockReturnValue(true);
187
188 const sut = new NodeWatcherAdapter();
189 sut.setHandler(key, handler);
190 sut.pause();
191
192 const node = document.createElement('div');
193 node.setAttribute('data-testid', nodeTestId);
194 document.body.append(node);
195
196 await waitFor(() => {
197 expect(handler.nodeFilter).toHaveBeenCalledTimes(0);
198 expect(handler.onMutatedNode).toHaveBeenCalledTimes(0);
199 });
200 });
201 });
202});