import React from 'react';
import { render, fireEvent, waitFor } from '@testing-library/react';
jest.mock('../../../src/static/js/utils/settings/config', () => ({
config: jest.fn(() => jest.requireActual('../../tests-constants').sampleMediaCMSConfig),
}));
jest.mock('../../../src/static/js/utils/classes/', () => ({
BrowserCache: jest.fn().mockImplementation(() => ({
get: jest.fn(),
set: jest.fn(),
})),
}));
let mockListHandler: any;
let addListItemsSpy = jest.fn();
const mockRemoveListener = jest.fn();
jest.mock('../../../src/static/js/utils/hooks/useItemList', () => ({
useItemList: (props: any, _ref: any) => {
mockListHandler = {
loadItems: jest.fn(),
totalPages: jest.fn().mockReturnValue(props.__totalPages ?? 1),
loadedAllItems: jest.fn().mockReturnValue(Boolean(props.__loadedAll ?? true)),
};
return [
props.__items ?? [], // items
props.__countedItems ?? 0, // countedItems
mockListHandler, // listHandler
jest.fn(), // setListHandler
jest.fn(), // onItemsLoad
jest.fn(), // onItemsCount
addListItemsSpy, // addListItems
];
},
}));
jest.mock('../../../src/static/js/utils/stores/', () => ({
PageStore: {
removeListener: mockRemoveListener,
},
}));
import { useItemListLazyLoad } from '../../../src/static/js/utils/hooks/useItemListLazyLoad';
function HookConsumer(props: any) {
const tuple = useItemListLazyLoad(props);
const [
_items,
_countedItems,
_listHandler,
_setListHandler,
classname,
_onItemsCount,
_onItemsLoad,
_onWindowScroll,
_onDocumentVisibilityChange,
_itemsListWrapperRef,
_itemsListRef,
renderBeforeListWrap,
renderAfterListWrap,
] = tuple as any;
return (
{classname.list}
{classname.listOuter}
{renderBeforeListWrap()}
{renderAfterListWrap()}
);
}
function HookConsumerWithRefs(props: any) {
const tuple = useItemListLazyLoad(props);
const [
_items,
_countedItems,
_listHandler,
_setListHandler,
classname,
_onItemsCount,
_onItemsLoad,
onWindowScroll,
onDocumentVisibilityChange,
itemsListWrapperRef,
itemsListRef,
renderBeforeListWrap,
renderAfterListWrap,
] = tuple as any;
return (
{classname.list}
{classname.listOuter}
{renderBeforeListWrap()}
{renderAfterListWrap()}
);
}
describe('utils/hooks', () => {
describe('useItemListLazyLoad', () => {
beforeEach(() => {
addListItemsSpy = jest.fn();
mockRemoveListener.mockClear();
});
afterEach(() => {
jest.clearAllMocks();
});
test('Computes classname.list and classname.listOuter with optional className prop', () => {
const { getByTestId, rerender } = render();
expect(getByTestId('class-outer').textContent).toBe('items-list-outer extra');
expect(getByTestId('class-list').textContent).toBe('items-list');
rerender();
expect(getByTestId('class-outer').textContent).toBe('items-list-outer');
expect(getByTestId('class-list').textContent).toBe('items-list');
});
test('Invokes addListItems when items change', () => {
const { rerender } = render();
expect(addListItemsSpy).toHaveBeenCalledTimes(1);
rerender();
expect(addListItemsSpy).toHaveBeenCalledTimes(2);
});
test('Renders nothing in renderBeforeListWrap and renderAfterListWrap', () => {
const { getByTestId } = render(
);
expect(getByTestId('render-before').textContent).toBe('');
expect(getByTestId('render-after').textContent).toBe('');
});
test('Does not call listHandler.loadItems when refs are not attached', () => {
render();
expect(mockListHandler.loadItems).not.toHaveBeenCalled();
});
test('Calls listHandler.loadItems when refs are set and scroll threshold is reached', async () => {
render();
await waitFor(() => {
expect(mockListHandler.loadItems).toHaveBeenCalled();
});
});
test('Calls PageStore.removeListener when refs are set and loadedAllItems is true', () => {
render();
expect(mockRemoveListener).toHaveBeenCalledWith('window_scroll', expect.any(Function));
});
test('onDocumentVisibilityChange schedules onWindowScroll when document is visible', () => {
jest.useFakeTimers();
const setTimeoutSpy = jest.spyOn(globalThis, 'setTimeout');
Object.defineProperty(document, 'hidden', { value: false, configurable: true });
const { getByTestId } = render();
fireEvent.click(getByTestId('trigger-visibility'));
expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), 10);
setTimeoutSpy.mockRestore();
jest.useRealTimers();
});
test('onDocumentVisibilityChange does nothing when document is hidden', () => {
jest.useFakeTimers();
const setTimeoutSpy = jest.spyOn(globalThis, 'setTimeout');
Object.defineProperty(document, 'hidden', { value: true, configurable: true });
const { getByTestId } = render();
fireEvent.click(getByTestId('trigger-visibility'));
expect(setTimeoutSpy).toHaveBeenCalledTimes(0);
setTimeoutSpy.mockRestore();
jest.useRealTimers();
});
});
});