Revision control

Copy as Markdown

Other Tools

// see https://www.w3.org/2000/10/rdf-tests/ for test files (including rss1)
// - test examples for all feed types
// - test items in test_download()
// - test rss1 feed with itunes `new-feed-url` redirect
// - test rss1 feed with RSS syndication extension tags (updatePeriod et al)
// - test multiple/missing authors (with fallback to feed title)
// - test missing dates
// - test content formatting
// Some RSS1 feeds in the wild:
// - uses html formatting in <dc:creator>
// Helper to compare feeditems.
function assertItemsEqual(got, expected) {
Assert.equal(got.length, expected.length);
for (let i = 0; i < expected.length; i++) {
// Only check fields in expected. Means testdata can exclude "description" and other bulky fields.
for (const k of Object.keys(expected[i])) {
Assert.equal(got[i][k], expected[i][k]);
}
}
}
// Test the rss1 feed parser
add_task(async function test_rss1() {
// Boilerplate.
const account = FeedUtils.createRssAccount("test_rss1");
const rootFolder = account.incomingServer.rootMsgFolder.QueryInterface(
Ci.nsIMsgLocalMailFolder
);
const folder = rootFolder.createLocalSubfolder("folderofeeds");
// These two files yield the same feed, but the second one has a sabotaged
// <items> to simulate badly-encoded feeds seen in the wild.
for (const testFile of [
"resources/rss_7_1.rdf",
"resources/rss_7_1_BORKED.rdf",
]) {
dump(`checking ${testFile}\n`);
// Would be nicer to use the test http server to fetch the file, but that
// would involve XMLHTTPRequest. This is more concise.
const doc = await do_parse_document(testFile, "application/xml");
const feed = new Feed(
folder
);
feed.parseItems = true; // We want items too, not just the feed details.
feed.onParseError = function () {
throw new Error("PARSE ERROR");
};
const parser = new FeedParser();
const items = parser.parseAsRSS1(feed, doc);
// Check some channel details.
Assert.equal(feed.title, "XML.com");
Assert.equal(feed.link, "http://xml.com/pub");
// Check the items (the titles and links at least!).
assertItemsEqual(items, [
{
title: "Processing Inclusions with XSLT",
},
{
title: "Putting RDF to Work",
},
]);
}
});
// Test feed downloading.
// Mainly checking that it doesn't crash and that the right feed parser is used.
add_task(async function test_download() {
// Boilerplate
const account = FeedUtils.createRssAccount("test_feed_download");
const rootFolder = account.incomingServer.rootMsgFolder.QueryInterface(
Ci.nsIMsgLocalMailFolder
);
// load & parse example rss feed
// Feed object rejects anything other than http and https, so we're
// running a local http server for testing (see head_feeds.js for it).
const feedTests = [
{
url: "http://localhost:" + SERVER_PORT + "/rss_7_1.rdf",
feedType: "RSS_1.xRDF",
title: "XML.com",
expectedItems: 2,
},
{
// Has Japanese title with leading/trailing whitespace.
url: "http://localhost:" + SERVER_PORT + "/rss2_example.xml",
feedType: "RSS_2.0",
title: "本当に簡単なシンジケーションの例",
expectedItems: 1,
},
{
// Has two items with same link but different guid (Bug 1656090).
url: "http://localhost:" + SERVER_PORT + "/rss2_guid.xml",
feedType: "RSS_2.0",
title: "GUID test",
expectedItems: 4,
},
// TODO: examples for the other feed types!
];
let n = 1;
for (const test of feedTests) {
const folder = rootFolder.createLocalSubfolder("feed" + n);
n++;
const feed = new Feed(test.url, folder);
const dl = new Promise(function (resolve, reject) {
const cb = {
downloaded(f, error) {
if (error != FeedUtils.kNewsBlogSuccess) {
reject(
new Error(`download failed (url=${feed.url} error=${error})`)
);
return;
}
// Feed has downloaded - make sure the right type was detected.
Assert.equal(feed.mFeedType, test.feedType, "feed type matching");
Assert.equal(feed.title, test.title, "title matching");
// Make sure we're got the expected number of messages in the folder.
const cnt = [...folder.messages].length;
Assert.equal(cnt, test.expectedItems, "itemcount matching");
resolve();
},
onProgress() {},
};
feed.download(true, cb);
});
// Wait for this feed to complete downloading.
await dl;
}
});