chore: Halkyon Learn moves into apps/learn
Its server, client, app and curator, and the tools that write its assets (maps, Anki fixtures, icons), as they are; paths are fixed in the commits that follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
11abd9afce
commit
649499be23
2 changed files with 0 additions and 0 deletions
|
|
@ -0,0 +1,161 @@
|
|||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/content/content_blocks.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/content/rich_content.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/editor/rich_content_document.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/card/model/card_content.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:halkyon_learn_flutter/src/feature/tag/data/tag_repository.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
import '../../../support/fake_card_gateway.dart';
|
||||
import '../../../support/fake_note_gateway.dart';
|
||||
import '../../../support/fake_studyset_gateway.dart';
|
||||
import '../../../support/fake_tag_gateway.dart';
|
||||
import '../../../support/pump_app.dart';
|
||||
import '../../../support/test_dependencies.dart';
|
||||
|
||||
void main() {
|
||||
late FakeStudysetGateway studysets;
|
||||
late FakeCardGateway cardGateway;
|
||||
late FakeTagGateway tagGateway;
|
||||
late String verb;
|
||||
|
||||
setUp(() async {
|
||||
studysets = FakeStudysetGateway()
|
||||
..receiveRemoteChange(
|
||||
'japanese',
|
||||
encodeStudysetPayload(StudysetContent.titled('Japanese')),
|
||||
);
|
||||
cardGateway = FakeCardGateway();
|
||||
tagGateway = FakeTagGateway();
|
||||
final cards = CardRepository(cardGateway);
|
||||
final tags = TagRepository(tagGateway);
|
||||
addTearDown(cards.dispose);
|
||||
addTearDown(tags.dispose);
|
||||
final taberu = await cards.create(
|
||||
'japanese',
|
||||
CardContent(
|
||||
front: RichContent.plain('食べる'),
|
||||
back: RichContent.plain('to eat'),
|
||||
),
|
||||
);
|
||||
await cards.create(
|
||||
'japanese',
|
||||
CardContent(
|
||||
front: RichContent.plain('猫'),
|
||||
back: RichContent.plain('cat'),
|
||||
),
|
||||
);
|
||||
verb = await tags.create('verb');
|
||||
await tags.setTagsOf(taberu, {verb});
|
||||
});
|
||||
|
||||
Future<void> showApp(WidgetTester tester, String location) async {
|
||||
tester.view.physicalSize = const Size(1200, 1000);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.reset);
|
||||
await pumpApp(
|
||||
tester,
|
||||
testDependencies(
|
||||
studysetGateway: studysets,
|
||||
cardGateway: cardGateway,
|
||||
tagGateway: tagGateway,
|
||||
noteGateway: FakeNoteGateway(),
|
||||
),
|
||||
location: location,
|
||||
);
|
||||
await tester.pump(const Duration(seconds: 1));
|
||||
}
|
||||
|
||||
/// A studyset whose description holds a study button of [attributes].
|
||||
void describedWithButton(Map<String, Object?> attributes) =>
|
||||
studysets.receiveRemoteChange(
|
||||
'lesson',
|
||||
encodeStudysetPayload(
|
||||
StudysetContent(
|
||||
title: 'Lesson',
|
||||
description: Document(
|
||||
root: pageNode(
|
||||
children: [
|
||||
Node(type: studyButtonBlockType, attributes: attributes),
|
||||
],
|
||||
),
|
||||
).toRichContent(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
testWidgets("goes into a note from Insert: the note's studyset studied "
|
||||
'first, with a tag, a label, and without its topics', (tester) async {
|
||||
await showApp(tester, RoutePaths.newNote('japanese'));
|
||||
await tester.tap(find.byType(AppFlowyEditor));
|
||||
await tester.pump(const Duration(seconds: 1));
|
||||
final editorState = tester
|
||||
.widget<AppFlowyEditor>(find.byType(AppFlowyEditor))
|
||||
.editorState;
|
||||
|
||||
await tester.tap(find.byTooltip('Insert'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.ensureVisible(find.text('Study button'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Study button'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Japanese'), findsOneWidget);
|
||||
|
||||
await tester.tap(find.text('All cards'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('verb').last);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.enterText(find.widgetWithText(TextField, 'Label'), 'Verbs');
|
||||
await tester.tap(find.text('With its topics'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Save'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final block = editorState.document.root.children.first;
|
||||
expect(block.type, studyButtonBlockType);
|
||||
expect(block.attributes, {
|
||||
studyButtonStudysetKey: 'japanese',
|
||||
studyButtonTagKey: verb,
|
||||
studyButtonTagNameKey: 'verb',
|
||||
studyButtonLabelKey: 'Verbs',
|
||||
studyButtonTopicsKey: false,
|
||||
studyButtonBackFirstKey: false,
|
||||
});
|
||||
expect(find.text('Verbs'), findsOneWidget);
|
||||
expect(find.text('Tagged verb · Without its topics'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('shown read-only, starts a session of the cards it says, '
|
||||
'back first if asked', (tester) async {
|
||||
describedWithButton({
|
||||
studyButtonStudysetKey: 'japanese',
|
||||
studyButtonTagKey: verb,
|
||||
studyButtonTagNameKey: 'verb',
|
||||
studyButtonLabelKey: 'Verbs',
|
||||
studyButtonBackFirstKey: true,
|
||||
});
|
||||
await showApp(tester, RoutePaths.studyset('lesson'));
|
||||
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'Verbs'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Only the verb, and its back first.
|
||||
expect(find.textContaining('to eat', findRichText: true), findsOneWidget);
|
||||
expect(find.textContaining('猫', findRichText: true), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('a button whose studyset is gone says so', (tester) async {
|
||||
describedWithButton({studyButtonStudysetKey: 'gone'});
|
||||
await showApp(tester, RoutePaths.studyset('lesson'));
|
||||
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'Study'));
|
||||
await tester.pump();
|
||||
|
||||
expect(find.text('That studyset no longer exists.'), findsOneWidget);
|
||||
});
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue