test(UnifiedFontStore): add pagination state tests
This commit is contained in:
@@ -28,12 +28,25 @@ vi.mock('../../../api', () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
import { queryClient } from '$shared/api/queryClient';
|
import { queryClient } from '$shared/api/queryClient';
|
||||||
|
import { flushSync } from 'svelte';
|
||||||
import { fetchProxyFonts } from '../../../api';
|
import { fetchProxyFonts } from '../../../api';
|
||||||
|
import { generateMockFonts } from '../../../lib/mocks/fonts.mock';
|
||||||
|
import type { UnifiedFont } from '../../types';
|
||||||
import { UnifiedFontStore } from './unifiedFontStore.svelte';
|
import { UnifiedFontStore } from './unifiedFontStore.svelte';
|
||||||
|
|
||||||
const mockedFetch = fetchProxyFonts as ReturnType<typeof vi.fn>;
|
const mockedFetch = fetchProxyFonts as ReturnType<typeof vi.fn>;
|
||||||
|
|
||||||
describe('UnifiedFontStore.fetchFn error paths', () => {
|
const makeResponse = (
|
||||||
|
fonts: UnifiedFont[],
|
||||||
|
meta: { total?: number; limit?: number; offset?: number } = {},
|
||||||
|
) => ({
|
||||||
|
fonts,
|
||||||
|
total: meta.total ?? fonts.length,
|
||||||
|
limit: meta.limit ?? 10,
|
||||||
|
offset: meta.offset ?? 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('fetchFn — error paths', () => {
|
||||||
let store: UnifiedFontStore;
|
let store: UnifiedFontStore;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -83,3 +96,117 @@ describe('UnifiedFontStore.fetchFn error paths', () => {
|
|||||||
expect((store.error as FontResponseError).received).toBe('bad');
|
expect((store.error as FontResponseError).received).toBe('bad');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('fetchFn — success path', () => {
|
||||||
|
let store: UnifiedFontStore;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
store = new UnifiedFontStore({ limit: 10 });
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
store.destroy();
|
||||||
|
queryClient.clear();
|
||||||
|
vi.resetAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('populates fonts after a successful fetch', async () => {
|
||||||
|
const fonts = generateMockFonts(3);
|
||||||
|
mockedFetch.mockResolvedValue(makeResponse(fonts));
|
||||||
|
await store.refetch();
|
||||||
|
|
||||||
|
expect(store.fonts).toHaveLength(3);
|
||||||
|
expect(store.fonts[0].id).toBe(fonts[0].id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('stores pagination metadata from response', async () => {
|
||||||
|
const fonts = generateMockFonts(3);
|
||||||
|
mockedFetch.mockResolvedValue(makeResponse(fonts, { total: 30, limit: 10, offset: 0 }));
|
||||||
|
await store.refetch();
|
||||||
|
|
||||||
|
expect(store.pagination.total).toBe(30);
|
||||||
|
expect(store.pagination.limit).toBe(10);
|
||||||
|
expect(store.pagination.offset).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('replaces accumulated fonts on offset-0 fetch', async () => {
|
||||||
|
const first = generateMockFonts(3);
|
||||||
|
mockedFetch.mockResolvedValue(makeResponse(first));
|
||||||
|
await store.refetch();
|
||||||
|
flushSync();
|
||||||
|
console.log('After first refetch + flushSync:', store.fonts.length);
|
||||||
|
|
||||||
|
const second = generateMockFonts(2);
|
||||||
|
mockedFetch.mockResolvedValue(makeResponse(second));
|
||||||
|
await store.refetch();
|
||||||
|
console.log('After second refetch, before flushSync:', store.fonts.length, store.fonts.map(f => f.id));
|
||||||
|
flushSync();
|
||||||
|
console.log('After second refetch + flushSync:', store.fonts.length, store.fonts.map(f => f.id));
|
||||||
|
|
||||||
|
expect(store.fonts).toHaveLength(2);
|
||||||
|
expect(store.fonts[0].id).toBe(second[0].id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('appends fonts when fetching at offset > 0', async () => {
|
||||||
|
const firstPage = generateMockFonts(3);
|
||||||
|
mockedFetch.mockResolvedValue(makeResponse(firstPage, { total: 6, limit: 3, offset: 0 }));
|
||||||
|
await store.refetch();
|
||||||
|
|
||||||
|
const secondPage = generateMockFonts(3).map((f, i) => ({
|
||||||
|
...f,
|
||||||
|
id: `page2-font-${i + 1}`,
|
||||||
|
}));
|
||||||
|
mockedFetch.mockResolvedValue(makeResponse(secondPage, { total: 6, limit: 3, offset: 3 }));
|
||||||
|
store.setParams({ offset: 3 });
|
||||||
|
await store.refetch();
|
||||||
|
|
||||||
|
expect(store.fonts).toHaveLength(6);
|
||||||
|
expect(store.fonts.slice(0, 3).map(f => f.id)).toEqual(firstPage.map(f => f.id));
|
||||||
|
expect(store.fonts.slice(3).map(f => f.id)).toEqual(secondPage.map(f => f.id));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('pagination state', () => {
|
||||||
|
let store: UnifiedFontStore;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
store = new UnifiedFontStore({ limit: 10 });
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
store.destroy();
|
||||||
|
queryClient.clear();
|
||||||
|
vi.resetAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns default pagination before any fetch', () => {
|
||||||
|
expect(store.pagination.total).toBe(0);
|
||||||
|
expect(store.pagination.hasMore).toBe(false);
|
||||||
|
expect(store.pagination.page).toBe(1);
|
||||||
|
expect(store.pagination.totalPages).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('computes hasMore as true when more pages remain', async () => {
|
||||||
|
mockedFetch.mockResolvedValue(makeResponse(generateMockFonts(10), { total: 30, limit: 10, offset: 0 }));
|
||||||
|
await store.refetch();
|
||||||
|
|
||||||
|
expect(store.pagination.hasMore).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('computes hasMore as false on last page', async () => {
|
||||||
|
mockedFetch.mockResolvedValue(makeResponse(generateMockFonts(10), { total: 20, limit: 10, offset: 10 }));
|
||||||
|
store.setParams({ offset: 10 });
|
||||||
|
await store.refetch();
|
||||||
|
|
||||||
|
expect(store.pagination.hasMore).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('computes page and totalPages from response metadata', async () => {
|
||||||
|
mockedFetch.mockResolvedValue(makeResponse(generateMockFonts(10), { total: 30, limit: 10, offset: 10 }));
|
||||||
|
store.setParams({ offset: 10 });
|
||||||
|
await store.refetch();
|
||||||
|
|
||||||
|
expect(store.pagination.page).toBe(2);
|
||||||
|
expect(store.pagination.totalPages).toBe(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user