the-mews/app/test/fake_fetch.dart

55 lines
1.9 KiB
Dart
Raw Normal View History

import 'package:actors/actors.dart';
import 'package:mews/application/actors/fetch_actor.dart';
import 'package:mews/mews/atom.dart';
import 'package:mews/mews/parser.dart';
/// Serves pages from an in-memory map without network or isolates, so
/// navigation tests are deterministic. [sources] wins over the cached source
/// a caller offers, the way a server answering 200 does, so a test can change
/// what a site publishes between two fetches. An address with no source is
/// unreachable, and the cached copy stands in for it if there is one.
class FakeFetch implements Actor<FetchCommand, FetchResult> {
FakeFetch(this.sources, {this.feeds = const {}});
final Map<String, String> sources;
/// Atom feeds by address, for sites that publish through one.
final Map<String, String> feeds;
@override
Future<FetchResult> send(FetchCommand message) async {
return switch (message) {
ParseSource(:final url, :final source) => _parse(url, source),
FetchPage(:final url, :final cachedSource) => switch ((
sources[url],
cachedSource,
)) {
(final String fresh, _) => _parse(url, fresh),
(null, final String cached) => _parse(url, cached),
_ => const FetchNetworkError(),
},
FetchFeed(:final url) => switch (feeds[url]) {
final String source =>
FetchFeedOk(url: url, entries: parseAtomEntries(source: source, feedUrl: url)),
null => const FetchNetworkError(),
},
_ => const FetchNetworkError(),
};
}
FetchResult _parse(String url, String source) {
try {
return FetchPageOk(page: parseMewsPage(source: source, url: url), source: source);
} on MewsParseException catch (e) {
return FetchParseError(e.message, source);
}
}
@override
Future<void> close() async {}
@override
dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}