mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2025-08-17 18:46:47 +00:00

* typos * added `LogbookPhotosProvider` * implemented `LogbookScreen` * implemented `LogbookPhotoEditScreen` * added photo update * save geolocation * added `CameraSettingsSection` * adjusted logbook grid * added hero animation * fixed logbook list updates * added empty logbook state * added `saveLogbookPhotos` option * fixed updating photos * made `DialogPicker` content scrollable * added tests for `LogbookPhotosProvider` * made image preview full-width * made note field multiline * wip * migrated to new iap service * fixed unit tests * typo * fixed arb formatting * stub logbook photos for tests * implemented integration test for logbook * moved date to title * redundant bottom padding * added logbook photo screen to screenshots generator * Update settings.gradle * aligned iap stub with iap release * sync * made logbook iap * debug screenshots * Update runner.dart * fixed dialog picker of optional values * added bottom padding to logbook edit screen * fixed tests * Create camera_stub_image.jpg * Update films_provider_test.dart * rename * aligned with iap * added missing translations * theme * adjusted products color * check pro status on settings open * added yearly subscription * handle purchase errors * fixed bottom navigation bar behaviour * handle only lifetime product case * don't fetch products * reworked restoring purchases * fixed mocks * fixed golden tests * fixed logbook integration test * sync pubspec * sync stub
119 lines
4 KiB
Dart
119 lines
4 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:lightmeter/application.dart';
|
|
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/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';
|
|
|
|
import '../mocks/iap_products_mock.dart';
|
|
import '../mocks/paid_features_mock.dart';
|
|
import 'finder_actions.dart';
|
|
import 'platform_channel_mock.dart';
|
|
|
|
const mockPhotoEv100 = 8.3;
|
|
|
|
extension WidgetTesterCommonActions on WidgetTester {
|
|
Future<void> pumpApplication({
|
|
bool isPro = true,
|
|
TogglableMap<EquipmentProfile>? equipmentProfiles,
|
|
String selectedEquipmentProfileId = '',
|
|
TogglableMap<Film>? predefinedFilms,
|
|
TogglableMap<FilmExponential>? customFilms,
|
|
String selectedFilmId = '',
|
|
}) async {
|
|
await pumpWidget(
|
|
MockIAPProductsProvider(
|
|
initialyPurchased: isPro,
|
|
child: ApplicationWrapper(
|
|
const Environment.dev(),
|
|
child: MockIAPProviders(
|
|
equipmentProfiles: equipmentProfiles,
|
|
selectedEquipmentProfileId: selectedEquipmentProfileId,
|
|
predefinedFilms: predefinedFilms,
|
|
customFilms: customFilms,
|
|
selectedFilmId: selectedFilmId,
|
|
child: const Application(),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
await pumpAndSettle();
|
|
}
|
|
|
|
Future<void> takePhoto() async {
|
|
await tap(find.measureButton());
|
|
await pump(const Duration(seconds: 2)); // wait for circular progress indicator
|
|
await pump(const Duration(seconds: 1)); // wait for circular progress indicator
|
|
await pumpAndSettle();
|
|
}
|
|
|
|
Future<void> toggleIncidentMetering(double ev) async {
|
|
await tap(find.measureButton());
|
|
await sendMockIncidentEv(ev);
|
|
await tap(find.measureButton());
|
|
await pumpAndSettle();
|
|
}
|
|
|
|
Future<void> openAnimatedPicker<T>() async {
|
|
await tap(find.byType(T));
|
|
await pumpAndSettle(Dimens.durationL);
|
|
}
|
|
|
|
Future<void> openSettings() async {
|
|
await tap(find.byTooltip(S.current.tooltipOpenSettings));
|
|
await pumpAndSettle();
|
|
}
|
|
|
|
Future<void> navigatorPop() async {
|
|
(state(find.byType(Navigator)) as NavigatorState).pop();
|
|
await pumpAndSettle(Dimens.durationML);
|
|
}
|
|
}
|
|
|
|
extension WidgetTesterListTileActions on WidgetTester {
|
|
/// Useful for tapping a specific [ListTile] inside a specific screen or dialog
|
|
Future<void> tapDescendantTextOf<T>(String text) async {
|
|
await tap(find.descendant(of: find.byType(T), matching: find.text(text)));
|
|
await pumpAndSettle();
|
|
}
|
|
}
|
|
|
|
extension WidgetTesterTextButtonActions on WidgetTester {
|
|
Future<void> tapSelectButton() => _tapTextButton(S.current.select);
|
|
|
|
Future<void> tapCancelButton() => _tapTextButton(S.current.cancel);
|
|
|
|
Future<void> tapSaveButton() => _tapTextButton(S.current.save);
|
|
|
|
Future<void> _tapTextButton(String text) async {
|
|
final button = find.byWidgetPredicate(
|
|
(widget) => widget is TextButton && widget.child is Text && (widget.child as Text?)?.data == text,
|
|
);
|
|
expect(button, findsOneWidget);
|
|
await tap(button);
|
|
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)),
|
|
);
|
|
}
|
|
}
|