import { describe, expect, it } from "vitest"; import type { GridApiResponse } from "./tvlistings.js"; import { buildChannelsXml, buildProgrammesXml, buildXmltv, escapeXml, formatDate, } from "./xmltv.js"; const mockData: GridApiResponse = { channels: [ { callSign: "KOMODT", affiliateName: "AMERICAN BROADCASTING COMPANY", affiliateCallSign: null, channelId: "19629", channelNo: "4.1", events: [ { callSign: "KOMODT", duration: "60", startTime: "2025-07-18T19:00:00Z", endTime: "2025-07-18T20:00:00Z", thumbnail: "p30687311_b_v13_aa", channelNo: "4.1", filter: ["filter-news"], seriesId: "SH05918266", rating: "TV-PG", flag: ["New"], tags: ["Stereo", "CC"], program: { title: "GMA3", id: "EP059182660025", tmsId: "EP059182660025", shortDesc: "BIA performs; comic Zarna Garg; lifestyle contributor Lori Bergamotto; ABC News chief medical correspondent Dr. Tara Narula.", season: "5", releaseYear: null, episode: "217", episodeTitle: "Special Episode", seriesId: "SH05918266", isGeneric: "0", }, }, ], id: "196290", stationGenres: [false], stationFilters: ["filter-news", "filter-talk"], thumbnail: "//zap2it.tmsimg.com/h3/NowShowing/19629/s28708_ll_h15_ac.png?w=55", }, ], }; describe("buildXmltv", () => { it("should generate valid XML structure", () => { const result = buildXmltv(mockData); expect(result).toContain(''); expect(result).toContain(''); expect(result).toContain(""); }); it("should include channel information", () => { const result = buildXmltv(mockData); expect(result).toContain(''); expect(result).toContain("KOMODT"); expect(result).toContain( "AMERICAN BROADCASTING COMPANY", ); expect(result).toContain("4.1"); }); it("should include programme information", () => { const result = buildXmltv(mockData); expect(result).toContain( '', ); expect(result).toContain("GMA3"); expect(result).toContain("Special Episode"); expect(result).toContain( "BIA performs; comic Zarna Garg; lifestyle contributor Lori Bergamotto; ABC News chief medical correspondent Dr. Tara Narula.", ); }); it("should include rating information", () => { const result = buildXmltv(mockData); expect(result).toContain("TV-PG"); }); it("should include categories from flags and tags", () => { const result = buildXmltv(mockData); expect(result).toContain("New"); expect(result).toContain("Stereo"); expect(result).toContain("CC"); }); it("should include episode information", () => { const result = buildXmltv(mockData); expect(result).toContain('5'); expect(result).toContain('217'); expect(result).toContain( 'SH05918266', ); }); it("should handle empty data gracefully", () => { const emptyData: GridApiResponse = { channels: [] }; const result = buildXmltv(emptyData); expect(result).toContain(''); expect(result).toContain(''); expect(result).toContain(""); expect(result).not.toContain(" { const minimalData: GridApiResponse = { channels: [ { callSign: "TEST", affiliateName: "", affiliateCallSign: null, channelId: "123", channelNo: "", events: [ { callSign: "TEST", duration: "30", startTime: "2025-07-18T19:00:00Z", endTime: "2025-07-18T19:30:00Z", thumbnail: "", channelNo: "", filter: [], seriesId: "", rating: "", flag: [], tags: [], program: { title: "Test Show", id: "TEST123", tmsId: "TEST123", shortDesc: "", season: "", releaseYear: null, episode: "", episodeTitle: null, seriesId: "", isGeneric: "0", }, }, ], id: "123", stationGenres: [], stationFilters: [], thumbnail: "", }, ], }; const result = buildXmltv(minimalData); expect(result).toContain(''); expect(result).toContain("TEST"); expect(result).toContain( '', ); expect(result).toContain("Test Show"); expect(result).not.toContain(""); expect(result).not.toContain(""); expect(result).not.toContain(""); expect(result).not.toContain(""); expect(result).not.toContain(" { it("should escape XML special characters", () => { expect(escapeXml("&")).toBe("&"); expect(escapeXml("<")).toBe("<"); expect(escapeXml(">")).toBe(">"); expect(escapeXml('"')).toBe("""); expect(escapeXml("'")).toBe("'"); }); it("should handle text with multiple special characters", () => { expect(escapeXml("A & B < C > D \"E\" 'F'")).toBe( "A & B < C > D "E" 'F'", ); }); it("should handle normal text without special characters", () => { expect(escapeXml("Normal text")).toBe("Normal text"); }); it("should handle empty string", () => { expect(escapeXml("")).toBe(""); }); }); describe("formatDate", () => { it("should format ISO date string correctly", () => { expect(formatDate("2025-07-18T19:00:00Z")).toBe("20250718190000 +0000"); expect(formatDate("2025-12-31T23:59:59Z")).toBe("20251231235959 +0000"); }); it("should handle different times", () => { expect(formatDate("2025-01-01T00:00:00Z")).toBe("20250101000000 +0000"); expect(formatDate("2025-06-15T12:30:45Z")).toBe("20250615123045 +0000"); }); it("should handle edge cases", () => { expect(formatDate("2025-02-28T23:59:59Z")).toBe("20250228235959 +0000"); expect(formatDate("2025-03-01T00:00:00Z")).toBe("20250301000000 +0000"); }); }); describe("buildChannelsXml", () => { it("should build channel XML correctly", () => { const result = buildChannelsXml(mockData); expect(result).toContain(''); expect(result).toContain("KOMODT"); expect(result).toContain( "AMERICAN BROADCASTING COMPANY", ); expect(result).toContain("4.1"); expect(result).toContain( '', ); }); it("should handle channels without optional fields", () => { const minimalChannel: GridApiResponse = { channels: [ { callSign: "TEST", affiliateName: "", affiliateCallSign: null, channelId: "123", channelNo: "", events: [], id: "123", stationGenres: [], stationFilters: [], thumbnail: "", }, ], }; const result = buildChannelsXml(minimalChannel); expect(result).toContain(''); expect(result).toContain("TEST"); expect(result).not.toContain(" { it("should build programme XML correctly", () => { const result = buildProgrammesXml(mockData); expect(result).toContain( '', ); expect(result).toContain("GMA3"); expect(result).toContain("Special Episode"); expect(result).toContain( "BIA performs; comic Zarna Garg; lifestyle contributor Lori Bergamotto; ABC News chief medical correspondent Dr. Tara Narula.", ); expect(result).toContain("TV-PG"); expect(result).toContain("New"); expect(result).toContain("Stereo"); expect(result).toContain("CC"); expect(result).toContain('5'); expect(result).toContain('217'); expect(result).toContain( 'SH05918266', ); expect(result).toContain(''); }); it("should handle programmes without optional fields", () => { const minimalProgramme: GridApiResponse = { channels: [ { callSign: "TEST", affiliateName: "", affiliateCallSign: null, channelId: "123", channelNo: "", events: [ { callSign: "TEST", duration: "30", startTime: "2025-07-18T19:00:00Z", endTime: "2025-07-18T19:30:00Z", thumbnail: "", channelNo: "", filter: [], seriesId: "", rating: "", flag: [], tags: [], program: { title: "Test Show", id: "TEST123", tmsId: "TEST123", shortDesc: "", season: "", releaseYear: null, episode: "", episodeTitle: null, seriesId: "", isGeneric: "0", }, }, ], id: "123", stationGenres: [], stationFilters: [], thumbnail: "", }, ], }; const result = buildProgrammesXml(minimalProgramme); expect(result).toContain( '', ); expect(result).toContain("Test Show"); expect(result).not.toContain(""); expect(result).not.toContain(""); expect(result).not.toContain(""); expect(result).not.toContain(""); expect(result).not.toContain("