import React, { createRef } from 'react'; import { render } from '@testing-library/react'; // Stub style imports used by the hook so Jest doesn't try to parse SCSS jest.mock('../../../src/static/js/components/item-list/ItemList.scss', () => ({}), { virtual: true }); jest.mock('../../../src/static/js/components/item-list/includes/itemLists/initItemsList', () => ({ __esModule: true, default: jest.fn((_lists: any[]) => [{ appendItems: jest.fn() }]), })); import initItemsList from '../../../src/static/js/components/item-list/includes/itemLists/initItemsList'; import { useItemList } from '../../../src/static/js/utils/hooks/useItemList'; function HookConsumer(props: any) { const listRef = createRef(); const [items, countedItems, listHandler, setListHandler, onItemsLoad, onItemsCount, addListItems] = useItemList( props, listRef ) as any[]; return (
{(items as any[]).map((_, idx) => (
))}
{String(countedItems)}
{items.length}
); } describe('utils/hooks', () => { describe('useItemList', () => { beforeEach(() => { jest.clearAllMocks(); }); test('Initial state: empty items and not counted', () => { const { getByTestId } = render(); expect(getByTestId('counted').textContent).toBe('false'); expect(getByTestId('len').textContent).toBe('0'); expect(getByTestId('has-handler').textContent).toBe('no'); }); test('onItemsLoad updates items and renders item nodes', () => { const { getByTestId, getByTestId: $ } = render(); (getByTestId('load-call') as HTMLButtonElement).click(); expect(getByTestId('len').textContent).toBe('2'); expect($('itm-0')).toBeTruthy(); expect($('itm-1')).toBeTruthy(); }); test('onItemsCount marks countedItems true and triggers callback if provided', () => { const cb = jest.fn(); const { getByTestId } = render(); (getByTestId('count-call') as HTMLButtonElement).click(); expect(getByTestId('counted').textContent).toBe('true'); expect(cb).toHaveBeenCalledWith(5); }); test('addListItems initializes itemsListInstance and appends only new items', () => { const mockInit = initItemsList as jest.Mock; const { getByTestId, rerender } = render(); const itemsLen = getByTestId('len') as HTMLDivElement; const addBtn = getByTestId('add-call') as HTMLButtonElement; const loadBtn = getByTestId('load-call') as HTMLButtonElement; expect(itemsLen.textContent).toBe('0'); loadBtn.click(); expect(itemsLen.textContent).toBe('2'); expect(mockInit).toHaveBeenCalledTimes(0); addBtn.click(); expect(mockInit).toHaveBeenCalledTimes(1); expect(mockInit.mock.results[0].value[0].appendItems).toHaveBeenCalledTimes(2); loadBtn.click(); expect(itemsLen.textContent).toBe('2'); addBtn.click(); expect(mockInit).toHaveBeenCalledTimes(2); expect(mockInit.mock.results[1].value[0].appendItems).toHaveBeenCalledTimes(2); rerender(); addBtn.click(); expect(mockInit).toHaveBeenCalledTimes(3); expect(mockInit.mock.results[2].value[0].appendItems).toHaveBeenCalledTimes(2); }); test('addListItems does nothing when there are no .item elements in the ref', () => { // Render, do not call onItemsLoad, then call addListItems const mockInit = initItemsList as jest.Mock; const { getByTestId } = render(); (getByTestId('add-call') as HTMLButtonElement).click(); expect(mockInit).not.toHaveBeenCalled(); }); test('itemsLoadCallback is invoked when items change', () => { const itemsLoadCallback = jest.fn(); const { getByTestId } = render(); (getByTestId('load-call') as HTMLButtonElement).click(); expect(itemsLoadCallback).toHaveBeenCalledTimes(1); }); test('setListHandler updates listHandler', () => { const { getByTestId } = render(); expect(getByTestId('has-handler').textContent).toBe('no'); (getByTestId('set-handler') as HTMLButtonElement).click(); expect(getByTestId('has-handler').textContent).toBe('yes'); }); }); });