feat: integrate client and server sharing workflows

This commit is contained in:
justme committed 2026-10-02 10:49:45 +08:00
1 parent 42b93ae2d8
commit 7406e2fe37
101 files changed
+3153 -253

No files matched your search

+32
View File
@@ -0,0 +1,32 @@
import { afterEach, describe, expect, it, vi } from 'vitest';
import { apiFetch, setApiBase } from './http';
describe('API contract preflight', () => {
afterEach(() => {
setApiBase('/api/v1');
vi.unstubAllGlobals();
});
it('blocks API requests when the server has a newer breaking major', async () => {
const fetchMock = vi.fn(async () => new Response(JSON.stringify({ contract_version: '2.0.0' }), { status: 200 }));
vi.stubGlobal('fetch', fetchMock);
setApiBase('http://api.test/api/v1');
await expect(apiFetch('/channels')).rejects.toThrow('api_contract_mismatch');
expect(fetchMock).toHaveBeenCalledTimes(1);
expect(fetchMock).toHaveBeenCalledWith('http://api.test/api/v1/info', expect.any(Object));
});
it('checks the contract once and then sends the API request', async () => {
const fetchMock = vi.fn()
.mockResolvedValueOnce(new Response(JSON.stringify({ contract_version: '1.2.0' }), { status: 200 }))
.mockResolvedValueOnce(new Response('{}', { status: 200 }))
.mockResolvedValueOnce(new Response('{}', { status: 200 }));
vi.stubGlobal('fetch', fetchMock);
setApiBase('http://api.test/api/v1');
await expect(apiFetch('/channels')).resolves.toBeInstanceOf(Response);
await expect(apiFetch('/shares')).resolves.toBeInstanceOf(Response);
expect(fetchMock).toHaveBeenCalledTimes(3);
});
});