import 'package:flutter_test/flutter_test.dart'; import 'package:halkyon_learn_flutter/src/feature/card/data/card_repository.dart'; import 'package:halkyon_learn_flutter/src/feature/card/model/card_content.dart'; import 'package:halkyon_learn_flutter/src/feature/dictionary/data/dictionary_adder.dart'; import 'package:halkyon_learn_flutter/src/feature/dictionary/data/dictionary_repository.dart'; import 'package:halkyon_learn_flutter/src/feature/dictionary/model/dictionary.dart'; import 'package:halkyon_learn_flutter/src/feature/tag/data/tag_repository.dart'; import '../../support/fake_card_gateway.dart'; import '../../support/fake_dictionary_gateway.dart'; import '../../support/fake_tag_gateway.dart'; final taberu = word( '1358280', '食べる', reading: 'たべる', glosses: ['to eat'], labels: ['common', 'jlpt:n5'], pos: ['v1', 'vt'], ); final terebi = word( '1080510', 'テレビ', glosses: ['television', 'TV'], labels: ['common', 'jlpt:n5'], pos: ['n'], ); void main() { group('a word', () { test('reads its senses from the entry, the codes with them', () { final read = DictionaryWord.fromEntry( ref: (source: 'jmdict', id: '1358280'), headword: '食べる', reading: 'たべる', labels: ['common', 'jlpt:n5'], entry: '{"forms":[{"text":"食べる"}],"senses":[{"glosses":["to eat"],' '"pos":["v1","vt"]},{"glosses":["to live on"],"misc":["uk"]}]}', ); expect(read.senses, const [ VocabularySense(glosses: ['to eat'], pos: ['v1', 'vt']), VocabularySense(glosses: ['to live on'], misc: ['uk']), ]); expect(read.jlpt, 5); }); test('becomes a vocabulary card that keeps where it is from; a word in ' 'kana has no reading', () { final card = taberu.card; expect(card.type, CardType.vocabulary); expect(card.front.plainText.trim(), '食べる'); expect(card.reading, 'たべる'); expect(card.meanings, ['to eat']); expect(card.entry, (source: 'jmdict', id: '1358280')); expect(terebi.card.reading, ''); }); }); group('the repository', () { test('asks for the dictionaries once, again after a failure', () async { final gateway = FakeDictionaryGateway()..fail = Exception('offline'); final repository = DictionaryRepository(gateway); await expectLater(repository.dictionaries(), throwsException); gateway.fail = null; expect(await repository.dictionaries(), [jmdict]); await repository.dictionaries(); expect(gateway.asked, 2); }); test("finds a studyset's dictionary by its front's language, with " "meanings in its back's, else in English", () async { const german = Dictionary( source: 'jmdict', sourceVersion: '1', language: 'ja', glossLanguage: 'de', license: 'CC-BY-SA-4.0', credits: [], entryCount: 1, ); final repository = DictionaryRepository( FakeDictionaryGateway(available: [jmdict, german]), ); expect(await repository.dictionaryFor((front: 'ja', back: 'de')), german); expect(await repository.dictionaryFor((front: 'ja', back: 'fr')), jmdict); expect(await repository.dictionaryFor((front: 'ja', back: null)), jmdict); expect(await repository.dictionaryFor((front: 'ko', back: 'en')), isNull); expect(await repository.dictionaryFor((front: null, back: 'en')), isNull); }); test('brings every word of a level, a page at a time', () async { final words = [ for (var i = 0; i < DictionaryRepository.page + 3; i++) word('$i', 'w$i', labels: ['jlpt:n5']), ]; final counts = []; final all = await DictionaryRepository( FakeDictionaryGateway(words: words), ).allLabelled(jmdict, 'jlpt:n5', onProgress: counts.add); expect(all, words); expect(counts, [ DictionaryRepository.page, DictionaryRepository.page + 3, ]); }); }); group('adding words', () { late CardRepository cards; late TagRepository tags; late DictionaryAdder adder; setUp(() { cards = CardRepository(FakeCardGateway()); tags = TagRepository(FakeTagGateway()); adder = DictionaryAdder(cards, tags); }); tearDown(() async { await cards.dispose(); await tags.dispose(); }); test('makes each word a card once, tagged with its level and word ' 'class, marked as from the dictionary', () async { expect(await adder.add('japanese', [taberu]), (added: 1, skipped: 0)); expect( await adder.add('japanese', [taberu, terebi]), (added: 1, skipped: 1), ); final made = await cards.cardsOf('japanese'); expect( [for (final card in made) card.content.entry?.id], [ '1358280', '1080510', ], ); final tagging = await tags.read(); expect( [for (final tag in tagging.of(made.first.id)) tag.name], [ 'JLPT-N5', 'Verb', ], ); expect( [for (final tag in tagging.of(made.last.id)) tag.name], [ 'JLPT-N5', 'Noun', ], ); expect((await cards.allCards()).every((card) => card.imported), isTrue); }); test('names the tags by level and word class', () { expect(tagNamesOf(taberu), ['JLPT-N5', 'Verb']); expect( tagNamesOf(word('1', 'x', pos: ['adj-na', 'n'])), ['na-Adjective', 'Noun'], ); expect(tagNamesOf(word('2', 'y', pos: ['vt'])), isEmpty); }); }); }