diff --git a/integration_test/e2e_test.dart b/integration_test/e2e_test.dart new file mode 100644 index 0000000..06688f6 --- /dev/null +++ b/integration_test/e2e_test.dart @@ -0,0 +1,143 @@ +import 'dart:convert'; + +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/metering_screen_layout_config.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/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'; +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:m3_lightmeter_resources/m3_lightmeter_resources.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../integration_test/utils/widget_tester_actions.dart'; +import 'mocks/paid_features_mock.dart'; +import 'utils/expectations.dart'; + +void main() { + setUp(() { + SharedPreferences.setMockInitialValues({ + /// Metering values + UserPreferencesService.evSourceTypeKey: EvSourceType.camera.index, + UserPreferencesService.meteringScreenLayoutKey: json.encode( + { + MeteringScreenLayoutFeature.equipmentProfiles: true, + MeteringScreenLayoutFeature.extremeExposurePairs: true, + MeteringScreenLayoutFeature.filmPicker: true, + }.toJson(), + ), + }); + }); + + testWidgets( + 'e2e', + (tester) async { + await tester.pumpApplication(); + + /** First launch */ + + /// Select some initial settings according to the selected gear and film + /// Then tale a photo and verify, that exposure pairs range and EV matches the selected settings + await tester.openPickerAndSelect('400'); + await tester.openPickerAndSelect(mockEquipmentProfiles[0].name); + await tester.openPickerAndSelect(mockFilms[0].name); + expectPickerTitle('400'); + expectPickerTitle(mockEquipmentProfiles[0].name); + expectPickerTitle(mockFilms[0].name); + await tester.takePhoto(); + await _expectMeteringState( + tester, + equipmentProfile: mockEquipmentProfiles[0], + fastest: 'f/1.8 - 1/400', + slowest: 'f/16 - 1/5', + ev: mockPhotoEv100 + 2, + ); + + /** Changing some settings in the field */ + + /// Add ND to shoot another scene + await tester.openPickerAndSelect('2'); + expectPickerTitle('2'); + await _expectMeteringStateAndMeasure( + tester, + equipmentProfile: mockEquipmentProfiles[0], + fastest: 'f/1.8 - 1/200', + slowest: 'f/16 - 1/2.5', + ev: mockPhotoEv100 + 2 - 1, + ); + + /// Select another lens without ND + await tester.openPickerAndSelect('None'); + expectPickerTitle('None'); + await _expectMeteringStateAndMeasure( + tester, + equipmentProfile: mockEquipmentProfiles[0], + fastest: 'f/1.8 - 1/400', + slowest: 'f/16 - 1/5', + ev: mockPhotoEv100 + 2, + ); + }, + ); +} + +extension on WidgetTester { + Future openPickerAndSelect

(String valueToSelect) async { + await openAnimatedPicker

(); + await tapDescendantTextOf>(valueToSelect); + await tapSelectButton(); + } +} + +Future _expectMeteringState( + WidgetTester tester, { + required EquipmentProfile equipmentProfile, + required String fastest, + required String slowest, + required double ev, + String? reason, +}) async { + expectPickerTitle(equipmentProfile.name); + expectExtremeExposurePairs(fastest, slowest); + expectExposurePairsListItem(tester, fastest.split(' - ')[0], fastest.split(' - ')[1]); + await tester.scrollToTheLastExposurePair(equipmentProfile: equipmentProfile); + expectExposurePairsListItem(tester, slowest.split(' - ')[0], slowest.split(' - ')[1]); + expectMeasureButton(ev); +} + +Future _expectMeteringStateAndMeasure( + WidgetTester tester, { + required EquipmentProfile equipmentProfile, + required String fastest, + required String slowest, + required double ev, +}) async { + await _expectMeteringState( + tester, + equipmentProfile: equipmentProfile, + fastest: fastest, + slowest: slowest, + ev: ev, + ); + await tester.takePhoto(); + await _expectMeteringState( + tester, + equipmentProfile: equipmentProfile, + fastest: fastest, + slowest: slowest, + ev: ev, + reason: + 'Metering screen state must be the same before and after the measurement assuming that the scene is exactly the same.', + ); +} + +void expectMeasureButton(double ev) { + find.descendant( + of: find.byType(MeteringMeasureButton), + matching: find.text('${ev.toStringAsFixed(1)}\n${S.current.ev}'), + ); +}