import 'package:cardash_launcher/core/display_controller.dart'; import 'package:cardash_launcher/core/theme/app_theme.dart'; import 'package:cardash_launcher/core/theme/theme_controller.dart'; import 'package:cardash_launcher/core/theme/theme_preference.dart'; import 'package:cardash_launcher/data/models/app_entry.dart'; import 'package:cardash_launcher/data/models/bluetooth_device_info.dart'; import 'package:cardash_launcher/data/models/bluetooth_power_state.dart'; import 'package:cardash_launcher/data/models/gps_speed.dart'; import 'package:cardash_launcher/data/models/jellyfin_models.dart'; import 'package:cardash_launcher/data/models/location_reading.dart'; import 'package:cardash_launcher/data/models/media_playback.dart'; import 'package:cardash_launcher/data/models/obd_state.dart'; import 'package:cardash_launcher/data/models/system_status.dart'; import 'package:cardash_launcher/data/models/update_info.dart'; import 'package:cardash_launcher/data/repositories/settings_repository.dart'; import 'package:cardash_launcher/data/services/jellyfin_service.dart'; import 'package:cardash_launcher/data/services/native_bridge.dart'; import 'package:cardash_launcher/data/services/pin_service.dart'; import 'package:cardash_launcher/data/services/secure_store.dart'; import 'package:cardash_launcher/data/services/telemetry_bridge.dart'; import 'package:cardash_launcher/features/home/launcher_controller.dart'; import 'package:cardash_launcher/features/home/obd_controller.dart'; import 'package:cardash_launcher/features/home/system_controller.dart'; import 'package:cardash_launcher/features/home/telemetry_settings_controller.dart'; import 'package:cardash_launcher/features/home/weather_controller.dart'; import 'package:cardash_launcher/features/lock/lock_controller.dart'; import 'package:cardash_launcher/features/settings/jellyfin_controller.dart'; import 'package:cardash_launcher/features/settings/settings_screen.dart'; import 'package:cardash_launcher/features/settings/update_controller.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; class _LauncherPlatform implements LauncherPlatform { @override Future> listApps() async => const []; @override Future launchApp({ required String packageName, required String activityName, }) async {} @override Future isDefaultHome() async => true; @override Future requestDefaultHome() async => true; @override Future getStatus() async => const SystemStatus(); @override Future getVolume() async => const VolumeInfo(); @override Future setVolume(int index) async {} @override Future isMusicPlaying() async => false; @override Future sendMediaKey(String action) async => true; @override Future getMediaState() async => const MediaPlayback(); @override Future openNotificationAccessSettings() async => true; @override Future setKeepScreenOn(bool enabled) async {} @override Future openUrl(String url) async => true; @override Future downloadAndInstallUpdate(String url) async { return const UpdateInstallResult(started: false, permissionRequired: false); } } class _TelemetryPlatform implements TelemetryPlatform { @override Future> listBondedDevices() async => const []; @override Future bluetoothState() async => BluetoothPowerState.on; @override Future ensureBluetoothPermission() async => true; @override Future openBluetoothSettings() async => true; @override Future ensureLocationPermission() async => true; @override Future getLocation() async => const LocationReading(latitude: 0, longitude: 0, place: 'Home'); @override Future connectObd(String address) async {} @override Future disconnectObd() async {} @override Future getObdState() async => const ObdState(); @override Future startGpsSpeed() async => false; @override Future stopGpsSpeed() async {} @override Future getGpsSpeed() async => const GpsSpeed(); } class _SecureStore implements SecureStore { @override Future read(String key) async => null; @override Future write(String key, String value) async {} @override Future delete(String key) async {} } class _JellyfinGateway implements JellyfinGateway { @override Future serverInfo(Uri baseUrl) async { return const JellyfinServerInfo(name: 'DarkTower', version: '12.2.0'); } @override Future startQuickConnect( Uri baseUrl, { required String deviceId, }) async { return const JellyfinQuickConnect(code: '491006', secret: 'secret'); } @override Future isQuickConnectApproved(Uri baseUrl, String secret) async { return false; } @override Future authenticateQuickConnect( Uri baseUrl, String secret, { required String deviceId, }) async { return const JellyfinSession( accessToken: 'token-1', userId: 'user-1', userName: 'wasp', ); } @override Future currentUser(Uri baseUrl, String token) async { return const JellyfinUser(id: 'user-1', name: 'wasp'); } @override void close() {} } void main() { TestWidgetsFlutterBinding.ensureInitialized(); testWidgets( 'settings shows the Jellyfin, OBD-II, Speed and Temperature cards', (tester) async { await tester.binding.setSurfaceSize(const Size(1280, 800)); addTearDown(() => tester.binding.setSurfaceSize(null)); SharedPreferences.setMockInitialValues({}); final prefs = await SharedPreferences.getInstance(); final settings = SettingsRepository(prefs); await settings.setThemePreference(ThemePreference.light); final platform = _LauncherPlatform(); final telemetry = _TelemetryPlatform(); final theme = ThemeController(settings); addTearDown(theme.dispose); final display = DisplayController(platform, settings); await display.initialize(); final launcher = LauncherController(platform, settings); final system = SystemController(platform); final obd = ObdController(telemetry, settings)..initialize(); final weather = WeatherController(telemetry); final telemetrySettings = TelemetrySettingsController(settings, weather) ..initialize(); final update = UpdateController(platform); final lock = LockController(PinService(_SecureStore(), iterations: 10)); await lock.initialize(); final jellyfin = JellyfinController( settings, _JellyfinGateway(), _SecureStore(), ); await jellyfin.initialize(); addTearDown(jellyfin.dispose); await tester.pumpWidget( MultiProvider( providers: [ ChangeNotifierProvider.value(value: theme), ChangeNotifierProvider.value(value: display), ChangeNotifierProvider.value(value: launcher), ChangeNotifierProvider.value(value: system), ChangeNotifierProvider.value(value: obd), ChangeNotifierProvider.value(value: weather), ChangeNotifierProvider.value(value: telemetrySettings), ChangeNotifierProvider.value(value: jellyfin), ChangeNotifierProvider.value(value: update), ChangeNotifierProvider.value(value: lock), ], child: MaterialApp( theme: AppTheme.light(), home: const SettingsScreen(), ), ), ); await tester.pumpAndSettle(); expect(find.text('OBD-II'), findsOneWidget); expect(find.text('Jellyfin'), findsWidgets); expect(find.text('Speed'), findsOneWidget); expect(find.text('Temperature'), findsOneWidget); expect(find.text('Show speed'), findsOneWidget); expect(find.text('Show temperature'), findsOneWidget); expect(tester.takeException(), isNull); obd.dispose(); weather.dispose(); telemetrySettings.dispose(); }, ); }