diff --git a/integration_test/e2e_test.dart b/integration_test/e2e_test.dart index 97022f1..6491b63 100644 --- a/integration_test/e2e_test.dart +++ b/integration_test/e2e_test.dart @@ -7,6 +7,7 @@ import 'package:lightmeter/data/models/metering_screen_layout_config.dart'; import 'package:lightmeter/data/shared_prefs_service.dart'; import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/res/dimens.dart'; +import 'package:lightmeter/screens/equipment_profiles/components/equipment_profile_type_picker/widget_picker_equipment_profile_type.dart'; import 'package:lightmeter/screens/metering/components/bottom_controls/widget_bottom_controls.dart'; import 'package:lightmeter/screens/metering/components/shared/readings_container/components/equipment_profile_picker/widget_picker_equipment_profiles.dart'; import 'package:lightmeter/screens/metering/components/shared/readings_container/components/film_picker/widget_picker_film.dart'; @@ -56,8 +57,7 @@ void testE2E(String description) { /// Create Praktica + Zenitar profile from scratch await tester.openSettings(); await tester.tapDescendantTextOf(S.current.equipmentProfiles); - await tester.tap(find.byIcon(Icons.add_outlined).first); - await tester.pumpAndSettle(); + await tester.addEquipmentProfile(EquipmentProfileType.regular); await tester.enterProfileName(mockEquipmentProfiles[0].name); await tester.setIsoValues(mockEquipmentProfiles[0].isoValues); await tester.setNdValues(mockEquipmentProfiles[0].ndValues); @@ -70,8 +70,7 @@ void testE2E(String description) { await tester.saveEdits(); /// Create Praktica + Jupiter profile from Zenitar profile - await tester.tap(find.byIcon(Icons.edit_outlined)); - await tester.pumpAndSettle(); + await tester.editEquipmentProfile(mockEquipmentProfiles[1].name); await tester.tap(find.byIcon(Icons.copy_outlined).first); await tester.pumpAndSettle(); await tester.enterProfileName(mockEquipmentProfiles[1].name); @@ -90,7 +89,7 @@ void testE2E(String description) { /// Select some initial settings according to the selected gear and film /// Then take a photo and verify, that exposure pairs range and EV matches the selected settings - await tester.openPickerAndSelect(mockEquipmentProfiles[0].name); + await tester.openPickerAndSelect(mockEquipmentProfiles[0].name); await tester.openPickerAndSelect(mockFilms[0].name); await tester.openPickerAndSelect('400'); expectPickerTitle(mockEquipmentProfiles[0].name); @@ -122,7 +121,7 @@ void testE2E(String description) { // ); /// Select another lens without ND - await tester.openPickerAndSelect(mockEquipmentProfiles[1].name); + await tester.openPickerAndSelect(mockEquipmentProfiles[1].name); await tester.openPickerAndSelect('None'); await _expectMeteringStateAndMeasure( tester, @@ -152,8 +151,7 @@ void testE2E(String description) { /// Delete profile await tester.openSettings(); await tester.tapDescendantTextOf(S.current.equipmentProfiles); - await tester.tap(find.byIcon(Icons.edit_outlined).first); - await tester.pumpAndSettle(); + await tester.editEquipmentProfile(mockEquipmentProfiles[0].name); await tester.deleteEdits(); expect(find.text(mockEquipmentProfiles[0].name), findsNothing); expect(find.text(mockEquipmentProfiles[1].name), findsOneWidget); diff --git a/integration_test/guard_pro_tap_test.dart b/integration_test/guard_pro_tap_test.dart index cb2a292..e180a8a 100644 --- a/integration_test/guard_pro_tap_test.dart +++ b/integration_test/guard_pro_tap_test.dart @@ -6,7 +6,7 @@ import 'package:lightmeter/data/models/ev_source_type.dart'; import 'package:lightmeter/data/models/metering_screen_layout_config.dart'; import 'package:lightmeter/data/shared_prefs_service.dart'; import 'package:lightmeter/generated/l10n.dart'; -import 'package:lightmeter/screens/equipment_profile_edit/screen_equipment_profile_edit.dart'; +import 'package:lightmeter/screens/equipment_profiles/components/equipment_profile_type_picker/widget_picker_equipment_profile_type.dart'; import 'package:lightmeter/screens/lightmeter_pro/screen_lightmeter_pro.dart'; import 'package:lightmeter/screens/logbook_photos/screen_logbook_photos.dart'; import 'package:lightmeter/screens/settings/screen_settings.dart'; @@ -49,7 +49,7 @@ void testGuardProTap(String description) { await tester.navigatorPop(true); await tester.pumpAndSettle(); expect(find.byType(LightmeterProScreen), findsNothing); - expect(find.byType(EquipmentProfileEditScreen), findsOneWidget); + expect(find.byType(EquipmentProfilesTypePicker), findsOneWidget); await tester.navigatorPop(); await tester.navigatorPop(); diff --git a/integration_test/logbook_test.dart b/integration_test/logbook_test.dart index f51ef11..546d2c7 100644 --- a/integration_test/logbook_test.dart +++ b/integration_test/logbook_test.dart @@ -104,8 +104,7 @@ void testLogbook(String description) { /// Got back and delete the equipment profile used to take the first picture await tester.navigatorPop(); await tester.tapDescendantTextOf(S.current.equipmentProfiles); - await tester.tap(find.byIcon(Icons.edit_outlined).first); - await tester.pumpAndSettle(); + await tester.editEquipmentProfile(mockEquipmentProfiles.first.name); await tester.tap(find.byIcon(Icons.delete_outlined)); await tester.pumpAndSettle(Dimens.durationML); expect(find.text(mockEquipmentProfiles[0].name), findsNothing); diff --git a/integration_test/mocks/paid_features_mock.dart b/integration_test/mocks/paid_features_mock.dart index 5a33209..d7fbd83 100644 --- a/integration_test/mocks/paid_features_mock.dart +++ b/integration_test/mocks/paid_features_mock.dart @@ -123,6 +123,9 @@ const defaultEquipmentProfile = EquipmentProfile( isoValues: IsoValue.values, ); +final mockProfiles = [...mockEquipmentProfiles, ...mockPinholeEquipmentProfiles] + ..sort((a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase())); + final mockEquipmentProfiles = [ EquipmentProfile( id: '1', diff --git a/integration_test/utils/widget_tester_actions.dart b/integration_test/utils/widget_tester_actions.dart index 477f209..dab3835 100644 --- a/integration_test/utils/widget_tester_actions.dart +++ b/integration_test/utils/widget_tester_actions.dart @@ -5,6 +5,7 @@ import 'package:lightmeter/application_wrapper.dart'; import 'package:lightmeter/environment.dart'; import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/res/dimens.dart'; +import 'package:lightmeter/screens/equipment_profiles/components/equipment_profile_type_picker/widget_picker_equipment_profile_type.dart'; import 'package:lightmeter/screens/metering/components/shared/exposure_pairs_list/widget_list_exposure_pairs.dart'; import 'package:lightmeter/screens/metering/screen_metering.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; @@ -117,3 +118,24 @@ extension WidgetTesterExposurePairsListActions on WidgetTester { ); } } + +extension WidgetTesterEquipmentProfilesActions on WidgetTester { + Future addEquipmentProfile(EquipmentProfileType type) async { + await tap(find.byIcon(Icons.add_outlined).first); + await pumpAndSettle(); + await tap( + find.text( + switch (type) { + EquipmentProfileType.regular => S.current.camera, + EquipmentProfileType.pinhole => S.current.pinholeCamera, + }, + ), + ); + await tapSelectButton(); + } + + Future editEquipmentProfile(String name) async { + await tap(find.byIcon(Icons.edit_outlined).at(mockProfiles.indexWhere((p) => p.name == name))); + await pumpAndSettle(); + } +} diff --git a/lib/screens/equipment_profiles/components/equipment_profile_type_picker/widget_picker_equipment_profile_type.dart b/lib/screens/equipment_profiles/components/equipment_profile_type_picker/widget_picker_equipment_profile_type.dart new file mode 100644 index 0000000..8857bab --- /dev/null +++ b/lib/screens/equipment_profiles/components/equipment_profile_type_picker/widget_picker_equipment_profile_type.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:lightmeter/generated/l10n.dart'; +import 'package:lightmeter/screens/settings/components/shared/dialog_picker/widget_dialog_picker.dart'; + +enum EquipmentProfileType { regular, pinhole } + +class EquipmentProfilesTypePicker extends StatelessWidget { + const EquipmentProfilesTypePicker._(); + + static Future show(BuildContext context) { + return showDialog( + context: context, + builder: (_) => const EquipmentProfilesTypePicker._(), + ); + } + + @override + Widget build(BuildContext context) { + return DialogPicker( + icon: Icons.camera_alt_outlined, + title: S.of(context).equipmentProfileType, + selectedValue: EquipmentProfileType.regular, + values: EquipmentProfileType.values, + titleAdapter: (context, value) => switch (value) { + EquipmentProfileType.regular => S.of(context).camera, + EquipmentProfileType.pinhole => S.of(context).pinholeCamera, + }, + ); + } +} diff --git a/lib/screens/equipment_profiles/screen_equipment_profiles.dart b/lib/screens/equipment_profiles/screen_equipment_profiles.dart index 1784a41..4494541 100644 --- a/lib/screens/equipment_profiles/screen_equipment_profiles.dart +++ b/lib/screens/equipment_profiles/screen_equipment_profiles.dart @@ -4,14 +4,12 @@ import 'package:lightmeter/navigation/routes.dart'; import 'package:lightmeter/providers/equipment_profile_provider.dart'; import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/screens/equipment_profile_edit/flow_equipment_profile_edit.dart'; -import 'package:lightmeter/screens/settings/components/shared/dialog_picker/widget_dialog_picker.dart'; +import 'package:lightmeter/screens/equipment_profiles/components/equipment_profile_type_picker/widget_picker_equipment_profile_type.dart'; import 'package:lightmeter/screens/shared/sliver_placeholder/widget_sliver_placeholder.dart'; import 'package:lightmeter/screens/shared/sliver_screen/screen_sliver.dart'; import 'package:lightmeter/utils/guard_pro_tap.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; -enum _EquipmentProfileType { regular, pinhole } - class EquipmentProfilesScreen extends StatefulWidget { const EquipmentProfilesScreen({super.key}); @@ -48,28 +46,16 @@ class _EquipmentProfilesScreenState extends State with guardProTap( context, () { - showDialog<_EquipmentProfileType>( - context: context, - builder: (_) => DialogPicker<_EquipmentProfileType>( - icon: Icons.camera_alt_outlined, - title: S.of(context).equipmentProfileType, - selectedValue: _EquipmentProfileType.regular, - values: _EquipmentProfileType.values, - titleAdapter: (context, value) => switch (value) { - _EquipmentProfileType.regular => S.of(context).camera, - _EquipmentProfileType.pinhole => S.of(context).pinholeCamera, - }, - ), - ).then((value) { + EquipmentProfilesTypePicker.show(context).then((value) { if (value != null && mounted) { Navigator.of(context).pushNamed( NavigationRoutes.equipmentProfileEditScreen.name, arguments: switch (value) { - _EquipmentProfileType.regular => const EquipmentProfileEditArgs( + EquipmentProfileType.regular => const EquipmentProfileEditArgs( editType: EquipmentProfileEditType.add, profile: EquipmentProfilesProvider.defaultProfile, ), - _EquipmentProfileType.pinhole => EquipmentProfileEditArgs( + EquipmentProfileType.pinhole => EquipmentProfileEditArgs( editType: EquipmentProfileEditType.add, profile: PinholeEquipmentProfile( id: EquipmentProfilesProvider.defaultProfile.id, diff --git a/screenshots/generate_screenshots.dart b/screenshots/generate_screenshots.dart index c80575f..4c5cfce 100644 --- a/screenshots/generate_screenshots.dart +++ b/screenshots/generate_screenshots.dart @@ -218,14 +218,9 @@ void main() { testWidgets( 'Generate timer screenshot', (tester) async { - const timerExposurePair = ExposurePair( - ApertureValue(16, StopType.full), - ShutterSpeedValue(8, false, StopType.full), - ); await mockSharedPrefs( - iso: 100, nd: 8, - calibration: -0.3, + calibration: -2.3, theme: ThemeType.light, color: _lightThemeColor, ); @@ -236,13 +231,22 @@ void main() { ); await tester.takePhoto(); - await tester.scrollToExposurePair( - ev: 5, - exposurePair: timerExposurePair, + + final exposurePairs = MeteringContainerBuidler.buildExposureValues( + 5, + StopType.third, + defaultEquipmentProfile, ); - await tester.tap(find.text(_mockFilm.reciprocityFailure(timerExposurePair.shutterSpeed).toString())); + final timerExposurePair = exposurePairs.firstWhere((e) => e.aperture == const ApertureValue(16, StopType.full)); + await tester.scrollToExposurePair( + exposurePairs: exposurePairs, + exposurePair: exposurePairs.firstWhere((e) => e.aperture == const ApertureValue(16, StopType.full)), + ); + + final correctedShutterSpeed = _mockFilm.reciprocityFailure(timerExposurePair.shutterSpeed); + await tester.tap(find.text(correctedShutterSpeed.toString())); await tester.pumpAndSettle(); - await tester.mockTimerResumedState(timerExposurePair.shutterSpeed); + await tester.mockTimerResumedState(correctedShutterSpeed); await tester.takeScreenshotLight(binding, 'timer'); }, ); @@ -257,32 +261,28 @@ extension on WidgetTester { _takeScreenshot(binding, name, _themeDark); Future _takeScreenshot(IntegrationTestWidgetsFlutterBinding binding, String name, ThemeData theme) async { - final Color backgroundColor = theme.colorScheme.surface; - await binding.takeScreenshot( - ScreenshotArgs( - name: name, - deviceName: const String.fromEnvironment('deviceName'), - platformFolder: _platformFolder, - backgroundColor: backgroundColor.toInt().toRadixString(16), - isDark: theme.brightness == Brightness.dark, - ).toString(), - ); - await pumpAndSettle(); + const deviceName = String.fromEnvironment('deviceName'); + if (deviceName.isNotEmpty) { + final Color backgroundColor = theme.colorScheme.surface; + await binding.takeScreenshot( + ScreenshotArgs( + name: name, + deviceName: deviceName, + platformFolder: _platformFolder, + backgroundColor: backgroundColor.toInt().toRadixString(16), + isDark: theme.brightness == Brightness.dark, + ).toString(), + ); + await pumpAndSettle(); + } } } extension on WidgetTester { Future scrollToExposurePair({ - double ev = mockPhotoEv100, - EquipmentProfile equipmentProfile = defaultEquipmentProfile, + required List exposurePairs, required ExposurePair exposurePair, }) async { - final exposurePairs = MeteringContainerBuidler.buildExposureValues( - ev, - StopType.third, - equipmentProfile, - ); - await scrollUntilVisible( find.byWidgetPredicate((widget) => widget is Row && widget.key == ValueKey(exposurePairs.indexOf(exposurePair))), 56,