import { expect, tap } from '@git.zone/tstest/tapbundle'; import * as smartfeed from '../ts/index.js'; let testSmartFeed: smartfeed.Smartfeed; tap.test('setup', async () => { testSmartFeed = new smartfeed.Smartfeed(); }); tap.test('should parse RSS feed from string', async () => { const feed = testSmartFeed.createFeed({ domain: 'example.com', title: 'Example Feed', category: 'Test', company: 'Test Inc', companyDomain: 'https://example.com', companyEmail: 'test@example.com', description: 'Test description', }); feed.addItem({ title: 'Test Article', authorName: 'John Doe', imageUrl: 'https://example.com/image.png', timestamp: Date.now(), url: 'https://example.com/article/test', content: 'Test content', }); const rssFeed = feed.exportRssFeedString(); const parsedFeed = await testSmartFeed.parseFeedFromString(rssFeed); expect(parsedFeed.title).toEqual('Example Feed'); expect(parsedFeed.description).toEqual('Test description'); expect(parsedFeed.items).toBeArray(); expect(parsedFeed.items.length).toEqual(1); expect(parsedFeed.items[0].title).toEqual('Test Article'); }); tap.test('should parse Atom feed from string', async () => { const feed = testSmartFeed.createFeed({ domain: 'example.com', title: 'Atom Test Feed', category: 'Test', company: 'Test Inc', companyDomain: 'https://example.com', companyEmail: 'test@example.com', description: 'Atom test description', }); feed.addItem({ title: 'Atom Article', authorName: 'Jane Doe', imageUrl: 'https://example.com/atom-image.png', timestamp: Date.now(), url: 'https://example.com/article/atom-test', content: 'Atom content', }); const atomFeed = feed.exportAtomFeed(); const parsedFeed = await testSmartFeed.parseFeedFromString(atomFeed); expect(parsedFeed.title).toEqual('Atom Test Feed'); expect(parsedFeed.items).toBeArray(); expect(parsedFeed.items.length).toEqual(1); expect(parsedFeed.items[0].title).toEqual('Atom Article'); }); tap.test('should parse feed with multiple items', async () => { const feed = testSmartFeed.createFeed({ domain: 'example.com', title: 'Multi-item Feed', category: 'Test', company: 'Test Inc', companyDomain: 'https://example.com', companyEmail: 'test@example.com', description: 'Feed with multiple items', }); const itemCount = 10; for (let i = 1; i <= itemCount; i++) { feed.addItem({ title: `Article ${i}`, authorName: `Author ${i}`, imageUrl: `https://example.com/image${i}.png`, timestamp: Date.now() + i, url: `https://example.com/article/${i}`, content: `Content ${i}`, }); } const rssFeed = feed.exportRssFeedString(); const parsedFeed = await testSmartFeed.parseFeedFromString(rssFeed); expect(parsedFeed.items.length).toEqual(itemCount); expect(parsedFeed.items[0].title).toEqual('Article 1'); expect(parsedFeed.items[9].title).toEqual('Article 10'); }); tap.test('should parse live RSS feed from URL', async () => { try { const parsedFeed = await testSmartFeed.parseFeedFromUrl( 'https://www.theverge.com/rss/index.xml' ); expect(parsedFeed).toBeObject(); expect(parsedFeed.title).toBeString(); expect(parsedFeed.items).toBeArray(); expect(parsedFeed.items.length).toBeGreaterThan(0); } catch (error) { // Network errors are acceptable in tests console.log('Network test skipped (expected in CI/offline):', error.message); } }); tap.test('should preserve feed metadata when parsing', async () => { const feed = testSmartFeed.createFeed({ domain: 'meta.example.com', title: 'Metadata Test Feed', category: 'Metadata', company: 'Metadata Inc', companyDomain: 'https://meta.example.com', companyEmail: 'meta@example.com', description: 'Testing metadata preservation', }); feed.addItem({ title: 'Meta Article', authorName: 'Meta Author', imageUrl: 'https://example.com/meta.png', timestamp: Date.now(), url: 'https://example.com/meta', content: 'Meta content', }); const rssFeed = feed.exportRssFeedString(); const parsedFeed = await testSmartFeed.parseFeedFromString(rssFeed); expect(parsedFeed.title).toEqual('Metadata Test Feed'); expect(parsedFeed.description).toEqual('Testing metadata preservation'); expect(parsedFeed.language).toEqual('en'); expect(parsedFeed.generator).toEqual('@push.rocks/smartfeed'); expect(parsedFeed.copyright).toInclude('Metadata Inc'); }); tap.test('should handle feed with enclosures', async () => { const feed = testSmartFeed.createFeed({ domain: 'example.com', title: 'Enclosure Test', category: 'Test', company: 'Test Inc', companyDomain: 'https://example.com', companyEmail: 'test@example.com', description: 'Testing enclosures', }); feed.addItem({ title: 'Article with image', authorName: 'Author', imageUrl: 'https://example.com/large-image.jpg', timestamp: Date.now(), url: 'https://example.com/article', content: 'Content with enclosure', }); const rssFeed = feed.exportRssFeedString(); const parsedFeed = await testSmartFeed.parseFeedFromString(rssFeed); // Enclosure support depends on the parser and feed format expect(parsedFeed.items.length).toBeGreaterThan(0); expect(parsedFeed.items[0].title).toEqual('Article with image'); // If enclosure exists, verify it if (parsedFeed.items[0].enclosure) { expect(parsedFeed.items[0].enclosure.url).toInclude('https://example.com/large-image.jpg'); } }); export default tap.start();