Files
searchi/apps/desktop/tests/capture-bridge.test.mjs
T
karl 79553ce921
Core CI / core (ubuntu-latest) (push) Failing after 3m29s
Core CI / core (macos-latest) (push) Canceled after 0s
Core CI / core (windows-latest) (push) Canceled after 0s
Core CI / desktop (ubuntu-latest) (push) Successful in 7m23s
Core CI / desktop (macos-latest) (push) Canceled after 0s
Core CI / desktop (windows-latest) (push) Canceled after 0s
feat: highlight search matches and document the working UI
2026-10-12 19:57:34 +02:00

59 lines
3.5 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import {CaptureBridge, captureRequested} from '../src/capture-bridge.ts';
const ready = () => new Response(JSON.stringify({mode: 'readme-capture', ready: true, token: 'a'.repeat(64)}));
test('ordinary previews and remote pages never initialize a capture bridge', async () => {
const bridge = new CaptureBridge();
let called = 0;
for (const href of ['http://127.0.0.1:1431/', 'https://example.com/?capture=1', 'file:///tmp/demo?capture=1', 'http://127.0.0.1:1431/?capture=0']) {
assert.equal(captureRequested(href), false);
assert.equal(await bridge.initialize(href, async () => { called++; return ready(); }), false);
}
assert.equal(called, 0);
assert.equal(bridge.active, false);
});
test('ready identity and nonce are required before any command dispatch', async () => {
for (const info of [{mode:'other',ready:true,token:'a'.repeat(64)}, {mode:'readme-capture',ready:false,token:'a'.repeat(64)}, {mode:'readme-capture',ready:true,token:'short'}]) {
const bridge = new CaptureBridge();
await assert.rejects(bridge.initialize('http://127.0.0.1:1431/?capture=1', async () => new Response(JSON.stringify(info))));
assert.equal(bridge.active, false);
await assert.rejects(bridge.invoke('stats', {}, async () => assert.fail('Must not dispatch')));
}
});
test('read-only commands use authenticated same-origin requests and mutation is rejected', async () => {
const bridge = new CaptureBridge();
await bridge.initialize('http://127.0.0.1:1431/?capture=1', async () => ready());
let request;
const result = await bridge.invoke('search_measured', {query:'real query'}, async (url, options) => {
request = {url, options}; return new Response(JSON.stringify({results:[],metrics:{total_ms:1}}));
});
assert.equal(result.metrics.total_ms, 1);
assert.equal(request.url, 'http://127.0.0.1:1431/capture-api/search_measured');
assert.equal(request.options.headers['X-Searchi-Capture-Token'], 'a'.repeat(64));
assert.equal(request.options.redirect, 'error');
assert.equal(request.options.credentials, 'omit');
for (const command of ['open_result','index_folder','set_cpu_threads','../../other']) {
await assert.rejects(bridge.invoke(command, {}, async () => assert.fail('Mutation must not dispatch')), /read-only/);
}
});
test('a failed reinitialization cannot retain earlier capture authorization', async () => {
const bridge = new CaptureBridge();
await bridge.initialize('http://127.0.0.1:1431/?capture=1', async () => ready());
await assert.rejects(bridge.initialize('http://127.0.0.1:1431/?capture=1', async () => new Response('{}')));
assert.equal(bridge.active, false);
await assert.rejects(bridge.invoke('stats', {}, async () => assert.fail('No stale authorization')));
});
test('media resolver rejects file paths, remote URLs and traversal; failed measured payload survives', async () => {
const bridge = new CaptureBridge();
await bridge.initialize('http://127.0.0.1:1431/?capture=1', async () => ready());
assert.equal(bridge.mediaURL('/capture-media/cat'), 'http://127.0.0.1:1431/capture-media/cat');
for (const path of ['C:/secret.jpg','https://example.com/cat','//example.com/cat','/capture-media/../secret','/capture-media/%2e%2e','/capture-media/cat?token=other']) assert.throws(() => bridge.mediaURL(path));
await assert.rejects(bridge.invoke('hybrid_search_measured', {}, async () => new Response(JSON.stringify({message:'busy',metrics:{total_ms:4}}), {status:503})), error => error.message === 'busy' && error.metrics.total_ms === 4);
});