From 4f1908c200f95589cb7d4dd116567ba8f50a7554 Mon Sep 17 00:00:00 2001 From: Vadim <44135514+vodemn@users.noreply.github.com> Date: Tue, 17 Oct 2023 12:00:32 +0200 Subject: [PATCH] removed mockito mocks for integration tests From no on these are the only mocks in use: - Mock shared prefs initial values - Mock platform responses (camera/light sensor) --- integration_test/generate_screenshots.dart | 286 +++++++----------- .../mocks/paid_features_mock.dart | 58 +--- .../utils/widget_tester_actions.dart | 54 +++- lib/application_wrapper.dart | 30 +- lib/main_dev.dart | 11 +- lib/main_prod.dart | 10 +- lib/main_release.dart | 10 +- 7 files changed, 202 insertions(+), 257 deletions(-) diff --git a/integration_test/generate_screenshots.dart b/integration_test/generate_screenshots.dart index 2000d3d..2a6bc99 100644 --- a/integration_test/generate_screenshots.dart +++ b/integration_test/generate_screenshots.dart @@ -1,200 +1,139 @@ +import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; -import 'package:lightmeter/application.dart'; -import 'package:lightmeter/data/caffeine_service.dart'; -import 'package:lightmeter/data/haptics_service.dart'; -import 'package:lightmeter/data/light_sensor_service.dart'; import 'package:lightmeter/data/models/ev_source_type.dart'; import 'package:lightmeter/data/models/metering_screen_layout_config.dart'; -import 'package:lightmeter/data/models/supported_locale.dart'; import 'package:lightmeter/data/models/theme_type.dart'; import 'package:lightmeter/data/models/volume_action.dart'; -import 'package:lightmeter/data/permissions_service.dart'; import 'package:lightmeter/data/shared_prefs_service.dart'; -import 'package:lightmeter/data/volume_events_service.dart'; -import 'package:lightmeter/environment.dart'; import 'package:lightmeter/generated/l10n.dart'; -import 'package:lightmeter/providers/services_provider.dart'; -import 'package:lightmeter/providers/user_preferences_provider.dart'; import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/theme.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/iso_picker/widget_picker_iso.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/settings/components/metering/components/equipment_profiles/components/equipment_profile_screen/components/equipment_profile_container/widget_container_equipment_profile.dart'; -import 'package:lightmeter/screens/settings/components/metering/components/equipment_profiles/components/equipment_profile_screen/screen_equipment_profile.dart'; -import 'package:lightmeter/screens/settings/screen_settings.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; -import 'package:mocktail/mocktail.dart'; -import 'package:permission_handler/permission_handler.dart'; +import 'package:shared_preferences/shared_preferences.dart'; -import 'mocks/paid_features_mock.dart'; - -class _MockUserPreferencesService extends Mock implements UserPreferencesService {} - -class _MockCaffeineService extends Mock implements CaffeineService {} - -class _MockHapticsService extends Mock implements HapticsService {} - -class _MockPermissionsService extends Mock implements PermissionsService {} - -class _MockLightSensorService extends Mock implements LightSensorService {} - -class _MockVolumeEventsService extends Mock implements VolumeEventsService {} +import 'utils/platform_channel_mock.dart'; +import 'utils/widget_tester_actions.dart'; //https://stackoverflow.com/a/67186625/13167574 void main() { - late _MockUserPreferencesService mockUserPreferencesService; - late _MockCaffeineService mockCaffeineService; - late _MockHapticsService mockHapticsService; - late _MockPermissionsService mockPermissionsService; - late _MockLightSensorService mockLightSensorService; - late _MockVolumeEventsService mockVolumeEventsService; - final binding = IntegrationTestWidgetsFlutterBinding(); IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + final Color lightThemeColor = primaryColorsList[5]; + final Color darkThemeColor = primaryColorsList[3]; - setUpAll(() { - mockUserPreferencesService = _MockUserPreferencesService(); - when(() => mockUserPreferencesService.evSourceType).thenReturn(EvSourceType.camera); - when(() => mockUserPreferencesService.stopType).thenReturn(StopType.third); - when(() => mockUserPreferencesService.locale).thenReturn(SupportedLocale.en); - when(() => mockUserPreferencesService.caffeine).thenReturn(true); - when(() => mockUserPreferencesService.volumeAction).thenReturn(VolumeAction.shutter); - when(() => mockUserPreferencesService.cameraEvCalibration).thenReturn(0.0); - when(() => mockUserPreferencesService.lightSensorEvCalibration).thenReturn(0.0); - when(() => mockUserPreferencesService.iso).thenReturn(const IsoValue(400, StopType.full)); - when(() => mockUserPreferencesService.ndFilter).thenReturn(NdValue.values.first); - when(() => mockUserPreferencesService.haptics).thenReturn(true); - when(() => mockUserPreferencesService.meteringScreenLayout).thenReturn({ - MeteringScreenLayoutFeature.equipmentProfiles: true, - MeteringScreenLayoutFeature.extremeExposurePairs: true, - MeteringScreenLayoutFeature.filmPicker: true, - MeteringScreenLayoutFeature.histogram: false, - }); - when(() => mockUserPreferencesService.themeType).thenReturn(ThemeType.light); - when(() => mockUserPreferencesService.dynamicColor).thenReturn(false); + void mockSharedPrefs(ThemeType theme, Color color) { + setUp(() { + SharedPreferences.setMockInitialValues({ + /// Metering values + UserPreferencesService.evSourceTypeKey: EvSourceType.camera.index, + UserPreferencesService.isoKey: 400, + UserPreferencesService.ndFilterKey: 0, - mockCaffeineService = _MockCaffeineService(); - when(() => mockCaffeineService.isKeepScreenOn()).thenAnswer((_) async => false); - when(() => mockCaffeineService.keepScreenOn(true)).thenAnswer((_) async => true); - when(() => mockCaffeineService.keepScreenOn(false)).thenAnswer((_) async => false); - - mockHapticsService = _MockHapticsService(); - when(() => mockHapticsService.quickVibration()).thenAnswer((_) async {}); - when(() => mockHapticsService.responseVibration()).thenAnswer((_) async {}); - when(() => mockHapticsService.errorVibration()).thenAnswer((_) async {}); - - mockPermissionsService = _MockPermissionsService(); - when(() => mockPermissionsService.requestCameraPermission()) - .thenAnswer((_) async => PermissionStatus.granted); - when(() => mockPermissionsService.checkCameraPermission()) - .thenAnswer((_) async => PermissionStatus.granted); - - mockLightSensorService = _MockLightSensorService(); - when(() => mockLightSensorService.hasSensor()).thenAnswer((_) async => true); - when(() => mockLightSensorService.luxStream()).thenAnswer((_) => Stream.fromIterable([100])); - - mockVolumeEventsService = _MockVolumeEventsService(); - when(() => mockVolumeEventsService.setVolumeHandling(true)).thenAnswer((_) async => true); - when(() => mockVolumeEventsService.setVolumeHandling(false)).thenAnswer((_) async => false); - when(() => mockVolumeEventsService.volumeButtonsEventStream()) - .thenAnswer((_) => const Stream.empty()); - - when(() => mockHapticsService.quickVibration()).thenAnswer((_) async {}); - when(() => mockHapticsService.responseVibration()).thenAnswer((_) async {}); - }); - - Future pumpApplication(WidgetTester tester) async { - await tester.pumpWidget( - MockIAPProviders.purchased( - selectedFilm: mockFilms.first, - child: ServicesProvider( - environment: const Environment.prod().copyWith(hasLightSensor: true), - userPreferencesService: mockUserPreferencesService, - caffeineService: mockCaffeineService, - hapticsService: mockHapticsService, - permissionsService: mockPermissionsService, - lightSensorService: mockLightSensorService, - volumeEventsService: mockVolumeEventsService, - child: const UserPreferencesProvider(child: Application()), + /// Metering settings + UserPreferencesService.stopTypeKey: StopType.third.index, + UserPreferencesService.cameraEvCalibrationKey: 0.0, + UserPreferencesService.lightSensorEvCalibrationKey: 0.0, + UserPreferencesService.meteringScreenLayoutKey: json.encode( + { + MeteringScreenLayoutFeature.equipmentProfiles: true, + MeteringScreenLayoutFeature.extremeExposurePairs: true, + MeteringScreenLayoutFeature.filmPicker: true, + MeteringScreenLayoutFeature.histogram: false, + }.toJson(), ), - ), - ); - await tester.pumpAndSettle(); - } - /// Generates several screenshots with the light theme - /// and the additionally the first one with the dark theme - void generateScreenshots(Color color) { - testWidgets('${color.value}_light', (tester) async { - when(() => mockUserPreferencesService.themeType).thenReturn(ThemeType.light); - when(() => mockUserPreferencesService.primaryColor).thenReturn(color); - await pumpApplication(tester); + /// General settings + UserPreferencesService.caffeineKey: true, + UserPreferencesService.hapticsKey: true, + UserPreferencesService.volumeActionKey: VolumeAction.shutter.toString(), + UserPreferencesService.localeKey: 'en', - await tester.takePhoto(); - await tester.takeScreenshot(binding, '${color.value}_metering_reflected'); - - await tester.tap(find.byTooltip(S.current.tooltipUseLightSensor)); - await tester.pumpAndSettle(); - await tester.tap(find.byType(MeteringMeasureButton)); - await tester.tap(find.byType(MeteringMeasureButton)); - await tester.takeScreenshot(binding, '${color.value}_metering_incident'); - - expect(find.byType(IsoValuePicker), findsOneWidget); - await tester.tap(find.byType(IsoValuePicker)); - await tester.pumpAndSettle(Dimens.durationL); - expect(find.byType(DialogPicker), findsOneWidget); - await tester.takeScreenshot(binding, '${color.value}_metering_iso_picker'); - - await tester.tapCancelButton(); - expect(find.byType(DialogPicker), findsNothing); - expect(find.byTooltip(S.current.tooltipOpenSettings), findsOneWidget); - await tester.tap(find.byTooltip(S.current.tooltipOpenSettings)); - await tester.pumpAndSettle(); - expect(find.byType(SettingsScreen), findsOneWidget); - await tester.takeScreenshot(binding, '${color.value}_settings'); - - await tester.tapListTile(S.current.meteringScreenLayout); - await tester.takeScreenshot(binding, '${color.value}_settings_metering_screen_layout'); - - await tester.tapCancelButton(); - await tester.tapListTile(S.current.equipmentProfiles); - expect(find.byType(EquipmentProfilesScreen), findsOneWidget); - await tester.tap(find.byType(EquipmentProfileContainer).first); - await tester.pumpAndSettle(); - await tester.takeScreenshot(binding, '${color.value}-equipment_profiles'); - - await tester.tap(find.byIcon(Icons.iso).first); - await tester.pumpAndSettle(); - await tester.takeScreenshot(binding, '${color.value}_equipment_profiles_iso_picker'); + /// Theme settings + UserPreferencesService.themeTypeKey: theme.index, + UserPreferencesService.primaryColorKey: color.value, + UserPreferencesService.dynamicColorKey: false, + }); }); - - testWidgets( - '${color.value}_dark', - (tester) async { - when(() => mockUserPreferencesService.themeType).thenReturn(ThemeType.dark); - when(() => mockUserPreferencesService.primaryColor).thenReturn(color); - await pumpApplication(tester); - - await tester.takePhoto(); - await tester.takeScreenshot(binding, '${color.value}_metering_reflected_dark'); - - await tester.tap(find.byTooltip(S.current.tooltipUseLightSensor)); - await tester.pumpAndSettle(); - await tester.tap(find.byType(MeteringMeasureButton)); - await tester.tap(find.byType(MeteringMeasureButton)); - await tester.takeScreenshot(binding, '${color.value}_metering_incident_dark'); - }, - ); } - generateScreenshots(primaryColorsList[5]); - generateScreenshots(primaryColorsList[3]); - generateScreenshots(primaryColorsList[9]); + group( + 'Light theme', + () { + mockSharedPrefs(ThemeType.light, lightThemeColor); + testWidgets( + 'Generate light screenshots', + (tester) async { + await tester.pumpApplication(); + + await tester.takePhoto(); + await tester.takeScreenshot(binding, '${lightThemeColor.value}_metering_reflected'); + + if (Platform.isAndroid) { + await tester.tap(find.byTooltip(S.current.tooltipUseLightSensor)); + await tester.pumpAndSettle(); + await tester.tap(find.byType(MeteringMeasureButton)); + await sendMockIncidentEv(7.3); + await tester.tap(find.byType(MeteringMeasureButton)); + await tester.takeScreenshot(binding, '${lightThemeColor.value}_metering_incident'); + } + + await tester.tap(find.byType(IsoValuePicker)); + await tester.pumpAndSettle(Dimens.durationL); + await tester.takeScreenshot(binding, '${lightThemeColor.value}_metering_iso_picker'); + + await tester.tapCancelButton(); + await tester.tap(find.byTooltip(S.current.tooltipOpenSettings)); + await tester.pumpAndSettle(); + await tester.takeScreenshot(binding, '${lightThemeColor.value}_settings'); + + await tester.tapListTile(S.current.meteringScreenLayout); + await tester.takeScreenshot(binding, '${lightThemeColor.value}_settings_metering_screen_layout'); + + await tester.tapCancelButton(); + await tester.tapListTile(S.current.equipmentProfiles); + await tester.tap(find.byType(EquipmentProfileContainer).first); + await tester.pumpAndSettle(); + await tester.takeScreenshot(binding, '${lightThemeColor.value}-equipment_profiles'); + + await tester.tap(find.byIcon(Icons.iso).first); + await tester.pumpAndSettle(); + await tester.takeScreenshot(binding, '${lightThemeColor.value}_equipment_profiles_iso_picker'); + }, + ); + }, + ); + + group( + 'Dark theme', + () { + mockSharedPrefs(ThemeType.dark, darkThemeColor); + testWidgets( + 'Generate dark screenshots', + (tester) async { + await tester.pumpApplication(); + + await tester.takePhoto(); + await tester.takeScreenshot(binding, '${darkThemeColor.value}_metering_reflected'); + + if (Platform.isAndroid) { + await tester.tap(find.byTooltip(S.current.tooltipUseLightSensor)); + await tester.pumpAndSettle(); + await tester.tap(find.byType(MeteringMeasureButton)); + await sendMockIncidentEv(7.3); + await tester.tap(find.byType(MeteringMeasureButton)); + await tester.takeScreenshot(binding, '${darkThemeColor.value}_metering_incident'); + } + }, + ); + }, + ); } extension on WidgetTester { @@ -214,22 +153,9 @@ extension on WidgetTester { await pumpAndSettle(); } - Future tapCancelButton() async { - final cancelButton = find.byWidgetPredicate( - (widget) => - widget is TextButton && - widget.child is Text && - (widget.child as Text?)?.data == S.current.cancel, - ); - expect(cancelButton, findsOneWidget); - await tap(cancelButton); - await pumpAndSettle(); - } - Future tapListTile(String title) async { final listTile = find.byWidgetPredicate( - (widget) => - widget is ListTile && widget.title is Text && (widget.title as Text?)?.data == title, + (widget) => widget is ListTile && widget.title is Text && (widget.title as Text?)?.data == title, ); expect(listTile, findsOneWidget); await tap(listTile); diff --git a/integration_test/mocks/paid_features_mock.dart b/integration_test/mocks/paid_features_mock.dart index da358c9..fe99260 100644 --- a/integration_test/mocks/paid_features_mock.dart +++ b/integration_test/mocks/paid_features_mock.dart @@ -8,7 +8,6 @@ import 'package:mocktail/mocktail.dart'; class _MockIAPStorageService extends Mock implements IAPStorageService {} class MockIAPProviders extends StatefulWidget { - final IAPProductStatus purchaseStatus; final String selectedEquipmentProfileId; final Film selectedFilm; final Widget child; @@ -16,25 +15,10 @@ class MockIAPProviders extends StatefulWidget { const MockIAPProviders({ this.selectedEquipmentProfileId = '', this.selectedFilm = const Film.other(), - required this.purchaseStatus, required this.child, super.key, }); - const MockIAPProviders.purchasable({ - this.selectedEquipmentProfileId = '', - this.selectedFilm = const Film.other(), - required this.child, - super.key, - }) : purchaseStatus = IAPProductStatus.purchasable; - - const MockIAPProviders.purchased({ - this.selectedEquipmentProfileId = '', - this.selectedFilm = const Film.other(), - required this.child, - super.key, - }) : purchaseStatus = IAPProductStatus.purchased; - @override State createState() => _MockIAPProvidersState(); } @@ -47,30 +31,19 @@ class _MockIAPProvidersState extends State { super.initState(); mockIAPStorageService = _MockIAPStorageService(); when(() => mockIAPStorageService.equipmentProfiles).thenReturn(mockEquipmentProfiles); - when(() => mockIAPStorageService.selectedEquipmentProfileId) - .thenReturn(widget.selectedEquipmentProfileId); + when(() => mockIAPStorageService.selectedEquipmentProfileId).thenReturn(widget.selectedEquipmentProfileId); when(() => mockIAPStorageService.filmsInUse).thenReturn(mockFilms); when(() => mockIAPStorageService.selectedFilm).thenReturn(widget.selectedFilm); } @override Widget build(BuildContext context) { - return IAPProductsProvider( - child: IAPProducts( - products: [ - IAPProduct( - storeId: IAPProductType.paidFeatures.storeId, - status: widget.purchaseStatus, - ) - ], - child: EquipmentProfileProvider( - storageService: mockIAPStorageService, - child: FilmsProvider( - storageService: mockIAPStorageService, - availableFilms: mockFilms, - child: widget.child, - ), - ), + return EquipmentProfileProvider( + storageService: mockIAPStorageService, + child: FilmsProvider( + storageService: mockIAPStorageService, + availableFilms: mockFilms, + child: widget.child, ), ); } @@ -120,18 +93,13 @@ final mockEquipmentProfiles = [ ), ]; -const mockFilms = [_MockFilm2x(), _MockFilm3x()]; +const mockFilms = [_MockFilm(400, 2), _MockFilm(3, 800), _MockFilm(400, 1.5)]; -class _MockFilm2x extends Film { - const _MockFilm2x() : super('Mock film 2x', 400); +class _MockFilm extends Film { + final double reciprocityMultiplier; + + const _MockFilm(int iso, this.reciprocityMultiplier) : super('Mock film $iso x$reciprocityMultiplier', iso); @override - double reciprocityFormula(double t) => t * 2; -} - -class _MockFilm3x extends Film { - const _MockFilm3x() : super('Mock film 3x', 800); - - @override - double reciprocityFormula(double t) => t * 3; + double reciprocityFormula(double t) => t * reciprocityMultiplier; } diff --git a/integration_test/utils/widget_tester_actions.dart b/integration_test/utils/widget_tester_actions.dart index 2c6f8c0..22c1e20 100644 --- a/integration_test/utils/widget_tester_actions.dart +++ b/integration_test/utils/widget_tester_actions.dart @@ -1,8 +1,49 @@ 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/bottom_controls/components/measure_button/widget_button_measure.dart'; +import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart'; +import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; + +import '../mocks/paid_features_mock.dart'; + +extension WidgetTesterCommonActions on WidgetTester { + Future pumpApplication({ + IAPProductStatus productStatus = IAPProductStatus.purchased, + String selectedEquipmentProfileId = '', + Film selectedFilm = const Film.other(), + }) async { + await pumpWidget( + MockIAPProductsProvider( + productStatus: productStatus, + child: ApplicationWrapper( + const Environment.dev(), + child: MockIAPProviders( + selectedEquipmentProfileId: selectedEquipmentProfileId, + selectedFilm: selectedFilm, + child: const Application(), + ), + ), + ), + ); + await pumpAndSettle(); + } + + Future toggleIncidentMetering() async { + await tap(find.byType(MeteringMeasureButton)); + await tap(find.byType(MeteringMeasureButton)); + await pumpAndSettle(); + } + + Future openAnimatedPicker() async { + await tap(find.byType(T)); + await pumpAndSettle(Dimens.durationL); + } +} extension WidgetTesterTextButtonActions on WidgetTester { Future tapSelectButton() => _tapTextButton(S.current.select); @@ -20,16 +61,3 @@ extension WidgetTesterTextButtonActions on WidgetTester { await pumpAndSettle(); } } - -extension WidgetTesterCommonActions on WidgetTester { - Future toggleIncidentMetering() async { - await tap(find.byType(MeteringMeasureButton)); - await tap(find.byType(MeteringMeasureButton)); - await pumpAndSettle(); - } - - Future openAnimatedPicker() async { - await tap(find.byType(T)); - await pumpAndSettle(Dimens.durationL); - } -} diff --git a/lib/application_wrapper.dart b/lib/application_wrapper.dart index fe53aec..364f9a2 100644 --- a/lib/application_wrapper.dart +++ b/lib/application_wrapper.dart @@ -30,23 +30,21 @@ class ApplicationWrapper extends StatelessWidget { builder: (_, snapshot) { if (snapshot.data != null) { final iapService = IAPStorageService(snapshot.data![0] as SharedPreferences); - return IAPProductsProvider( - child: ServicesProvider( - caffeineService: const CaffeineService(), - environment: env.copyWith(hasLightSensor: snapshot.data![1] as bool), - hapticsService: const HapticsService(), - lightSensorService: const LightSensorService(LocalPlatform()), - permissionsService: const PermissionsService(), - userPreferencesService: - UserPreferencesService(snapshot.data![0] as SharedPreferences), - volumeEventsService: const VolumeEventsService(LocalPlatform()), - child: EquipmentProfileProvider( + return ServicesProvider( + caffeineService: const CaffeineService(), + environment: env.copyWith(hasLightSensor: snapshot.data![1] as bool), + hapticsService: const HapticsService(), + lightSensorService: const LightSensorService(LocalPlatform()), + permissionsService: const PermissionsService(), + userPreferencesService: + UserPreferencesService(snapshot.data![0] as SharedPreferences), + volumeEventsService: const VolumeEventsService(LocalPlatform()), + child: EquipmentProfileProvider( + storageService: iapService, + child: FilmsProvider( storageService: iapService, - child: FilmsProvider( - storageService: iapService, - child: UserPreferencesProvider( - child: child, - ), + child: UserPreferencesProvider( + child: child, ), ), ), diff --git a/lib/main_dev.dart b/lib/main_dev.dart index 9ef3faf..24191be 100644 --- a/lib/main_dev.dart +++ b/lib/main_dev.dart @@ -2,8 +2,17 @@ import 'package:flutter/material.dart'; import 'package:lightmeter/application.dart'; import 'package:lightmeter/application_wrapper.dart'; import 'package:lightmeter/environment.dart'; +import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); - runApp(const ApplicationWrapper(Environment.dev(), child: Application())); + runApp( + const MockIAPProductsProvider( + productStatus: IAPProductStatus.purchasable, + child: ApplicationWrapper( + Environment.dev(), + child: Application(), + ), + ), + ); } diff --git a/lib/main_prod.dart b/lib/main_prod.dart index b75513e..3460f32 100644 --- a/lib/main_prod.dart +++ b/lib/main_prod.dart @@ -3,9 +3,17 @@ import 'package:lightmeter/application.dart'; import 'package:lightmeter/application_wrapper.dart'; import 'package:lightmeter/environment.dart'; import 'package:lightmeter/firebase.dart'; +import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); await initializeFirebase(handleErrors: true); - runApp(const ApplicationWrapper(Environment.prod(), child: Application())); + runApp( + const IAPProductsProvider( + child: ApplicationWrapper( + Environment.prod(), + child: Application(), + ), + ), + ); } diff --git a/lib/main_release.dart b/lib/main_release.dart index bb6384a..eea83e2 100644 --- a/lib/main_release.dart +++ b/lib/main_release.dart @@ -3,9 +3,17 @@ import 'package:lightmeter/application.dart'; import 'package:lightmeter/application_wrapper.dart'; import 'package:lightmeter/environment.dart'; import 'package:lightmeter/firebase.dart'; +import 'package:m3_lightmeter_iap/m3_lightmeter_iap.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); await initializeFirebase(handleErrors: false); - runApp(const ApplicationWrapper(Environment.prod(), child: Application())); + runApp( + const IAPProductsProvider( + child: ApplicationWrapper( + Environment.prod(), + child: Application(), + ), + ), + ); }