settings_screen_test.dart 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. import 'package:cardash_launcher/core/display_controller.dart';
  2. import 'package:cardash_launcher/core/theme/app_theme.dart';
  3. import 'package:cardash_launcher/core/theme/theme_controller.dart';
  4. import 'package:cardash_launcher/core/theme/theme_preference.dart';
  5. import 'package:cardash_launcher/data/models/app_entry.dart';
  6. import 'package:cardash_launcher/data/models/bluetooth_device_info.dart';
  7. import 'package:cardash_launcher/data/models/bluetooth_power_state.dart';
  8. import 'package:cardash_launcher/data/models/gps_speed.dart';
  9. import 'package:cardash_launcher/data/models/jellyfin_models.dart';
  10. import 'package:cardash_launcher/data/models/location_reading.dart';
  11. import 'package:cardash_launcher/data/models/media_playback.dart';
  12. import 'package:cardash_launcher/data/models/obd_state.dart';
  13. import 'package:cardash_launcher/data/models/system_status.dart';
  14. import 'package:cardash_launcher/data/models/update_info.dart';
  15. import 'package:cardash_launcher/data/repositories/settings_repository.dart';
  16. import 'package:cardash_launcher/data/services/jellyfin_service.dart';
  17. import 'package:cardash_launcher/data/services/native_bridge.dart';
  18. import 'package:cardash_launcher/data/services/pin_service.dart';
  19. import 'package:cardash_launcher/data/services/secure_store.dart';
  20. import 'package:cardash_launcher/data/services/telemetry_bridge.dart';
  21. import 'package:cardash_launcher/features/home/gps_speed_controller.dart';
  22. import 'package:cardash_launcher/features/home/launcher_controller.dart';
  23. import 'package:cardash_launcher/features/home/obd_controller.dart';
  24. import 'package:cardash_launcher/features/home/system_controller.dart';
  25. import 'package:cardash_launcher/features/home/telemetry_settings_controller.dart';
  26. import 'package:cardash_launcher/features/home/weather_controller.dart';
  27. import 'package:cardash_launcher/features/lock/lock_controller.dart';
  28. import 'package:cardash_launcher/features/settings/jellyfin_controller.dart';
  29. import 'package:cardash_launcher/features/settings/settings_screen.dart';
  30. import 'package:cardash_launcher/features/settings/update_controller.dart';
  31. import 'package:flutter/material.dart';
  32. import 'package:flutter_test/flutter_test.dart';
  33. import 'package:provider/provider.dart';
  34. import 'package:shared_preferences/shared_preferences.dart';
  35. class _LauncherPlatform implements LauncherPlatform {
  36. @override
  37. Future<List<AppEntry>> listApps() async => const [];
  38. @override
  39. Future<void> launchApp({
  40. required String packageName,
  41. required String activityName,
  42. }) async {}
  43. @override
  44. Future<bool> isDefaultHome() async => true;
  45. @override
  46. Future<bool> requestDefaultHome() async => true;
  47. @override
  48. Future<SystemStatus> getStatus() async => const SystemStatus();
  49. @override
  50. Future<VolumeInfo> getVolume() async => const VolumeInfo();
  51. @override
  52. Future<void> setVolume(int index) async {}
  53. @override
  54. Future<bool> isMusicPlaying() async => false;
  55. @override
  56. Future<bool> sendMediaKey(String action) async => true;
  57. @override
  58. Future<MediaPlayback> getMediaState() async => const MediaPlayback();
  59. @override
  60. Future<bool> openNotificationAccessSettings() async => true;
  61. @override
  62. Future<void> setKeepScreenOn(bool enabled) async {}
  63. @override
  64. Future<bool> openUrl(String url) async => true;
  65. @override
  66. Future<UpdateInstallResult> downloadAndInstallUpdate(String url) async {
  67. return const UpdateInstallResult(started: false, permissionRequired: false);
  68. }
  69. }
  70. class _TelemetryPlatform implements TelemetryPlatform {
  71. @override
  72. Future<List<BluetoothDeviceInfo>> listBondedDevices() async => const [];
  73. @override
  74. Future<BluetoothPowerState> bluetoothState() async => BluetoothPowerState.on;
  75. @override
  76. Future<bool> ensureBluetoothPermission() async => true;
  77. @override
  78. Future<bool> openBluetoothSettings() async => true;
  79. @override
  80. Future<bool> ensureLocationPermission() async => true;
  81. @override
  82. Future<LocationReading> getLocation() async =>
  83. const LocationReading(latitude: 0, longitude: 0, place: 'Home');
  84. @override
  85. Future<void> connectObd(String address) async {}
  86. @override
  87. Future<void> disconnectObd() async {}
  88. @override
  89. Future<ObdState> getObdState() async => const ObdState();
  90. @override
  91. Future<bool> startGpsSpeed() async => false;
  92. @override
  93. Future<void> stopGpsSpeed() async {}
  94. @override
  95. Future<GpsSpeed> getGpsSpeed() async => const GpsSpeed();
  96. }
  97. class _SecureStore implements SecureStore {
  98. @override
  99. Future<String?> read(String key) async => null;
  100. @override
  101. Future<void> write(String key, String value) async {}
  102. @override
  103. Future<void> delete(String key) async {}
  104. }
  105. class _JellyfinGateway implements JellyfinGateway {
  106. @override
  107. Future<JellyfinServerInfo> serverInfo(Uri baseUrl) async {
  108. return const JellyfinServerInfo(name: 'DarkTower', version: '12.2.0');
  109. }
  110. @override
  111. Future<JellyfinQuickConnect> startQuickConnect(
  112. Uri baseUrl, {
  113. required String deviceId,
  114. }) async {
  115. return const JellyfinQuickConnect(code: '491006', secret: 'secret');
  116. }
  117. @override
  118. Future<bool> isQuickConnectApproved(Uri baseUrl, String secret) async {
  119. return false;
  120. }
  121. @override
  122. Future<JellyfinSession> authenticateQuickConnect(
  123. Uri baseUrl,
  124. String secret, {
  125. required String deviceId,
  126. }) async {
  127. return const JellyfinSession(
  128. accessToken: 'token-1',
  129. userId: 'user-1',
  130. userName: 'wasp',
  131. );
  132. }
  133. @override
  134. Future<JellyfinUser> currentUser(Uri baseUrl, String token) async {
  135. return const JellyfinUser(id: 'user-1', name: 'wasp');
  136. }
  137. @override
  138. void close() {}
  139. }
  140. void main() {
  141. TestWidgetsFlutterBinding.ensureInitialized();
  142. testWidgets(
  143. 'settings shows the Jellyfin, OBD-II, Speed and Temperature cards',
  144. (tester) async {
  145. await tester.binding.setSurfaceSize(const Size(1280, 800));
  146. addTearDown(() => tester.binding.setSurfaceSize(null));
  147. SharedPreferences.setMockInitialValues({});
  148. final prefs = await SharedPreferences.getInstance();
  149. final settings = SettingsRepository(prefs);
  150. await settings.setThemePreference(ThemePreference.light);
  151. final platform = _LauncherPlatform();
  152. final telemetry = _TelemetryPlatform();
  153. final theme = ThemeController(settings);
  154. addTearDown(theme.dispose);
  155. final display = DisplayController(platform, settings);
  156. await display.initialize();
  157. final launcher = LauncherController(platform, settings);
  158. final system = SystemController(platform);
  159. final obd = ObdController(telemetry, settings)..initialize();
  160. final gps = GpsSpeedController(telemetry);
  161. final weather = WeatherController(telemetry);
  162. final telemetrySettings = TelemetrySettingsController(
  163. settings,
  164. weather,
  165. gps,
  166. )..initialize();
  167. final update = UpdateController(platform);
  168. final lock = LockController(PinService(_SecureStore(), iterations: 10));
  169. await lock.initialize();
  170. final jellyfin = JellyfinController(
  171. settings,
  172. _JellyfinGateway(),
  173. _SecureStore(),
  174. );
  175. await jellyfin.initialize();
  176. addTearDown(jellyfin.dispose);
  177. await tester.pumpWidget(
  178. MultiProvider(
  179. providers: [
  180. ChangeNotifierProvider.value(value: theme),
  181. ChangeNotifierProvider.value(value: display),
  182. ChangeNotifierProvider.value(value: launcher),
  183. ChangeNotifierProvider.value(value: system),
  184. ChangeNotifierProvider.value(value: obd),
  185. ChangeNotifierProvider.value(value: weather),
  186. ChangeNotifierProvider.value(value: telemetrySettings),
  187. ChangeNotifierProvider.value(value: jellyfin),
  188. ChangeNotifierProvider.value(value: update),
  189. ChangeNotifierProvider.value(value: lock),
  190. ],
  191. child: MaterialApp(
  192. theme: AppTheme.light(),
  193. home: const SettingsScreen(),
  194. ),
  195. ),
  196. );
  197. await tester.pumpAndSettle();
  198. expect(find.text('OBD-II'), findsOneWidget);
  199. expect(find.text('Jellyfin'), findsWidgets);
  200. expect(find.text('Speed'), findsOneWidget);
  201. expect(find.text('Temperature'), findsOneWidget);
  202. expect(find.text('Show speed'), findsOneWidget);
  203. expect(find.text('Show temperature'), findsOneWidget);
  204. expect(tester.takeException(), isNull);
  205. obd.dispose();
  206. gps.dispose();
  207. weather.dispose();
  208. telemetrySettings.dispose();
  209. },
  210. );
  211. }