Files
blb-throne-of-the-bone-king/__tests__/toolkitContentStore.test.ts
T
jacob-mathison 47567589e4
ci/woodpecker/push/woodpecker Pipeline was successful
Lint and Build Checks / Lint, Test, and Build (push) Failing after 368h6m42s
feat(toolkit): add structured media authoring
2026-06-24 11:30:26 -05:00

197 lines
5.5 KiB
TypeScript

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(
[],
);
});
});