UNPKG

@eeacms/volto-anchors

Version:

@eeacms/volto-anchors: Volto add-on

262 lines (224 loc) 7.31 kB
import { isArray } from 'lodash'; import config from '@plone/volto/registry'; import { serializeNodes } from '@plone/volto-slate/editor/render'; import * as helpers from './helpers'; import '@testing-library/jest-dom/extend-expect'; import configureStore from 'redux-mock-store'; import { Provider } from 'react-intl-redux'; import { BrowserRouter as Router } from 'react-router-dom'; import { render } from '@testing-library/react'; const mockStore = configureStore(); const store = mockStore({ intl: { locale: 'en', messages: {}, }, }); jest.mock('@plone/volto-slate/editor/render', () => ({ serializeNodes: jest.fn(), })); describe('createSlateParagraph', () => { beforeEach(() => { jest.resetAllMocks(); }); it('should return default value when input is not an array', () => { const input = 'test'; const slate = helpers.createSlateParagraph(input); expect(slate).toEqual(config.settings.slate.defaultValue('test')); }); it('should return input when input is an array', () => { const input = ['test']; const result = helpers.createSlateParagraph(input); expect(result).toBe(input); }); }); describe('serializeText', () => { beforeEach(() => { jest.resetAllMocks(); }); it('should return the text when it is not an array', () => { const text = 'Hello, World!'; expect(helpers.serializeText(text)).toEqual(text); expect(isArray(text)).toBe(false); expect(serializeNodes).not.toHaveBeenCalled(); }); it('should call serializeNodes when text is an array', () => { const text = ['Hello', 'World!']; helpers.serializeText(text); expect(isArray(text)).toBe(true); expect(serializeNodes).toHaveBeenCalledWith(text); }); }); describe('toSlug', () => { it('should convert string to slug', () => { const input = 'Hello World'; const result = helpers.toSlug(input); expect(result).toBe('hello-world'); }); }); describe('waitForElm', () => { let mockObserver; beforeEach(() => { // Reset the document.querySelector mock document.querySelector = jest.fn(); // Mock the MutationObserver mockObserver = { observe: jest.fn(), disconnect: jest.fn(), }; global.MutationObserver = jest.fn((callback) => { mockObserver.callback = callback; return mockObserver; }); }); it('should resolve immediately if the element is already in the DOM', async () => { const mockElement = {}; document.querySelector.mockReturnValue(mockElement); const result = await helpers.waitForElm('.test'); expect(result).toBe(mockElement); expect(mockObserver.observe).not.toHaveBeenCalled(); }); it('should start observing if the element is not in the DOM', () => { document.querySelector.mockReturnValue(null); // Call our function but don't await its promise (because the .test is never going to be added to the DOM) const promise = helpers.waitForElm('.test'); expect(mockObserver.observe).toHaveBeenCalledWith(document.body, { childList: true, subtree: true, }); // Clean up promise.catch(() => {}); }); it('should resolve and stop observing when the element is added to the DOM', async () => { const mockElement = {}; document.querySelector = jest.fn((selector) => selector === '.test' ? mockElement : null, ); // we need to mock the querySelector twice, because the first time it will return null (not added to the DOM) // and the second time it will return the mockElement (added to the DOM) document.querySelector .mockReturnValueOnce(null) .mockReturnValueOnce(mockElement); const promise = helpers.waitForElm('.test'); // Simulate a DOM change mockObserver.callback([]); await expect(promise).resolves.toBe(mockElement); expect(mockObserver.disconnect).toHaveBeenCalled(); }); }); describe('scrollToTarget', () => { it('should call window.scrollTo with the correct arguments', () => { window.scrollTo = jest.fn(); // Create a mock element and mock its getBoundingClientRect function const mockElement = { getBoundingClientRect: jest.fn(), }; // Mock the return values of getBoundingClientRect document.body.getBoundingClientRect = jest.fn(() => ({ top: 100 })); mockElement.getBoundingClientRect.mockReturnValue({ top: 200 }); // Call our function helpers.scrollToTarget(mockElement, 50); // Assert that window.scrollTo was called with the correct arguments expect(window.scrollTo).toHaveBeenCalledWith({ top: 50, // 200 - 100 - 50 behavior: 'smooth', }); }); }); describe('visitBlocks', () => { it('should call callback with correct arguments and in correct order', () => { const content = { blocks: { 1: { id: 1, value: 'test1', blocks: { 3: { id: 3, value: 'test3' }, }, }, 2: { id: 2, value: 'test2', data: { blocks: { 4: { id: 4, value: 'test2.1' }, }, }, }, }, blocks_layout: { items: [1, 2], }, }; const callback = jest.fn(); helpers.visitBlocks(content, callback); expect(callback).toHaveBeenNthCalledWith(1, [ 2, { id: 2, value: 'test2', data: { blocks: { 4: { id: 4, value: 'test2.1' }, }, }, }, ]); expect(callback).toHaveBeenNthCalledWith(2, [ 1, { id: 1, value: 'test1', blocks: { 3: { id: 3, value: 'test3' } }, }, ]); }); }); describe('renderLinkElement', () => { it('renders a link element with children and default props', () => { const TestComponent = helpers.renderLinkElement('div'); const { getByText } = render( <Provider store={store}> <Router> <TestComponent attributes={{ id: 'test' }}>Test test</TestComponent> </Router> </Provider>, ); expect(getByText('Test test')).toBeInTheDocument(); expect(getByText('Test test').tagName).toBe('DIV'); expect(getByText('Test test')).toHaveAttribute('id', 'test'); }); it('renders a link element with a className', () => { const TestComponent = helpers.renderLinkElement('div'); const { getByText } = render( <Provider store={store}> <Router> <TestComponent className="test-class" attributes={{ id: 'test' }}> Test test </TestComponent> </Router> </Provider>, ); expect(getByText('Test test')).toBeInTheDocument(); expect(getByText('Test test')).toHaveClass('test-class'); }); it('renders an anchor link when mode is set to view', () => { const TestComponent = helpers.renderLinkElement('div'); const { container } = render( <Provider store={store}> <Router> <TestComponent mode="view" className="test-class" attributes={{ id: 'test' }} > Test test </TestComponent> </Router> </Provider>, ); const aTag = container.querySelector('a'); expect(aTag).toBeInTheDocument(); expect(aTag).toHaveAttribute('href', '/#test'); }); });