diff --git a/integration_test/metering_screen_test.dart b/integration_test/metering_screen_test.dart deleted file mode 100644 index 0cfe6fb..0000000 --- a/integration_test/metering_screen_test.dart +++ /dev/null @@ -1,278 +0,0 @@ -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:integration_test/integration_test.dart'; -import 'package:lightmeter/data/models/ev_source_type.dart'; -import 'package:lightmeter/data/models/exposure_pair.dart'; -import 'package:lightmeter/data/shared_prefs_service.dart'; -import 'package:lightmeter/generated/l10n.dart'; -import 'package:lightmeter/screens/metering/components/bottom_controls/components/measure_button/widget_button_measure.dart'; -import 'package:lightmeter/screens/metering/components/camera_container/widget_container_camera.dart'; -import 'package:lightmeter/screens/metering/components/light_sensor_container/widget_container_light_sensor.dart'; -import 'package:lightmeter/screens/metering/components/shared/exposure_pairs_list/widget_list_exposure_pairs.dart'; -import 'package:lightmeter/screens/metering/components/shared/readings_container/components/extreme_exposure_pairs_container/widget_container_extreme_exposure_pairs.dart'; -import 'package:lightmeter/screens/metering/components/shared/readings_container/components/film_picker/widget_picker_film.dart'; -import 'package:lightmeter/screens/metering/components/shared/readings_container/components/iso_picker/widget_picker_iso.dart'; -import 'package:lightmeter/screens/metering/components/shared/readings_container/components/nd_picker/widget_picker_nd.dart'; -import 'package:lightmeter/screens/metering/screen_metering.dart'; -import 'package:lightmeter/screens/shared/icon_placeholder/widget_icon_placeholder.dart'; -import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart'; -import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -import 'mocks/paid_features_mock.dart'; -import 'utils/expectations.dart'; -import 'utils/metering_picker_test.dart'; -import 'utils/platform_channel_mock.dart'; -import 'utils/widget_tester_actions.dart'; - -const defaultIsoValue = IsoValue(100, StopType.full); -const mockPhotoEv100 = 8.3; -const mockPhotoFastestAperture = ApertureValue(1, StopType.full); -const mockPhotoSlowestAperture = ApertureValue(45, StopType.full); -const mockPhotoFastestShutterSpeed = ShutterSpeedValue(320, true, StopType.third); -const mockPhotoSlowestShutterSpeed = ShutterSpeedValue(6, false, StopType.third); -const mockPhotoFastestExposurePair = ExposurePair(mockPhotoFastestAperture, mockPhotoFastestShutterSpeed); -const mockPhotoSlowestExposurePair = ExposurePair(mockPhotoSlowestAperture, mockPhotoSlowestShutterSpeed); - -//https://stackoverflow.com/a/67186625/13167574 -void main() { - IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - - tearDown(() { - SharedPreferences.resetStatic(); - }); - - group( - '[Light sensor availability]', - () { - tearDown(() { - resetLightSensorAvilability(); - }); - - testWidgets( - 'Android - has sensor', - (tester) async { - SharedPreferences.setMockInitialValues({UserPreferencesService.evSourceTypeKey: EvSourceType.sensor.index}); - setLightSensorAvilability(hasSensor: true); - await tester.pumpApplication(productStatus: IAPProductStatus.purchasable); - - /// Verify that [LightSensorContainer] is shown in correspondance with the saved ev source - expect(find.byType(LightSensorContainer), findsOneWidget); - }, - skip: Platform.isIOS, - ); - - testWidgets( - 'Android - no sensor', - (tester) async { - SharedPreferences.setMockInitialValues({UserPreferencesService.evSourceTypeKey: EvSourceType.sensor.index}); - setLightSensorAvilability(hasSensor: false); - await tester.pumpApplication(productStatus: IAPProductStatus.purchasable); - - /// Verify that [CameraContainer] is shown instead of [LightSensorContainer] - expect(find.byType(CameraContainer), findsOneWidget); - - /// and there is no ability to switch to the incident metering - expect(find.byTooltip(S.current.tooltipUseLightSensor), findsNothing); - }, - skip: Platform.isIOS, - ); - - testWidgets( - 'iOS - no sensor', - (tester) async { - SharedPreferences.setMockInitialValues({UserPreferencesService.evSourceTypeKey: EvSourceType.sensor.index}); - await tester.pumpApplication(productStatus: IAPProductStatus.purchasable); - - /// verify no button to switch to the incident light mode - expect(find.byType(CameraContainer), findsOneWidget); - - /// and there is no ability to switch to the incident metering - expect(find.byTooltip(S.current.tooltipUseLightSensor), findsNothing); - }, - skip: Platform.isAndroid, - ); - }, - ); - - group( - '[Match extreme exposure pairs & pairs list edge values]', - () { - Future> scrollToTheLastExposurePair(WidgetTester tester) async { - final exposurePairs = MeteringContainerBuidler.buildExposureValues( - mockPhotoEv100, - StopType.third, - defaultEquipmentProfile, - ); - await tester.scrollUntilVisible( - find.byWidgetPredicate((widget) => widget is Row && widget.key == ValueKey(exposurePairs.length - 1)), - 56, - scrollable: find.descendant(of: find.byType(ExposurePairsList), matching: find.byType(Scrollable)), - ); - return exposurePairs; - } - - void expectExposurePairsListItem(int index, String aperture, String shutterSpeed) { - final firstPairRow = find.byWidgetPredicate((widget) => widget is Row && widget.key == ValueKey(index)); - expect(find.descendant(of: firstPairRow, matching: find.text(aperture)), findsOneWidget); - expect(find.descendant(of: firstPairRow, matching: find.text(shutterSpeed)), findsOneWidget); - } - - setUp(() { - SharedPreferences.setMockInitialValues({UserPreferencesService.evSourceTypeKey: EvSourceType.camera.index}); - }); - - testWidgets( - 'No exposure pairs', - (tester) async { - await tester.pumpApplication(productStatus: IAPProductStatus.purchasable); - - /// Verify that no exposure pairs are shown in [ExtremeExposurePairsContainer] - final pickerFinder = find.byType(ExtremeExposurePairsContainer); - expect(pickerFinder, findsOneWidget); - expect(find.descendant(of: pickerFinder, matching: find.text(S.current.fastestExposurePair)), findsOneWidget); - expect(find.descendant(of: pickerFinder, matching: find.text(S.current.slowestExposurePair)), findsOneWidget); - expect(find.descendant(of: pickerFinder, matching: find.text('-')), findsNWidgets(2)); - - /// Verify that the exposure pairs list is empty - expect( - find.descendant( - of: find.byType(ExposurePairsList), - matching: find.byWidgetPredicate( - (widget) => - widget is IconPlaceholder && - widget.icon == Icons.not_interested && - widget.text == S.current.noExposurePairs, - ), - ), - findsOneWidget, - ); - }, - skip: true, - ); - - testWidgets( - 'Multiple exposure pairs w/o reciprocity', - (tester) async { - await tester.pumpApplication(productStatus: IAPProductStatus.purchasable); - await tester.takePhoto(); - - /// Verify that reciprocity is not applied to the slowest exposure pair in the container - expectExposurePairsContainer('$mockPhotoFastestAperture - 1/320', '$mockPhotoSlowestAperture - 6"'); - expectMeasureButton(mockPhotoEv100); - - /// Verify that reciprocity is not applied to the slowest exposure pair in the list - expectExposurePairsListItem(0, '$mockPhotoFastestAperture', '1/320'); - final exposurePairs = await scrollToTheLastExposurePair(tester); - expectExposurePairsListItem(exposurePairs.length - 1, '$mockPhotoSlowestAperture', '6"'); - expectMeasureButton(mockPhotoEv100); - }, - ); - - testWidgets( - 'Multiple exposure pairs w/ reciprocity', - (tester) async { - await tester.pumpApplication(selectedFilm: mockFilms.first); - await tester.takePhoto(); - - /// Verify that reciprocity is applied to the slowest exposure pair in the container - expectExposurePairsContainer('$mockPhotoFastestAperture - 1/320', '$mockPhotoSlowestAperture - 12"'); - expectMeasureButton(mockPhotoEv100); - - /// Verify that reciprocity is applied to the slowest exposure pair in the list - expectExposurePairsListItem(0, '$mockPhotoFastestAperture', '1/320'); - final exposurePairs = await scrollToTheLastExposurePair(tester); - expectExposurePairsListItem(exposurePairs.length - 1, '$mockPhotoSlowestAperture', '12"'); - expectMeasureButton(mockPhotoEv100); - }, - ); - }, - skip: true, // TODO(@vodemn) move this test to widgets tests - ); - - group( - '[Pickers tests]', - () { - setUpAll(() { - setupLightSensorStreamHandler(); - setLightSensorAvilability(hasSensor: true); - }); - - tearDownAll(() { - resetLightSensorAvilability(); - resetLightSensorStreamHandler(); - }); - - setUp(() { - SharedPreferences.setMockInitialValues({UserPreferencesService.evSourceTypeKey: EvSourceType.sensor.index}); - }); - - group( - 'Select film', - () { - testMeteringPicker( - 'with the same ISO', - expectBefore: MeteringValuesExpectation( - mockPhotoFastestExposurePair.toString(), - mockPhotoSlowestExposurePair.toString(), - mockPhotoEv100, - ), - valueToSelect: mockFilms[0].name, - expectAfter: MeteringValuesExpectation( - mockPhotoFastestExposurePair.toString(), - '$mockPhotoSlowestAperture - ${mockFilms[0].reciprocityFailure(mockPhotoSlowestShutterSpeed)}', - mockPhotoEv100, - ), - ); - - testMeteringPicker( - 'with greater ISO', - expectBefore: MeteringValuesExpectation( - mockPhotoFastestExposurePair.toString(), - mockPhotoSlowestExposurePair.toString(), - mockPhotoEv100, - ), - valueToSelect: mockFilms[1].name, - expectAfter: MeteringValuesExpectation( - mockPhotoFastestExposurePair.toString(), - '$mockPhotoSlowestAperture - ${mockFilms[1].reciprocityFailure(mockPhotoSlowestShutterSpeed)}', - mockPhotoEv100, - ), - ); - }, - ); - - testMeteringPicker( - 'Select ISO +1 EV', - expectBefore: MeteringValuesExpectation( - mockPhotoFastestExposurePair.toString(), - mockPhotoSlowestExposurePair.toString(), - mockPhotoEv100, - ), - valueToSelect: '400', - expectAfter: MeteringValuesExpectation( - '$mockPhotoFastestAperture - 1/1250', - '$mockPhotoSlowestAperture - 1.6"', - mockPhotoEv100 + 2, - ), - ); - - testMeteringPicker( - 'Select ND -1 EV', - expectBefore: MeteringValuesExpectation( - mockPhotoFastestExposurePair.toString(), - mockPhotoSlowestExposurePair.toString(), - mockPhotoEv100, - ), - valueToSelect: '2', - expectAfter: MeteringValuesExpectation( - '$mockPhotoFastestAperture - 1/160', - '$mockPhotoSlowestAperture - 13"', - mockPhotoEv100 - 1, - ), - ); - }, - ); -} diff --git a/integration_test/run_integration_tests.sh b/integration_test/run_integration_tests.sh deleted file mode 100644 index 526c9fb..0000000 --- a/integration_test/run_integration_tests.sh +++ /dev/null @@ -1,17 +0,0 @@ -# https://github.com/flutter/flutter/issues/86295#issuecomment-1192766368 -devices=$(adb devices) -devicesIds=$(echo $devices | grep -Eo '[A-Z0-9]{2,}') -firstDeviceId=$(echo $devicesIds | cut -d " " -f 1) -# adb -s $firstDeviceId shell pm grant com.vodemn.lightmeter.dev android.permission.CAMERA - -flutter drive \ - --dart-define="cameraPreviewAspectRatio=240/320" \ - --dart-define="cameraStubImage=assets/camera_stub_image.jpg" \ - --driver=test_driver/integration_driver.dart \ - --target=integration_test/metering_screen_test.dart \ - --profile \ - --flavor=dev \ - --no-dds \ - --endless-trace-buffer \ - --purge-persistent-cache \ - -d $firstDeviceId \ No newline at end of file diff --git a/integration_test/settings_screen_test.dart b/integration_test/settings_screen_test.dart deleted file mode 100644 index e1b8ca8..0000000 --- a/integration_test/settings_screen_test.dart +++ /dev/null @@ -1,294 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:integration_test/integration_test.dart'; -import 'package:lightmeter/application.dart'; -import 'package:lightmeter/data/caffeine_service.dart'; -import 'package:lightmeter/data/haptics_service.dart'; -import 'package:lightmeter/data/light_sensor_service.dart'; -import 'package:lightmeter/data/models/ev_source_type.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/models/volume_action.dart'; -import 'package:lightmeter/data/permissions_service.dart'; -import 'package:lightmeter/data/shared_prefs_service.dart'; -import 'package:lightmeter/data/volume_events_service.dart'; -import 'package:lightmeter/environment.dart'; -import 'package:lightmeter/generated/l10n.dart'; -import 'package:lightmeter/providers/services_provider.dart'; -import 'package:lightmeter/providers/user_preferences_provider.dart'; -import 'package:lightmeter/res/theme.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/extreme_exposure_pairs_container/widget_container_extreme_exposure_pairs.dart'; -import 'package:lightmeter/screens/metering/components/shared/readings_container/components/film_picker/widget_picker_film.dart'; -import 'package:lightmeter/screens/metering/components/shared/readings_container/components/shared/animated_dialog_picker/components/dialog_picker/widget_picker_dialog.dart'; -import 'package:lightmeter/screens/settings/components/metering/components/metering_screen_layout/components/meterins_screen_layout_features_dialog/widget_dialog_metering_screen_layout_features.dart'; -import 'package:lightmeter/screens/settings/components/shared/dialog_filter/widget_dialog_filter.dart'; -import 'package:lightmeter/screens/settings/screen_settings.dart'; -import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart'; -import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; -import 'package:mocktail/mocktail.dart'; -import 'package:permission_handler/permission_handler.dart'; - -import 'mocks/paid_features_mock.dart'; -import 'utils/expectations.dart'; -import 'utils/widget_tester_actions.dart'; - -class _MockUserPreferencesService extends Mock implements UserPreferencesService {} - -class _MockCaffeineService extends Mock implements CaffeineService {} - -class _MockHapticsService extends Mock implements HapticsService {} - -class _MockPermissionsService extends Mock implements PermissionsService {} - -class _MockLightSensorService extends Mock implements LightSensorService {} - -class _MockVolumeEventsService extends Mock implements VolumeEventsService {} - -const _defaultIsoValue = IsoValue(400, StopType.full); - -//https://stackoverflow.com/a/67186625/13167574 -void main() { - IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - - late _MockUserPreferencesService mockUserPreferencesService; - late _MockCaffeineService mockCaffeineService; - late _MockHapticsService mockHapticsService; - late _MockPermissionsService mockPermissionsService; - late _MockLightSensorService mockLightSensorService; - late _MockVolumeEventsService mockVolumeEventsService; - - setUpAll(() { - mockUserPreferencesService = _MockUserPreferencesService(); - when(() => mockUserPreferencesService.evSourceType).thenReturn(EvSourceType.sensor); - when(() => mockUserPreferencesService.stopType).thenReturn(StopType.third); - when(() => mockUserPreferencesService.locale).thenReturn(SupportedLocale.en); - when(() => mockUserPreferencesService.caffeine).thenReturn(true); - when(() => mockUserPreferencesService.volumeAction).thenReturn(VolumeAction.shutter); - when(() => mockUserPreferencesService.cameraEvCalibration).thenReturn(0.0); - when(() => mockUserPreferencesService.lightSensorEvCalibration).thenReturn(0.0); - when(() => mockUserPreferencesService.iso).thenReturn(_defaultIsoValue); - when(() => mockUserPreferencesService.ndFilter).thenReturn(NdValue.values.first); - when(() => mockUserPreferencesService.haptics).thenReturn(true); - when(() => mockUserPreferencesService.meteringScreenLayout).thenReturn({ - MeteringScreenLayoutFeature.equipmentProfiles: true, - MeteringScreenLayoutFeature.extremeExposurePairs: true, - MeteringScreenLayoutFeature.filmPicker: true, - MeteringScreenLayoutFeature.histogram: true, - }); - when(() => mockUserPreferencesService.themeType).thenReturn(ThemeType.light); - when(() => mockUserPreferencesService.primaryColor).thenReturn(primaryColorsList[5]); - when(() => mockUserPreferencesService.dynamicColor).thenReturn(false); - - mockCaffeineService = _MockCaffeineService(); - when(() => mockCaffeineService.isKeepScreenOn()).thenAnswer((_) async => false); - when(() => mockCaffeineService.keepScreenOn(true)).thenAnswer((_) async => true); - when(() => mockCaffeineService.keepScreenOn(false)).thenAnswer((_) async => false); - - mockHapticsService = _MockHapticsService(); - when(() => mockHapticsService.quickVibration()).thenAnswer((_) async {}); - when(() => mockHapticsService.responseVibration()).thenAnswer((_) async {}); - when(() => mockHapticsService.errorVibration()).thenAnswer((_) async {}); - - mockPermissionsService = _MockPermissionsService(); - when(() => mockPermissionsService.requestCameraPermission()).thenAnswer((_) async => PermissionStatus.granted); - when(() => mockPermissionsService.checkCameraPermission()).thenAnswer((_) async => PermissionStatus.granted); - - mockLightSensorService = _MockLightSensorService(); - when(() => mockLightSensorService.hasSensor()).thenAnswer((_) async => true); - when(() => mockLightSensorService.luxStream()).thenAnswer((_) => Stream.fromIterable([100])); - - mockVolumeEventsService = _MockVolumeEventsService(); - when(() => mockVolumeEventsService.setVolumeHandling(true)).thenAnswer((_) async => true); - when(() => mockVolumeEventsService.setVolumeHandling(false)).thenAnswer((_) async => false); - when(() => mockVolumeEventsService.volumeButtonsEventStream()).thenAnswer((_) => const Stream.empty()); - - when(() => mockHapticsService.quickVibration()).thenAnswer((_) async {}); - when(() => mockHapticsService.responseVibration()).thenAnswer((_) async {}); - }); - - Future pumpApplication( - WidgetTester tester, - IAPProductStatus purchaseStatus, { - String selectedEquipmentProfileId = '', - Film selectedFilm = const Film.other(), - }) async { - await tester.pumpWidget( - MockIAPProviders( - purchaseStatus: purchaseStatus, - selectedEquipmentProfileId: selectedEquipmentProfileId, - selectedFilm: selectedFilm, - child: ServicesProvider( - environment: const Environment.prod().copyWith(hasLightSensor: true), - userPreferencesService: mockUserPreferencesService, - caffeineService: mockCaffeineService, - hapticsService: mockHapticsService, - permissionsService: mockPermissionsService, - lightSensorService: mockLightSensorService, - volumeEventsService: mockVolumeEventsService, - child: const UserPreferencesProvider( - child: Application(), - ), - ), - ), - ); - await tester.pumpAndSettle(); - } - - group( - '[Metering layout features]', - () { - Future toggleFeatureAndClose(WidgetTester tester, String feature) async { - await tester.openSettings(); - expect(find.byType(SettingsScreen), findsOneWidget); - await tester.tap(find.text(S.current.meteringScreenLayout)); - await tester.pumpAndSettle(); - expect(find.byType(MeteringScreenLayoutFeaturesDialog), findsOneWidget); - await tester.tap( - find.descendant( - of: find.byType(SwitchListTile), - matching: find.text(feature), - ), - ); - await tester.tapSaveButton(); - expect(find.byType(MeteringScreenLayoutFeaturesDialog), findsNothing); - await tester.tap(find.byIcon(Icons.close)); - await tester.pumpAndSettle(); - } - - testWidgets( - 'Toggle equipmentProfiles & discard selected', - (tester) async { - await pumpApplication( - tester, - IAPProductStatus.purchased, - selectedEquipmentProfileId: mockEquipmentProfiles[0].id, - ); - await tester.toggleIncidentMetering(); - expectAnimatedPickerWith(value: mockEquipmentProfiles[0].name); - expectExposurePairsContainer('f/1.8 - 1/50', 'f/16 - 1.6"'); - expectMeasureButton(7.3); - - await toggleFeatureAndClose(tester, S.current.meteringScreenLayoutHintEquipmentProfiles); - expect(find.byType(EquipmentProfilePicker), findsNothing); - expectExposurePairsContainer('f/1.0 - 1/160', 'f/45 - 13"'); - expectMeasureButton(7.3); - - await toggleFeatureAndClose(tester, S.current.meteringScreenLayoutHintEquipmentProfiles); - expectAnimatedPickerWith(value: S.current.none); - expectExposurePairsContainer('f/1.0 - 1/160', 'f/45 - 13"'); - expectMeasureButton(7.3); - }, - ); - - testWidgets( - 'Toggle extremeExposurePairs', - (tester) async { - await pumpApplication(tester, IAPProductStatus.purchased); - await tester.toggleIncidentMetering(); - expectExposurePairsContainer('f/1.0 - 1/160', 'f/45 - 13"'); - expectMeasureButton(7.3); - - await toggleFeatureAndClose(tester, S.current.meteringScreenFeatureExtremeExposurePairs); - expect(find.byType(ExtremeExposurePairsContainer), findsNothing); - expectMeasureButton(7.3); - - await toggleFeatureAndClose(tester, S.current.meteringScreenFeatureExtremeExposurePairs); - expectExposurePairsContainer('f/1.0 - 1/160', 'f/45 - 13"'); - expectMeasureButton(7.3); - }, - ); - - testWidgets( - 'Toggle film & discard selected', - (tester) async { - await pumpApplication( - tester, - IAPProductStatus.purchased, - selectedFilm: mockFilms.first, - ); - await tester.toggleIncidentMetering(); - expectAnimatedPickerWith(value: mockFilms.first.name); - expectExposurePairsContainer('f/1.0 - 1/160', 'f/45 - 26"'); - expectMeasureButton(7.3); - - await toggleFeatureAndClose(tester, S.current.meteringScreenFeatureFilmPicker); - expect(find.byType(FilmPicker), findsNothing); - expectExposurePairsContainer('f/1.0 - 1/160', 'f/45 - 13"'); - expectMeasureButton(7.3); - - await toggleFeatureAndClose(tester, S.current.meteringScreenFeatureFilmPicker); - expectAnimatedPickerWith(value: S.current.none); - expectExposurePairsContainer('f/1.0 - 1/160', 'f/45 - 13"'); - expectMeasureButton(7.3); - }, - ); - - testWidgets( - 'Toggle histogram', - (tester) async { - await pumpApplication(tester, IAPProductStatus.purchased); - }, - skip: true, // TODO(@vodemn) - ); - }, - ); - - testWidgets( - '[Films in use] Deselect current', - (tester) async { - await pumpApplication( - tester, - IAPProductStatus.purchased, - selectedFilm: mockFilms[0], - ); - - // Check that film is selected and reciprocity is applied - await tester.toggleIncidentMetering(); - expectAnimatedPickerWith(value: mockFilms[0].name); - expectExposurePairsContainer('f/1.0 - 1/160', 'f/45 - 26"'); - expectMeasureButton(7.3); - - // Deselect the first films - await tester.openSettings(); - expect(find.byType(SettingsScreen), findsOneWidget); - await tester.tap(find.text(S.current.filmsInUse)); - await tester.pumpAndSettle(); - expect(find.byType(DialogFilter), findsOneWidget); - await tester.tap( - find.descendant( - of: find.byType(CheckboxListTile), - matching: find.text(mockFilms[0].name), - ), - ); - await tester.tapSaveButton(); - expect(find.byType(DialogFilter), findsNothing); - await tester.tap(find.byIcon(Icons.close)); - await tester.pumpAndSettle(); - - // The previously selected films is no longer in use and therefore is discarded to None - expectAnimatedPickerWith(value: S.current.none); - expectMeasureButton(7.3); - - // The previously selected films is no longer in use and therefore is not present in the picker - await tester.openAnimatedPicker(); - expect(find.byType(DialogPicker), findsOneWidget); - expect( - find.descendant( - of: find.byWidgetPredicate((widget) => widget is RadioListTile && widget.selected), - matching: find.text(mockFilms[0].name), - ), - findsNothing, - ); - }, - ); -} - -extension _WidgetTesterActions on WidgetTester { - Future openSettings() async { - expect(find.byTooltip(S.current.tooltipOpenSettings), findsOneWidget); - await tap(find.byTooltip(S.current.tooltipOpenSettings)); - await pumpAndSettle(); - } -} diff --git a/integration_test/utils/expectations.dart b/integration_test/utils/expectations.dart deleted file mode 100644 index 06f9429..0000000 --- a/integration_test/utils/expectations.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:lightmeter/generated/l10n.dart'; -import 'package:lightmeter/screens/metering/components/bottom_controls/components/measure_button/widget_button_measure.dart'; -import 'package:lightmeter/screens/metering/components/shared/readings_container/components/extreme_exposure_pairs_container/widget_container_extreme_exposure_pairs.dart'; -import 'package:lightmeter/screens/settings/components/shared/dialog_picker/widget_dialog_picker.dart'; - -/// Expects exactly one picker of the specified type and verifies `title` or/and `value` if any of the values is not null. -void expectAnimatedPickerWith({String? title, String? value}) { - final pickerFinder = find.byType(T); - expect(pickerFinder, findsOneWidget); - if (title != null) expect(find.descendant(of: pickerFinder, matching: find.text(title)), findsOneWidget); - if (value != null) expect(find.descendant(of: pickerFinder, matching: find.text(value)), findsOneWidget); -} - -/// Finds exactly one dialog picker of the provided value type -void expectDialogPicker() { - expect(find.byType(DialogPicker), findsOneWidget); -} - -void expectMeasureButton(double ev) { - find.descendant( - of: find.byType(MeteringMeasureButton), - matching: find.text('${ev.toStringAsFixed(1)}\n${S.current.ev}'), - ); -} - -void expectExposurePairsContainer(String fastest, String slowest) { - final pickerFinder = find.byType(ExtremeExposurePairsContainer); - expect(pickerFinder, findsOneWidget); - expect(find.descendant(of: pickerFinder, matching: find.text(S.current.fastestExposurePair)), findsOneWidget); - expect(find.descendant(of: pickerFinder, matching: find.text(fastest)), findsOneWidget); - expect(find.descendant(of: pickerFinder, matching: find.text(S.current.slowestExposurePair)), findsOneWidget); - expect(find.descendant(of: pickerFinder, matching: find.text(slowest)), findsOneWidget); -} - -void expectRadioListTile(String text, {bool isSelected = false}) { - expect( - find.descendant(of: find.byWidgetPredicate((widget) => widget is RadioListTile), matching: find.text(text)), - findsOneWidget, - ); -} diff --git a/integration_test/utils/metering_picker_test.dart b/integration_test/utils/metering_picker_test.dart deleted file mode 100644 index bbe4880..0000000 --- a/integration_test/utils/metering_picker_test.dart +++ /dev/null @@ -1,60 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:lightmeter/screens/metering/components/shared/readings_container/components/shared/animated_dialog_picker/components/dialog_picker/widget_picker_dialog.dart'; -import 'package:meta/meta.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -import 'expectations.dart'; -import 'widget_tester_actions.dart'; - -class MeteringValuesExpectation { - final String fastestExposurePair; - final String slowestExposurePair; - final double ev; - - const MeteringValuesExpectation( - this.fastestExposurePair, - this.slowestExposurePair, - this.ev, - ); -} - -/// Runs the picker test -/// -/// 1. Takes photo and verifies `expectBefore` values -/// 2. Opens a picker and select the provided value -/// 3. Verifies `expectAfter` -/// 4. Takes photo and verifies `expectAfter` values -@isTest -void testMeteringPicker( - String description, { - required MeteringValuesExpectation expectBefore, - required String valueToSelect, - required MeteringValuesExpectation expectAfter, - bool? skip, -}) { - testWidgets( - description, - (tester) async { - await tester.pumpApplication(); - await tester.toggleIncidentMetering(expectBefore.ev); - - // Verify that reciprocity failure is applies for the film is not selected - expectExposurePairsContainer(expectBefore.fastestExposurePair, expectBefore.slowestExposurePair); - expectMeasureButton(expectBefore.ev); - - await tester.openAnimatedPicker

(); - await tester.tapDescendantTextOf>(valueToSelect); - await tester.tapSelectButton(); - - /// Verify that exposure pairs are the same, except that the reciprocity failure is applied - expectExposurePairsContainer(expectAfter.fastestExposurePair, expectAfter.slowestExposurePair); - expectMeasureButton(expectAfter.ev); - - /// Make sure, that the EV is not changed - await tester.toggleIncidentMetering(expectBefore.ev); - expectExposurePairsContainer(expectAfter.fastestExposurePair, expectAfter.slowestExposurePair); - expectMeasureButton(expectAfter.ev); - }, - skip: skip, - ); -} diff --git a/integration_test/utils/platform_channel_mock.dart b/integration_test/utils/platform_channel_mock.dart index 3d91320..65e3c88 100644 --- a/integration_test/utils/platform_channel_mock.dart +++ b/integration_test/utils/platform_channel_mock.dart @@ -3,9 +3,12 @@ import 'dart:math'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; +const _systemFeatureMethodChannel = MethodChannel('system_feature'); +const _lightSensorMethodChannel = MethodChannel("light.eventChannel"); + void setLightSensorAvilability({required bool hasSensor}) { TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler( - const MethodChannel('system_feature'), + _systemFeatureMethodChannel, (methodCall) async { switch (methodCall.method) { case "sensor": @@ -19,7 +22,7 @@ void setLightSensorAvilability({required bool hasSensor}) { void resetLightSensorAvilability() { TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler( - const MethodChannel('system_feature'), + _systemFeatureMethodChannel, null, ); } @@ -28,7 +31,7 @@ Future sendMockIncidentEv(double ev) => sendMockLux((2.5 * pow(2, ev)).toI Future sendMockLux([int lux = 100]) async { await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.handlePlatformMessage( - "light.eventChannel", + _lightSensorMethodChannel.name, const StandardMethodCodec().encodeSuccessEnvelope(lux), (ByteData? data) {}, ); @@ -36,7 +39,7 @@ Future sendMockLux([int lux = 100]) async { void setupLightSensorStreamHandler() { TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler( - const MethodChannel('light.eventChannel'), + _lightSensorMethodChannel, (methodCall) async { switch (methodCall.method) { case "listen": @@ -52,7 +55,7 @@ void setupLightSensorStreamHandler() { void resetLightSensorStreamHandler() { TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler( - const MethodChannel('light.eventChannel'), + _lightSensorMethodChannel, null, ); } diff --git a/integration_test/utils/widget_tester_actions.dart b/integration_test/utils/widget_tester_actions.dart index 1769b72..8fc7883 100644 --- a/integration_test/utils/widget_tester_actions.dart +++ b/integration_test/utils/widget_tester_actions.dart @@ -55,10 +55,6 @@ extension WidgetTesterCommonActions on WidgetTester { } extension WidgetTesterListTileActions on WidgetTester { - Future tapRadioListTile(String text) async { - await tap(find.descendant(of: find.byType(RadioListTile), matching: find.text(text))); - } - /// Useful for tapping a specific [ListTile] inside a specific screen or dialog Future tapDescendantTextOf(String text) async { await tap(find.descendant(of: find.byType(T), matching: find.text(text)));