131 lines
4.1 KiB
TypeScript
131 lines
4.1 KiB
TypeScript
// Tests fuer notes-api (Client-Funktionen mit fetch-Mock)
|
|
// Phase 4.1
|
|
|
|
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
|
|
import {
|
|
loadNote,
|
|
saveNote,
|
|
triggerSync,
|
|
listNotes,
|
|
type NoteData,
|
|
} from '../../webapp/src/notes-api';
|
|
|
|
describe('notes-api Client', () => {
|
|
let originalFetch: typeof globalThis.fetch;
|
|
|
|
beforeEach(() => {
|
|
originalFetch = globalThis.fetch;
|
|
});
|
|
|
|
afterEach(() => {
|
|
globalThis.fetch = originalFetch;
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
describe('loadNote', () => {
|
|
it('gibt null zurueck bei 404', async () => {
|
|
globalThis.fetch = vi.fn(
|
|
async () => new Response('Not Found', { status: 404, statusText: 'Not Found' }),
|
|
) as typeof fetch;
|
|
const result = await loadNote('notiz.md');
|
|
expect(result).toBeNull();
|
|
});
|
|
|
|
it('parst Notiz-Antwort korrekt', async () => {
|
|
const noteData: NoteData = {
|
|
id: 'test.md',
|
|
content: '# Test',
|
|
frontmatter: { title: 'Test' },
|
|
lastModified: '2026-09-05T10:00:00Z',
|
|
};
|
|
globalThis.fetch = vi.fn(
|
|
async () =>
|
|
new Response(JSON.stringify(noteData), {
|
|
status: 200,
|
|
headers: { 'Content-Type': 'application/json' },
|
|
}),
|
|
) as typeof fetch;
|
|
const result = await loadNote('test.md');
|
|
expect(result).toEqual(noteData);
|
|
});
|
|
|
|
it('wirft bei HTTP-Fehler (500)', async () => {
|
|
globalThis.fetch = vi.fn(
|
|
async () =>
|
|
new Response('Server Error', { status: 500, statusText: 'Internal Server Error' }),
|
|
) as typeof fetch;
|
|
await expect(loadNote('test.md')).rejects.toThrow('HTTP 500');
|
|
});
|
|
|
|
it('encoded den noteId in der URL', async () => {
|
|
const fetchMock = vi.fn(async () => new Response('null', { status: 404 })) as typeof fetch;
|
|
globalThis.fetch = fetchMock;
|
|
await loadNote('path with spaces.md');
|
|
expect(fetchMock).toHaveBeenCalledWith('/api/notes/path%20with%20spaces.md');
|
|
});
|
|
});
|
|
|
|
describe('saveNote', () => {
|
|
it('sendet PUT mit Content im Body', async () => {
|
|
const fetchMock = vi.fn(
|
|
async () =>
|
|
new Response(
|
|
JSON.stringify({ id: 'x.md', content: 'Y', frontmatter: {}, lastModified: 'now' }),
|
|
{
|
|
status: 200,
|
|
headers: { 'Content-Type': 'application/json' },
|
|
},
|
|
),
|
|
) as typeof fetch;
|
|
globalThis.fetch = fetchMock;
|
|
await saveNote('x.md', 'Y');
|
|
const [url, init] = fetchMock.mock.calls[0];
|
|
expect(url).toBe('/api/notes/x.md');
|
|
expect(init?.method).toBe('PUT');
|
|
expect((init?.headers as Record<string, string>)['Content-Type']).toBe('application/json');
|
|
const body = JSON.parse(init?.body as string);
|
|
expect(body.content).toBe('Y');
|
|
});
|
|
});
|
|
|
|
describe('triggerSync', () => {
|
|
it('sendet POST an /api/sync und gibt ok zurueck', async () => {
|
|
const fetchMock = vi.fn(
|
|
async () =>
|
|
new Response(JSON.stringify({ ok: true, message: 'Sync OK' }), {
|
|
status: 200,
|
|
headers: { 'Content-Type': 'application/json' },
|
|
}),
|
|
) as typeof fetch;
|
|
globalThis.fetch = fetchMock;
|
|
const result = await triggerSync();
|
|
expect(result.ok).toBe(true);
|
|
expect(result.message).toBe('Sync OK');
|
|
});
|
|
|
|
it('gibt Fehler zurueck bei 500', async () => {
|
|
globalThis.fetch = vi.fn(async () => new Response('Fail', { status: 500 })) as typeof fetch;
|
|
await expect(triggerSync()).rejects.toThrow('HTTP 500');
|
|
});
|
|
});
|
|
|
|
describe('listNotes', () => {
|
|
it('parst Notiz-Liste', async () => {
|
|
globalThis.fetch = vi.fn(
|
|
async () =>
|
|
new Response(JSON.stringify({ notes: ['a.md', 'b.md'] }), {
|
|
status: 200,
|
|
headers: { 'Content-Type': 'application/json' },
|
|
}),
|
|
) as typeof fetch;
|
|
const notes = await listNotes();
|
|
expect(notes).toEqual(['a.md', 'b.md']);
|
|
});
|
|
|
|
it('gibt leeres Array bei Fehler', async () => {
|
|
globalThis.fetch = vi.fn(async () => new Response('Boom', { status: 500 })) as typeof fetch;
|
|
await expect(listNotes()).rejects.toThrow('HTTP 500');
|
|
});
|
|
});
|
|
});
|