feature/unified-tanstack-query #36

Merged
ilia merged 8 commits from feature/unified-tanstack-query into main 2026-04-16 04:53:29 +00:00
3 changed files with 60 additions and 1 deletions
Showing only changes of commit 10f4781a67 - Show all commits

View File

@@ -8,7 +8,10 @@ import {
vi, vi,
} from 'vitest'; } from 'vitest';
import * as api from '../../api/proxy/proxyFonts'; import * as api from '../../api/proxy/proxyFonts';
import { FontNetworkError } from '../../lib/errors/errors'; import {
FontNetworkError,
FontResponseError,
} from '../../lib/errors/errors';
import { BatchFontStore } from './batchFontStore.svelte'; import { BatchFontStore } from './batchFontStore.svelte';
describe('BatchFontStore', () => { describe('BatchFontStore', () => {
@@ -58,6 +61,31 @@ describe('BatchFontStore', () => {
vi.spyOn(api, 'fetchFontsByIds').mockResolvedValue(null as any); vi.spyOn(api, 'fetchFontsByIds').mockResolvedValue(null as any);
const store = new BatchFontStore(['a']); const store = new BatchFontStore(['a']);
await vi.waitFor(() => expect(store.isError).toBe(true), { timeout: 1000 }); await vi.waitFor(() => expect(store.isError).toBe(true), { timeout: 1000 });
expect(store.error).toBeInstanceOf(FontResponseError);
});
it('should have null error in success state', async () => {
const fonts = [{ id: 'a' }] as any[];
vi.spyOn(api, 'fetchFontsByIds').mockResolvedValue(fonts);
const store = new BatchFontStore(['a']);
await vi.waitFor(() => expect(store.fonts).toEqual(fonts), { timeout: 1000 });
expect(store.error).toBeNull();
});
});
describe('Disable Behavior', () => {
it('should return empty fonts and not fetch when setIds is called with empty array', async () => {
const fonts1 = [{ id: 'a' }] as any[];
const spy = vi.spyOn(api, 'fetchFontsByIds').mockResolvedValueOnce(fonts1);
const store = new BatchFontStore(['a']);
await vi.waitFor(() => expect(store.fonts).toEqual(fonts1), { timeout: 1000 });
spy.mockClear();
store.setIds([]);
await vi.waitFor(() => expect(store.fonts).toEqual([]), { timeout: 1000 });
expect(spy).not.toHaveBeenCalled();
}); });
}); });

View File

@@ -27,6 +27,17 @@ describe('fontKeys', () => {
it('should handle empty ID arrays', () => { it('should handle empty ID arrays', () => {
expect(fontKeys.batch([])).toEqual(['fonts', 'batch', []]); expect(fontKeys.batch([])).toEqual(['fonts', 'batch', []]);
}); });
it('should not mutate the input array when sorting', () => {
const ids = ['c', 'b', 'a'];
fontKeys.batch(ids);
expect(ids).toEqual(['c', 'b', 'a']);
});
it('batch key should be rooted in batches() base', () => {
const key = fontKeys.batch(['a']);
expect(key.slice(0, 2)).toEqual(fontKeys.batches());
});
}); });
describe('List Keys (Parameters)', () => { describe('List Keys (Parameters)', () => {
@@ -38,11 +49,25 @@ describe('fontKeys', () => {
it('should handle empty parameters', () => { it('should handle empty parameters', () => {
expect(fontKeys.list({})).toEqual(['fonts', 'list', {}]); expect(fontKeys.list({})).toEqual(['fonts', 'list', {}]);
}); });
it('list key should be rooted in lists() base', () => {
const key = fontKeys.list({ provider: 'google' });
expect(key.slice(0, 2)).toEqual(fontKeys.lists());
});
}); });
describe('Detail Keys', () => { describe('Detail Keys', () => {
it('should generate unique detail keys per ID', () => { it('should generate unique detail keys per ID', () => {
expect(fontKeys.detail('roboto')).toEqual(['fonts', 'detail', 'roboto']); expect(fontKeys.detail('roboto')).toEqual(['fonts', 'detail', 'roboto']);
}); });
it('should generate different keys for different IDs', () => {
expect(fontKeys.detail('roboto')).not.toEqual(fontKeys.detail('open-sans'));
});
it('detail key should be rooted in details() base', () => {
const key = fontKeys.detail('roboto');
expect(key.slice(0, 2)).toEqual(fontKeys.details());
});
}); });
}); });

View File

@@ -51,6 +51,12 @@ describe('BaseQueryStore', () => {
await vi.waitFor(() => expect(store.data).toBe('ok'), { timeout: 1000 }); await vi.waitFor(() => expect(store.data).toBe('ok'), { timeout: 1000 });
expect(store.isLoading).toBe(false); expect(store.isLoading).toBe(false);
}); });
it('should have undefined data and no error in initial loading state', () => {
const store = new TestStore(['initial-state'], () => new Promise(r => setTimeout(() => r('late'), 500)));
expect(store.data).toBeUndefined();
expect(store.isError).toBe(false);
});
}); });
describe('Error Handling', () => { describe('Error Handling', () => {