feat(01-01): add core infrastructure, localization, and Wave 0 tests

- AppDatabase with schemaVersion 1, in-memory executor for testing
- Database provider with @Riverpod(keepAlive: true)
- AppTheme with sage green seed ColorScheme and warm surface overrides
- ThemeNotifier with SharedPreferences persistence, defaults to system
- Full German ARB localization (15 keys) with proper umlauts
- Minimal main.dart with ProviderScope placeholder
- Drift schema v1 captured via make-migrations
- All .g.dart files generated via build_runner
- Wave 0 tests: database (3), color scheme (6), theme (3), localization (2) -- 14 total, all passing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-15 19:59:44 +01:00
parent 4b27aeadf6
commit 51738f78bc
17 changed files with 784 additions and 149 deletions

View File

@@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:household_keeper/core/theme/app_theme.dart';
void main() {
group('AppTheme ColorScheme', () {
test('lightTheme has Brightness.light', () {
final theme = AppTheme.lightTheme();
expect(theme.colorScheme.brightness, equals(Brightness.light));
});
test('darkTheme has Brightness.dark', () {
final theme = AppTheme.darkTheme();
expect(theme.colorScheme.brightness, equals(Brightness.dark));
});
test('both themes use sage green seed (primary in green hue range)', () {
final lightPrimary = HSLColor.fromColor(
AppTheme.lightTheme().colorScheme.primary,
);
final darkPrimary = HSLColor.fromColor(
AppTheme.darkTheme().colorScheme.primary,
);
// Sage green hue is approximately 100-150 degrees
expect(lightPrimary.hue, inInclusiveRange(80, 160));
expect(darkPrimary.hue, inInclusiveRange(80, 160));
});
test('light surface color is warm stone (0xFFF5F0E8)', () {
final theme = AppTheme.lightTheme();
expect(theme.colorScheme.surface, equals(const Color(0xFFF5F0E8)));
});
test('dark surface color is warm charcoal (0xFF2A2520), not cold gray', () {
final theme = AppTheme.darkTheme();
expect(theme.colorScheme.surface, equals(const Color(0xFF2A2520)));
});
test('both themes use Material 3', () {
expect(AppTheme.lightTheme().useMaterial3, isTrue);
expect(AppTheme.darkTheme().useMaterial3, isTrue);
});
});
}

View File

@@ -0,0 +1,41 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:household_keeper/core/theme/theme_provider.dart';
void main() {
group('ThemeNotifier', () {
setUp(() {
SharedPreferences.setMockInitialValues({});
});
test('defaults to ThemeMode.system', () {
final container = ProviderContainer();
addTearDown(container.dispose);
final themeMode = container.read(themeProvider);
expect(themeMode, equals(ThemeMode.system));
});
test('setThemeMode(dark) updates state to dark', () async {
final container = ProviderContainer();
addTearDown(container.dispose);
await container.read(themeProvider.notifier).setThemeMode(
ThemeMode.dark,
);
expect(container.read(themeProvider), equals(ThemeMode.dark));
});
test('setThemeMode(light) updates state to light', () async {
final container = ProviderContainer();
addTearDown(container.dispose);
await container.read(themeProvider.notifier).setThemeMode(
ThemeMode.light,
);
expect(container.read(themeProvider), equals(ThemeMode.light));
});
});
}