moving
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled

This commit is contained in:
Oleg Maslov
2026-09-02 10:10:29 +02:00
commit 0c3e2ead3b
3841 changed files with 970576 additions and 0 deletions

View File

@@ -0,0 +1,132 @@
/**
* E2E Tests: Startup, Onboarding, and Settings Persistence
*
* Scenarios covered:
* 1. Service starts and responds to health check
* 2. Onboarding wizard completes successfully (config save/load via settings API)
* 7. Settings saved and persisted across restart
*/
import { describe, it, expect, afterEach } from 'vitest';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import type { FastifyInstance } from 'fastify';
import { startService } from '@waggle/server/local/service';
import { injectWithAuth } from './test-utils.js';
function makeTmpDir(): string {
return fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-e2e-'));
}
// Port 0 lets the OS assign a free port; inject() bypasses the network anyway
const TEST_PORT = 0;
describe('Startup & Settings E2E', () => {
const servers: FastifyInstance[] = [];
const tmpDirs: string[] = [];
afterEach(async () => {
for (const s of servers) {
try { await s.close(); } catch { /* ignore */ }
}
servers.length = 0;
for (const d of tmpDirs) {
try { fs.rmSync(d, { recursive: true, force: true }); } catch { /* ignore */ }
}
tmpDirs.length = 0;
});
// Scenario 1: Service starts and responds to health check
it('health check returns 200 with status ok and mode local', async () => {
const dataDir = makeTmpDir();
tmpDirs.push(dataDir);
const port = TEST_PORT;
const { server } = await startService({ dataDir, port, skipLiteLLM: true });
servers.push(server);
const res = await server.inject({ method: 'GET', url: '/health' });
expect(res.statusCode).toBe(200);
const body = JSON.parse(res.payload);
// With skipLiteLLM, health is degraded (no verified LLM), not 'ok' — truthful health
expect(['ok', 'degraded', 'unavailable']).toContain(body.status);
expect(body.mode).toBe('local');
expect(body.timestamp).toBeDefined();
// Deep health fields present
expect(body.llm).toBeDefined();
expect(body.database).toBeDefined();
});
// Scenario 2: Onboarding — save config via PUT, read it back via GET
it('onboarding: saves and loads config via settings API', async () => {
const dataDir = makeTmpDir();
tmpDirs.push(dataDir);
const port = TEST_PORT;
const { server } = await startService({ dataDir, port, skipLiteLLM: true });
servers.push(server);
// Save onboarding config
const putRes = await injectWithAuth(server, {
method: 'PUT',
url: '/api/settings',
payload: {
defaultModel: 'anthropic/claude-sonnet-4-20250514',
providers: {
anthropic: { apiKey: 'sk-ant-test-key-1234567890', models: ['claude-sonnet-4-20250514'] },
},
},
});
expect(putRes.statusCode).toBe(200);
const putBody = JSON.parse(putRes.payload);
expect(putBody.defaultModel).toBe('anthropic/claude-sonnet-4-20250514');
// Read config back
const getRes = await injectWithAuth(server, { method: 'GET', url: '/api/settings' });
expect(getRes.statusCode).toBe(200);
const getBody = JSON.parse(getRes.payload);
expect(getBody.defaultModel).toBe('anthropic/claude-sonnet-4-20250514');
expect(getBody.providers).toBeDefined();
expect(getBody.dataDir).toBe(dataDir);
});
// Scenario 7: Settings persisted across restart
it('settings persist across server restart', async () => {
const dataDir = makeTmpDir();
tmpDirs.push(dataDir);
// --- First server: save settings ---
const port1 = TEST_PORT;
const { server: server1 } = await startService({ dataDir, port: port1, skipLiteLLM: true });
servers.push(server1);
const putRes = await injectWithAuth(server1, {
method: 'PUT',
url: '/api/settings',
payload: {
defaultModel: 'openai/gpt-4o',
providers: {
openai: { apiKey: 'sk-test-openai-key-1234567', models: ['gpt-4o'] },
},
},
});
expect(putRes.statusCode).toBe(200);
await server1.close();
servers.pop();
// --- Second server: read settings back ---
const port2 = TEST_PORT;
const { server: server2 } = await startService({ dataDir, port: port2, skipLiteLLM: true });
servers.push(server2);
const getRes = await injectWithAuth(server2, { method: 'GET', url: '/api/settings' });
expect(getRes.statusCode).toBe(200);
const body = JSON.parse(getRes.payload);
expect(body.defaultModel).toBe('openai/gpt-4o');
});
});