const test = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const { JSDOM } = require('jsdom'); const root = path.resolve(__dirname, '..'); const projection = require('../public/js/services/liveChannelProjection.js'); const script = relativePath => fs.readFileSync(path.join(root, 'public', relativePath), 'utf8'); test('minimal non-enriched live projection payload maps and renders without an exception', () => { const mapped = projection.mapResponse({ projection: { stale: false }, filters: { availableLanguages: [null, {}] }, channels: [ { id: 'logical-news:und', logicalChannelId: 'logical-news', displayName: 'News', standard: null, language: {}, epg: null, preferredVariant: null, variants: [{ id: 'news-raw', sourceId: 1, name: 'News Raw', tvgId: 'news.raw', categoryName: 'News', language: null, isHidden: false }] }, { id: 'logical-sports:und', logicalChannelId: 'logical-sports', displayName: 'Sports', language: null, variants: null, preferredVariant: { id: 'sports-raw', sourceId: 1, name: 'Sports Raw', tvgId: 'sports.raw', categoryName: 'Sports', isHidden: false } }, { id: 'empty', logicalChannelId: 'empty', displayName: 'Empty', language: null, variants: null, preferredVariant: null } ] }, [{ id: 1, type: 'm3u', name: 'Provider' }]); assert.equal(mapped.logicalChannels.length, 2); assert.ok(mapped.logicalChannels.every(channel => channel.language.code === 'und')); assert.equal(mapped.logicalChannels[0].tvgId, 'news.raw'); assert.deepEqual(mapped.availableLanguages.map(language => language.code), ['und']); const dom = new JSDOM('
', { url: 'http://nodecast.test/', runScripts: 'outside-only' }); const { window } = dom; window.eval(script('js/icons.js')); window.eval(script('js/services/channelLanguageDetection.js')); window.eval(script('js/services/channelLanguageFusion.js')); window.eval(script('js/services/channelVariantGrouping.js')); window.eval(`${script('js/components/ChannelList.js')}\nwindow.ChannelList = ChannelList;`); window.app = { epgGuide: { getCurrentProgram: () => null, loadError: null } }; const channelList = Object.create(window.ChannelList.prototype); channelList.expandedVariants = new Set(); channelList.sources = [{ id: 1, type: 'm3u', name: 'Provider' }]; channelList.showHidden = false; channelList.isFavorite = () => false; channelList.isHidden = () => false; const result = window.document.getElementById('result'); assert.doesNotThrow(() => { result.innerHTML = mapped.logicalChannels.map(channel => channelList.renderLogicalChannel(channel, 'render-id', 'News') ).join(''); }); assert.equal(result.querySelectorAll('.logical-channel').length, 2); assert.equal(result.querySelector('.channel-language-badge').getAttribute('aria-label'), 'Unknown language'); assert.match(result.textContent, /No program information/); dom.window.close(); });