blob: 82621f6ee65df17df15ee7246b27f98a40116fb3 [file] [log] [blame]
import { beforeAll, describe, expect, it, jest } from '@jest/globals';
import { waitFor } from '@testing-library/dom';
import { NodeWatcherAdapter } from './NodeWatcher.adapter';
import {
NodeMutationType,
NodeWatcherHandler,
} from '../../../presentation/nodeWatcher/NodeWatcherHandler';
describe('NodeWatcherAdapter', () => {
beforeAll(() => {
jest.resetAllMocks();
});
const createFakeHandler = () => {
return {
nodeFilter: jest.fn<NodeWatcherHandler['nodeFilter']>(),
onMutatedNode: jest.fn<NodeWatcherHandler['onMutatedNode']>(),
};
};
describe('Regarding start', () => {
it('should not throw an error when calling start', () => {
const sut = new NodeWatcherAdapter();
expect(() => sut.start()).not.toThrow();
});
it('should only call MutationObserver.prototype.observe 1 time after calling start 2 times', () => {
const sut = new NodeWatcherAdapter();
const observeSpy = jest.spyOn(MutationObserver.prototype, 'observe');
sut.start();
sut.start();
expect(observeSpy).toHaveBeenCalledTimes(1);
});
});
describe('Regarding setHandler', () => {
it('should not throw an error when setting a handler', () => {
const sut = new NodeWatcherAdapter();
const key = 'handler';
const handler = createFakeHandler();
expect(() => sut.setHandler(key, handler)).not.toThrow();
});
it('should call onMutatedNode when watching the node for initial discovery and it already exists in the DOM when the handler is set', async () => {
const nodeTestId = 'test-node';
const key = 'handler';
const handler = {
...createFakeHandler(),
initialDiscoverySelector: '[data-testid="test-node"]',
};
handler.nodeFilter.mockImplementation((nodeMutation) => {
return (
nodeMutation.node instanceof HTMLElement &&
nodeMutation.type === NodeMutationType.InitialDiscovery &&
nodeMutation.node.getAttribute('data-testid') === nodeTestId
);
});
const newNode = document.createElement('div');
newNode.setAttribute('data-testid', nodeTestId);
document.body.append(newNode);
const sut = new NodeWatcherAdapter();
sut.setHandler(key, handler);
await waitFor(() => {
expect(handler.onMutatedNode).toHaveBeenCalledTimes(1);
});
});
it('should call onMutatedNode when watching for node creation and the watched node is created', async () => {
const nodeTestId = 'new-node';
const key = 'handler';
const handler = createFakeHandler();
handler.nodeFilter.mockImplementation((nodeMutation) => {
return (
nodeMutation.node instanceof HTMLElement &&
nodeMutation.type === NodeMutationType.NewNode &&
nodeMutation.node.getAttribute('data-testid') === nodeTestId
);
});
const sut = new NodeWatcherAdapter();
sut.setHandler(key, handler);
const newNode = document.createElement('div');
newNode.setAttribute('data-testid', nodeTestId);
document.body.append(newNode);
await waitFor(() => {
expect(handler.onMutatedNode).toHaveBeenCalledTimes(1);
});
});
it('should call onMutatedNode when watching for node removal and the watched node is removed', async () => {
const nodeTestId = 'will-not-last-very-long';
const key = 'handler';
const handler = createFakeHandler();
handler.nodeFilter.mockImplementation((nodeMutation) => {
return (
nodeMutation.node instanceof HTMLElement &&
nodeMutation.type === NodeMutationType.RemovedNode &&
nodeMutation.node.getAttribute('data-testid') === nodeTestId
);
});
const node = document.createElement('div');
node.setAttribute('data-testid', nodeTestId);
document.body.append(node);
const sut = new NodeWatcherAdapter();
sut.setHandler(key, handler);
node.remove();
await waitFor(() => {
expect(handler.onMutatedNode).toHaveBeenCalledTimes(1);
});
});
it('should not call nodeFilter when a mutation other than a node being added or removed is fired', async () => {
const nodeTestId = 'test-node';
const key = 'handler';
const handler = createFakeHandler();
handler.nodeFilter.mockImplementation((nodeMutation) => {
return (
nodeMutation.node instanceof HTMLElement &&
nodeMutation.type === NodeMutationType.RemovedNode &&
nodeMutation.node.getAttribute('data-testid') === nodeTestId
);
});
const node = document.createElement('div');
node.setAttribute('data-testid', nodeTestId);
document.body.append(node);
const sut = new NodeWatcherAdapter();
sut.setHandler(key, handler);
node.setAttribute('data-someattribute', 'random-value');
await waitFor(() => {
expect(handler.nodeFilter).toHaveBeenCalledTimes(0);
});
});
});
describe('Regarding removeHandler', () => {
it('should not call nodeFilter nor onMutatedNode when a node changes but the handler has been removed', async () => {
const nodeTestId = 'test-node';
const key = 'handler';
const handler = createFakeHandler();
handler.nodeFilter.mockReturnValue(true);
const sut = new NodeWatcherAdapter();
sut.setHandler(key, handler);
sut.removeHandler(key);
const node = document.createElement('div');
node.setAttribute('data-testid', nodeTestId);
document.body.append(node);
await waitFor(() => {
expect(handler.nodeFilter).toHaveBeenCalledTimes(0);
expect(handler.onMutatedNode).toHaveBeenCalledTimes(0);
});
});
});
describe('Regarding pause', () => {
it('should not call nodeFilter nor onMutatedNode when a node changes but the NodeWatcher has been paused', async () => {
const nodeTestId = 'test-node';
const key = 'handler';
const handler = createFakeHandler();
handler.nodeFilter.mockReturnValue(true);
const sut = new NodeWatcherAdapter();
sut.setHandler(key, handler);
sut.pause();
const node = document.createElement('div');
node.setAttribute('data-testid', nodeTestId);
document.body.append(node);
await waitFor(() => {
expect(handler.nodeFilter).toHaveBeenCalledTimes(0);
expect(handler.onMutatedNode).toHaveBeenCalledTimes(0);
});
});
});
});