telemetry_settings_controller_test.dart 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. import 'package:cardash_launcher/data/models/bluetooth_device_info.dart';
  2. import 'package:cardash_launcher/data/models/bluetooth_power_state.dart';
  3. import 'package:cardash_launcher/data/models/gps_speed.dart';
  4. import 'package:cardash_launcher/data/models/location_reading.dart';
  5. import 'package:cardash_launcher/data/models/obd_state.dart';
  6. import 'package:cardash_launcher/data/repositories/settings_repository.dart';
  7. import 'package:cardash_launcher/data/services/telemetry_bridge.dart';
  8. import 'package:cardash_launcher/data/services/weather_service.dart';
  9. import 'package:cardash_launcher/features/home/gps_speed_controller.dart';
  10. import 'package:cardash_launcher/features/home/telemetry_settings_controller.dart';
  11. import 'package:cardash_launcher/features/home/weather_controller.dart';
  12. import 'package:flutter_test/flutter_test.dart';
  13. import 'package:shared_preferences/shared_preferences.dart';
  14. class _TelemetryPlatform implements TelemetryPlatform {
  15. _TelemetryPlatform({this.locationGranted = true});
  16. bool locationGranted;
  17. int locationRequests = 0;
  18. @override
  19. Future<bool> ensureLocationPermission() async {
  20. locationRequests++;
  21. return locationGranted;
  22. }
  23. @override
  24. Future<LocationReading> getLocation() async =>
  25. const LocationReading(latitude: 1, longitude: 2, place: 'Sofia');
  26. @override
  27. Future<List<BluetoothDeviceInfo>> listBondedDevices() async => const [];
  28. @override
  29. Future<BluetoothPowerState> bluetoothState() async => BluetoothPowerState.on;
  30. @override
  31. Future<bool> ensureBluetoothPermission() async => true;
  32. @override
  33. Future<bool> openBluetoothSettings() async => true;
  34. @override
  35. Future<void> connectObd(String address) async {}
  36. @override
  37. Future<void> disconnectObd() async {}
  38. @override
  39. Future<ObdState> getObdState() async => const ObdState();
  40. @override
  41. Future<bool> startGpsSpeed() async => false;
  42. @override
  43. Future<void> stopGpsSpeed() async {}
  44. @override
  45. Future<GpsSpeed> getGpsSpeed() async => const GpsSpeed();
  46. }
  47. class _WeatherService extends WeatherService {
  48. @override
  49. Future<double?> temperatureCelsius({
  50. required double latitude,
  51. required double longitude,
  52. }) async => 12;
  53. }
  54. void main() {
  55. TestWidgetsFlutterBinding.ensureInitialized();
  56. test('persists source choices and starts weather when needed', () async {
  57. SharedPreferences.setMockInitialValues({});
  58. final prefs = await SharedPreferences.getInstance();
  59. final settings = SettingsRepository(prefs);
  60. await settings.setTemperatureEnabled(true);
  61. final weather = WeatherController(
  62. _TelemetryPlatform(),
  63. weatherService: _WeatherService(),
  64. );
  65. final gps = GpsSpeedController(_TelemetryPlatform());
  66. final controller = TelemetrySettingsController(settings, weather, gps)
  67. ..initialize();
  68. addTearDown(controller.dispose);
  69. addTearDown(gps.dispose);
  70. addTearDown(weather.dispose);
  71. expect(controller.speedEnabled, isTrue);
  72. expect(controller.speedUseObd, isTrue);
  73. expect(controller.temperatureEnabled, isTrue);
  74. expect(controller.temperatureUseObd, isTrue);
  75. await controller.setSpeedEnabled(false);
  76. await controller.setSpeedUseObd(false);
  77. await controller.setTemperatureUseObd(false);
  78. expect(settings.speedEnabled, isFalse);
  79. expect(settings.speedUseObd, isFalse);
  80. expect(settings.temperatureUseObd, isFalse);
  81. expect(weather.enabled, isTrue);
  82. expect(weather.hasTemperature, isTrue);
  83. expect(settings.weatherLocationTemperature, isTrue);
  84. });
  85. test('turning temperature off stops and clears the weather poller', () async {
  86. SharedPreferences.setMockInitialValues({});
  87. final prefs = await SharedPreferences.getInstance();
  88. final settings = SettingsRepository(prefs);
  89. await settings.setTemperatureEnabled(true);
  90. final weather = WeatherController(
  91. _TelemetryPlatform(),
  92. weatherService: _WeatherService(),
  93. );
  94. final gps = GpsSpeedController(_TelemetryPlatform());
  95. final controller = TelemetrySettingsController(settings, weather, gps)
  96. ..initialize();
  97. addTearDown(controller.dispose);
  98. addTearDown(gps.dispose);
  99. addTearDown(weather.dispose);
  100. await controller.setTemperatureUseObd(false);
  101. expect(weather.hasTemperature, isTrue);
  102. await controller.setTemperatureEnabled(false);
  103. expect(controller.temperatureEnabled, isFalse);
  104. expect(settings.temperatureEnabled, isFalse);
  105. expect(weather.enabled, isFalse);
  106. expect(weather.hasTemperature, isFalse);
  107. expect(settings.weatherLocationTemperature, isFalse);
  108. });
  109. test(
  110. 'denied location leaves the switch on but reports weather failure',
  111. () async {
  112. SharedPreferences.setMockInitialValues({});
  113. final prefs = await SharedPreferences.getInstance();
  114. final settings = SettingsRepository(prefs);
  115. await settings.setTemperatureEnabled(true);
  116. final weather = WeatherController(
  117. _TelemetryPlatform(locationGranted: false),
  118. weatherService: _WeatherService(),
  119. );
  120. final gps = GpsSpeedController(_TelemetryPlatform());
  121. final controller = TelemetrySettingsController(settings, weather, gps)
  122. ..initialize();
  123. addTearDown(controller.dispose);
  124. addTearDown(gps.dispose);
  125. addTearDown(weather.dispose);
  126. final granted = await controller.setTemperatureUseObd(false);
  127. expect(granted, isFalse);
  128. expect(controller.temperatureUseObd, isFalse);
  129. expect(weather.enabled, isFalse);
  130. expect(controller.weatherError, isNotNull);
  131. },
  132. );
  133. test('enabling speed asks for location without an OBD adapter', () async {
  134. SharedPreferences.setMockInitialValues({});
  135. final prefs = await SharedPreferences.getInstance();
  136. final settings = SettingsRepository(prefs);
  137. await settings.setSpeedEnabled(false);
  138. final platform = _TelemetryPlatform();
  139. final weather = WeatherController(platform);
  140. final gps = GpsSpeedController(platform);
  141. final controller = TelemetrySettingsController(settings, weather, gps)
  142. ..initialize();
  143. addTearDown(controller.dispose);
  144. addTearDown(gps.dispose);
  145. addTearDown(weather.dispose);
  146. final granted = await controller.setSpeedEnabled(true);
  147. expect(granted, isTrue);
  148. expect(platform.locationRequests, 1);
  149. expect(controller.speedEnabled, isTrue);
  150. expect(settings.speedEnabled, isTrue);
  151. });
  152. test('enabling speed does not ask when OBD speed is selected', () async {
  153. SharedPreferences.setMockInitialValues({});
  154. final prefs = await SharedPreferences.getInstance();
  155. final settings = SettingsRepository(prefs);
  156. await settings.setSpeedEnabled(false);
  157. await settings.setObdAdapterAddress('AA:BB:CC:DD:EE:FF');
  158. final platform = _TelemetryPlatform();
  159. final weather = WeatherController(platform);
  160. final gps = GpsSpeedController(platform);
  161. final controller = TelemetrySettingsController(settings, weather, gps)
  162. ..initialize();
  163. addTearDown(controller.dispose);
  164. addTearDown(gps.dispose);
  165. addTearDown(weather.dispose);
  166. final granted = await controller.setSpeedEnabled(true);
  167. expect(granted, isTrue);
  168. expect(platform.locationRequests, 0);
  169. expect(controller.speedEnabled, isTrue);
  170. });
  171. test('denied location keeps speed on and reports the failure', () async {
  172. SharedPreferences.setMockInitialValues({});
  173. final prefs = await SharedPreferences.getInstance();
  174. final settings = SettingsRepository(prefs);
  175. await settings.setSpeedEnabled(false);
  176. final platform = _TelemetryPlatform(locationGranted: false);
  177. final weather = WeatherController(platform);
  178. final gps = GpsSpeedController(platform);
  179. final controller = TelemetrySettingsController(settings, weather, gps)
  180. ..initialize();
  181. addTearDown(controller.dispose);
  182. addTearDown(gps.dispose);
  183. addTearDown(weather.dispose);
  184. final granted = await controller.setSpeedEnabled(true);
  185. expect(granted, isFalse);
  186. expect(platform.locationRequests, 1);
  187. expect(controller.speedEnabled, isTrue);
  188. expect(settings.speedEnabled, isTrue);
  189. });
  190. test('choosing GPS speed asks for location while speed is on', () async {
  191. SharedPreferences.setMockInitialValues({});
  192. final prefs = await SharedPreferences.getInstance();
  193. final settings = SettingsRepository(prefs);
  194. await settings.setObdAdapterAddress('AA:BB:CC:DD:EE:FF');
  195. final platform = _TelemetryPlatform();
  196. final weather = WeatherController(platform);
  197. final gps = GpsSpeedController(platform);
  198. final controller = TelemetrySettingsController(settings, weather, gps)
  199. ..initialize();
  200. addTearDown(controller.dispose);
  201. addTearDown(gps.dispose);
  202. addTearDown(weather.dispose);
  203. final granted = await controller.setSpeedUseObd(false);
  204. expect(granted, isTrue);
  205. expect(platform.locationRequests, 1);
  206. expect(controller.speedUseObd, isFalse);
  207. expect(await controller.setSpeedUseObd(true), isTrue);
  208. expect(platform.locationRequests, 1);
  209. });
  210. }