import { act } from 'react-test-renderer'; import { fallbackCreditsContent } from '../src/data'; import { createToolkitContentRecord, deleteToolkitContentRecord, readToolkitContent, saveToolkitContent, updateToolkitContentRecord, } from '../src/socket/toolkitSocketClient'; import { useToolkitContentStore } from '../src/state/toolkitContentStore'; jest.mock('../src/socket/toolkitSocketClient', () => ({ createToolkitContentRecord: jest.fn(), deleteToolkitContentRecord: jest.fn(), readToolkitContent: jest.fn(), saveToolkitContent: jest.fn(), updateToolkitContentRecord: jest.fn(), })); const mockedCreateToolkitContentRecord = jest.mocked(createToolkitContentRecord); const mockedDeleteToolkitContentRecord = jest.mocked(deleteToolkitContentRecord); const mockedReadToolkitContent = jest.mocked(readToolkitContent); const mockedSaveToolkitContent = jest.mocked(saveToolkitContent); const mockedUpdateToolkitContentRecord = jest.mocked(updateToolkitContentRecord); const changedCredits = { ...fallbackCreditsContent, mainLogo: { image: null, subtitle: 'Changed subtitle', title: 'Changed Credits', }, }; describe('useToolkitContentStore', () => { beforeEach(() => { mockedReadToolkitContent.mockReset(); mockedSaveToolkitContent.mockReset(); mockedCreateToolkitContentRecord.mockReset(); mockedDeleteToolkitContentRecord.mockReset(); mockedUpdateToolkitContentRecord.mockReset(); useToolkitContentStore.setState({ contentByResource: { ...useToolkitContentStore.getState().contentByResource, credits: fallbackCreditsContent, }, credits: fallbackCreditsContent, error: null, errorsByResource: {}, lastLoadedAt: null, revision: null, revisionsByResource: {}, status: 'idle', statusByResource: {}, }); }); it('loads credits from the socket client', async () => { mockedReadToolkitContent.mockResolvedValue({ content: changedCredits, resource: 'credits', revision: '123', }); await act(async () => { await useToolkitContentStore.getState().refreshCredits(); }); expect(mockedReadToolkitContent).toHaveBeenCalledWith('credits'); expect(useToolkitContentStore.getState()).toMatchObject({ credits: changedCredits, error: null, revision: '123', status: 'ready', }); expect(useToolkitContentStore.getState().lastLoadedAt).not.toBeNull(); }); it('saves credits through the socket client', async () => { mockedSaveToolkitContent.mockResolvedValue({ content: changedCredits, resource: 'credits', revision: '456', }); await act(async () => { await useToolkitContentStore.getState().saveCredits(changedCredits); }); expect(mockedSaveToolkitContent).toHaveBeenCalledWith( 'credits', changedCredits, ); expect(useToolkitContentStore.getState()).toMatchObject({ credits: changedCredits, error: null, revision: '456', status: 'ready', }); }); it('replaces credits from a socket change event', () => { act(() => { useToolkitContentStore .getState() .setCreditsFromSocket(changedCredits, '789'); }); expect(useToolkitContentStore.getState()).toMatchObject({ credits: changedCredits, error: null, revision: '789', status: 'ready', }); }); it('tracks content request errors without losing fallback credits', async () => { mockedReadToolkitContent.mockRejectedValue(new Error('socket unavailable')); await act(async () => { await useToolkitContentStore.getState().refreshCredits(); }); expect(useToolkitContentStore.getState()).toMatchObject({ credits: fallbackCreditsContent, error: 'socket unavailable', status: 'error', }); }); it('creates, updates, and deletes toolkit records through the socket client', async () => { const newPetitioner = { id: 'petitioner_test_001', name: 'Test Petitioner', sourceWikiPages: ['Gameplay'], tags: ['test'], }; const changedPetitioners = [newPetitioner]; mockedCreateToolkitContentRecord.mockResolvedValue({ content: changedPetitioners, resource: 'petitioners', revision: '101', }); mockedUpdateToolkitContentRecord.mockResolvedValue({ content: changedPetitioners, resource: 'petitioners', revision: '102', }); mockedDeleteToolkitContentRecord.mockResolvedValue({ content: [], resource: 'petitioners', revision: '103', }); await act(async () => { await useToolkitContentStore .getState() .createRecord('petitioners', newPetitioner); }); expect(mockedCreateToolkitContentRecord).toHaveBeenCalledWith( 'petitioners', newPetitioner, ); expect(useToolkitContentStore.getState().contentByResource.petitioners).toEqual( changedPetitioners, ); await act(async () => { await useToolkitContentStore .getState() .updateRecord('petitioners', newPetitioner); }); expect(mockedUpdateToolkitContentRecord).toHaveBeenCalledWith( 'petitioners', newPetitioner, ); await act(async () => { await useToolkitContentStore .getState() .deleteRecord('petitioners', newPetitioner.id); }); expect(mockedDeleteToolkitContentRecord).toHaveBeenCalledWith( 'petitioners', newPetitioner.id, ); expect(useToolkitContentStore.getState().contentByResource.petitioners).toEqual( [], ); }); });