135 lines
5.4 KiB
Dart
135 lines
5.4 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
import 'package:motorcycle_dash/core/theme/app_colors.dart';
|
|
import 'package:motorcycle_dash/core/theme/app_spacing.dart';
|
|
import 'package:motorcycle_dash/core/theme/app_typography.dart';
|
|
import 'package:motorcycle_dash/core/theme/theme.dart';
|
|
import 'package:motorcycle_dash/core/theme/theme_extensions.dart';
|
|
import 'package:motorcycle_dash/core/theme/theme_mode_provider.dart';
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
group('MotorSignal Design System - Tokens & Hierarchy', () {
|
|
test('AppColors verifies dark and light semantic palette definitions', () {
|
|
expect(AppColors.cyberCyan, const Color(0xFF00E5FF));
|
|
expect(AppColors.velocityBlue, const Color(0xFF2E7DFF));
|
|
expect(AppColors.raceRed, const Color(0xFFFF2A2A));
|
|
expect(AppColors.darkBackground, const Color(0xFF0A0A0A));
|
|
expect(AppColors.darkSurface, const Color(0xFF0D0D0D));
|
|
expect(AppColors.lightBackground, const Color(0xFFF0F0F0));
|
|
expect(AppColors.lightSurface, const Color(0xFFF5F5F5));
|
|
});
|
|
|
|
test('AppTypography specifies authoritative multi-font system', () {
|
|
expect(AppTypography.fontTelemetry, 'JetBrains Mono');
|
|
expect(AppTypography.fontHeadline, 'Sora');
|
|
expect(AppTypography.fontBody, 'Inter');
|
|
|
|
expect(AppTypography.speedometer.fontFamily, 'JetBrains Mono');
|
|
expect(AppTypography.speedometer.fontSize, 96);
|
|
expect(AppTypography.speedometer.fontWeight, FontWeight.w900);
|
|
|
|
expect(AppTypography.headingCompass.fontFamily, 'Sora');
|
|
expect(AppTypography.bodyMd.fontFamily, 'Inter');
|
|
expect(AppTypography.button.fontFamily, 'Sora');
|
|
});
|
|
|
|
test('AppSpacing and AppRadius conform to 4dp base grid and 48dp touch targets', () {
|
|
expect(AppSpacing.xs, 4.0);
|
|
expect(AppSpacing.sm, 8.0);
|
|
expect(AppSpacing.md, 12.0);
|
|
expect(AppSpacing.lg, 16.0);
|
|
expect(AppSpacing.xl, 24.0);
|
|
expect(AppSpacing.minTouchTarget, 48.0);
|
|
|
|
expect(AppRadius.sm, 4.0);
|
|
expect(AppRadius.md, 8.0);
|
|
expect(AppRadius.lg, 12.0);
|
|
expect(AppRadius.xl, 16.0);
|
|
expect(AppRadius.full, 999.0);
|
|
});
|
|
});
|
|
|
|
group('MotorSignalThemeColors Extension', () {
|
|
test('Dark and Light presets have correct brightness semantics', () {
|
|
const dark = MotorSignalThemeColors.dark;
|
|
expect(dark.cyberCyan, AppColors.cyberCyan);
|
|
expect(dark.launchGreen, AppColors.launchGreen);
|
|
expect(dark.surfaceContainer, AppColors.darkSurfaceContainer);
|
|
|
|
const light = MotorSignalThemeColors.light;
|
|
expect(light.cyberCyan, AppColors.technicalBlue);
|
|
expect(light.launchGreen, AppColors.successGreen);
|
|
expect(light.surfaceContainer, AppColors.lightSurfaceContainer);
|
|
});
|
|
|
|
test('copyWith and lerp interpolate colors accurately', () {
|
|
const dark = MotorSignalThemeColors.dark;
|
|
final modified = dark.copyWith(cyberCyan: Colors.purple);
|
|
expect(modified.cyberCyan, Colors.purple);
|
|
expect(modified.velocityBlue, dark.velocityBlue);
|
|
|
|
final lerped = dark.lerp(MotorSignalThemeColors.light, 0.5);
|
|
expect(lerped, isA<MotorSignalThemeColors>());
|
|
expect(lerped.cyberCyan, Color.lerp(dark.cyberCyan, MotorSignalThemeColors.light.cyberCyan, 0.5));
|
|
});
|
|
});
|
|
|
|
group('AppTheme ThemeData', () {
|
|
test('darkTheme configures Material 3 dark brightness and extensions', () {
|
|
final theme = AppTheme.darkTheme;
|
|
expect(theme.useMaterial3, isTrue);
|
|
expect(theme.brightness, Brightness.dark);
|
|
expect(theme.scaffoldBackgroundColor, AppColors.darkBackground);
|
|
expect(theme.colorScheme.primary, AppColors.darkPrimary);
|
|
|
|
final ext = theme.extension<MotorSignalThemeColors>();
|
|
expect(ext, isNotNull);
|
|
expect(ext?.cyberCyan, AppColors.cyberCyan);
|
|
});
|
|
|
|
test('lightTheme configures Material 3 light brightness and extensions', () {
|
|
final theme = AppTheme.lightTheme;
|
|
expect(theme.useMaterial3, isTrue);
|
|
expect(theme.brightness, Brightness.light);
|
|
expect(theme.scaffoldBackgroundColor, AppColors.lightBackground);
|
|
expect(theme.colorScheme.primary, AppColors.lightPrimary);
|
|
|
|
final ext = theme.extension<MotorSignalThemeColors>();
|
|
expect(ext, isNotNull);
|
|
expect(ext?.cyberCyan, AppColors.technicalBlue);
|
|
});
|
|
});
|
|
|
|
group('ThemeMode & Persistence Provider', () {
|
|
test('AppThemeModeNotifier defaults to ThemeMode.system and persists transitions', () async {
|
|
SharedPreferences.setMockInitialValues({});
|
|
final prefs = await SharedPreferences.getInstance();
|
|
|
|
final notifier = AppThemeModeNotifier(prefs);
|
|
expect(notifier.state, ThemeMode.system);
|
|
|
|
await notifier.setThemeMode(ThemeMode.dark);
|
|
expect(notifier.state, ThemeMode.dark);
|
|
expect(prefs.getString('app_theme_mode'), 'dark');
|
|
|
|
await notifier.setThemeMode(ThemeMode.light);
|
|
expect(notifier.state, ThemeMode.light);
|
|
expect(prefs.getString('app_theme_mode'), 'light');
|
|
|
|
await notifier.toggleTheme();
|
|
expect(notifier.state, ThemeMode.system);
|
|
});
|
|
|
|
test('AppThemeModeNotifier restores saved theme from SharedPreferences', () async {
|
|
SharedPreferences.setMockInitialValues({'app_theme_mode': 'light'});
|
|
final prefs = await SharedPreferences.getInstance();
|
|
|
|
final notifier = AppThemeModeNotifier(prefs);
|
|
expect(notifier.state, ThemeMode.light);
|
|
});
|
|
});
|
|
}
|