leafittome/test/widget_test.dart
cschlaefke 1b2c880c89 V2: Haushalt teilen – Einladungscodes, Mitglieder- und Sitter-Rolle, sichtbare Bestätigungen
- Einladen per einmaligem 6-stelligem Code (7 Tage gültig), wahlweise als Mitglied oder Pflanzen-Sitter
- Beitritt über Cloud Function joinHousehold (Transaktion, Admin-Rechte)
- Security Rules: Sitter dürfen an Pflanzen nur Bestätigungs-Felder ändern; invites nur erstellen, nie lesen
- Haushalts-Screen: Mitgliederliste mit Rollen, Einladen, Beitreten mit Wechsel-Warnung
- UI-Gating: Sitter sehen keine Anlegen-/Bearbeiten-/Löschen-Aktionen
- Bestätigungen speichern den Namen (lastWateredBy/lastFertilizedBy), Anzeige im Profil
- Tests: Members-Map im Seed, neuer Sitter-Test

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 19:14:34 +02:00

110 lines
3.7 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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:firebase_auth/firebase_auth.dart';
import 'package:leafittome/app.dart';
import 'package:leafittome/core/firebase/firebase_providers.dart';
import 'package:leafittome/core/settings/settings_provider.dart';
import 'package:leafittome/features/notifications/data/push_registration_service.dart';
import 'package:shared_preferences/shared_preferences.dart';
/// Tests brauchen kein echtes FCM Push-Registrierung ist ein No-Op.
class _FakePushRegistrationService implements PushRegistrationService {
@override
Future<void> registerDevice(User user) async {}
@override
Future<void> syncReminderTime(TimeOfDay time) async {}
}
/// 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({String role = 'member'}) 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'],
'members': {
'u1': {'role': role, 'email': 'test@example.com'},
},
});
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),
pushRegistrationServiceProvider
.overrideWithValue(_FakePushRegistrationService()),
],
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);
});
testWidgets('Sitter kann abhaken, sieht aber keinen Anlegen-Button',
(tester) async {
await tester.pumpWidget(await buildTestApp(role: 'sitter'));
await tester.pumpAndSettle();
// Abhaken ist erlaubt …
expect(find.text('Erledigt'), findsWidgets);
// … aber Pflanzen anlegen nicht.
expect(find.text('Pflanze hinzufügen'), findsNothing);
});
}