180 lines
5.5 KiB
TypeScript
180 lines
5.5 KiB
TypeScript
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();
|