import assert from 'node:assert/strict'; import { test } from 'node:test'; import { mbLevenshtein, mbStrlen } from '../lib/mbLevenshtein.js'; import { bucket, entryPath } from '../lib/paths.js'; import { parseQuery } from '../lib/queryParser.js'; import { filterAndLower, filterTitle, translit } from '../lib/titleFilter.js'; test('mbLevenshtein basic', () => { assert.equal(mbLevenshtein('kitten', 'sitting'), 3); assert.equal(mbLevenshtein('', 'abc'), 3); assert.equal(mbLevenshtein('abc', ''), 3); assert.equal(mbLevenshtein('abc', 'abc'), 0); }); test('mbLevenshtein utf-8', () => { // PHP mb_levenshtein remaps multibyte chars; JS works on code points. // The distance for équal chars should be 0. assert.equal(mbLevenshtein('café', 'café'), 0); assert.equal(mbLevenshtein('été', 'été'), 0); assert.equal(mbLevenshtein('é', 'e'), 1); }); test('mbLevenshtein custom costs', () => { // INS=10 REP=12 DEL=10 mirrors searchmultithreads.php assert.equal(mbLevenshtein('abc', 'abcd', 10, 12, 10), 10); assert.equal(mbLevenshtein('abcd', 'abc', 10, 12, 10), 10); assert.equal(mbLevenshtein('abc', 'abd', 10, 12, 10), 12); }); test('mbStrlen counts code points', () => { assert.equal(mbStrlen('abc'), 3); assert.equal(mbStrlen('café'), 4); assert.equal(mbStrlen('œuf'), 3); }); test('translit replaces ligatures and superscripts', () => { assert.equal(translit('Œuf'), 'Oeuf'); assert.equal(translit('cœur'), 'coeur'); assert.equal(translit('m²'), 'm2'); }); test('filterTitle strips non-Latin/digit', () => { assert.equal(filterTitle('Hello, World!'), 'HelloWorld'); assert.equal(filterTitle('Inception (2010)'), 'Inception2010'); assert.equal(filterTitle('北京'), ''); assert.equal(filterTitle('Café au lait'), 'Caféaulait'); }); test('filterAndLower', () => { assert.equal(filterAndLower('Mr. Robot S01E02'), 'mrrobots01e02'); assert.equal(filterAndLower('Cœur de Pirate'), 'coeurdepirate'); }); test('parseQuery: movie with year', () => { const r = parseQuery('Inception 2010 1080p BluRay'); assert.equal(r.type, 'movie'); assert.equal(r.yearin, 2010); assert.equal(r.episodein, ''); assert.equal(r.titlein.startsWith('Inception '), true); }); test('parseQuery: 1080 is not a year', () => { const r = parseQuery('Inception 2010 1080p'); assert.equal(r.yearin, 2010); }); test('parseQuery: tv with episode', () => { const r = parseQuery('Mr.Robot.S01E02.FRENCH.1080p'); assert.equal(r.type, 'tv'); assert.equal(r.episodein, 'S01E02'); assert.equal(r.titlein.startsWith('Mr.Robot'), true); }); test('parseQuery: tv with year + episode', () => { const r = parseQuery('Some.Show.2015.S02E10'); assert.equal(r.type, 'tv'); assert.equal(r.yearin, 2015); assert.equal(r.episodein, 'S02E10'); }); test('parseQuery: no year no episode', () => { const r = parseQuery('Just a title'); assert.ok(r.error); }); test('paths bucket + entryPath', () => { assert.equal(bucket(100), '0'); assert.equal(bucket(1500), '1'); assert.equal(bucket(1675803), '1675'); assert.ok(entryPath('movie', 100).endsWith('/movie/0/100.json')); assert.ok(entryPath('tv', 1408).endsWith('/tv/1/1408.json')); });