Initialise l'app Flutter mobile : BDD Drift, onboarding sans compte et tableau de bord.

Phase 1 du MVP : schéma SQLite porté depuis le prototype web, seed des règles/récompenses, flux d'onboarding en 4 étapes et écran d'accueil minimal.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Julien Martin
2026-06-12 12:12:01 +02:00
co-authored by Cursor
parent a82dffe959
commit aac3a729a2
45 changed files with 6328 additions and 4 deletions
+60
View File
@@ -0,0 +1,60 @@
import 'package:bonpoint/data/database/app_database.dart';
import 'package:drift/native.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
late AppDatabase db;
setUp(() async {
db = AppDatabase.forTesting(NativeDatabase.memory());
await db.importDefaultPack();
});
tearDown(() async {
await db.close();
});
test('appliquerRegle respecte le plancher à 0', () async {
final childId = await db.insertChild(
prenom: 'Test',
couleur: '#6C63FF',
);
final rules = await db.select(db.regles).get();
final positiveRule = rules.firstWhere((r) => r.points == 1);
final negativeRule = rules.firstWhere((r) => r.points == -2);
await db.applyRule(childId, positiveRule.id);
// Score = 1, puis règle -2 → score 0, delta réel -1
await db.applyRule(childId, negativeRule.id);
// Score déjà 0, règle -2 → score 0, delta réel 0
await db.applyRule(childId, negativeRule.id);
final child = await (db.select(db.enfants)
..where((e) => e.id.equals(childId)))
.getSingle();
expect(child.score, 0);
final movements = await db.select(db.mouvements).get();
expect(movements.length, 3);
expect(movements[0].delta, 1);
expect(movements[1].delta, -1);
expect(movements[2].delta, 0);
});
test('delta enregistré est le delta réel (pas le delta théorique)', () async {
final childId = await db.insertChild(
prenom: 'Test',
couleur: '#6C63FF',
);
final rules = await db.select(db.regles).get();
final rule = rules.firstWhere((r) => r.points == -2);
await db.applyRule(childId, rule.id);
final movement = await db.select(db.mouvements).getSingle();
expect(movement.delta, 0);
});
}
+23
View File
@@ -0,0 +1,23 @@
import 'package:bonpoint/app.dart';
import 'package:bonpoint/providers/database_provider.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('Affiche l\'écran de bienvenue au premier lancement',
(tester) async {
await tester.pumpWidget(
ProviderScope(
overrides: [
onboardingCompleteProvider.overrideWith((ref) async => false),
],
child: const BonpointApp(),
),
);
await tester.pump();
await tester.pump(const Duration(milliseconds: 100));
expect(find.text('Bons Points'), findsWidgets);
expect(find.text('Commencer'), findsOneWidget);
});
}