Files
tools/core/stdlib/src/text/trigram-distance/index.test.ts
T
robonen 96f4cba4a8 feat(stdlib): new modules + eslint/tsconfig migration
- Add array/async/etc. modules and type tests; migrate to eslint flat config
  and composite tsconfig (vitest typecheck enabled).
- Fix PubSub.emit to snapshot listeners before iterating (stable EventEmitter
  semantics; avoids invoking listeners added during the same emit).
2026-06-07 16:29:08 +07:00

101 lines
2.7 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { trigramDistance, trigramProfile } from '.';
describe('trigramProfile', () => {
it('trigram profile of a text with different trigrams', () => {
const different_trigrams = 'hello world';
const profile1 = trigramProfile(different_trigrams);
expect(profile1).toEqual(new Map([
['\n\nh', 1],
['\nhe', 1],
['hel', 1],
['ell', 1],
['llo', 1],
['lo ', 1],
['o w', 1],
[' wo', 1],
['wor', 1],
['orl', 1],
['rld', 1],
['ld\n', 1],
['d\n\n', 1],
]));
});
it('trigram profile of a text with repeated trigrams', () => {
const repeated_trigrams = 'hello hello';
const profile2 = trigramProfile(repeated_trigrams);
expect(profile2).toEqual(new Map([
['\n\nh', 1],
['\nhe', 1],
['hel', 2],
['ell', 2],
['llo', 2],
['lo ', 1],
['o h', 1],
[' he', 1],
['lo\n', 1],
['o\n\n', 1],
]));
});
it('trigram profile of an empty text', () => {
const text = '';
const profile = trigramProfile(text);
expect(profile).toEqual(new Map([
['\n\n\n', 2],
]));
});
});
describe('trigramDistance', () => {
it('zero when comparing the same text', () => {
const profile1 = trigramProfile('hello world');
const profile2 = trigramProfile('hello world');
expect(trigramDistance(profile1, profile2)).toBe(0);
});
it('one for completely different text', () => {
const profile1 = trigramProfile('hello world');
const profile2 = trigramProfile('lorem ipsum');
expect(trigramDistance(profile1, profile2)).toBe(1);
});
it('is symmetric', () => {
const a = trigramProfile('hello world');
const b = trigramProfile('hello lorem');
expect(trigramDistance(a, b)).toBe(trigramDistance(b, a));
});
it('one for empty text and non-empty text', () => {
const profile1 = trigramProfile('hello world');
const profile2 = trigramProfile('');
expect(trigramDistance(profile1, profile2)).toBe(1);
});
it('approximately 0.5 for similar text', () => {
const profile1 = trigramProfile('hello world');
const profile2 = trigramProfile('hello lorem');
const approx = trigramDistance(profile1, profile2);
expect(approx).toBeGreaterThan(0.45);
expect(approx).toBeLessThan(0.55);
});
it('triangle inequality', () => {
const A = trigramDistance(trigramProfile('metric'), trigramProfile('123ric'));
const B = trigramDistance(trigramProfile('123ric'), trigramProfile('123456'));
const C = trigramDistance(trigramProfile('metric'), trigramProfile('123456'));
expect(A + B).toBeGreaterThanOrEqual(C);
});
});