Core CI / core (ubuntu-latest) (push) Failing after 3m27s
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 5m45s
Core CI / desktop (macos-latest) (push) Canceled after 0s
Core CI / desktop (windows-latest) (push) Canceled after 0s
70 lines
3.6 KiB
JavaScript
70 lines
3.6 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { LatestLane, AutomaticIndexGate, emptySearchState } from '../src/search-state.ts';
|
|
const settle = () => new Promise(resolve => setImmediate(resolve));
|
|
|
|
test('coalesces queued keystrokes and discards stale responses', async () => {
|
|
let revision = 1; let release; const executed = []; const accepted = [];
|
|
const lane = new LatestLane(async value => {
|
|
executed.push(value);
|
|
if (value === 1) await new Promise(resolve => { release = resolve; });
|
|
if (value === revision) accepted.push(value);
|
|
}, value => value === revision, () => assert.fail('Unexpected failure'));
|
|
lane.submit(1); revision = 2; lane.submit(2); revision = 3; lane.submit(3);
|
|
release(); await settle();
|
|
assert.deepEqual(executed, [1, 3]); assert.deepEqual(accepted, [3]);
|
|
});
|
|
|
|
test('Escape invalidates both active and queued work', async () => {
|
|
let revision = 1; let release; const accepted = [];
|
|
const lane = new LatestLane(async value => {
|
|
await new Promise(resolve => { release = resolve; });
|
|
if (value === revision) accepted.push(value);
|
|
}, value => value === revision, () => assert.fail('Unexpected failure'));
|
|
lane.submit(1); lane.submit(1); revision++; lane.clear(); release(); await settle();
|
|
assert.deepEqual(accepted, []);
|
|
});
|
|
|
|
test('busy retries are bounded and stop when superseded', async () => {
|
|
let attempts = 0; let errors = 0;
|
|
const lane = new LatestLane(async () => { attempts++; throw new Error('worker busy'); }, () => true, () => errors++, async () => {});
|
|
lane.submit(1); await settle(); assert.equal(attempts, 2); assert.equal(errors, 1);
|
|
let revision = 1; let release; const executed = [];
|
|
const superseded = new LatestLane(async value => { executed.push(value); if (value === 1) throw new Error('busy'); }, value => value === revision, () => assert.fail('Unexpected failure'), () => new Promise(resolve => { release = resolve; }));
|
|
superseded.submit(1); await settle(); revision = 2; superseded.submit(2); release(); await settle();
|
|
assert.deepEqual(executed, [1, 2]);
|
|
});
|
|
|
|
test('automatic rebuild failures wait for a changed revision', () => {
|
|
const gate = new AutomaticIndexGate();
|
|
assert.equal(gate.claim('generation1:pending4:folder1'), true);
|
|
assert.equal(gate.claim('generation1:pending4:folder1'), false);
|
|
assert.equal(gate.claim('generation1:pending4:folder2'), true);
|
|
});
|
|
|
|
test('empty keyword results stay provisional while semantic setup or search is pending', () => {
|
|
for (const phase of ['preparing', 'indexing', 'pending']) {
|
|
const state = emptySearchState('lexical', phase);
|
|
assert.equal(state.title, 'No keyword matches yet.');
|
|
assert.match(state.detail, /preparing|indexing|Searching by meaning/);
|
|
assert.doesNotMatch(state.title, /No matching files|No matches for this search/);
|
|
}
|
|
});
|
|
|
|
test('only a completed hybrid search gives a final no-match message', () => {
|
|
const complete = emptySearchState('hybrid', 'complete');
|
|
assert.equal(complete.title, 'No matches for this search.');
|
|
assert.match(complete.detail, /filters/);
|
|
const rebuilding = emptySearchState('hybrid', 'indexing');
|
|
assert.equal(rebuilding.title, 'No matches in the current index yet.');
|
|
assert.match(rebuilding.detail, /may change/);
|
|
for (const phase of ['preparing', 'indexing', 'pending', 'unavailable', 'no-content']) {
|
|
assert.notEqual(emptySearchState('hybrid', phase).title, complete.title);
|
|
}
|
|
});
|
|
|
|
test('no document content and unavailable semantics have actionable distinct guidance', () => {
|
|
assert.match(emptySearchState('lexical', 'no-content').detail, /readable documents/);
|
|
assert.match(emptySearchState('lexical', 'unavailable').detail, /retry the search/);
|
|
});
|