Compare commits

...

2 commits

Author SHA1 Message Date
Vadim
c2f72bbf99
Merge 960c2360d2 into 3aa0014b6a 2025-09-06 12:06:58 +02:00
Vadim
960c2360d2 fixed tests 2025-09-06 12:06:53 +02:00
8 changed files with 98 additions and 60 deletions

View file

@ -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<SettingsScreen>(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<EquipmentProfilePicker, EquipmentProfile>(mockEquipmentProfiles[0].name);
await tester.openPickerAndSelect<EquipmentProfilePicker, IEquipmentProfile>(mockEquipmentProfiles[0].name);
await tester.openPickerAndSelect<FilmPicker, Film>(mockFilms[0].name);
await tester.openPickerAndSelect<IsoValuePicker, IsoValue>('400');
expectPickerTitle<EquipmentProfilePicker>(mockEquipmentProfiles[0].name);
@ -122,7 +121,7 @@ void testE2E(String description) {
// );
/// Select another lens without ND
await tester.openPickerAndSelect<EquipmentProfilePicker, EquipmentProfile>(mockEquipmentProfiles[1].name);
await tester.openPickerAndSelect<EquipmentProfilePicker, IEquipmentProfile>(mockEquipmentProfiles[1].name);
await tester.openPickerAndSelect<NdValuePicker, NdValue>('None');
await _expectMeteringStateAndMeasure(
tester,
@ -152,8 +151,7 @@ void testE2E(String description) {
/// Delete profile
await tester.openSettings();
await tester.tapDescendantTextOf<SettingsScreen>(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);

View file

@ -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();

View file

@ -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<SettingsScreen>(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);

View file

@ -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',

View file

@ -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<void> 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<void> editEquipmentProfile(String name) async {
await tap(find.byIcon(Icons.edit_outlined).at(mockProfiles.indexWhere((p) => p.name == name)));
await pumpAndSettle();
}
}

View file

@ -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<EquipmentProfileType?> show(BuildContext context) {
return showDialog<EquipmentProfileType>(
context: context,
builder: (_) => const EquipmentProfilesTypePicker._(),
);
}
@override
Widget build(BuildContext context) {
return 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,
},
);
}
}

View file

@ -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<EquipmentProfilesScreen> 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,

View file

@ -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,11 +261,13 @@ extension on WidgetTester {
_takeScreenshot(binding, name, _themeDark);
Future<void> _takeScreenshot(IntegrationTestWidgetsFlutterBinding binding, String name, ThemeData theme) async {
const deviceName = String.fromEnvironment('deviceName');
if (deviceName.isNotEmpty) {
final Color backgroundColor = theme.colorScheme.surface;
await binding.takeScreenshot(
ScreenshotArgs(
name: name,
deviceName: const String.fromEnvironment('deviceName'),
deviceName: deviceName,
platformFolder: _platformFolder,
backgroundColor: backgroundColor.toInt().toRadixString(16),
isDark: theme.brightness == Brightness.dark,
@ -269,20 +275,14 @@ extension on WidgetTester {
);
await pumpAndSettle();
}
}
}
extension on WidgetTester {
Future<void> scrollToExposurePair({
double ev = mockPhotoEv100,
EquipmentProfile equipmentProfile = defaultEquipmentProfile,
required List<ExposurePair> 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,