feat: read subscriptions from an Atom feed when a page lists no dated links
This commit is contained in:
parent
b0b86ef5b1
commit
fa51d5793d
9 changed files with 411 additions and 4 deletions
113
app/test/atom_test.dart
Normal file
113
app/test/atom_test.dart
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
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);
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue