diff --git a/integration_test/metering_screen_test.dart b/integration_test/metering_screen_test.dart index 933d669..0416f65 100644 --- a/integration_test/metering_screen_test.dart +++ b/integration_test/metering_screen_test.dart @@ -7,7 +7,6 @@ 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'; @@ -15,7 +14,6 @@ import 'package:lightmeter/screens/metering/components/shared/readings_container 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/components/shared/readings_container/components/shared/animated_dialog_picker/components/dialog_picker/widget_picker_dialog.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'; @@ -24,6 +22,7 @@ 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'; @@ -40,9 +39,17 @@ const mockPhotoSlowestExposurePair = ExposurePair(mockPhotoSlowestAperture, mock void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + tearDown(() { + SharedPreferences.resetStatic(); + }); + group( '[Light sensor availability]', () { + tearDown(() { + resetLightSensorAvilability(); + }); + testWidgets( 'Android - has sensor', (tester) async { @@ -112,7 +119,7 @@ void main() { expect(find.descendant(of: firstPairRow, matching: find.text(shutterSpeed)), findsOneWidget); } - setUpAll(() { + setUp(() { SharedPreferences.setMockInitialValues({UserPreferencesService.evSourceTypeKey: EvSourceType.camera.index}); }); @@ -185,118 +192,83 @@ void main() { group( '[Pickers tests]', () { - group('Select film', () { - testWidgets( - 'with the same ISO', - (tester) async { - await tester.pumpApplication(); - await tester.takePhoto(); - - // Verify that reciprocity failure is applies for the film is not selected - expectAnimatedPickerWith(title: S.current.film, value: S.current.none); - expectExposurePairsContainer('$mockPhotoFastestExposurePair', '$mockPhotoSlowestExposurePair'); - expectMeasureButton(mockPhotoEv100); - - await tester.openAnimatedPicker(); - await tester.tapDescendantTextOf>(mockFilms.first.name); - await tester.tapSelectButton(); - - /// Verify that exposure pairs are the same, except that the reciprocity failure is applied - expectExposurePairsContainer( - '$mockPhotoFastestExposurePair', - '$mockPhotoSlowestAperture - ${mockFilms.first.reciprocityFailure(mockPhotoSlowestShutterSpeed)}', - ); - expectMeasureButton(mockPhotoEv100); - - /// Make sure, that the EV is not changed - await tester.takePhoto(); - expectExposurePairsContainer( - '$mockPhotoFastestExposurePair', - '$mockPhotoSlowestAperture - ${mockFilms.first.reciprocityFailure(mockPhotoSlowestShutterSpeed)}', - ); - expectMeasureButton(mockPhotoEv100); - }, - ); - - testWidgets( - 'with greater ISO', - (tester) async { - await tester.pumpApplication(); - await tester.takePhoto(); - - // Verify that reciprocity failure is applies for the film is not selected - expectAnimatedPickerWith(title: S.current.film, value: S.current.none); - expectExposurePairsContainer('$mockPhotoFastestExposurePair', '$mockPhotoSlowestExposurePair'); - expectMeasureButton(mockPhotoEv100); - - await tester.openAnimatedPicker(); - await tester.tapDescendantTextOf>(mockFilms[1].name); - await tester.tapSelectButton(); - - /// Verify that exposure pairs are the same, except that the reciprocity failure is applied - expectExposurePairsContainer( - '$mockPhotoFastestExposurePair', - '$mockPhotoSlowestAperture - ${mockFilms[1].reciprocityFailure(mockPhotoSlowestShutterSpeed)}', - ); - expectMeasureButton(mockPhotoEv100); - - /// Make sure, that the EV is not changed - await tester.takePhoto(); - expectExposurePairsContainer( - '$mockPhotoFastestExposurePair', - '$mockPhotoSlowestAperture - ${mockFilms[1].reciprocityFailure(mockPhotoSlowestShutterSpeed)}', - ); - expectMeasureButton(mockPhotoEv100); - }, - ); + setUpAll(() { + setupLightSensorStreamHandler(); + setLightSensorAvilability(hasSensor: true); }); - testWidgets( - 'Select ISO +1 EV', - (tester) async { - await tester.pumpApplication(productStatus: IAPProductStatus.purchased); - expectExposurePairsContainer('f/1.0 - 1/320', 'f/45 - 13"'); - expectMeasureButton(mockPhotoEv100); + tearDownAll(() { + resetLightSensorAvilability(); + resetLightSensorStreamHandler(); + }); - await tester.openAnimatedPicker(); - expect(find.byType(DialogPicker), findsOneWidget); - await tester.tapRadioListTile('800'); - await tester.tapSelectButton(); - expectExposurePairsContainer('f/1.0 - 1/320', 'f/45 - 6"'); - expectMeasureButton(8.3); + setUp(() { + SharedPreferences.setMockInitialValues({UserPreferencesService.evSourceTypeKey: EvSourceType.sensor.index}); + }); - /// Make sure, that current ISO is used in metering - await tester.tap(find.byType(MeteringMeasureButton)); - await tester.tap(find.byType(MeteringMeasureButton)); - await tester.pumpAndSettle(); - expectExposurePairsContainer('f/1.0 - 1/320', 'f/45 - 6"'); - expectMeasureButton(8.3); + 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, + ), + ); }, - skip: true, ); - testWidgets( + 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', - (tester) async { - await tester.pumpApplication(productStatus: IAPProductStatus.purchased); - expectExposurePairsContainer('f/1.0 - 1/320', 'f/45 - 13"'); - expectMeasureButton(mockPhotoEv100); - - await tester.openAnimatedPicker(); - expect(find.byType(DialogPicker), findsOneWidget); - await tester.tapRadioListTile('2'); - await tester.tapSelectButton(); - expectExposurePairsContainer('f/1.0 - 1/80', 'f/36 - 16"'); - expectMeasureButton(6.3); - - /// Make sure, that current ISO is used in metering - await tester.tap(find.byType(MeteringMeasureButton)); - await tester.tap(find.byType(MeteringMeasureButton)); - await tester.pumpAndSettle(); - expectExposurePairsContainer('f/1.0 - 1/80', 'f/36 - 16"'); - expectMeasureButton(6.3); - }, - skip: true, + expectBefore: MeteringValuesExpectation( + mockPhotoFastestExposurePair.toString(), + mockPhotoSlowestExposurePair.toString(), + mockPhotoEv100, + ), + valueToSelect: '2', + expectAfter: MeteringValuesExpectation( + '$mockPhotoFastestAperture - 1/160', + '$mockPhotoSlowestAperture - 13"', + mockPhotoEv100 - 1, + ), ); }, ); diff --git a/integration_test/utils/metering_picker_test.dart b/integration_test/utils/metering_picker_test.dart new file mode 100644 index 0000000..bbe4880 --- /dev/null +++ b/integration_test/utils/metering_picker_test.dart @@ -0,0 +1,60 @@ +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 cb57cc9..3d91320 100644 --- a/integration_test/utils/platform_channel_mock.dart +++ b/integration_test/utils/platform_channel_mock.dart @@ -3,22 +3,6 @@ import 'dart:math'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -Future sendMockLux([int lux = 100]) async { - await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.handlePlatformMessage( - "light.eventChannel", - const StandardMethodCodec().encodeSuccessEnvelope(lux), - (ByteData? data) {}, - ); -} - -Future sendMockIncidentEv(double ev) async { - await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.handlePlatformMessage( - "light.eventChannel", - const StandardMethodCodec().encodeSuccessEnvelope((2.5 * pow(2, ev)).toInt()), - (ByteData? data) {}, - ); -} - void setLightSensorAvilability({required bool hasSensor}) { TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler( const MethodChannel('system_feature'), @@ -32,3 +16,43 @@ void setLightSensorAvilability({required bool hasSensor}) { }, ); } + +void resetLightSensorAvilability() { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler( + const MethodChannel('system_feature'), + null, + ); +} + +Future sendMockIncidentEv(double ev) => sendMockLux((2.5 * pow(2, ev)).toInt()); + +Future sendMockLux([int lux = 100]) async { + await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.handlePlatformMessage( + "light.eventChannel", + const StandardMethodCodec().encodeSuccessEnvelope(lux), + (ByteData? data) {}, + ); +} + +void setupLightSensorStreamHandler() { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler( + const MethodChannel('light.eventChannel'), + (methodCall) async { + switch (methodCall.method) { + case "listen": + return; + case "cancel": + return; + default: + return null; + } + }, + ); +} + +void resetLightSensorStreamHandler() { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler( + const MethodChannel('light.eventChannel'), + null, + ); +}