96f4cba4a8
- 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).
101 lines
2.7 KiB
TypeScript
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);
|
|
});
|
|
});
|