From 66f37664d28f0f56b176596a4706da50f374940b Mon Sep 17 00:00:00 2001 From: Larry Aasen Date: Sun, 14 Jan 2024 10:44:36 -0500 Subject: [PATCH] [371] Added the parameter `dialogKey` to `UpgraderAlert` that is used by the alert dialog. --- CHANGELOG.md | 4 + example/lib/main-custom-alert.dart | 1 + example/lib/main_dialog_key.dart | 40 ++++++ lib/src/upgrade_alert.dart | 7 +- pubspec.yaml | 2 +- test/test_utils.dart | 12 ++ test/upgrade_card_test.dart | 199 +++++++++++++++++++++++++++++ test/upgrader_test.dart | 191 +-------------------------- 8 files changed, 268 insertions(+), 188 deletions(-) create mode 100644 example/lib/main_dialog_key.dart create mode 100644 test/test_utils.dart create mode 100644 test/upgrade_card_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index d758ae3e..16c9d575 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 9.0.0-alpha.3 + +- [371] Added the parameter `dialogKey` to `UpgraderAlert` that is used by the alert dialog. + ## 9.0.0-alpha.2 - Changed currentAppStoreListingURL, currentAppStoreVersion, and currentInstalledVersion from functions to getters. diff --git a/example/lib/main-custom-alert.dart b/example/lib/main-custom-alert.dart index cbc51b40..8aa45fa8 100644 --- a/example/lib/main-custom-alert.dart +++ b/example/lib/main-custom-alert.dart @@ -78,6 +78,7 @@ class MyUpgradeAlertState extends UpgradeAlertState { context: context, builder: (BuildContext context) { return AlertDialog( + key: key, title: const Text('Update?'), content: const SingleChildScrollView( child: ListBody( diff --git a/example/lib/main_dialog_key.dart b/example/lib/main_dialog_key.dart new file mode 100644 index 00000000..4f4418ce --- /dev/null +++ b/example/lib/main_dialog_key.dart @@ -0,0 +1,40 @@ +// Copyright (c) 2024 Larry Aasen. All rights reserved. + +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:upgrader/upgrader.dart'; + +final dialogKey = GlobalKey(debugLabel: 'gloabl_upgrader_alert_dialog'); + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + + // Only call clearSavedSettings() during testing to reset internal values. + await Upgrader.clearSavedSettings(); // REMOVE this for release builds + + final log = + () => print('$dialogKey mounted=${dialogKey.currentContext?.mounted}'); + unawaited(Future.delayed(Duration(seconds: 0)).then((value) => log())); + unawaited(Future.delayed(Duration(seconds: 3)).then((value) => log())); + unawaited(Future.delayed(Duration(seconds: 4)).then((value) => log())); + + runApp(MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Upgrader Example', + home: UpgradeAlert( + dialogKey: dialogKey, + child: Scaffold( + appBar: AppBar(title: Text('Upgrader Example')), + body: Center(child: Text('Checking...')), + )), + ); + } +} diff --git a/lib/src/upgrade_alert.dart b/lib/src/upgrade_alert.dart index d1d448fc..ec64db7d 100644 --- a/lib/src/upgrade_alert.dart +++ b/lib/src/upgrade_alert.dart @@ -29,6 +29,7 @@ class UpgradeAlert extends StatefulWidget { this.showLater = true, this.showReleaseNotes = true, this.cupertinoButtonTextStyle, + this.dialogKey, this.navigatorKey, this.child, }) : upgrader = upgrader ?? Upgrader.sharedInstance; @@ -71,6 +72,9 @@ class UpgradeAlert extends StatefulWidget { /// [UpgradeDialogStyle.cupertino]. Optional. final TextStyle? cupertinoButtonTextStyle; + /// The [Key] assigned to the dialog when it is shown. + final GlobalKey? dialogKey; + /// For use by the Router architecture as part of the RouterDelegate. final GlobalKey? navigatorKey; @@ -138,6 +142,7 @@ class UpgradeAlertState extends State { Future.delayed(const Duration(milliseconds: 0), () { showTheDialog( + key: widget.dialogKey ?? const Key('upgrader_alert_dialog'), context: context, title: appMessages.message(UpgraderMessage.title), message: widget.upgrader.body(appMessages), @@ -208,7 +213,7 @@ class UpgradeAlertState extends State { /// Show the alert dialog. void showTheDialog({ - Key? key = const Key('upgrader_alert_dialog'), + Key? key, required BuildContext context, required String? title, required String message, diff --git a/pubspec.yaml b/pubspec.yaml index 37072d76..c7e22d07 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: upgrader description: Flutter package for prompting users to upgrade when there is a newer version of the app in the store. -version: 9.0.0-alpha.2 +version: 9.0.0-alpha.3 homepage: https://github.com/larryaasen/upgrader environment: diff --git a/test/test_utils.dart b/test/test_utils.dart new file mode 100644 index 00000000..f5f95110 --- /dev/null +++ b/test/test_utils.dart @@ -0,0 +1,12 @@ +// Copyright (c) 2024 Larry Aasen. All rights reserved. + +import 'package:flutter/material.dart'; + +Widget wrapper(Widget child) { + return MaterialApp( + home: Scaffold( + body: child, + appBar: AppBar(title: const Text('Upgrader test')), + ), + ); +} diff --git a/test/upgrade_card_test.dart b/test/upgrade_card_test.dart new file mode 100644 index 00000000..d84c7f09 --- /dev/null +++ b/test/upgrade_card_test.dart @@ -0,0 +1,199 @@ +// Copyright (c) 2024 Larry Aasen. All rights reserved. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:package_info_plus/package_info_plus.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:upgrader/upgrader.dart'; + +import 'mock_itunes_client.dart'; +import 'test_utils.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + late SharedPreferences preferences; + + setUp(() async { + SharedPreferences.setMockInitialValues({}); + preferences = await SharedPreferences.getInstance(); + }); + + tearDown(() async { + await preferences.clear(); + return true; + }); + testWidgets('test UpgradeCard no update', (WidgetTester tester) async { + expect(Upgrader.sharedInstance.isTooSoon(), false); + + final upgradeCard = wrapper(UpgradeCard()); + await tester.pumpWidget(upgradeCard); + + // Pump the UI + await tester.pumpAndSettle(); + + expect(find.text('IGNORE'), findsNothing); + expect(find.text('LATER'), findsNothing); + expect(find.text('UPDATE'), findsNothing); + expect(find.text('Release Notes'), findsNothing); + }); + + testWidgets('test UpgradeCard upgrade', (WidgetTester tester) async { + final client = MockITunesSearchClient.setupMockClient(); + final upgrader = Upgrader( + upgraderOS: MockUpgraderOS(ios: true), + client: client, + debugLogging: true); + + upgrader.installPackageInfo( + packageInfo: PackageInfo( + appName: 'Upgrader', + packageName: 'com.larryaasen.upgrader', + version: '0.9.9', + buildNumber: '400')); + upgrader.initialize().then((value) {}); + await tester.pumpAndSettle(); + + expect(upgrader.isTooSoon(), false); + + var called = false; + var notCalled = true; + final upgradeCard = wrapper( + UpgradeCard( + upgrader: upgrader, + onUpdate: () { + called = true; + return true; + }, + onIgnore: () { + notCalled = false; + return true; + }, + onLater: () { + notCalled = false; + }, + ), + ); + await tester.pumpWidget(upgradeCard); + + // Pump the UI so the upgrade card is displayed + await tester.pumpAndSettle(); + + expect(upgrader.messages, isNull); + upgrader.messages = UpgraderMessages(); + expect(upgrader.messages, isNotNull); + + expect(find.text(upgrader.messages!.releaseNotes), findsOneWidget); + expect(find.text(upgrader.releaseNotes!), findsOneWidget); + await tester.tap(find.text(upgrader.messages!.buttonTitleUpdate)); + await tester.pumpAndSettle(); + + expect(called, true); + expect(notCalled, true); + expect(find.text(upgrader.messages!.buttonTitleUpdate), findsNothing); + }, skip: false); + + testWidgets('test UpgradeCard ignore', (WidgetTester tester) async { + final client = MockITunesSearchClient.setupMockClient(); + final upgrader = Upgrader( + upgraderOS: MockUpgraderOS(ios: true), + client: client, + debugLogging: true); + + upgrader.installPackageInfo( + packageInfo: PackageInfo( + appName: 'Upgrader', + packageName: 'com.larryaasen.upgrader', + version: '0.9.9', + buildNumber: '400')); + upgrader.initialize().then((value) {}); + await tester.pumpAndSettle(); + + expect(upgrader.isTooSoon(), false); + + var called = false; + var notCalled = true; + final upgradeCard = wrapper( + UpgradeCard( + upgrader: upgrader, + onUpdate: () { + notCalled = false; + return true; + }, + onIgnore: () { + called = true; + return true; + }, + onLater: () { + notCalled = false; + }, + ), + ); + await tester.pumpWidget(upgradeCard); + + // Pump the UI so the upgrade card is displayed + await tester.pumpAndSettle(); + + expect(upgrader.messages, isNull); + upgrader.messages = UpgraderMessages(); + expect(upgrader.messages, isNotNull); + + await tester.tap(find.text(upgrader.messages!.buttonTitleIgnore)); + await tester.pumpAndSettle(); + + expect(called, true); + expect(notCalled, true); + expect(find.text(upgrader.messages!.buttonTitleIgnore), findsNothing); + }, skip: false); + + testWidgets('test UpgradeCard later', (WidgetTester tester) async { + final client = MockITunesSearchClient.setupMockClient(); + final upgrader = Upgrader( + upgraderOS: MockUpgraderOS(ios: true), + client: client, + debugLogging: true); + + upgrader.installPackageInfo( + packageInfo: PackageInfo( + appName: 'Upgrader', + packageName: 'com.larryaasen.upgrader', + version: '0.9.9', + buildNumber: '400')); + upgrader.initialize().then((value) {}); + await tester.pumpAndSettle(); + + expect(upgrader.isTooSoon(), false); + + var called = false; + var notCalled = true; + final upgradeCard = wrapper( + UpgradeCard( + upgrader: upgrader, + onUpdate: () { + notCalled = false; + return true; + }, + onIgnore: () { + notCalled = false; + return true; + }, + onLater: () { + called = true; + }, + ), + ); + await tester.pumpWidget(upgradeCard); + + // Pump the UI so the upgrade card is displayed + await tester.pumpAndSettle(const Duration(milliseconds: 5000)); + + expect(upgrader.messages, isNull); + upgrader.messages = UpgraderMessages(); + expect(upgrader.messages, isNotNull); + + await tester.tap(find.text(upgrader.messages!.buttonTitleLater)); + await tester.pumpAndSettle(); + + expect(called, true); + expect(notCalled, true); + expect(find.text(upgrader.messages!.buttonTitleLater), findsNothing); + }, skip: false); +} diff --git a/test/upgrader_test.dart b/test/upgrader_test.dart index d7720914..4b455da2 100644 --- a/test/upgrader_test.dart +++ b/test/upgrader_test.dart @@ -15,6 +15,7 @@ import 'appcast_test.dart'; import 'fake_appcast.dart'; import 'mock_itunes_client.dart'; import 'mock_play_store_client.dart'; +import 'test_utils.dart'; // FYI: Platform.operatingSystem can be "macos" or "linux" in a unit test. // FYI: defaultTargetPlatform is TargetPlatform.android in a unit test. @@ -202,8 +203,10 @@ void main() { var called = false; var notCalled = true; + final dialogKey = GlobalKey(debugLabel: 'gloabl_upgrader_alert_dialog'); final upgradeAlert = wrapper( UpgradeAlert( + dialogKey: dialogKey, upgrader: upgrader, onUpdate: () { called = true; @@ -240,7 +243,7 @@ void main() { expect(find.text(upgrader.messages!.buttonTitleLater), findsOneWidget); expect(find.text(upgrader.messages!.buttonTitleUpdate), findsOneWidget); expect(find.text(upgrader.messages!.releaseNotes), findsOneWidget); - expect(find.byKey(const Key('upgrader_alert_dialog')), findsOneWidget); + expect(find.byKey(dialogKey), findsOneWidget); await tester.tap(find.text(upgrader.messages!.buttonTitleUpdate)); await tester.pumpAndSettle(); @@ -340,6 +343,7 @@ void main() { expect(find.text(upgrader.messages!.buttonTitleIgnore), findsOneWidget); expect(find.text(upgrader.messages!.buttonTitleLater), findsOneWidget); expect(find.text(upgrader.messages!.buttonTitleUpdate), findsOneWidget); + expect(find.byKey(const Key('upgrader_alert_dialog')), findsOneWidget); await tester.tap(find.text(upgrader.messages!.buttonTitleUpdate)); await tester.pumpAndSettle(); @@ -519,182 +523,6 @@ void main() { expect(find.text('Release Notes'), findsNothing); }); - testWidgets('test UpgradeCard no update', (WidgetTester tester) async { - expect(Upgrader.sharedInstance.isTooSoon(), false); - - final upgradeCard = wrapper(UpgradeCard()); - await tester.pumpWidget(upgradeCard); - - // Pump the UI - await tester.pumpAndSettle(); - - expect(find.text('IGNORE'), findsNothing); - expect(find.text('LATER'), findsNothing); - expect(find.text('UPDATE'), findsNothing); - expect(find.text('Release Notes'), findsNothing); - }); - - testWidgets('test UpgradeCard upgrade', (WidgetTester tester) async { - final client = MockITunesSearchClient.setupMockClient(); - final upgrader = Upgrader( - upgraderOS: MockUpgraderOS(ios: true), - client: client, - debugLogging: true); - - upgrader.installPackageInfo( - packageInfo: PackageInfo( - appName: 'Upgrader', - packageName: 'com.larryaasen.upgrader', - version: '0.9.9', - buildNumber: '400')); - upgrader.initialize().then((value) {}); - await tester.pumpAndSettle(); - - expect(upgrader.isTooSoon(), false); - - var called = false; - var notCalled = true; - final upgradeCard = wrapper( - UpgradeCard( - upgrader: upgrader, - onUpdate: () { - called = true; - return true; - }, - onIgnore: () { - notCalled = false; - return true; - }, - onLater: () { - notCalled = false; - }, - ), - ); - await tester.pumpWidget(upgradeCard); - - // Pump the UI so the upgrade card is displayed - await tester.pumpAndSettle(); - - expect(upgrader.messages, isNull); - upgrader.messages = UpgraderMessages(); - expect(upgrader.messages, isNotNull); - - expect(find.text(upgrader.messages!.releaseNotes), findsOneWidget); - expect(find.text(upgrader.releaseNotes!), findsOneWidget); - await tester.tap(find.text(upgrader.messages!.buttonTitleUpdate)); - await tester.pumpAndSettle(); - - expect(called, true); - expect(notCalled, true); - expect(find.text(upgrader.messages!.buttonTitleUpdate), findsNothing); - }, skip: false); - - testWidgets('test UpgradeCard ignore', (WidgetTester tester) async { - final client = MockITunesSearchClient.setupMockClient(); - final upgrader = Upgrader( - upgraderOS: MockUpgraderOS(ios: true), - client: client, - debugLogging: true); - - upgrader.installPackageInfo( - packageInfo: PackageInfo( - appName: 'Upgrader', - packageName: 'com.larryaasen.upgrader', - version: '0.9.9', - buildNumber: '400')); - upgrader.initialize().then((value) {}); - await tester.pumpAndSettle(); - - expect(upgrader.isTooSoon(), false); - - var called = false; - var notCalled = true; - final upgradeCard = wrapper( - UpgradeCard( - upgrader: upgrader, - onUpdate: () { - notCalled = false; - return true; - }, - onIgnore: () { - called = true; - return true; - }, - onLater: () { - notCalled = false; - }, - ), - ); - await tester.pumpWidget(upgradeCard); - - // Pump the UI so the upgrade card is displayed - await tester.pumpAndSettle(); - - expect(upgrader.messages, isNull); - upgrader.messages = UpgraderMessages(); - expect(upgrader.messages, isNotNull); - - await tester.tap(find.text(upgrader.messages!.buttonTitleIgnore)); - await tester.pumpAndSettle(); - - expect(called, true); - expect(notCalled, true); - expect(find.text(upgrader.messages!.buttonTitleIgnore), findsNothing); - }, skip: false); - - testWidgets('test UpgradeCard later', (WidgetTester tester) async { - final client = MockITunesSearchClient.setupMockClient(); - final upgrader = Upgrader( - upgraderOS: MockUpgraderOS(ios: true), - client: client, - debugLogging: true); - - upgrader.installPackageInfo( - packageInfo: PackageInfo( - appName: 'Upgrader', - packageName: 'com.larryaasen.upgrader', - version: '0.9.9', - buildNumber: '400')); - upgrader.initialize().then((value) {}); - await tester.pumpAndSettle(); - - expect(upgrader.isTooSoon(), false); - - var called = false; - var notCalled = true; - final upgradeCard = wrapper( - UpgradeCard( - upgrader: upgrader, - onUpdate: () { - notCalled = false; - return true; - }, - onIgnore: () { - notCalled = false; - return true; - }, - onLater: () { - called = true; - }, - ), - ); - await tester.pumpWidget(upgradeCard); - - // Pump the UI so the upgrade card is displayed - await tester.pumpAndSettle(const Duration(milliseconds: 5000)); - - expect(upgrader.messages, isNull); - upgrader.messages = UpgraderMessages(); - expect(upgrader.messages, isNotNull); - - await tester.tap(find.text(upgrader.messages!.buttonTitleLater)); - await tester.pumpAndSettle(); - - expect(called, true); - expect(notCalled, true); - expect(find.text(upgrader.messages!.buttonTitleLater), findsNothing); - }, skip: false); - testWidgets('test upgrader minAppVersion', (WidgetTester tester) async { final client = MockITunesSearchClient.setupMockClient(); final upgrader = Upgrader( @@ -1254,12 +1082,3 @@ class MyUpgraderMessages extends UpgraderMessages { @override String get releaseNotes => 'ddd'; } - -Widget wrapper(Widget child) { - return MaterialApp( - home: Scaffold( - body: child, - appBar: AppBar(title: const Text('Upgrader test')), - ), - ); -}