package dev.castarr.tv.playlist import org.junit.Assert.assertEquals import org.junit.Assert.assertThrows import org.junit.Assert.assertTrue import org.junit.Test class M3uParserTest { @Test fun `keeps commas inside display names`() { val channels = M3uParser.parse( """ #EXTM3U #EXTINF:-1 group-title="Doku",Comedy Central, HD http://example.com/a.ts """.trimIndent() ) assertEquals(1, channels.size) assertEquals("Comedy Central, HD", channels[0].name) assertEquals("Doku", channels[0].group) } @Test fun `commas inside attributes do not split the name`() { val channels = M3uParser.parse( """ #EXTM3U #EXTINF:-1 group-title="News, Sport" tvg-id="x",Das Erste HD http://example.com/b.ts """.trimIndent() ) assertEquals("Das Erste HD", channels[0].name) assertEquals("News, Sport", channels[0].group) assertEquals("x", channels[0].tvgId) } @Test fun `strips a UTF-8 BOM instead of inventing a channel`() { val channels = M3uParser.parse( "#EXTM3U\n#EXTINF:-1,Channel A\nhttp://example.com/a.ts\n" ) assertEquals(1, channels.size) assertEquals("Channel A", channels[0].name) } @Test fun `rejects HTML instead of turning it into channels`() { assertThrows(M3uParser.NotAPlaylistException::class.java) { M3uParser.parse("\n\n404\n") } } @Test fun `rejects an empty payload`() { assertThrows(M3uParser.NotAPlaylistException::class.java) { M3uParser.parse("") } } @Test fun `accepts a playlist whose header is missing but has entries`() { val channels = M3uParser.parse("#EXTINF:-1,Nur ein Sender\nhttp://example.com/c.ts") assertEquals(1, channels.size) assertEquals("Nur ein Sender", channels[0].name) } @Test fun `falls back to the url when the name is empty`() { val channels = M3uParser.parse("#EXTM3U\n#EXTINF:-1,\nhttp://example.com/d.ts") assertEquals("http://example.com/d.ts", channels[0].name) } @Test fun `carries EXTGRP over to a bare url`() { val channels = M3uParser.parse("#EXTM3U\n#EXTGRP:Sport\nhttp://example.com/e.ts") assertTrue(channels.isNotEmpty()) assertEquals("Sport", channels[0].group) } }