mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2024-11-21 23:10:40 +00:00
refined tester extension and expectations
This commit is contained in:
parent
a70ce5012a
commit
b80c46fd3a
4 changed files with 346 additions and 71 deletions
|
@ -6,21 +6,16 @@ import 'package:lightmeter/data/models/ev_source_type.dart';
|
||||||
import 'package:lightmeter/data/models/metering_screen_layout_config.dart';
|
import 'package:lightmeter/data/models/metering_screen_layout_config.dart';
|
||||||
import 'package:lightmeter/data/shared_prefs_service.dart';
|
import 'package:lightmeter/data/shared_prefs_service.dart';
|
||||||
import 'package:lightmeter/generated/l10n.dart';
|
import 'package:lightmeter/generated/l10n.dart';
|
||||||
import 'package:lightmeter/screens/metering/components/shared/exposure_pairs_list/components/exposure_pairs_list_item/widget_item_list_exposure_pairs.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/equipment_profile_picker/widget_picker_equipment_profiles.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/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/film_picker/widget_picker_film.dart';
|
||||||
import 'package:lightmeter/screens/metering/screen_metering.dart';
|
|
||||||
import 'package:lightmeter/screens/settings/screen_settings.dart';
|
import 'package:lightmeter/screens/settings/screen_settings.dart';
|
||||||
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
import '../integration_test/utils/widget_tester_actions.dart';
|
import '../integration_test/utils/widget_tester_actions.dart';
|
||||||
import 'mocks/paid_features_mock.dart';
|
import 'mocks/paid_features_mock.dart';
|
||||||
|
import 'utils/expectations.dart';
|
||||||
const _mockPhotoEv100 = 8.3;
|
|
||||||
|
|
||||||
@isTestGroup
|
@isTestGroup
|
||||||
void testToggleLayoutFeatures(String description) {
|
void testToggleLayoutFeatures(String description) {
|
||||||
|
@ -46,11 +41,11 @@ void testToggleLayoutFeatures(String description) {
|
||||||
(tester) async {
|
(tester) async {
|
||||||
await tester.pumpApplication(selectedEquipmentProfileId: mockEquipmentProfiles.first.id);
|
await tester.pumpApplication(selectedEquipmentProfileId: mockEquipmentProfiles.first.id);
|
||||||
await tester.takePhoto();
|
await tester.takePhoto();
|
||||||
_expectPickerTitle<EquipmentProfilePicker>(mockEquipmentProfiles.first.name);
|
expectPickerTitle<EquipmentProfilePicker>(mockEquipmentProfiles.first.name);
|
||||||
_expectExtremeExposurePairs('f/1.8 - 1/100', 'f/16 - 1/1.3');
|
expectExtremeExposurePairs('f/1.8 - 1/100', 'f/16 - 1/1.3');
|
||||||
_expectExposurePairsListItem(tester, 'f/1.8', '1/100');
|
expectExposurePairsListItem(tester, 'f/1.8', '1/100');
|
||||||
await tester.scrollToTheLastExposurePair(mockEquipmentProfiles.first);
|
await tester.scrollToTheLastExposurePair(equipmentProfile: mockEquipmentProfiles.first);
|
||||||
_expectExposurePairsListItem(tester, 'f/16', '1/1.3');
|
expectExposurePairsListItem(tester, 'f/16', '1/1.3');
|
||||||
|
|
||||||
// Disable layout feature
|
// Disable layout feature
|
||||||
await tester.toggleLayoutFeature(S.current.meteringScreenLayoutHintEquipmentProfiles);
|
await tester.toggleLayoutFeature(S.current.meteringScreenLayoutHintEquipmentProfiles);
|
||||||
|
@ -60,12 +55,12 @@ void testToggleLayoutFeatures(String description) {
|
||||||
reason:
|
reason:
|
||||||
'Equipment profile picker must be hidden from the metering screen when the corresponding layout feature is disabled.',
|
'Equipment profile picker must be hidden from the metering screen when the corresponding layout feature is disabled.',
|
||||||
);
|
);
|
||||||
_expectExtremeExposurePairs(
|
expectExtremeExposurePairs(
|
||||||
'f/1.0 - 1/320',
|
'f/1.0 - 1/320',
|
||||||
'f/45 - 6"',
|
'f/45 - 6"',
|
||||||
reason: 'Aperture and shutter speed ranges must be reset to default values when equipment profile is reset',
|
reason: 'Aperture and shutter speed ranges must be reset to default values when equipment profile is reset',
|
||||||
);
|
);
|
||||||
_expectExposurePairsListItem(
|
expectExposurePairsListItem(
|
||||||
tester,
|
tester,
|
||||||
'f/1.0',
|
'f/1.0',
|
||||||
'1/320',
|
'1/320',
|
||||||
|
@ -73,7 +68,7 @@ void testToggleLayoutFeatures(String description) {
|
||||||
'Aperture and shutter speed ranges must be reset to default values when equipment profile is reset.',
|
'Aperture and shutter speed ranges must be reset to default values when equipment profile is reset.',
|
||||||
);
|
);
|
||||||
await tester.scrollToTheLastExposurePair();
|
await tester.scrollToTheLastExposurePair();
|
||||||
_expectExposurePairsListItem(
|
expectExposurePairsListItem(
|
||||||
tester,
|
tester,
|
||||||
'f/45',
|
'f/45',
|
||||||
'6"',
|
'6"',
|
||||||
|
@ -83,7 +78,7 @@ void testToggleLayoutFeatures(String description) {
|
||||||
|
|
||||||
// Enable layout feature
|
// Enable layout feature
|
||||||
await tester.toggleLayoutFeature(S.current.meteringScreenLayoutHintEquipmentProfiles);
|
await tester.toggleLayoutFeature(S.current.meteringScreenLayoutHintEquipmentProfiles);
|
||||||
_expectPickerTitle<EquipmentProfilePicker>(
|
expectPickerTitle<EquipmentProfilePicker>(
|
||||||
S.current.none,
|
S.current.none,
|
||||||
reason: 'Equipment profile must remain unselected when the corresponding layout feature is re-enabled.',
|
reason: 'Equipment profile must remain unselected when the corresponding layout feature is re-enabled.',
|
||||||
);
|
);
|
||||||
|
@ -95,10 +90,10 @@ void testToggleLayoutFeatures(String description) {
|
||||||
(tester) async {
|
(tester) async {
|
||||||
await tester.pumpApplication();
|
await tester.pumpApplication();
|
||||||
await tester.takePhoto();
|
await tester.takePhoto();
|
||||||
_expectExtremeExposurePairs('f/1.0 - 1/320', 'f/45 - 6"');
|
expectExtremeExposurePairs('f/1.0 - 1/320', 'f/45 - 6"');
|
||||||
_expectExposurePairsListItem(tester, 'f/1.0', '1/320');
|
expectExposurePairsListItem(tester, 'f/1.0', '1/320');
|
||||||
await tester.scrollToTheLastExposurePair();
|
await tester.scrollToTheLastExposurePair();
|
||||||
_expectExposurePairsListItem(tester, 'f/45', '6"');
|
expectExposurePairsListItem(tester, 'f/45', '6"');
|
||||||
|
|
||||||
// Disable layout feature
|
// Disable layout feature
|
||||||
await tester.toggleLayoutFeature(S.current.meteringScreenFeatureExtremeExposurePairs);
|
await tester.toggleLayoutFeature(S.current.meteringScreenFeatureExtremeExposurePairs);
|
||||||
|
@ -108,7 +103,7 @@ void testToggleLayoutFeatures(String description) {
|
||||||
reason:
|
reason:
|
||||||
'Extreme exposure pairs container must be hidden from the metering screen when the corresponding layout feature is disabled.',
|
'Extreme exposure pairs container must be hidden from the metering screen when the corresponding layout feature is disabled.',
|
||||||
);
|
);
|
||||||
_expectExposurePairsListItem(
|
expectExposurePairsListItem(
|
||||||
tester,
|
tester,
|
||||||
'f/1.0',
|
'f/1.0',
|
||||||
'1/320',
|
'1/320',
|
||||||
|
@ -116,7 +111,7 @@ void testToggleLayoutFeatures(String description) {
|
||||||
'Exposure pairs list must not be affected by the visibility of the extreme exposure pairs container.',
|
'Exposure pairs list must not be affected by the visibility of the extreme exposure pairs container.',
|
||||||
);
|
);
|
||||||
await tester.scrollToTheLastExposurePair();
|
await tester.scrollToTheLastExposurePair();
|
||||||
_expectExposurePairsListItem(
|
expectExposurePairsListItem(
|
||||||
tester,
|
tester,
|
||||||
'f/45',
|
'f/45',
|
||||||
'6"',
|
'6"',
|
||||||
|
@ -126,7 +121,7 @@ void testToggleLayoutFeatures(String description) {
|
||||||
|
|
||||||
// Enable layout feature
|
// Enable layout feature
|
||||||
await tester.toggleLayoutFeature(S.current.meteringScreenFeatureExtremeExposurePairs);
|
await tester.toggleLayoutFeature(S.current.meteringScreenFeatureExtremeExposurePairs);
|
||||||
_expectExtremeExposurePairs(
|
expectExtremeExposurePairs(
|
||||||
'f/1.0 - 1/320',
|
'f/1.0 - 1/320',
|
||||||
'f/45 - 6"',
|
'f/45 - 6"',
|
||||||
reason:
|
reason:
|
||||||
|
@ -140,11 +135,11 @@ void testToggleLayoutFeatures(String description) {
|
||||||
(tester) async {
|
(tester) async {
|
||||||
await tester.pumpApplication(selectedFilm: mockFilms.first);
|
await tester.pumpApplication(selectedFilm: mockFilms.first);
|
||||||
await tester.takePhoto();
|
await tester.takePhoto();
|
||||||
_expectPickerTitle<FilmPicker>(mockFilms.first.name);
|
expectPickerTitle<FilmPicker>(mockFilms.first.name);
|
||||||
_expectExtremeExposurePairs('f/1.0 - 1/320', 'f/45 - 12"');
|
expectExtremeExposurePairs('f/1.0 - 1/320', 'f/45 - 12"');
|
||||||
_expectExposurePairsListItem(tester, 'f/1.0', '1/320');
|
expectExposurePairsListItem(tester, 'f/1.0', '1/320');
|
||||||
await tester.scrollToTheLastExposurePair();
|
await tester.scrollToTheLastExposurePair();
|
||||||
_expectExposurePairsListItem(tester, 'f/45', '12"');
|
expectExposurePairsListItem(tester, 'f/45', '12"');
|
||||||
|
|
||||||
// Disable layout feature
|
// Disable layout feature
|
||||||
await tester.toggleLayoutFeature(S.current.meteringScreenFeatureFilmPicker);
|
await tester.toggleLayoutFeature(S.current.meteringScreenFeatureFilmPicker);
|
||||||
|
@ -154,19 +149,19 @@ void testToggleLayoutFeatures(String description) {
|
||||||
reason:
|
reason:
|
||||||
'Film picker must be hidden from the metering screen when the corresponding layout feature is disabled.',
|
'Film picker must be hidden from the metering screen when the corresponding layout feature is disabled.',
|
||||||
);
|
);
|
||||||
_expectExtremeExposurePairs(
|
expectExtremeExposurePairs(
|
||||||
'f/1.0 - 1/320',
|
'f/1.0 - 1/320',
|
||||||
'f/45 - 6"',
|
'f/45 - 6"',
|
||||||
reason: 'Shutter speed must not be affected by reciprocity when film is discarded.',
|
reason: 'Shutter speed must not be affected by reciprocity when film is discarded.',
|
||||||
);
|
);
|
||||||
_expectExposurePairsListItem(
|
expectExposurePairsListItem(
|
||||||
tester,
|
tester,
|
||||||
'f/1.0',
|
'f/1.0',
|
||||||
'1/320',
|
'1/320',
|
||||||
reason: 'Shutter speed must not be affected by reciprocity when film is discarded.',
|
reason: 'Shutter speed must not be affected by reciprocity when film is discarded.',
|
||||||
);
|
);
|
||||||
await tester.scrollToTheLastExposurePair();
|
await tester.scrollToTheLastExposurePair();
|
||||||
_expectExposurePairsListItem(
|
expectExposurePairsListItem(
|
||||||
tester,
|
tester,
|
||||||
'f/45',
|
'f/45',
|
||||||
'6"',
|
'6"',
|
||||||
|
@ -175,7 +170,7 @@ void testToggleLayoutFeatures(String description) {
|
||||||
|
|
||||||
// Enable layout feature
|
// Enable layout feature
|
||||||
await tester.toggleLayoutFeature(S.current.meteringScreenFeatureFilmPicker);
|
await tester.toggleLayoutFeature(S.current.meteringScreenFeatureFilmPicker);
|
||||||
_expectPickerTitle<FilmPicker>(
|
expectPickerTitle<FilmPicker>(
|
||||||
S.current.none,
|
S.current.none,
|
||||||
reason: 'Film must remain unselected when the corresponding layout feature is re-enabled.',
|
reason: 'Film must remain unselected when the corresponding layout feature is re-enabled.',
|
||||||
);
|
);
|
||||||
|
@ -193,46 +188,4 @@ extension on WidgetTester {
|
||||||
await tapSaveButton();
|
await tapSaveButton();
|
||||||
await navigatorPop();
|
await navigatorPop();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> scrollToTheLastExposurePair([EquipmentProfile equipmentProfile = defaultEquipmentProfile]) async {
|
|
||||||
final exposurePairs = MeteringContainerBuidler.buildExposureValues(
|
|
||||||
_mockPhotoEv100,
|
|
||||||
StopType.third,
|
|
||||||
equipmentProfile,
|
|
||||||
);
|
|
||||||
await 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)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _expectPickerTitle<T>(String title, {String? reason}) {
|
|
||||||
expect(find.descendant(of: find.byType(T), matching: find.text(title)), findsOneWidget, reason: reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _expectExtremeExposurePairs(String fastest, String slowest, {String? reason}) {
|
|
||||||
final pickerFinder = find.byType(ExtremeExposurePairsContainer);
|
|
||||||
expect(find.descendant(of: pickerFinder, matching: find.text(fastest)), findsOneWidget, reason: reason);
|
|
||||||
expect(find.descendant(of: pickerFinder, matching: find.text(slowest)), findsOneWidget, reason: reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _expectExposurePairsListItem(WidgetTester tester, String aperture, String shutterSpeed, {String? reason}) {
|
|
||||||
Key? findKey<T extends PhotographyStopValue<num>>(String value) => tester
|
|
||||||
.widget<Row>(
|
|
||||||
find.ancestor(
|
|
||||||
of: find.ancestor(
|
|
||||||
of: find.text(value),
|
|
||||||
matching: find.byType(ExposurePairsListItem<T>),
|
|
||||||
),
|
|
||||||
matching: find.descendant(of: find.byType(ExposurePairsList), matching: find.byType(Row)),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.key;
|
|
||||||
expect(
|
|
||||||
findKey<ApertureValue>(aperture),
|
|
||||||
findKey<ShutterSpeedValue>(shutterSpeed),
|
|
||||||
reason: reason,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
264
integration_test/metering_screen_pickers_test.dart
Normal file
264
integration_test/metering_screen_pickers_test.dart
Normal file
|
@ -0,0 +1,264 @@
|
||||||
|
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/exposure_pair.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/exposure_pairs_list/components/exposure_pairs_list_item/widget_item_list_exposure_pairs.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/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/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/settings/screen_settings.dart';
|
||||||
|
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import '../integration_test/utils/widget_tester_actions.dart';
|
||||||
|
import 'mocks/paid_features_mock.dart';
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
class MeteringValuesExpectation {
|
||||||
|
final String fastestExposurePair;
|
||||||
|
final String slowestExposurePair;
|
||||||
|
final double ev;
|
||||||
|
|
||||||
|
const MeteringValuesExpectation(
|
||||||
|
this.fastestExposurePair,
|
||||||
|
this.slowestExposurePair,
|
||||||
|
this.ev,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@isTestGroup
|
||||||
|
void testMeteringScreenPickers(String description) {
|
||||||
|
group(
|
||||||
|
description,
|
||||||
|
() {
|
||||||
|
setUp(() {
|
||||||
|
SharedPreferences.setMockInitialValues({
|
||||||
|
/// Metering values
|
||||||
|
UserPreferencesService.evSourceTypeKey: EvSourceType.camera.index,
|
||||||
|
UserPreferencesService.meteringScreenLayoutKey: json.encode(
|
||||||
|
{
|
||||||
|
MeteringScreenLayoutFeature.equipmentProfiles: true,
|
||||||
|
MeteringScreenLayoutFeature.extremeExposurePairs: true,
|
||||||
|
MeteringScreenLayoutFeature.filmPicker: true,
|
||||||
|
}.toJson(),
|
||||||
|
),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group(
|
||||||
|
'Select film',
|
||||||
|
() {
|
||||||
|
testMeteringPicker<FilmPicker, Film>(
|
||||||
|
'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<FilmPicker, Film>(
|
||||||
|
'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<IsoValuePicker, IsoValue>(
|
||||||
|
'Select ISO +1 EV',
|
||||||
|
expectBefore: MeteringValuesExpectation(
|
||||||
|
mockPhotoFastestExposurePair.toString(),
|
||||||
|
mockPhotoSlowestExposurePair.toString(),
|
||||||
|
mockPhotoEv100,
|
||||||
|
),
|
||||||
|
valueToSelect: '400',
|
||||||
|
expectAfter: MeteringValuesExpectation(
|
||||||
|
'$mockPhotoFastestAperture - 1/1250',
|
||||||
|
'$mockPhotoSlowestAperture - 1.6"',
|
||||||
|
mockPhotoEv100 + 2,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
testMeteringPicker<NdValuePicker, NdValue>(
|
||||||
|
'Select ND -1 EV',
|
||||||
|
expectBefore: MeteringValuesExpectation(
|
||||||
|
mockPhotoFastestExposurePair.toString(),
|
||||||
|
mockPhotoSlowestExposurePair.toString(),
|
||||||
|
mockPhotoEv100,
|
||||||
|
),
|
||||||
|
valueToSelect: '2',
|
||||||
|
expectAfter: MeteringValuesExpectation(
|
||||||
|
'$mockPhotoFastestAperture - 1/160',
|
||||||
|
'$mockPhotoSlowestAperture - 13"',
|
||||||
|
mockPhotoEv100 - 1,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
testWidgets(
|
||||||
|
description,
|
||||||
|
(tester) async {
|
||||||
|
Future<void> selectAndExpect<P, V>(
|
||||||
|
String valueToSelect,
|
||||||
|
MeteringValuesExpectation expectation, {
|
||||||
|
String? reason,
|
||||||
|
}) async {
|
||||||
|
/// Verify, that EV is recalculated with a new setting
|
||||||
|
await tester.openPickerAndSelect<P, V>(valueToSelect);
|
||||||
|
_expectPickerTitle<P>(valueToSelect);
|
||||||
|
expectExposurePairsContainer(expectation.fastestExposurePair, expectation.slowestExposurePair);
|
||||||
|
expectMeasureButton(expectation.ev);
|
||||||
|
|
||||||
|
/// Make sure, that the selected setting is applied in the subsequent measurements
|
||||||
|
await tester.takePhoto();
|
||||||
|
await tester.takePhoto();
|
||||||
|
expectExposurePairsContainer(expectation.fastestExposurePair, expectation.slowestExposurePair);
|
||||||
|
expectMeasureButton(expectation.ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
await tester.pumpApplication();
|
||||||
|
await tester.takePhoto();
|
||||||
|
|
||||||
|
await selectAndExpect<IsoValuePicker, IsoValue>(
|
||||||
|
'400',
|
||||||
|
MeteringValuesExpectation(
|
||||||
|
'$mockPhotoFastestAperture - 1/1250',
|
||||||
|
'$mockPhotoSlowestAperture - 1.6"',
|
||||||
|
mockPhotoEv100 + 2,
|
||||||
|
),
|
||||||
|
reason: 'Selecting ISO value must change EV value and therefore exposure pairs.',
|
||||||
|
);
|
||||||
|
|
||||||
|
await selectAndExpect<NdValuePicker, NdValue>(
|
||||||
|
'2',
|
||||||
|
MeteringValuesExpectation(
|
||||||
|
'$mockPhotoFastestAperture - 1/640',
|
||||||
|
'$mockPhotoSlowestAperture - 3"',
|
||||||
|
mockPhotoEv100 - 1,
|
||||||
|
),
|
||||||
|
reason: 'Selecting ND value must change EV value and therefore exposure pairs.',
|
||||||
|
);
|
||||||
|
|
||||||
|
await selectAndExpect<FilmPicker, Film>(
|
||||||
|
mockFilms[0].name,
|
||||||
|
MeteringValuesExpectation(
|
||||||
|
mockPhotoFastestExposurePair.toString(),
|
||||||
|
'$mockPhotoSlowestAperture - ${mockFilms[0].reciprocityFailure(mockPhotoSlowestShutterSpeed)}',
|
||||||
|
mockPhotoEv100,
|
||||||
|
),
|
||||||
|
reason: 'Selecting with the same ISO must change nothing exept exposure pairs due to reciprocity.',
|
||||||
|
);
|
||||||
|
await selectAndExpect<FilmPicker, Film>(
|
||||||
|
mockFilms[1].name,
|
||||||
|
MeteringValuesExpectation(
|
||||||
|
mockPhotoFastestExposurePair.toString(),
|
||||||
|
'$mockPhotoSlowestAperture - ${mockFilms[0].reciprocityFailure(mockPhotoSlowestShutterSpeed)}',
|
||||||
|
mockPhotoEv100,
|
||||||
|
),
|
||||||
|
reason:
|
||||||
|
'Selecting with a different ISO must must indicate push/pull and can change nothing exept exposure pairs due to reciprocity.',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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<P, V>(
|
||||||
|
String description, {
|
||||||
|
required MeteringValuesExpectation expectBefore,
|
||||||
|
required String valueToSelect,
|
||||||
|
required MeteringValuesExpectation expectAfter,
|
||||||
|
bool? skip,
|
||||||
|
}) {
|
||||||
|
testWidgets(
|
||||||
|
description,
|
||||||
|
(tester) async {
|
||||||
|
await tester.pumpApplication();
|
||||||
|
|
||||||
|
// Verify initial EV
|
||||||
|
await tester.toggleIncidentMetering(expectBefore.ev);
|
||||||
|
expectExposurePairsContainer(expectBefore.fastestExposurePair, expectBefore.slowestExposurePair);
|
||||||
|
expectMeasureButton(expectBefore.ev);
|
||||||
|
|
||||||
|
/// Verify, that EV is recalculated with a new setting
|
||||||
|
await tester.openPickerAndSelect<P, V>(valueToSelect);
|
||||||
|
expectExposurePairsContainer(expectAfter.fastestExposurePair, expectAfter.slowestExposurePair);
|
||||||
|
expectMeasureButton(expectAfter.ev);
|
||||||
|
|
||||||
|
/// Make sure, that the selected setting is applied in the subsequent measurements
|
||||||
|
await tester.toggleIncidentMetering(expectBefore.ev);
|
||||||
|
expectExposurePairsContainer(expectAfter.fastestExposurePair, expectAfter.slowestExposurePair);
|
||||||
|
expectMeasureButton(expectAfter.ev);
|
||||||
|
},
|
||||||
|
skip: skip,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
extension on WidgetTester {
|
||||||
|
Future<void> openPickerAndSelect<P, V>(String valueToSelect) async {
|
||||||
|
await openAnimatedPicker<P>();
|
||||||
|
await tapDescendantTextOf<DialogPicker<V>>(valueToSelect);
|
||||||
|
await tapSelectButton();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _expectPickerTitle<T>(String title, {String? reason}) {
|
||||||
|
expect(find.descendant(of: find.byType(T), matching: find.text(title)), findsOneWidget, reason: reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 expectMeasureButton(double ev) {
|
||||||
|
find.descendant(
|
||||||
|
of: find.byType(MeteringMeasureButton),
|
||||||
|
matching: find.text('${ev.toStringAsFixed(1)}\n${S.current.ev}'),
|
||||||
|
);
|
||||||
|
}
|
35
integration_test/utils/expectations.dart
Normal file
35
integration_test/utils/expectations.dart
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:lightmeter/screens/metering/components/shared/exposure_pairs_list/components/exposure_pairs_list_item/widget_item_list_exposure_pairs.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:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
||||||
|
|
||||||
|
void expectPickerTitle<P extends Widget>(String title, {String? reason}) {
|
||||||
|
expect(find.descendant(of: find.byType(P), matching: find.text(title)), findsOneWidget, reason: reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
void expectExtremeExposurePairs(String fastest, String slowest, {String? reason}) {
|
||||||
|
final pickerFinder = find.byType(ExtremeExposurePairsContainer);
|
||||||
|
expect(find.descendant(of: pickerFinder, matching: find.text(fastest)), findsOneWidget, reason: reason);
|
||||||
|
expect(find.descendant(of: pickerFinder, matching: find.text(slowest)), findsOneWidget, reason: reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
void expectExposurePairsListItem(WidgetTester tester, String aperture, String shutterSpeed, {String? reason}) {
|
||||||
|
Key? findKey<T extends PhotographyStopValue<num>>(String value) => tester
|
||||||
|
.widget<Row>(
|
||||||
|
find.ancestor(
|
||||||
|
of: find.ancestor(
|
||||||
|
of: find.text(value),
|
||||||
|
matching: find.byType(ExposurePairsListItem<T>),
|
||||||
|
),
|
||||||
|
matching: find.descendant(of: find.byType(ExposurePairsList), matching: find.byType(Row)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.key;
|
||||||
|
expect(
|
||||||
|
findKey<ApertureValue>(aperture),
|
||||||
|
findKey<ShutterSpeedValue>(shutterSpeed),
|
||||||
|
reason: reason,
|
||||||
|
);
|
||||||
|
}
|
|
@ -6,6 +6,8 @@ import 'package:lightmeter/environment.dart';
|
||||||
import 'package:lightmeter/generated/l10n.dart';
|
import 'package:lightmeter/generated/l10n.dart';
|
||||||
import 'package:lightmeter/res/dimens.dart';
|
import 'package:lightmeter/res/dimens.dart';
|
||||||
import 'package:lightmeter/screens/metering/components/bottom_controls/components/measure_button/widget_button_measure.dart';
|
import 'package:lightmeter/screens/metering/components/bottom_controls/components/measure_button/widget_button_measure.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_iap/m3_lightmeter_iap.dart';
|
import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart';
|
||||||
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
||||||
|
|
||||||
|
@ -13,6 +15,8 @@ import '../mocks/iap_products_mock.dart';
|
||||||
import '../mocks/paid_features_mock.dart';
|
import '../mocks/paid_features_mock.dart';
|
||||||
import 'platform_channel_mock.dart';
|
import 'platform_channel_mock.dart';
|
||||||
|
|
||||||
|
const mockPhotoEv100 = 8.3;
|
||||||
|
|
||||||
extension WidgetTesterCommonActions on WidgetTester {
|
extension WidgetTesterCommonActions on WidgetTester {
|
||||||
Future<void> pumpApplication({
|
Future<void> pumpApplication({
|
||||||
IAPProductStatus productStatus = IAPProductStatus.purchased,
|
IAPProductStatus productStatus = IAPProductStatus.purchased,
|
||||||
|
@ -89,3 +93,22 @@ extension WidgetTesterTextButtonActions on WidgetTester {
|
||||||
await pumpAndSettle();
|
await pumpAndSettle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension WidgetTesterExposurePairsListActions on WidgetTester {
|
||||||
|
Future<void> scrollToTheLastExposurePair({
|
||||||
|
double ev = mockPhotoEv100,
|
||||||
|
StopType stopType = StopType.third,
|
||||||
|
EquipmentProfile equipmentProfile = defaultEquipmentProfile,
|
||||||
|
}) async {
|
||||||
|
final exposurePairs = MeteringContainerBuidler.buildExposureValues(
|
||||||
|
ev,
|
||||||
|
StopType.third,
|
||||||
|
equipmentProfile,
|
||||||
|
);
|
||||||
|
await 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)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue