import { expect, tap } from '@git.zone/tstest/tapbundle'; import * as smartfeed from '../ts/index.js'; let testSmartFeed: smartfeed.Smartfeed; let testPodcast: smartfeed.PodcastFeed; tap.test('setup', async () => { testSmartFeed = new smartfeed.Smartfeed(); }); tap.test('should create a podcast feed', async () => { testPodcast = testSmartFeed.createPodcastFeed({ domain: 'podcast.example.com', title: 'Test Podcast', description: 'A test podcast about testing', category: 'Technology', company: 'Test Podcast Inc', companyEmail: 'podcast@example.com', companyDomain: 'https://example.com', itunesCategory: 'Technology', itunesAuthor: 'John Tester', itunesOwner: { name: 'John Tester', email: 'john@example.com', }, itunesImage: 'https://example.com/podcast-artwork.jpg', itunesExplicit: false, podcastGuid: 'test-podcast-guid-001', }); expect(testPodcast).toBeInstanceOf(smartfeed.PodcastFeed); expect(testPodcast.podcastOptions.itunesCategory).toEqual('Technology'); expect(testPodcast.podcastOptions.itunesAuthor).toEqual('John Tester'); }); tap.test('should create podcast feed with episodic type', async () => { const podcast = testSmartFeed.createPodcastFeed({ domain: 'episodic.example.com', title: 'Episodic Podcast', description: 'An episodic podcast', category: 'Comedy', company: 'Comedy Inc', companyEmail: 'comedy@example.com', companyDomain: 'https://example.com', itunesCategory: 'Comedy', itunesAuthor: 'Comedian', itunesOwner: { name: 'Comedian', email: 'comedian@example.com' }, itunesImage: 'https://example.com/comedy.jpg', itunesExplicit: true, podcastGuid: 'test-podcast-guid-002', itunesType: 'episodic', }); expect(podcast.podcastOptions.itunesType).toEqual('episodic'); expect(podcast.podcastOptions.itunesExplicit).toEqual(true); }); tap.test('should create podcast feed with serial type', async () => { const podcast = testSmartFeed.createPodcastFeed({ domain: 'serial.example.com', title: 'Serial Podcast', description: 'A serial podcast', category: 'True Crime', company: 'Crime Inc', companyEmail: 'crime@example.com', companyDomain: 'https://example.com', itunesCategory: 'True Crime', itunesAuthor: 'Detective', itunesOwner: { name: 'Detective', email: 'detective@example.com' }, itunesImage: 'https://example.com/crime.jpg', itunesExplicit: false, podcastGuid: 'test-podcast-guid-003', itunesType: 'serial', }); expect(podcast.podcastOptions.itunesType).toEqual('serial'); }); tap.test('should add episode to podcast', async () => { testPodcast.addEpisode({ title: 'Episode 1: Introduction', authorName: 'John Tester', imageUrl: 'https://example.com/episode1.jpg', timestamp: Date.now(), url: 'https://podcast.example.com/episode/1', content: 'In this episode, we introduce the podcast', audioUrl: 'https://example.com/audio/episode1.mp3', audioType: 'audio/mpeg', audioLength: 45678900, itunesDuration: 3600, itunesEpisode: 1, itunesSeason: 1, itunesEpisodeType: 'full', }); expect(testPodcast.episodes.length).toEqual(1); expect(testPodcast.episodes[0].title).toEqual('Episode 1: Introduction'); expect(testPodcast.episodes[0].itunesEpisode).toEqual(1); }); tap.test('should add multiple episodes', async () => { const podcast = testSmartFeed.createPodcastFeed({ domain: 'multi.example.com', title: 'Multi-Episode Podcast', description: 'Podcast with multiple episodes', category: 'Education', company: 'Edu Inc', companyEmail: 'edu@example.com', companyDomain: 'https://example.com', itunesCategory: 'Education', itunesAuthor: 'Teacher', itunesOwner: { name: 'Teacher', email: 'teacher@example.com' }, itunesImage: 'https://example.com/edu.jpg', itunesExplicit: false, podcastGuid: 'test-podcast-guid-004', }); for (let i = 1; i <= 5; i++) { podcast.addEpisode({ title: `Episode ${i}`, authorName: 'Teacher', imageUrl: `https://example.com/episode${i}.jpg`, timestamp: Date.now() + i, url: `https://example.com/episode/${i}`, content: `Content for episode ${i}`, audioUrl: `https://example.com/audio/episode${i}.mp3`, audioType: 'audio/mpeg', audioLength: 40000000 + i * 1000000, itunesDuration: 3000 + i * 100, itunesEpisode: i, itunesSeason: 1, }); } expect(podcast.episodes.length).toEqual(5); }); tap.test('should add episode with trailer type', async () => { const podcast = testSmartFeed.createPodcastFeed({ domain: 'trailer.example.com', title: 'Podcast with Trailer', description: 'Podcast with trailer episode', category: 'News', company: 'News Inc', companyEmail: 'news@example.com', companyDomain: 'https://example.com', itunesCategory: 'News', itunesAuthor: 'Reporter', itunesOwner: { name: 'Reporter', email: 'reporter@example.com' }, itunesImage: 'https://example.com/news.jpg', itunesExplicit: false, podcastGuid: 'test-podcast-guid-005', }); podcast.addEpisode({ title: 'Season 1 Trailer', authorName: 'Reporter', imageUrl: 'https://example.com/trailer.jpg', timestamp: Date.now(), url: 'https://example.com/episode/trailer', content: 'Trailer for season 1', audioUrl: 'https://example.com/audio/trailer.mp3', audioType: 'audio/mpeg', audioLength: 5000000, itunesDuration: 300, itunesEpisodeType: 'trailer', itunesSeason: 1, }); expect(podcast.episodes[0].itunesEpisodeType).toEqual('trailer'); }); tap.test('should add episode with bonus type', async () => { const podcast = testSmartFeed.createPodcastFeed({ domain: 'bonus.example.com', title: 'Podcast with Bonus', description: 'Podcast with bonus episode', category: 'Business', company: 'Business Inc', companyEmail: 'business@example.com', companyDomain: 'https://example.com', itunesCategory: 'Business', itunesAuthor: 'Entrepreneur', itunesOwner: { name: 'Entrepreneur', email: 'entrepreneur@example.com' }, itunesImage: 'https://example.com/business.jpg', itunesExplicit: false, podcastGuid: 'test-podcast-guid-006', }); podcast.addEpisode({ title: 'Bonus: Behind the Scenes', authorName: 'Entrepreneur', imageUrl: 'https://example.com/bonus.jpg', timestamp: Date.now(), url: 'https://example.com/episode/bonus', content: 'Bonus behind the scenes content', audioUrl: 'https://example.com/audio/bonus.mp3', audioType: 'audio/mpeg', audioLength: 8000000, itunesDuration: 600, itunesEpisodeType: 'bonus', }); expect(podcast.episodes[0].itunesEpisodeType).toEqual('bonus'); }); tap.test('should support M4A audio format', async () => { const podcast = testSmartFeed.createPodcastFeed({ domain: 'm4a.example.com', title: 'M4A Podcast', description: 'Podcast with M4A audio', category: 'Music', company: 'Music Inc', companyEmail: 'music@example.com', companyDomain: 'https://example.com', itunesCategory: 'Music', itunesAuthor: 'Musician', itunesOwner: { name: 'Musician', email: 'musician@example.com' }, itunesImage: 'https://example.com/music.jpg', itunesExplicit: false, podcastGuid: 'test-podcast-guid-007', }); podcast.addEpisode({ title: 'Musical Episode', authorName: 'Musician', imageUrl: 'https://example.com/musical.jpg', timestamp: Date.now(), url: 'https://example.com/episode/musical', content: 'A musical episode', audioUrl: 'https://example.com/audio/episode.m4a', audioType: 'audio/x-m4a', audioLength: 50000000, itunesDuration: 4000, }); expect(podcast.episodes[0].audioType).toEqual('audio/x-m4a'); }); tap.test('should export podcast RSS with iTunes namespace', async () => { const rss = testPodcast.exportPodcastRss(); expect(rss).toInclude(''); expect(rss).toInclude('xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"'); expect(rss).toInclude('John Tester'); expect(rss).toInclude(''); expect(rss).toInclude('John Tester'); expect(rss).toInclude('john@example.com'); expect(rss).toInclude('false'); }); tap.test('should include episode in RSS export', async () => { const rss = testPodcast.exportPodcastRss(); expect(rss).toInclude('Episode 1: Introduction'); expect(rss).toInclude('https://example.com/audio/episode1.mp3'); expect(rss).toInclude('01:00:00'); expect(rss).toInclude('1'); expect(rss).toInclude('1'); }); export default tap.start();