halkyon/halkyon_learn_flutter/test/support/fake_dictionary_gateway.dart

118 lines
3.2 KiB
Dart
Raw Normal View History

import 'package:halkyon_learn_flutter/src/feature/card/model/card_content.dart';
import 'package:halkyon_learn_flutter/src/feature/dictionary/data/dictionary_gateway.dart';
import 'package:halkyon_learn_flutter/src/feature/dictionary/model/dictionary.dart';
/// JMdict in English, as an instance that loaded it lists it.
const jmdict = Dictionary(
source: 'jmdict',
sourceVersion: '3.6.2 (2026-10-05)',
kind: DictionaryKind.words,
language: 'ja',
glossLanguage: 'en',
license: 'CC-BY-SA-4.0',
credits: [
(
name: 'JMdict',
by: 'Electronic Dictionary Research and Development Group (EDRDG)',
license: 'CC-BY-SA-4.0',
url: 'https://www.edrdg.org/edrdg/licence.html',
),
],
entryCount: 3,
);
/// KANJIDIC2 in English, with the kana, as an instance that loaded it lists
/// it.
const kanjidic = Dictionary(
source: 'kanjidic',
sourceVersion: '2026-282',
kind: DictionaryKind.characters,
language: 'ja',
glossLanguage: 'en',
license: 'CC-BY-SA-4.0',
credits: [
(
name: 'KANJIDIC2',
by: 'Electronic Dictionary Research and Development Group (EDRDG)',
license: 'CC-BY-SA-4.0',
url: 'https://www.edrdg.org/edrdg/licence.html',
),
],
entryCount: 2,
);
/// A JMdict word: [headword] read [reading], meaning [glosses], [labels]
/// and the parts of speech [pos] on its one sense.
DictionaryWord word(
String id,
String headword, {
String? reading,
List<String> glosses = const [],
List<String> labels = const [],
List<String> pos = const [],
}) => DictionaryWord(
ref: (source: 'jmdict', id: id),
headword: headword,
reading: reading,
labels: labels,
senses: [VocabularySense(glosses: glosses, pos: pos)],
);
/// A [DictionaryGateway] in memory: an instance with the dictionaries
/// [available], each holding its [words] in their order. A search finds the words whose
/// headword, reading or a meaning starts with the query.
class FakeDictionaryGateway({
final List<Dictionary> available = const [jmdict],
final List<DictionaryWord> words = const [],
}) implements DictionaryGateway {
/// When set, every request fails with it.
Exception? fail;
/// How often the dictionaries were asked for.
int asked = 0;
@override
Future<List<Dictionary>> dictionaries() async {
asked++;
if (fail case final error?) {
throw error;
}
return available;
}
@override
Future<List<DictionaryWord>> search(
Dictionary dictionary,
String query,
) async {
if (fail case final error?) {
throw error;
}
final typed = query.trim().toLowerCase();
return [
for (final word in words)
if ([
word.headword,
?word.reading,
for (final sense in word.senses) ...sense.glosses,
].any((key) => key.toLowerCase().startsWith(typed)))
word,
];
}
@override
Future<int> countLabelled(Dictionary dictionary, String label) async =>
words.where((word) => word.labels.contains(label)).length;
@override
Future<List<DictionaryWord>> labelled(
Dictionary dictionary,
String label, {
required int offset,
required int limit,
}) async => words
.where((word) => word.labels.contains(label))
.skip(offset)
.take(limit)
.toList();
}