import 'package:flutter_test/flutter_test.dart'; import 'package:halkyon_learn_flutter/src/core/content/rich_content.dart'; import 'package:halkyon_learn_flutter/src/core/router/route_paths.dart'; import 'package:halkyon_learn_flutter/src/feature/card/data/card_repository.dart'; import 'package:halkyon_learn_flutter/src/feature/studyset/data/studyset_payload.dart'; import 'package:halkyon_learn_flutter/src/feature/studyset/model/studyset_content.dart'; import 'package:material_ui/material_ui.dart'; import '../../support/fake_card_gateway.dart'; import '../../support/fake_dictionary_gateway.dart'; import '../../support/fake_studyset_gateway.dart'; import '../../support/pump_app.dart'; import '../../support/test_dependencies.dart'; final taberu = word( '1358280', '食べる', reading: 'たべる', glosses: ['to eat'], labels: ['common', 'jlpt:n5'], pos: ['v1'], ); final terebi = word( '1080510', 'テレビ', glosses: ['television'], labels: ['common', 'jlpt:n5'], pos: ['n'], ); final toukyou = word( '1447690', '東京', reading: 'とうきょう', glosses: ['Tokyo'], labels: ['common'], pos: ['n'], ); void main() { late FakeCardGateway cardGateway; late CardRepository cards; setUp(() { cardGateway = FakeCardGateway(); cards = CardRepository(cardGateway); }); tearDown(() => cards.dispose()); /// Lets the editors' timers run out and the screen settle. Future settle(WidgetTester tester) async { await tester.pump(const Duration(seconds: 1)); await tester.pumpAndSettle(); } /// Opens the studyset [id]: `japanese` (Japanese with English meanings) /// or `german`, on an instance with JMdict. Future show(WidgetTester tester, {String id = 'japanese'}) async { tester.view.physicalSize = const Size(1400, 1600); tester.view.devicePixelRatio = 1; addTearDown(tester.view.reset); final studysets = FakeStudysetGateway() ..receiveRemoteChange( 'japanese', encodeStudysetPayload( StudysetContent( title: 'Japanese', description: RichContent.empty(), frontLanguage: 'ja', backLanguage: 'en', ), ), ) ..receiveRemoteChange( 'german', encodeStudysetPayload( StudysetContent( title: 'German', description: RichContent.empty(), frontLanguage: 'de', backLanguage: 'en', ), ), ); await pumpApp( tester, testDependencies( studysetGateway: studysets, cardGateway: cardGateway, dictionaryGateway: FakeDictionaryGateway( words: [taberu, terebi, toukyou], ), ), location: RoutePaths.studyset(id), ); await settle(tester); } /// Chooses [item] under Add material. Future addMaterial(WidgetTester tester, String item) async { await tester.tap(find.text('Add material')); await tester.pumpAndSettle(); await tester.tap(find.text(item)); await tester.pump(); await tester.pump(); await settle(tester); } testWidgets('Add material offers the dictionary only where the ' "studyset's language has one", (tester) async { await show(tester, id: 'german'); await tester.tap(find.text('Add material')); await tester.pumpAndSettle(); expect(find.text('From the dictionary'), findsNothing); }); testWidgets('a word found is added as a flashcard, and then shows as in ' 'the studyset; the screen credits its sources', (tester) async { await show(tester); await addMaterial(tester, 'From the dictionary'); expect(find.textContaining('Words from JMdict'), findsOneWidget); await tester.enterText(find.byType(TextField), 'たべ'); await tester.pump(const Duration(milliseconds: 300)); await tester.pumpAndSettle(); expect(find.textContaining('食べる'), findsOneWidget); await tester.tap(find.text('Add')); await tester.pumpAndSettle(); expect(find.text('Added “食べる”.'), findsOneWidget); expect(find.byTooltip('In this studyset'), findsOneWidget); final card = (await cards.cardsOf('japanese')).single; expect(card.content.entry, (source: 'jmdict', id: '1358280')); expect(card.content.reading, 'たべる'); }); testWidgets('a whole level becomes flashcards, its words in its order', ( tester, ) async { await show(tester); await addMaterial(tester, 'From the dictionary'); expect(find.text('N5'), findsOneWidget); await tester.tap(find.text('Add 2 words')); await tester.pumpAndSettle(); expect(find.text('Added 2 words.'), findsOneWidget); expect( [ for (final card in await cards.cardsOf('japanese')) card.content.front.plainText.trim(), ], ['食べる', 'テレビ'], ); }); testWidgets('Look up fills a vocabulary card with a word of the ' 'dictionary', (tester) async { await show(tester); await addMaterial(tester, 'Create flashcards'); await tester.tap(find.text('Vocabulary')); await settle(tester); await tester.tap(find.byTooltip('Look up in the dictionary')); await tester.pumpAndSettle(); await tester.enterText(find.byType(TextField).last, 'たべる'); await tester.pump(const Duration(milliseconds: 300)); await tester.pumpAndSettle(); await tester.tap(find.textContaining('食べる').last); await settle(tester); expect(find.text('食べる', findRichText: true), findsWidgets); expect(find.widgetWithText(TextField, 'たべる'), findsOneWidget); expect(find.text('to eat'), findsWidgets); }); testWidgets("About names whose work the instance's dictionaries are", ( tester, ) async { await pumpApp( tester, testDependencies(dictionaryGateway: FakeDictionaryGateway()), location: RoutePaths.settings, ); await tester.scrollUntilVisible( find.text('About Halkyon Learn'), 200, scrollable: find.byType(Scrollable).first, ); await tester.tap(find.text('About Halkyon Learn')); await tester.pumpAndSettle(); expect(find.text('Dictionaries on this instance'), findsOneWidget); expect( find.text( 'JMdict: Electronic Dictionary Research and Development Group ' '(EDRDG), CC-BY-SA-4.0', ), findsOneWidget, ); }); }