Ctrl+F7, Review ▸ Thesaurus and the context menu open one dialog: the word at the caret, the sense groups it is in, click one to replace it, and a box to look up any other word. The data is MyThes re-packed to one group per line (de 3.0MB/37k groups, en 6.7MB/143k) — the format repeats every group once per member, ten times the bytes. Loaded on first use for the document's language and scanned, not indexed: ~4ms a lookup, where a word→group index measured ~100MB of memory against the text's ~8MB.
51 lines
1.9 KiB
TypeScript
51 lines
1.9 KiB
TypeScript
// The thesaurus lookup: a word is matched as a whole group member, never as a
|
|
// substring of one, and the groups come back without the word itself.
|
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
import { synonyms, loadThesaurus } from '../../src/lib/spell/thesaurus';
|
|
import { NO_LANGUAGE } from '../../src/lib/storage/documentLanguage';
|
|
|
|
const DATA = [
|
|
'Ausgedingehaus;Stöckli;Haus',
|
|
'Haus;Gebäude;Bauwerk',
|
|
'Haus;Zuhause;Heim',
|
|
'Hausboot;Boot',
|
|
'schnell;rasch;flink',
|
|
'C++;Programmiersprache',
|
|
].join('\n');
|
|
|
|
// One language per test file run: the module caches a loaded thesaurus for the session.
|
|
beforeEach(() => {
|
|
vi.stubGlobal('fetch', vi.fn(async () => new Response(DATA, { status: 200 })));
|
|
});
|
|
|
|
describe('synonyms', () => {
|
|
it('returns every group the word is in, without the word', async () => {
|
|
// The groups leading with it come first — its own senses before a compound's.
|
|
expect(await synonyms('de', 'Haus')).toEqual([
|
|
['Gebäude', 'Bauwerk'],
|
|
['Zuhause', 'Heim'],
|
|
['Ausgedingehaus', 'Stöckli'],
|
|
]);
|
|
});
|
|
|
|
it('matches whole members only, and ignores case', async () => {
|
|
expect(await synonyms('de', 'haus')).toHaveLength(3); // the groups holding Haus, not Hausboot's
|
|
expect(await synonyms('de', 'boot')).toEqual([['Hausboot']]);
|
|
});
|
|
|
|
it('takes a word with regex characters in it', async () => {
|
|
expect(await synonyms('de', 'C++')).toEqual([['Programmiersprache']]);
|
|
});
|
|
|
|
it('has nothing for an unknown word or no language', async () => {
|
|
expect(await synonyms('de', 'Fahrrad')).toEqual([]);
|
|
expect(await synonyms(NO_LANGUAGE, 'Haus')).toEqual([]);
|
|
});
|
|
|
|
it('fetches the file once per language', async () => {
|
|
await synonyms('en', 'Haus'); // 'en' is untouched above, so this is its first load
|
|
await loadThesaurus('en');
|
|
expect(vi.mocked(fetch)).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|