Compare commits

...

2 commits

Author SHA1 Message Date
Vadim
aa3d9ddec1 added test for guard Pro tap 2025-08-12 13:36:53 +02:00
Vadim
cff78ecf1e typo 2025-08-12 11:01:29 +02:00
6 changed files with 91 additions and 7 deletions

View file

@ -0,0 +1,79 @@
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/equipment_profile_edit/screen_equipment_profile_edit.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';
import 'package:lightmeter/utils/platform_utils.dart';
import 'package:meta/meta.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../integration_test/utils/widget_tester_actions.dart';
import 'mocks/iap_products_mock.dart';
@isTest
void testGuardProTap(String description) {
testWidgets(
description,
(tester) async {
SharedPreferences.setMockInitialValues({
/// Metering values
UserPreferencesService.evSourceTypeKey: EvSourceType.camera.index,
UserPreferencesService.meteringScreenLayoutKey: json.encode(
{
MeteringScreenLayoutFeature.equipmentProfiles: true,
MeteringScreenLayoutFeature.extremeExposurePairs: true,
MeteringScreenLayoutFeature.filmPicker: true,
}.toJson(),
),
UserPreferencesService.seenChangelogVersionKey: await const PlatformUtils().version,
});
await tester.pumpApplication(isPro: false);
await tester.openSettings();
await tester.tapDescendantTextOf<SettingsScreen>(S.current.equipmentProfiles);
/// Try adding a new equipment profile
await tester.tap(find.byIcon(Icons.add_outlined).first);
await tester.pumpAndSettle();
expect(find.byType(LightmeterProScreen), findsOneWidget);
/// Purchase Pro
(tester.state(find.byType(MockIAPProductsProvider)) as MockIAPProductsProviderState).buy();
await tester.navigatorPop(true);
await tester.pumpAndSettle();
expect(find.byType(LightmeterProScreen), findsNothing);
expect(find.byType(EquipmentProfileEditScreen), findsOneWidget);
await tester.navigatorPop();
await tester.navigatorPop();
/// Refund
(tester.state(find.byType(MockIAPProductsProvider)) as MockIAPProductsProviderState).clearPurchases();
await tester.pumpAndSettle();
await tester.tapDescendantTextOf<SettingsScreen>(S.current.logbook);
/// Try enabling logbook
await tester.tap(find.text(S.current.saveNewPhotos));
await tester.pumpAndSettle();
expect(find.byType(LightmeterProScreen), findsOneWidget);
(tester.state(find.byType(MockIAPProductsProvider)) as MockIAPProductsProviderState).buy();
await tester.navigatorPop(true);
await tester.pumpAndSettle();
expect(find.byType(LightmeterProScreen), findsNothing);
await tester.pumpAndSettle();
expect(
find.descendant(
of: find.byType(LogbookPhotosScreen),
matching: find.byWidgetPredicate((widget) => widget is SwitchListTile && widget.value),
),
findsOneWidget,
);
},
);
}

View file

@ -2,6 +2,7 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'e2e_test.dart';
import 'guard_pro_tap_test.dart';
import 'logbook_test.dart';
import 'metering_screen_layout_test.dart';
import 'purchases_test.dart';
@ -19,6 +20,7 @@ void main() {
});
testPurchases('Purchase & refund premium features');
testGuardProTap('Guard Pro tap');
testToggleLayoutFeatures('Toggle metering screen layout features');
testLogbook('Logbook');
testE2E('e2e');

View file

@ -68,8 +68,8 @@ extension WidgetTesterCommonActions on WidgetTester {
await pumpAndSettle();
}
Future<void> navigatorPop() async {
(state(find.byType(Navigator)) as NavigatorState).pop();
Future<void> navigatorPop([Object? result]) async {
(state(find.byType(Navigator)) as NavigatorState).pop(result);
await pumpAndSettle(Dimens.durationML);
}
}

View file

@ -115,7 +115,7 @@ class _LightmeterProScreenState extends State<LightmeterProScreen> {
try {
final isPro = await IAPProductsProvider.of(context).restorePurchases();
if (mounted && isPro) {
Navigator.of(context).pop();
Navigator.of(context).pop(true);
}
} on PlatformException catch (e) {
_showSnackbar(e.message ?? '');
@ -131,7 +131,7 @@ class _LightmeterProScreenState extends State<LightmeterProScreen> {
try {
final isPro = await IAPProductsProvider.of(context).buyPro(product);
if (mounted && isPro) {
Navigator.of(context).pop();
Navigator.of(context).pop(true);
}
} on PlatformException catch (e) {
_showSnackbar(e.message ?? '');

View file

@ -20,7 +20,7 @@ class AboutSettingsSection extends StatelessWidget {
const ReportIssueListTile(),
const WriteEmailListTile(),
const VersionListTile(),
if (context.isPro) const RestorePurchasesListTile(),
if (!context.isPro) const RestorePurchasesListTile(),
],
);
}

View file

@ -2,10 +2,13 @@ import 'package:flutter/material.dart';
import 'package:lightmeter/navigation/routes.dart';
import 'package:lightmeter/utils/context_utils.dart';
void guardProTap(BuildContext context, VoidCallback callback) {
Future<void> guardProTap(BuildContext context, VoidCallback callback) async {
if (context.isPro) {
callback();
} else {
Navigator.of(context).pushNamed(NavigationRoutes.proFeaturesScreen.name);
final isPro = await Navigator.of(context).pushNamed(NavigationRoutes.proFeaturesScreen.name);
if (isPro == true) {
callback();
}
}
}