const test = require('node:test'); const assert = require('node:assert/strict'); const Database = require('better-sqlite3'); const { detectLanguage } = require('../server/services/channelLanguage'); const { matchesSearch, normalizeSearch } = require('../server/services/flexibleChannelSearch'); const { ensureBuiltinSources } = require('../server/services/builtinEpgRegistry'); const iptvOrg = require('../server/services/iptvOrgCatalogService'); const { LIVE_PROJECTION_SCHEMA_SQL } = require('../server/db/liveProjectionSchema'); test('flexible search ignores accents, punctuation, case and simple plurals', () => { const channel = { displayName: 'beIN Sports 1', variants: [{ name: 'BéIN SPORTS 1 HD' }] }; for (const query of ['Bein Sport 1', 'bein sports 1', 'beIN Sport 1']) assert.equal(matchesSearch(channel, query), true); assert.deepEqual(normalizeSearch('Chaînes-Sports'), ['chaine', 'sport']); }); test('backend language detection uses und and separates explicit languages', () => { assert.equal(detectLanguage({ name: 'Generic Sports' }).code, 'und'); assert.equal(detectLanguage({ name: '|FR| Sports One' }).code, 'fr'); assert.equal(detectLanguage({ name: '[UK] Sports One' }).code, 'en'); }); test('built-in EPG registry is idempotent and protected while remaining disabled by default', () => { const data = ensureBuiltinSources({ sources: [], nextId: 1 }); ensureBuiltinSources(data); assert.equal(data.sources.length, 2); assert.ok(data.sources.every(source => source.type === 'epg' && source.readonly && !source.removable && !source.enabled)); }); test('iptv-org adapter refreshes a persistent cache and matches aliases by language', async () => { const db = new Database(':memory:'); db.exec(`CREATE TABLE playlist_items (id TEXT PRIMARY KEY, logical_channel_id TEXT, grouping_fingerprint TEXT);`); db.exec(LIVE_PROJECTION_SCHEMA_SQL); const payloads = { 'channels.json': [{ id: 'BeInSports1.fr', name: 'beIN Sports 1', alt_names: ['Bein Sport 1'], country: 'FR' }], 'feeds.json': [{ channel: 'BeInSports1.fr', languages: ['fr'] }] }; await iptvOrg.refresh(db, async url => ({ ok: true, json: async () => payloads[url.split('/').pop()] })); const match = iptvOrg.findMatch(db, { displayName: 'Bein Sport 1', language: { code: 'fr' }, variants: [] }); assert.equal(match.channelId, 'BeInSports1.fr'); assert.equal(match.name, 'beIN Sports 1'); assert.equal(db.prepare("SELECT item_count FROM iptv_org_cache_state WHERE resource = 'catalog'").get().item_count, 1); });