114 lines
3.5 KiB
Dart
114 lines
3.5 KiB
Dart
|
|
import 'package:flutter_test/flutter_test.dart';
|
||
|
|
|
||
|
|
import 'package:mews/mews/atom.dart';
|
||
|
|
import 'package:mews/mews/parser.dart';
|
||
|
|
|
||
|
|
const defaultNamespaced = '''
|
||
|
|
<?xml version="1.0" encoding="utf-8"?>
|
||
|
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||
|
|
<title>Signal Bars</title>
|
||
|
|
<entry>
|
||
|
|
<title>Collecting retro phones</title>
|
||
|
|
<link rel="alternate" href="2026-10-08-retro.html" />
|
||
|
|
<id>tag:example.com,2026:retro</id>
|
||
|
|
<updated>2026-10-08T09:30:00Z</updated>
|
||
|
|
</entry>
|
||
|
|
<entry>
|
||
|
|
<title>First post</title>
|
||
|
|
<link href="2026-09-21-first.html" />
|
||
|
|
<published>2026-09-21T12:00:00Z</published>
|
||
|
|
</entry>
|
||
|
|
</feed>
|
||
|
|
''';
|
||
|
|
|
||
|
|
const prefixed = '''
|
||
|
|
<?xml version="1.0" encoding="utf-8"?>
|
||
|
|
<atom:feed xmlns:atom="http://www.w3.org/2005/Atom">
|
||
|
|
<atom:entry>
|
||
|
|
<atom:title>Reading the bars</atom:title>
|
||
|
|
<atom:link rel="alternate" href="https://example.com/bars.html" />
|
||
|
|
<atom:updated>2026-10-09T08:00:00Z</atom:updated>
|
||
|
|
</atom:entry>
|
||
|
|
</atom:feed>
|
||
|
|
''';
|
||
|
|
|
||
|
|
void main() {
|
||
|
|
test('reads entries from a feed in the default namespace', () {
|
||
|
|
final entries = parseAtomEntries(
|
||
|
|
source: defaultNamespaced, feedUrl: 'https://example.com/feed.xml');
|
||
|
|
|
||
|
|
expect(entries, hasLength(2));
|
||
|
|
// Newest first, like the dated links a page lists.
|
||
|
|
expect(entries.first.title, 'Collecting retro phones');
|
||
|
|
expect(entries.first.date, DateTime.utc(2026, 10, 8, 9, 30));
|
||
|
|
// Relative links resolve against the feed's own address.
|
||
|
|
expect(entries.first.url, 'https://example.com/2026-10-08-retro.html');
|
||
|
|
// A link without a rel is the alternate one.
|
||
|
|
expect(entries.last.url, 'https://example.com/2026-09-21-first.html');
|
||
|
|
// published stands in when updated is absent.
|
||
|
|
expect(entries.last.date, DateTime.utc(2026, 9, 21, 12));
|
||
|
|
});
|
||
|
|
|
||
|
|
test('reads a feed using an atom prefix', () {
|
||
|
|
final entries =
|
||
|
|
parseAtomEntries(source: prefixed, feedUrl: 'https://example.com/feed.xml');
|
||
|
|
expect(entries.single.title, 'Reading the bars');
|
||
|
|
expect(entries.single.url, 'https://example.com/bars.html');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('falls back to the id when it is a web address', () {
|
||
|
|
const source = '''
|
||
|
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||
|
|
<entry>
|
||
|
|
<title>No link here</title>
|
||
|
|
<id>https://example.com/no-link.html</id>
|
||
|
|
<updated>2026-10-08T09:30:00Z</updated>
|
||
|
|
</entry>
|
||
|
|
</feed>
|
||
|
|
''';
|
||
|
|
final entries =
|
||
|
|
parseAtomEntries(source: source, feedUrl: 'https://example.com/feed.xml');
|
||
|
|
expect(entries.single.url, 'https://example.com/no-link.html');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('skips entries with nothing to identify or date them', () {
|
||
|
|
const source = '''
|
||
|
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||
|
|
<entry>
|
||
|
|
<title>No date</title>
|
||
|
|
<link rel="alternate" href="a.html" />
|
||
|
|
</entry>
|
||
|
|
<entry>
|
||
|
|
<title>No address</title>
|
||
|
|
<id>tag:example.com,2026:nope</id>
|
||
|
|
<updated>2026-10-08T09:30:00Z</updated>
|
||
|
|
</entry>
|
||
|
|
<entry>
|
||
|
|
<title>Unreadable date</title>
|
||
|
|
<link rel="alternate" href="b.html" />
|
||
|
|
<updated>last Tuesday</updated>
|
||
|
|
</entry>
|
||
|
|
</feed>
|
||
|
|
''';
|
||
|
|
expect(
|
||
|
|
parseAtomEntries(source: source, feedUrl: 'https://example.com/feed.xml'),
|
||
|
|
isEmpty);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('a malformed feed is an error, not a guess', () {
|
||
|
|
expect(
|
||
|
|
() => parseAtomEntries(
|
||
|
|
source: '<feed><entry><title>Half', feedUrl: 'https://example.com/feed.xml'),
|
||
|
|
throwsA(isA<MewsParseException>()),
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('an empty feed reads as no entries', () {
|
||
|
|
expect(
|
||
|
|
parseAtomEntries(
|
||
|
|
source: '<feed xmlns="http://www.w3.org/2005/Atom"></feed>',
|
||
|
|
feedUrl: 'https://example.com/feed.xml'),
|
||
|
|
isEmpty);
|
||
|
|
});
|
||
|
|
}
|