- Datenmodell: users/{uid}, households/{id} mit memberUids, plants/locations als Subcollections
- StreamProvider liefern Live-Daten, Repositories kapseln Schreibzugriffe
- Login-Screen mit Registrierung (legt Haushalt automatisch an), Logout in Einstellungen
- Router-Redirect bei Login/Logout, firestore.rules mit Haushalts-Prinzip
- Tests auf firebase_auth_mocks + fake_cloud_firestore umgestellt
- Verifiziert: analyze/test grün, Android-Debug-Build erfolgreich
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
83 lines
2.8 KiB
Dart
83 lines
2.8 KiB
Dart
import 'package:cloud_firestore/cloud_firestore.dart';
|
|
import 'package:fake_cloud_firestore/fake_cloud_firestore.dart';
|
|
import 'package:firebase_auth_mocks/firebase_auth_mocks.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:leafittome/app.dart';
|
|
import 'package:leafittome/core/firebase/firebase_providers.dart';
|
|
import 'package:leafittome/core/settings/settings_provider.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
/// Baut die App mit gemocktem Firebase: angemeldeter Nutzer 'u1' im Haushalt
|
|
/// 'h1' mit einer Monstera, deren Gießen seit einem Tag überfällig ist.
|
|
Future<Widget> buildTestApp() async {
|
|
SharedPreferences.setMockInitialValues({});
|
|
final prefs = await SharedPreferences.getInstance();
|
|
|
|
final auth = MockFirebaseAuth(
|
|
signedIn: true,
|
|
mockUser: MockUser(uid: 'u1', email: 'test@example.com'),
|
|
);
|
|
|
|
final firestore = FakeFirebaseFirestore();
|
|
await firestore.collection('users').doc('u1').set({
|
|
'email': 'test@example.com',
|
|
'householdId': 'h1',
|
|
});
|
|
await firestore.collection('households').doc('h1').set({
|
|
'name': 'Mein Haushalt',
|
|
'memberUids': ['u1'],
|
|
});
|
|
final now = DateTime.now();
|
|
await firestore
|
|
.collection('households')
|
|
.doc('h1')
|
|
.collection('plants')
|
|
.add({
|
|
'nickname': 'Monstera',
|
|
'species': 'Monstera deliciosa',
|
|
'locationId': null,
|
|
'description': '',
|
|
'careNotes': '',
|
|
'wateringIntervalDays': 7,
|
|
'fertilizingIntervalDays': 28,
|
|
'lastWatered':
|
|
Timestamp.fromDate(now.subtract(const Duration(days: 8))),
|
|
'lastFertilized':
|
|
Timestamp.fromDate(now.subtract(const Duration(days: 3))),
|
|
});
|
|
|
|
return ProviderScope(
|
|
overrides: [
|
|
sharedPreferencesProvider.overrideWithValue(prefs),
|
|
firebaseAuthProvider.overrideWithValue(auth),
|
|
firestoreProvider.overrideWithValue(firestore),
|
|
],
|
|
child: const LeafItToMeApp(),
|
|
);
|
|
}
|
|
|
|
void main() {
|
|
testWidgets('Angemeldeter Nutzer sieht die Heute-Checkliste mit fälliger Aufgabe',
|
|
(tester) async {
|
|
await tester.pumpWidget(await buildTestApp());
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('Heute'), findsOneWidget);
|
|
expect(find.textContaining('offene Aufgabe'), findsOneWidget);
|
|
expect(find.textContaining('Monstera gießen'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('Aufgabe bestätigen schreibt nach Firestore und leert die Liste',
|
|
(tester) async {
|
|
await tester.pumpWidget(await buildTestApp());
|
|
await tester.pumpAndSettle();
|
|
|
|
await tester.tap(find.text('Erledigt').first);
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('Erledigt'), findsNothing);
|
|
expect(find.text('Alles versorgt!'), findsOneWidget);
|
|
});
|
|
}
|