202 lines
6.3 KiB
Dart
202 lines
6.3 KiB
Dart
|
|
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<void> 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<void> 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<void> 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,
|
||
|
|
);
|
||
|
|
});
|
||
|
|
}
|