diff --git a/lib/data/shared_prefs_service.dart b/lib/data/shared_prefs_service.dart index a86a7d1..56207ea 100644 --- a/lib/data/shared_prefs_service.dart +++ b/lib/data/shared_prefs_service.dart @@ -10,22 +10,22 @@ import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; import 'package:shared_preferences/shared_preferences.dart'; class UserPreferencesService { - static const _isoKey = "iso"; - static const _ndFilterKey = "ndFilter"; + static const isoKey = "iso"; + static const ndFilterKey = "ndFilter"; - static const _evSourceTypeKey = "evSourceType"; - static const _cameraEvCalibrationKey = "cameraEvCalibration"; - static const _lightSensorEvCalibrationKey = "lightSensorEvCalibration"; - static const _meteringScreenLayoutKey = "meteringScreenLayout"; - static const _filmKey = "film"; + static const evSourceTypeKey = "evSourceType"; + static const cameraEvCalibrationKey = "cameraEvCalibration"; + static const lightSensorEvCalibrationKey = "lightSensorEvCalibration"; + static const meteringScreenLayoutKey = "meteringScreenLayout"; + static const filmKey = "film"; - static const _caffeineKey = "caffeine"; - static const _hapticsKey = "haptics"; - static const _localeKey = "locale"; + static const caffeineKey = "caffeine"; + static const hapticsKey = "haptics"; + static const localeKey = "locale"; - static const _themeTypeKey = "themeType"; - static const _primaryColorKey = "primaryColor"; - static const _dynamicColorKey = "dynamicColor"; + static const themeTypeKey = "themeType"; + static const primaryColorKey = "primaryColor"; + static const dynamicColorKey = "dynamicColor"; final SharedPreferences _sharedPreferences; @@ -69,22 +69,22 @@ class UserPreferencesService { } IsoValue get iso => - IsoValue.values.firstWhere((v) => v.value == (_sharedPreferences.getInt(_isoKey) ?? 100)); - set iso(IsoValue value) => _sharedPreferences.setInt(_isoKey, value.value); + IsoValue.values.firstWhere((v) => v.value == (_sharedPreferences.getInt(isoKey) ?? 100)); + set iso(IsoValue value) => _sharedPreferences.setInt(isoKey, value.value); NdValue get ndFilter => - NdValue.values.firstWhere((v) => v.value == (_sharedPreferences.getInt(_ndFilterKey) ?? 0)); - set ndFilter(NdValue value) => _sharedPreferences.setInt(_ndFilterKey, value.value); + NdValue.values.firstWhere((v) => v.value == (_sharedPreferences.getInt(ndFilterKey) ?? 0)); + set ndFilter(NdValue value) => _sharedPreferences.setInt(ndFilterKey, value.value); EvSourceType get evSourceType => - EvSourceType.values[_sharedPreferences.getInt(_evSourceTypeKey) ?? 0]; - set evSourceType(EvSourceType value) => _sharedPreferences.setInt(_evSourceTypeKey, value.index); + EvSourceType.values[_sharedPreferences.getInt(evSourceTypeKey) ?? 0]; + set evSourceType(EvSourceType value) => _sharedPreferences.setInt(evSourceTypeKey, value.index); - bool get caffeine => _sharedPreferences.getBool(_caffeineKey) ?? false; - set caffeine(bool value) => _sharedPreferences.setBool(_caffeineKey, value); + bool get caffeine => _sharedPreferences.getBool(caffeineKey) ?? false; + set caffeine(bool value) => _sharedPreferences.setBool(caffeineKey, value); MeteringScreenLayoutConfig get meteringScreenLayout { - final configJson = _sharedPreferences.getString(_meteringScreenLayoutKey); + final configJson = _sharedPreferences.getString(meteringScreenLayoutKey); if (configJson != null) { return MeteringScreenLayoutConfigJson.fromJson( json.decode(configJson) as Map, @@ -98,40 +98,40 @@ class UserPreferencesService { } set meteringScreenLayout(MeteringScreenLayoutConfig value) => - _sharedPreferences.setString(_meteringScreenLayoutKey, json.encode(value.toJson())); + _sharedPreferences.setString(meteringScreenLayoutKey, json.encode(value.toJson())); - bool get haptics => _sharedPreferences.getBool(_hapticsKey) ?? true; - set haptics(bool value) => _sharedPreferences.setBool(_hapticsKey, value); + bool get haptics => _sharedPreferences.getBool(hapticsKey) ?? true; + set haptics(bool value) => _sharedPreferences.setBool(hapticsKey, value); SupportedLocale get locale => SupportedLocale.values.firstWhere( - (e) => e.toString() == _sharedPreferences.getString(_localeKey), + (e) => e.toString() == _sharedPreferences.getString(localeKey), orElse: () => SupportedLocale.en, ); - set locale(SupportedLocale value) => _sharedPreferences.setString(_localeKey, value.toString()); + set locale(SupportedLocale value) => _sharedPreferences.setString(localeKey, value.toString()); - double get cameraEvCalibration => _sharedPreferences.getDouble(_cameraEvCalibrationKey) ?? 0.0; + double get cameraEvCalibration => _sharedPreferences.getDouble(cameraEvCalibrationKey) ?? 0.0; set cameraEvCalibration(double value) => - _sharedPreferences.setDouble(_cameraEvCalibrationKey, value); + _sharedPreferences.setDouble(cameraEvCalibrationKey, value); double get lightSensorEvCalibration => - _sharedPreferences.getDouble(_lightSensorEvCalibrationKey) ?? 0.0; + _sharedPreferences.getDouble(lightSensorEvCalibrationKey) ?? 0.0; set lightSensorEvCalibration(double value) => - _sharedPreferences.setDouble(_lightSensorEvCalibrationKey, value); + _sharedPreferences.setDouble(lightSensorEvCalibrationKey, value); - ThemeType get themeType => ThemeType.values[_sharedPreferences.getInt(_themeTypeKey) ?? 0]; - set themeType(ThemeType value) => _sharedPreferences.setInt(_themeTypeKey, value.index); + ThemeType get themeType => ThemeType.values[_sharedPreferences.getInt(themeTypeKey) ?? 0]; + set themeType(ThemeType value) => _sharedPreferences.setInt(themeTypeKey, value.index); - Color get primaryColor => Color(_sharedPreferences.getInt(_primaryColorKey) ?? 0xff2196f3); - set primaryColor(Color value) => _sharedPreferences.setInt(_primaryColorKey, value.value); + Color get primaryColor => Color(_sharedPreferences.getInt(primaryColorKey) ?? 0xff2196f3); + set primaryColor(Color value) => _sharedPreferences.setInt(primaryColorKey, value.value); - bool get dynamicColor => _sharedPreferences.getBool(_dynamicColorKey) ?? false; - set dynamicColor(bool value) => _sharedPreferences.setBool(_dynamicColorKey, value); + bool get dynamicColor => _sharedPreferences.getBool(dynamicColorKey) ?? false; + set dynamicColor(bool value) => _sharedPreferences.setBool(dynamicColorKey, value); Film get film => Film.values.firstWhere( - (e) => e.name == _sharedPreferences.getString(_filmKey), + (e) => e.name == _sharedPreferences.getString(filmKey), orElse: () => Film.values.first, ); - set film(Film value) => _sharedPreferences.setString(_filmKey, value.name); + set film(Film value) => _sharedPreferences.setString(filmKey, value.name); String get selectedEquipmentProfileId => ''; set selectedEquipmentProfileId(String id) {} diff --git a/test/data/shared_prefs_service_test.dart b/test/data/shared_prefs_service_test.dart new file mode 100644 index 0000000..e2b1088 --- /dev/null +++ b/test/data/shared_prefs_service_test.dart @@ -0,0 +1,326 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:lightmeter/data/models/ev_source_type.dart'; +import 'package:lightmeter/data/models/film.dart'; +import 'package:lightmeter/data/models/metering_screen_layout_config.dart'; +import 'package:lightmeter/data/models/supported_locale.dart'; +import 'package:lightmeter/data/models/theme_type.dart'; +import 'package:lightmeter/data/shared_prefs_service.dart'; +import 'package:lightmeter/providers/theme_provider.dart'; +import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class _MockSharedPreferences extends Mock implements SharedPreferences {} + +void main() { + late _MockSharedPreferences sharedPreferences; + late UserPreferencesService service; + + setUpAll(() { + sharedPreferences = _MockSharedPreferences(); + service = UserPreferencesService(sharedPreferences); + }); + + group('iso', () { + test('get default', () { + when(() => sharedPreferences.getInt(UserPreferencesService.isoKey)).thenReturn(null); + expect(service.iso, const IsoValue(100, StopType.full)); + }); + + test('get', () { + when(() => sharedPreferences.getInt(UserPreferencesService.isoKey)).thenReturn(100); + expect(service.iso, const IsoValue(100, StopType.full)); + }); + + test('set', () { + when(() => sharedPreferences.setInt(UserPreferencesService.isoKey, 200)) + .thenAnswer((_) => Future.value(true)); + service.iso = const IsoValue(200, StopType.full); + verify(() => sharedPreferences.setInt(UserPreferencesService.isoKey, 200)).called(1); + }); + }); + + group('ndFilter', () { + test('get default', () { + when(() => sharedPreferences.getInt(UserPreferencesService.ndFilterKey)).thenReturn(null); + expect(service.ndFilter, const NdValue(0)); + }); + + test('get', () { + when(() => sharedPreferences.getInt(UserPreferencesService.ndFilterKey)).thenReturn(4); + expect(service.ndFilter, const NdValue(4)); + }); + + test('set', () { + when(() => sharedPreferences.setInt(UserPreferencesService.ndFilterKey, 0)) + .thenAnswer((_) => Future.value(true)); + service.ndFilter = const NdValue(0); + verify(() => sharedPreferences.setInt(UserPreferencesService.ndFilterKey, 0)).called(1); + }); + }); + + group('evSourceType', () { + test('get default', () { + when(() => sharedPreferences.getInt(UserPreferencesService.evSourceTypeKey)).thenReturn(null); + expect(service.evSourceType, EvSourceType.camera); + }); + + test('get', () { + when(() => sharedPreferences.getInt(UserPreferencesService.evSourceTypeKey)).thenReturn(1); + expect(service.evSourceType, EvSourceType.sensor); + }); + + test('set', () { + when(() => sharedPreferences.setInt(UserPreferencesService.evSourceTypeKey, 1)) + .thenAnswer((_) => Future.value(true)); + service.evSourceType = EvSourceType.sensor; + verify(() => sharedPreferences.setInt(UserPreferencesService.evSourceTypeKey, 1)).called(1); + }); + }); + + group('caffeine', () { + test('get default', () { + when(() => sharedPreferences.getBool(UserPreferencesService.caffeineKey)).thenReturn(null); + expect(service.caffeine, false); + }); + + test('get', () { + when(() => sharedPreferences.getBool(UserPreferencesService.caffeineKey)).thenReturn(true); + expect(service.caffeine, true); + }); + + test('set', () { + when(() => sharedPreferences.setBool(UserPreferencesService.caffeineKey, false)) + .thenAnswer((_) => Future.value(true)); + service.caffeine = false; + verify(() => sharedPreferences.setBool(UserPreferencesService.caffeineKey, false)).called(1); + }); + }); + + group('meteringScreenLayout', () { + test('get default', () { + when( + () => sharedPreferences.getString(UserPreferencesService.meteringScreenLayoutKey), + ).thenReturn(null); + expect( + service.meteringScreenLayout, + { + MeteringScreenLayoutFeature.extremeExposurePairs: true, + MeteringScreenLayoutFeature.filmPicker: true, + }, + ); + }); + + test('get', () { + when( + () => sharedPreferences.getString(UserPreferencesService.meteringScreenLayoutKey), + ).thenReturn("""{"0":false,"1":true}"""); + expect( + service.meteringScreenLayout, + { + MeteringScreenLayoutFeature.extremeExposurePairs: false, + MeteringScreenLayoutFeature.filmPicker: true, + }, + ); + }); + + test('set', () { + when( + () => sharedPreferences.setString( + UserPreferencesService.meteringScreenLayoutKey, + """{"0":false,"1":true}""", + ), + ).thenAnswer((_) => Future.value(true)); + service.meteringScreenLayout = { + MeteringScreenLayoutFeature.extremeExposurePairs: false, + MeteringScreenLayoutFeature.filmPicker: true, + }; + verify( + () => sharedPreferences.setString( + UserPreferencesService.meteringScreenLayoutKey, + """{"0":false,"1":true}""", + ), + ).called(1); + }); + }); + + group('haptics', () { + test('get default', () { + when(() => sharedPreferences.getBool(UserPreferencesService.hapticsKey)).thenReturn(null); + expect(service.haptics, true); + }); + + test('get', () { + when(() => sharedPreferences.getBool(UserPreferencesService.hapticsKey)).thenReturn(true); + expect(service.haptics, true); + }); + + test('set', () { + when(() => sharedPreferences.setBool(UserPreferencesService.hapticsKey, false)) + .thenAnswer((_) => Future.value(true)); + service.haptics = false; + verify(() => sharedPreferences.setBool(UserPreferencesService.hapticsKey, false)).called(1); + }); + }); + + group('locale', () { + test('get default', () { + when(() => sharedPreferences.getString(UserPreferencesService.localeKey)).thenReturn(null); + expect(service.locale, SupportedLocale.en); + }); + + test('get', () { + when(() => sharedPreferences.getString(UserPreferencesService.localeKey)) + .thenReturn('SupportedLocale.ru'); + expect(service.locale, SupportedLocale.ru); + }); + + test('set', () { + when( + () => sharedPreferences.setString(UserPreferencesService.localeKey, 'SupportedLocale.en'), + ).thenAnswer((_) => Future.value(true)); + service.locale = SupportedLocale.en; + verify( + () => sharedPreferences.setString(UserPreferencesService.localeKey, 'SupportedLocale.en'), + ).called(1); + }); + }); + + group('cameraEvCalibration', () { + test('get default', () { + when(() => sharedPreferences.getDouble(UserPreferencesService.cameraEvCalibrationKey)) + .thenReturn(null); + expect(service.cameraEvCalibration, 0.0); + }); + + test('get', () { + when(() => sharedPreferences.getDouble(UserPreferencesService.cameraEvCalibrationKey)) + .thenReturn(2.0); + expect(service.cameraEvCalibration, 2.0); + }); + + test('set', () { + when( + () => sharedPreferences.setDouble(UserPreferencesService.cameraEvCalibrationKey, 1.0), + ).thenAnswer((_) => Future.value(true)); + service.cameraEvCalibration = 1.0; + verify( + () => sharedPreferences.setDouble(UserPreferencesService.cameraEvCalibrationKey, 1.0), + ).called(1); + }); + }); + + group('lightSensorEvCalibration', () { + test('get default', () { + when(() => sharedPreferences.getDouble(UserPreferencesService.lightSensorEvCalibrationKey)) + .thenReturn(null); + expect(service.lightSensorEvCalibration, 0.0); + }); + + test('get', () { + when(() => sharedPreferences.getDouble(UserPreferencesService.lightSensorEvCalibrationKey)) + .thenReturn(2.0); + expect(service.lightSensorEvCalibration, 2.0); + }); + + test('set', () { + when( + () => sharedPreferences.setDouble(UserPreferencesService.lightSensorEvCalibrationKey, 1.0), + ).thenAnswer((_) => Future.value(true)); + service.lightSensorEvCalibration = 1.0; + verify( + () => sharedPreferences.setDouble(UserPreferencesService.lightSensorEvCalibrationKey, 1.0), + ).called(1); + }); + }); + + group('themeType', () { + test('get default', () { + when(() => sharedPreferences.getInt(UserPreferencesService.themeTypeKey)).thenReturn(null); + expect(service.themeType, ThemeType.light); + }); + + test('get', () { + when(() => sharedPreferences.getInt(UserPreferencesService.themeTypeKey)).thenReturn(1); + expect(service.themeType, ThemeType.dark); + }); + + test('set', () { + when( + () => sharedPreferences.setInt(UserPreferencesService.themeTypeKey, 1), + ).thenAnswer((_) => Future.value(true)); + service.themeType = ThemeType.dark; + verify( + () => sharedPreferences.setInt(UserPreferencesService.themeTypeKey, 1), + ).called(1); + }); + }); + + group('primaryColor', () { + test('get default', () { + when(() => sharedPreferences.getInt(UserPreferencesService.primaryColorKey)).thenReturn(null); + expect(service.primaryColor, ThemeProvider.primaryColorsList[5]); + }); + + test('get', () { + when(() => sharedPreferences.getInt(UserPreferencesService.primaryColorKey)) + .thenReturn(0xff9c27b0); + expect(service.primaryColor, ThemeProvider.primaryColorsList[2]); + }); + + test('set', () { + when( + () => sharedPreferences.setInt(UserPreferencesService.primaryColorKey, 0xff000000), + ).thenAnswer((_) => Future.value(true)); + service.primaryColor = Colors.black; + verify( + () => sharedPreferences.setInt(UserPreferencesService.primaryColorKey, 0xff000000), + ).called(1); + }); + }); + + group('dynamicColor', () { + test('get default', () { + when(() => sharedPreferences.getBool(UserPreferencesService.dynamicColorKey)) + .thenReturn(null); + expect(service.dynamicColor, false); + }); + + test('get', () { + when(() => sharedPreferences.getBool(UserPreferencesService.dynamicColorKey)) + .thenReturn(true); + expect(service.dynamicColor, true); + }); + + test('set', () { + when(() => sharedPreferences.setBool(UserPreferencesService.dynamicColorKey, false)) + .thenAnswer((_) => Future.value(true)); + service.dynamicColor = false; + verify(() => sharedPreferences.setBool(UserPreferencesService.dynamicColorKey, false)) + .called(1); + }); + }); + + group('film', () { + test('get default', () { + when(() => sharedPreferences.getString(UserPreferencesService.filmKey)).thenReturn(null); + expect(service.film, Film.values.first); + }); + + test('get', () { + when(() => sharedPreferences.getString(UserPreferencesService.filmKey)) + .thenReturn('Fomapan ACTION 400'); + expect(service.film, const FomapanFilm.action400()); + }); + + test('set', () { + when(() => sharedPreferences.setString(UserPreferencesService.filmKey, 'Fomapan ACTION 400')) + .thenAnswer((_) => Future.value(true)); + service.film = const FomapanFilm.action400(); + verify( + () => sharedPreferences.setString(UserPreferencesService.filmKey, 'Fomapan ACTION 400'), + ).called(1); + }); + }); +}