feat(app): the home dashboard: streak, goal, week, activity
Home opens on a study dashboard. The streak's flame sits in the app bar and opens a sheet of how it stands this week. Below: the study goal (a ring of the day's or week's progress, set and removed in its sheet), the week (each day studied, rested, missed or to come with the cards falling due; days to go back and on; today or a day to come made a rest day), and a year of activity as a heatmap, its weekdays staying in view while the weeks scroll. A long press arranges the dashboard: drag a widget elsewhere, hide or show it; the arrangement is synced. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
d846ee4582
commit
111532435f
1 changed files with 1747 additions and 63 deletions
|
|
@ -0,0 +1,112 @@
|
|||
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/home/widget/goal_card.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/home/widget/streak.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/study/data/review_repository.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/study/model/rating.dart';
|
||||
import 'package:material_ui/material_ui.dart' hide Card;
|
||||
|
||||
import '../../../support/fake_card_gateway.dart';
|
||||
import '../../../support/fake_review_gateway.dart';
|
||||
import '../../../support/fake_settings_gateway.dart';
|
||||
import '../../../support/pump_app.dart';
|
||||
import '../../../support/test_dependencies.dart';
|
||||
|
||||
void main() {
|
||||
late FakeCardGateway cardGateway;
|
||||
late FakeReviewGateway reviewGateway;
|
||||
late FakeSettingsGateway settingsGateway;
|
||||
|
||||
setUp(() {
|
||||
cardGateway = FakeCardGateway();
|
||||
reviewGateway = FakeReviewGateway();
|
||||
settingsGateway = FakeSettingsGateway();
|
||||
});
|
||||
|
||||
Future<void> showHome(WidgetTester tester) async {
|
||||
tester.view.physicalSize = const Size(1200, 1600);
|
||||
tester.view.devicePixelRatio = 1;
|
||||
addTearDown(tester.view.reset);
|
||||
await pumpApp(
|
||||
tester,
|
||||
testDependencies(
|
||||
cardGateway: cardGateway,
|
||||
reviewGateway: reviewGateway,
|
||||
settingsGateway: settingsGateway,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
int streak(WidgetTester tester) =>
|
||||
tester.widget<StreakChip>(find.byType(StreakChip)).streak;
|
||||
|
||||
testWidgets('a card rated today lights the streak and the heatmap', (
|
||||
tester,
|
||||
) async {
|
||||
final cards = CardRepository(cardGateway);
|
||||
addTearDown(cards.dispose);
|
||||
final id = await cards.create(
|
||||
'japanese',
|
||||
CardContent(front: RichContent.empty(), back: RichContent.empty()),
|
||||
);
|
||||
await ReviewRepository(reviewGateway).record(
|
||||
cardId: id,
|
||||
rating: Rating.good,
|
||||
reviewedAt: DateTime.now(),
|
||||
duration: Duration.zero,
|
||||
);
|
||||
|
||||
await showHome(tester);
|
||||
|
||||
expect(streak(tester), 1);
|
||||
// The card written and the rating.
|
||||
expect(find.text('2 activities in the last year'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('a goal is set in its sheet and shows its progress', (
|
||||
tester,
|
||||
) async {
|
||||
await showHome(tester);
|
||||
|
||||
await tester.tap(find.text('Set a study goal'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Per week'));
|
||||
await tester.pump();
|
||||
await tester.tap(find.byTooltip('More'));
|
||||
await tester.pump();
|
||||
await tester.tap(find.text('Save goal'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Weekly goal'), findsOneWidget);
|
||||
expect(find.text('0 of 21 cards this week'), findsOneWidget);
|
||||
expect(find.byType(GoalCard), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('resting today keeps the streak', (tester) async {
|
||||
await showHome(tester);
|
||||
expect(streak(tester), 0);
|
||||
|
||||
await tester.tap(find.text('Rest day'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(streak(tester), 1);
|
||||
});
|
||||
|
||||
testWidgets('a long press arranges the dashboard: a widget hidden stays '
|
||||
'hidden', (tester) async {
|
||||
await showHome(tester);
|
||||
|
||||
await tester.longPress(find.text('Set a study goal'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Arrange widgets'), findsOneWidget);
|
||||
await tester.tap(find.byTooltip('Hide Study goal'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Done'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Set a study goal'), findsNothing);
|
||||
expect(find.text('Your activity'), findsOneWidget);
|
||||
});
|
||||
}
|
||||
Loading…
Reference in a new issue