settings_screen_test.dart 8.1 KB

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