test: add Ollama provider tests across endpoint, sidecar, and chain layers

Three test files covering Ollama integration:

api/ollama-summarize.test.mjs (9 tests):
- Fallback signal when unconfigured, on API error, on empty response
- Success path with correct provider label and response shape
- Model selection via OLLAMA_MODEL env / default fallback
- Network error handling (ECONNREFUSED)
- Translate mode prompt verification

tests/summarization-chain.test.mjs (7 tests):
- Ollama success short-circuits chain (Groq never called)
- Ollama fail → Groq success fallback
- Full fallback when both unconfigured
- Provider label correctness for Ollama and Groq
- Uniform response shape across providers
- Identical fallback signal shapes

src-tauri/sidecar/local-api-server.test.mjs (8 new tests):
- OLLAMA_API_URL and OLLAMA_MODEL accepted via env-update allowlist
- Unknown keys rejected (403)
- Validation via /v1/models probe (reachable mock)
- Validation via /api/tags native fallback
- OLLAMA_MODEL pass-through validation
- Non-http protocol rejection (422)
- Auth-required behavior preserved with token

https://claude.ai/code/session_01AGg9fG6LZ8Y6XhvLszdfeY
This commit is contained in:
Claude
2026-02-19 14:41:32 +00:00
parent 3f5fa51f40
commit ba329e2a2a
3 changed files with 697 additions and 0 deletions

View File

@@ -359,3 +359,261 @@ test('resolves packaged tauri resource layout under _up_/api', async () => {
await remote.close();
}
});
// ── Ollama env key allowlist + validation tests ──
test('accepts OLLAMA_API_URL via /api/local-env-update', async () => {
const localApi = await setupApiDir({});
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
});
const { port } = await app.start();
try {
const response = await fetch(`http://127.0.0.1:${port}/api/local-env-update`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ key: 'OLLAMA_API_URL', value: 'http://127.0.0.1:11434' }),
});
assert.equal(response.status, 200);
const body = await response.json();
assert.equal(body.ok, true);
assert.equal(body.key, 'OLLAMA_API_URL');
assert.equal(process.env.OLLAMA_API_URL, 'http://127.0.0.1:11434');
} finally {
delete process.env.OLLAMA_API_URL;
await app.close();
await localApi.cleanup();
}
});
test('accepts OLLAMA_MODEL via /api/local-env-update', async () => {
const localApi = await setupApiDir({});
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
});
const { port } = await app.start();
try {
const response = await fetch(`http://127.0.0.1:${port}/api/local-env-update`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ key: 'OLLAMA_MODEL', value: 'llama3.1:8b' }),
});
assert.equal(response.status, 200);
const body = await response.json();
assert.equal(body.ok, true);
assert.equal(body.key, 'OLLAMA_MODEL');
assert.equal(process.env.OLLAMA_MODEL, 'llama3.1:8b');
} finally {
delete process.env.OLLAMA_MODEL;
await app.close();
await localApi.cleanup();
}
});
test('rejects unknown key via /api/local-env-update', async () => {
const localApi = await setupApiDir({});
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
});
const { port } = await app.start();
try {
const response = await fetch(`http://127.0.0.1:${port}/api/local-env-update`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ key: 'NOT_ALLOWED_KEY', value: 'some-value' }),
});
assert.equal(response.status, 403);
const body = await response.json();
assert.equal(body.error, 'key not in allowlist');
} finally {
await app.close();
await localApi.cleanup();
}
});
test('validates OLLAMA_API_URL via /api/local-validate-secret (reachable endpoint)', async () => {
// Stand up a mock Ollama server that responds to /v1/models
const mockOllama = createServer((req, res) => {
if (req.url === '/v1/models') {
res.writeHead(200, { 'content-type': 'application/json' });
res.end(JSON.stringify({ data: [{ id: 'llama3.1:8b' }] }));
} else {
res.writeHead(404);
res.end('not found');
}
});
const ollamaPort = await listen(mockOllama);
const localApi = await setupApiDir({});
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
});
const { port } = await app.start();
try {
const response = await fetch(`http://127.0.0.1:${port}/api/local-validate-secret`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ key: 'OLLAMA_API_URL', value: `http://127.0.0.1:${ollamaPort}` }),
});
assert.equal(response.status, 200);
const body = await response.json();
assert.equal(body.valid, true);
assert.equal(body.message, 'Ollama endpoint verified');
} finally {
await app.close();
await localApi.cleanup();
await new Promise((resolve, reject) => {
mockOllama.close((err) => (err ? reject(err) : resolve()));
});
}
});
test('validates OLLAMA_API_URL via native /api/tags fallback', async () => {
// Mock server that only responds to /api/tags (not /v1/models)
const mockOllama = createServer((req, res) => {
if (req.url === '/api/tags') {
res.writeHead(200, { 'content-type': 'application/json' });
res.end(JSON.stringify({ models: [{ name: 'llama3.1:8b' }] }));
} else {
res.writeHead(404);
res.end('not found');
}
});
const ollamaPort = await listen(mockOllama);
const localApi = await setupApiDir({});
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
});
const { port } = await app.start();
try {
const response = await fetch(`http://127.0.0.1:${port}/api/local-validate-secret`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ key: 'OLLAMA_API_URL', value: `http://127.0.0.1:${ollamaPort}` }),
});
assert.equal(response.status, 200);
const body = await response.json();
assert.equal(body.valid, true);
assert.equal(body.message, 'Ollama endpoint verified (native API)');
} finally {
await app.close();
await localApi.cleanup();
await new Promise((resolve, reject) => {
mockOllama.close((err) => (err ? reject(err) : resolve()));
});
}
});
test('validates OLLAMA_MODEL stores model name', async () => {
const localApi = await setupApiDir({});
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
});
const { port } = await app.start();
try {
const response = await fetch(`http://127.0.0.1:${port}/api/local-validate-secret`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ key: 'OLLAMA_MODEL', value: 'mistral:7b' }),
});
assert.equal(response.status, 200);
const body = await response.json();
assert.equal(body.valid, true);
assert.equal(body.message, 'Model name stored');
} finally {
await app.close();
await localApi.cleanup();
}
});
test('rejects OLLAMA_API_URL with non-http protocol', async () => {
const localApi = await setupApiDir({});
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
});
const { port } = await app.start();
try {
const response = await fetch(`http://127.0.0.1:${port}/api/local-validate-secret`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ key: 'OLLAMA_API_URL', value: 'ftp://127.0.0.1:11434' }),
});
assert.equal(response.status, 422);
const body = await response.json();
assert.equal(body.valid, false);
assert.equal(body.message, 'Must be an http(s) URL');
} finally {
await app.close();
await localApi.cleanup();
}
});
test('auth-required behavior unchanged — rejects unauthenticated requests when token is set', async () => {
const localApi = await setupApiDir({});
const originalToken = process.env.LOCAL_API_TOKEN;
process.env.LOCAL_API_TOKEN = 'secret-token-123';
const app = await createLocalApiServer({
port: 0,
apiDir: localApi.apiDir,
logger: { log() {}, warn() {}, error() {} },
});
const { port } = await app.start();
try {
// Request without auth header should be rejected
const response = await fetch(`http://127.0.0.1:${port}/api/local-env-update`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ key: 'OLLAMA_API_URL', value: 'http://127.0.0.1:11434' }),
});
assert.equal(response.status, 401);
const body = await response.json();
assert.equal(body.error, 'Unauthorized');
// Request with correct auth header should succeed
const authedResponse = await fetch(`http://127.0.0.1:${port}/api/local-env-update`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer secret-token-123',
},
body: JSON.stringify({ key: 'OLLAMA_API_URL', value: 'http://127.0.0.1:11434' }),
});
assert.equal(authedResponse.status, 200);
} finally {
if (originalToken !== undefined) {
process.env.LOCAL_API_TOKEN = originalToken;
} else {
delete process.env.LOCAL_API_TOKEN;
}
delete process.env.OLLAMA_API_URL;
await app.close();
await localApi.cleanup();
}
});