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
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,130 @@
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/content/rich_content.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/settings/data/settings_repository.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/study/bloc/study_settings_bloc.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/study/model/study_options.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/studyset/data/studyset_payload.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/studyset/data/studyset_repository.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 '../../../support/fake_card_gateway.dart';
|
||||
import '../../../support/fake_settings_gateway.dart';
|
||||
import '../../../support/fake_studyset_gateway.dart';
|
||||
import '../../../support/fake_tag_gateway.dart';
|
||||
|
||||
void main() {
|
||||
late StudysetRepository studysets;
|
||||
late CardRepository cards;
|
||||
late TagRepository tags;
|
||||
late SettingsRepository settings;
|
||||
late StudySettingsBloc bloc;
|
||||
|
||||
CardContent card(String front) =>
|
||||
CardContent(front: RichContent.empty(), back: RichContent.empty());
|
||||
|
||||
setUp(() async {
|
||||
studysets = StudysetRepository(
|
||||
FakeStudysetGateway()
|
||||
..receiveRemoteChange(
|
||||
'japanese',
|
||||
encodeStudysetPayload(StudysetContent.titled('Japanese')),
|
||||
)
|
||||
..receiveRemoteChange(
|
||||
'kanji',
|
||||
encodeStudysetPayload(StudysetContent.titled('Kanji')),
|
||||
parentId: 'japanese',
|
||||
)
|
||||
..receiveRemoteChange(
|
||||
'german',
|
||||
encodeStudysetPayload(StudysetContent.titled('German')),
|
||||
),
|
||||
);
|
||||
cards = CardRepository(FakeCardGateway());
|
||||
tags = TagRepository(FakeTagGateway());
|
||||
settings = SettingsRepository(FakeSettingsGateway());
|
||||
final neko = await cards.create('japanese', card('猫'));
|
||||
final kanji = await cards.create('kanji', card('日'));
|
||||
final hund = await cards.create('german', card('Hund'));
|
||||
await tags.setTagsOf(neko, {await tags.create('noun')});
|
||||
await tags.setTagsOf(kanji, {await tags.create('kanji')});
|
||||
await tags.setTagsOf(hund, {await tags.create('german noun')});
|
||||
await tags.create('unused');
|
||||
bloc = StudySettingsBloc(studysets, cards, tags, settings, 'japanese')
|
||||
..add(const StudySettingsEventStarted());
|
||||
});
|
||||
tearDown(() async {
|
||||
await bloc.close();
|
||||
await studysets.dispose();
|
||||
await cards.dispose();
|
||||
await tags.dispose();
|
||||
await settings.dispose();
|
||||
});
|
||||
|
||||
Future<StudySettingsStateLoaded> loaded() async =>
|
||||
await bloc.stream.firstWhere((s) => s is StudySettingsStateLoaded)
|
||||
as StudySettingsStateLoaded;
|
||||
|
||||
test('offers the tags the studied cards have, those inside included, '
|
||||
'none chosen at first', () async {
|
||||
final state = await loaded();
|
||||
|
||||
expect(state.tags.map((tag) => tag.name), ['kanji', 'noun']);
|
||||
expect(state.chosen, isEmpty);
|
||||
expect(state.canSave, isFalse);
|
||||
});
|
||||
|
||||
test('saves the tags chosen into the settings, by id and name', () async {
|
||||
final noun = (await loaded()).tags.last;
|
||||
|
||||
bloc
|
||||
..add(StudySettingsEventTagToggled(noun.id))
|
||||
..add(const StudySettingsEventSaveRequested());
|
||||
await bloc.stream.firstWhere(
|
||||
(s) => s is StudySettingsStateLoaded && s.isDone,
|
||||
);
|
||||
|
||||
expect((await settings.read()).studyTagsOf('japanese'), [noun.ref]);
|
||||
});
|
||||
|
||||
test('a reset chooses none, and saving that studies every card '
|
||||
'again', () async {
|
||||
final noun = (await loaded()).tags.last;
|
||||
await settings.update((s) => s.withStudyTags('japanese', [noun.ref]));
|
||||
await bloc.close();
|
||||
bloc = StudySettingsBloc(studysets, cards, tags, settings, 'japanese')
|
||||
..add(const StudySettingsEventStarted());
|
||||
expect((await loaded()).chosen, {noun.id});
|
||||
|
||||
bloc
|
||||
..add(const StudySettingsEventResetRequested())
|
||||
..add(const StudySettingsEventSaveRequested());
|
||||
await bloc.stream.firstWhere(
|
||||
(s) => s is StudySettingsStateLoaded && s.isDone,
|
||||
);
|
||||
|
||||
expect((await settings.read()).studyTags, isEmpty);
|
||||
});
|
||||
|
||||
test('saves the study options chosen, with the tags', () async {
|
||||
await loaded();
|
||||
|
||||
bloc
|
||||
..add(
|
||||
const StudySettingsEventOptionsChanged(
|
||||
StudyOptions(mode: LearnMode.cram, cardsPerRound: 10),
|
||||
),
|
||||
)
|
||||
..add(const StudySettingsEventSaveRequested());
|
||||
await bloc.stream.firstWhere(
|
||||
(s) => s is StudySettingsStateLoaded && s.isDone,
|
||||
);
|
||||
|
||||
expect(
|
||||
(await settings.read()).study,
|
||||
const StudyOptions(mode: LearnMode.cram, cardsPerRound: 10),
|
||||
);
|
||||
});
|
||||
}
|
||||
Loading…
Reference in a new issue