diff --git a/integration_test/e2e_test.dart b/integration_test/e2e_test.dart index a5b43c3..88edb94 100644 --- a/integration_test/e2e_test.dart +++ b/integration_test/e2e_test.dart @@ -47,7 +47,11 @@ void testE2E(String description) { testWidgets( description, (tester) async { - await tester.pumpApplication(equipmentProfiles: [], filmsInUse: []); + await tester.pumpApplication( + equipmentProfiles: [], + predefinedFilms: mockFilms.toFilmsMap(isUsed: true), + customFilms: {}, + ); /// Create Praktica + Zenitar profile from scratch await tester.openSettings(); @@ -76,11 +80,6 @@ void testE2E(String description) { expect(find.text('f/3.5 - f/22'), findsOneWidget); expect(find.text('1/1000 - B'), findsNWidgets(2)); await tester.navigatorPop(); - - /// Select some films - await tester.tap(find.text(S.current.filmsInUse)); - await tester.pumpAndSettle(); - await tester.setDialogFilterValues([mockFilms[0], mockFilms[1]], deselectAll: false); await tester.navigatorPop(); /// Select some initial settings according to the selected gear and film diff --git a/integration_test/metering_screen_layout_test.dart b/integration_test/metering_screen_layout_test.dart index ec2ce7b..1d29f73 100644 --- a/integration_test/metering_screen_layout_test.dart +++ b/integration_test/metering_screen_layout_test.dart @@ -135,7 +135,7 @@ void testToggleLayoutFeatures(String description) { testWidgets( 'Film picker', (tester) async { - await tester.pumpApplication(selectedFilm: mockFilms.first); + await tester.pumpApplication(selectedFilmId: mockFilms.first.id); await tester.takePhoto(); expectPickerTitle(mockFilms.first.name); expectExtremeExposurePairs('f/1.0 - 1/320', 'f/45 - 12"'); diff --git a/integration_test/mocks/paid_features_mock.dart b/integration_test/mocks/paid_features_mock.dart index 161a338..42d2b33 100644 --- a/integration_test/mocks/paid_features_mock.dart +++ b/integration_test/mocks/paid_features_mock.dart @@ -7,24 +7,27 @@ import 'package:mocktail/mocktail.dart'; class _MockIAPStorageService extends Mock implements IAPStorageService {} +class _MockFilmsStorageService extends Mock implements FilmsStorageService {} + class MockIAPProviders extends StatefulWidget { final List? equipmentProfiles; final String selectedEquipmentProfileId; - final List availableFilms; - final List filmsInUse; - final Film selectedFilm; + final Map> predefinedFilms; + final Map> customFilms; + final String selectedFilmId; final Widget child; - const MockIAPProviders({ + MockIAPProviders({ this.equipmentProfiles = const [], this.selectedEquipmentProfileId = '', - List? availableFilms, - List? filmsInUse, - this.selectedFilm = const FilmStub(), + Map>? predefinedFilms, + Map>? customFilms, + String? selectedFilmId, required this.child, super.key, - }) : availableFilms = availableFilms ?? mockFilms, - filmsInUse = filmsInUse ?? mockFilms; + }) : predefinedFilms = predefinedFilms ?? mockFilms.toFilmsMap(), + customFilms = customFilms ?? mockFilms.toFilmsMap(), + selectedFilmId = selectedFilmId ?? const FilmStub().id; @override State createState() => _MockIAPProvidersState(); @@ -32,6 +35,7 @@ class MockIAPProviders extends StatefulWidget { class _MockIAPProvidersState extends State { late final _MockIAPStorageService mockIAPStorageService; + late final _MockFilmsStorageService mockFilmsStorageService; @override void initState() { @@ -39,8 +43,11 @@ class _MockIAPProvidersState extends State { mockIAPStorageService = _MockIAPStorageService(); when(() => mockIAPStorageService.equipmentProfiles).thenReturn(widget.equipmentProfiles ?? mockEquipmentProfiles); when(() => mockIAPStorageService.selectedEquipmentProfileId).thenReturn(widget.selectedEquipmentProfileId); - when(() => mockIAPStorageService.filmsInUse).thenReturn(widget.filmsInUse); - when(() => mockIAPStorageService.selectedFilm).thenReturn(widget.selectedFilm); + + mockFilmsStorageService = _MockFilmsStorageService(); + when(() => mockFilmsStorageService.getPredefinedFilms()).thenAnswer((_) => Future.value(widget.predefinedFilms)); + when(() => mockFilmsStorageService.getCustomFilms()).thenAnswer((_) => Future.value(widget.customFilms)); + when(() => mockFilmsStorageService.selectedFilmId).thenReturn(widget.selectedFilmId); } @override @@ -48,8 +55,7 @@ class _MockIAPProvidersState extends State { return EquipmentProfileProvider( storageService: mockIAPStorageService, child: FilmsProvider( - storageService: mockIAPStorageService, - availableFilms: widget.availableFilms, + filmsStorageService: mockFilmsStorageService, child: widget.child, ), ); @@ -129,8 +135,51 @@ final mockEquipmentProfiles = [ ]; const mockFilms = [ - FilmExponential(id: '1', name: 'Mock film 1', iso: 100, exponent: 1.34), - FilmExponential(id: '2', name: 'Mock film 2', iso: 400, exponent: 1.34), - FilmExponential(id: '3', name: 'Mock film 3', iso: 800, exponent: 1.34), - FilmExponential(id: '4', name: 'Mock film 4', iso: 1200, exponent: 1.34), + FilmMultiplying(id: '1', name: 'Mock film 1', iso: 100, reciprocityMultiplier: 2), + FilmMultiplying(id: '2', name: 'Mock film 2', iso: 400, reciprocityMultiplier: 2), + FilmMultiplying(id: '3', name: 'Mock film 3', iso: 800, reciprocityMultiplier: 3), + FilmMultiplying(id: '4', name: 'Mock film 4', iso: 1200, reciprocityMultiplier: 1.5), ]; + +extension FilmMapper on List { + Map toFilmsMap({bool isUsed = true}) => + Map.fromEntries(map((e) => MapEntry(e.id, (film: e as T, isUsed: isUsed)))); +} + +class FilmMultiplying extends FilmExponential { + final double reciprocityMultiplier; + + const FilmMultiplying({ + String? id, + required super.name, + required super.iso, + required this.reciprocityMultiplier, + }) : super(id: id ?? name, exponent: 1); + + @override + ShutterSpeedValue reciprocityFailure(ShutterSpeedValue shutterSpeed) { + if (shutterSpeed.isFraction) { + return shutterSpeed; + } else { + return ShutterSpeedValue( + shutterSpeed.rawValue * reciprocityMultiplier, + shutterSpeed.isFraction, + shutterSpeed.stopType, + ); + } + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + if (other.runtimeType != runtimeType) return false; + return other is FilmMultiplying && + other.id == id && + other.name == name && + other.iso == iso && + other.reciprocityMultiplier == reciprocityMultiplier; + } + + @override + int get hashCode => Object.hash(id, name, iso, reciprocityMultiplier, runtimeType); +} diff --git a/integration_test/utils/widget_tester_actions.dart b/integration_test/utils/widget_tester_actions.dart index de58c29..8ff2bb4 100644 --- a/integration_test/utils/widget_tester_actions.dart +++ b/integration_test/utils/widget_tester_actions.dart @@ -22,9 +22,9 @@ extension WidgetTesterCommonActions on WidgetTester { IAPProductStatus productStatus = IAPProductStatus.purchased, List? equipmentProfiles, String selectedEquipmentProfileId = '', - List? availableFilms, - List? filmsInUse, - Film selectedFilm = const FilmStub(), + Map>? predefinedFilms, + Map>? customFilms, + String selectedFilmId = '', }) async { await pumpWidget( MockIAPProductsProvider( @@ -34,9 +34,9 @@ extension WidgetTesterCommonActions on WidgetTester { child: MockIAPProviders( equipmentProfiles: equipmentProfiles, selectedEquipmentProfileId: selectedEquipmentProfileId, - availableFilms: availableFilms, - filmsInUse: filmsInUse, - selectedFilm: selectedFilm, + predefinedFilms: predefinedFilms, + customFilms: customFilms, + selectedFilmId: selectedFilmId, child: const Application(), ), ), diff --git a/screenshots/generate_screenshots.dart b/screenshots/generate_screenshots.dart index dd89d77..77ad568 100644 --- a/screenshots/generate_screenshots.dart +++ b/screenshots/generate_screenshots.dart @@ -92,9 +92,9 @@ void main() { testWidgets('Generate light theme screenshots', (tester) async { await mockSharedPrefs(theme: ThemeType.light, color: _lightThemeColor); await tester.pumpApplication( - availableFilms: [_mockFilm], - filmsInUse: [_mockFilm], - selectedFilm: _mockFilm, + predefinedFilms: [_mockFilm].toFilmsMap(), + customFilms: {}, + selectedFilmId: _mockFilm.id, ); await tester.takePhoto(); @@ -132,9 +132,9 @@ void main() { (tester) async { await mockSharedPrefs(theme: ThemeType.dark, color: _darkThemeColor); await tester.pumpApplication( - availableFilms: [_mockFilm], - filmsInUse: [_mockFilm], - selectedFilm: _mockFilm, + predefinedFilms: [_mockFilm].toFilmsMap(), + customFilms: {}, + selectedFilmId: _mockFilm.id, ); await tester.takePhoto(); @@ -157,9 +157,9 @@ void main() { color: _lightThemeColor, ); await tester.pumpApplication( - availableFilms: [_mockFilm], - filmsInUse: [_mockFilm], - selectedFilm: _mockFilm, + predefinedFilms: [_mockFilm].toFilmsMap(), + customFilms: {}, + selectedFilmId: _mockFilm.id, ); await tester.takePhoto(); diff --git a/test/application_mock.dart b/test/application_mock.dart index a7882cc..f9644c4 100644 --- a/test/application_mock.dart +++ b/test/application_mock.dart @@ -99,7 +99,7 @@ class _GoldenTestApplicationMockState extends State { child: MockIAPProviders( equipmentProfiles: mockEquipmentProfiles, selectedEquipmentProfileId: mockEquipmentProfiles.first.id, - selectedFilm: mockFilms.first, + selectedFilmId: mockFilms.first.id, child: Builder( builder: (context) { return MaterialApp(