diff --git a/example/lib/pages/alert_page.dart b/example/lib/pages/alert_page.dart index c867df0..7bc56f9 100644 --- a/example/lib/pages/alert_page.dart +++ b/example/lib/pages/alert_page.dart @@ -1,8 +1,10 @@ import 'package:adaptive_dialog/adaptive_dialog.dart'; +import 'package:example/result_provider.dart'; import 'package:example/router/router.dart'; import 'package:example/util/logger.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; class AlertRoute extends GoRouteData { @@ -11,11 +13,11 @@ class AlertRoute extends GoRouteData { Widget build(BuildContext context, GoRouterState state) => const AlertPage(); } -class AlertPage extends StatelessWidget { +class AlertPage extends ConsumerWidget { const AlertPage({super.key}); @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { return Scaffold( appBar: AppBar( title: Text(pascalCaseFromRouteUri(GoRouterState.of(context).uri)), @@ -30,7 +32,7 @@ class AlertPage extends StatelessWidget { title: 'Title', message: 'This is message.', ); - logger.info(result); + ref.read(resultProvider.notifier).set(result); }, ), ListTile( @@ -43,7 +45,7 @@ class AlertPage extends StatelessWidget { canPop: false, ); assert(result == OkCancelResult.ok); - logger.info(result); + ref.read(resultProvider.notifier).set(result); }, ), ListTile( @@ -55,7 +57,7 @@ class AlertPage extends StatelessWidget { message: 'This is message.', barrierDismissible: false, ); - logger.info(result); + ref.read(resultProvider.notifier).set(result); }, ), ListTile( diff --git a/example/lib/result_provider.dart b/example/lib/result_provider.dart new file mode 100644 index 0000000..c60120f --- /dev/null +++ b/example/lib/result_provider.dart @@ -0,0 +1,21 @@ +import 'package:example/util/util.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final resultProvider = + StateNotifierProvider((ref) => ResultNotifier()); + +class ResultNotifier extends StateNotifier { + ResultNotifier() : super(null); + // ignore: use_setters_to_change_properties + void set(dynamic text) { + state = text; + } + + void clear() => set(''); + + @override + set state(dynamic value) { + super.state = value; + logger.info(state); + } +} diff --git a/example/lib/util/logger.dart b/example/lib/util/logger.dart index dea0936..9f16daf 100644 --- a/example/lib/util/logger.dart +++ b/example/lib/util/logger.dart @@ -5,4 +5,5 @@ final SimpleLogger logger = SimpleLogger() ..setLevel( Level.FINEST, includeCallerInfo: true, + callerInfoFrameLevelOffset: 2, ); diff --git a/example/macos/Podfile.lock b/example/macos/Podfile.lock index 681f2de..2185f92 100644 --- a/example/macos/Podfile.lock +++ b/example/macos/Podfile.lock @@ -1,4 +1,6 @@ PODS: + - appkit_ui_element_colors (1.0.0): + - FlutterMacOS - dynamic_color (0.0.2): - FlutterMacOS - file_selector_macos (0.0.1): @@ -12,6 +14,7 @@ PODS: - FlutterMacOS DEPENDENCIES: + - appkit_ui_element_colors (from `Flutter/ephemeral/.symlinks/plugins/appkit_ui_element_colors/macos`) - dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`) - file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`) - FlutterMacOS (from `Flutter/ephemeral`) @@ -20,6 +23,8 @@ DEPENDENCIES: - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) EXTERNAL SOURCES: + appkit_ui_element_colors: + :path: Flutter/ephemeral/.symlinks/plugins/appkit_ui_element_colors/macos dynamic_color: :path: Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos file_selector_macos: @@ -34,6 +39,7 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos SPEC CHECKSUMS: + appkit_ui_element_colors: 39bb2d80be3f19b152ccf4c70d5bbe6cba43d74a dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f file_selector_macos: 468fb6b81fac7c0e88d71317f3eec34c3b008ff9 FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 diff --git a/example/test/pages/alert_page_test.dart b/example/test/pages/alert_page_test.dart new file mode 100644 index 0000000..0d8d26b --- /dev/null +++ b/example/test/pages/alert_page_test.dart @@ -0,0 +1,98 @@ +import 'package:adaptive_dialog/adaptive_dialog.dart'; +import 'package:example/result_provider.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../util.dart'; + +extension on WidgetTester { + Future setUpAlert() => setup('Alert'); + Future openOkDialog() => open('OK Dialog'); + Future openOkCanPopFalseDialog() => open('OK Dialog (canPop: false)'); + Future openOkBarrierDismissibleFalseDialog() => + open('OK Dialog (barrierDismissible: false)'); +} + +void main() { + group('OK Dialog', () { + testWidgets('OK', (tester) async { + final container = await tester.setUpAlert(); + await tester.openOkDialog(); + + expect(find.text('Title'), findsOneWidget); + expect(find.text('This is message.'), findsOneWidget); + await tester.tap(find.widgetWithText(TextButton, 'OK')); + await tester.pumpAndSettle(); + + expect(container.read(resultProvider), OkCancelResult.ok); + }); + testWidgets('barrier', (tester) async { + final container = await tester.setUpAlert(); + await tester.openOkDialog(); + + await tester.tapBarrier(); + + expect(container.read(resultProvider), OkCancelResult.cancel); + }); + + testWidgets('maybePop', (tester) async { + final container = await tester.setUpAlert(); + await tester.openOkDialog(); + + final context = tester.element(find.text('Title')); + await Navigator.of(context).maybePop(); + await tester.pumpAndSettle(); + + expect(container.read(resultProvider), OkCancelResult.cancel); + }); + }); + + group('OK Dialog (canPop: false)', () { + testWidgets('OK', (tester) async { + final container = await tester.setUpAlert(); + await tester.openOkCanPopFalseDialog(); + + expect(find.text('Title'), findsOneWidget); + expect(find.text('This is message.'), findsOneWidget); + await tester.tap(find.widgetWithText(TextButton, 'OK')); + await tester.pumpAndSettle(); + + expect(container.read(resultProvider), OkCancelResult.ok); + }); + testWidgets('maybePop', (tester) async { + final container = await tester.setUpAlert(); + await tester.openOkCanPopFalseDialog(); + + final context = tester.element(find.text('Title')); + await Navigator.of(context).maybePop(); + await tester.pumpAndSettle(); + + expect(container.read(resultProvider), isNull); + expect(find.text('Title'), findsOneWidget); + }); + }); + + group('OK Dialog (barrierDismissible: false)', () { + testWidgets('OK', (tester) async { + final container = await tester.setUpAlert(); + await tester.openOkBarrierDismissibleFalseDialog(); + + expect(find.text('Title'), findsOneWidget); + expect(find.text('This is message.'), findsOneWidget); + await tester.tap(find.widgetWithText(TextButton, 'OK')); + await tester.pumpAndSettle(); + + expect(container.read(resultProvider), OkCancelResult.ok); + }); + testWidgets('barrier', (tester) async { + final container = await tester.setUpAlert(); + await tester.openOkBarrierDismissibleFalseDialog(); + + await tester.tapBarrier(); + + expect(container.read(resultProvider), isNull); + expect(find.text('Title'), findsOneWidget); + }); + }); +} diff --git a/example/test/util.dart b/example/test/util.dart new file mode 100644 index 0000000..80e6f4a --- /dev/null +++ b/example/test/util.dart @@ -0,0 +1,31 @@ +import 'package:example/app.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_test/flutter_test.dart'; + +extension WidgetTesterX on WidgetTester { + Future setup(String pageName) async { + final container = ProviderContainer(); + addTearDown(container.dispose); + await pumpWidget( + ProviderScope( + parent: container, + child: const App(), + ), + ); + + await tap(find.widgetWithText(ListTile, pageName)); + await pumpAndSettle(); + return container; + } + + Future open(String label) async { + await tap(find.widgetWithText(ListTile, label)); + await pumpAndSettle(); + } + + Future tapBarrier() async { + await tapAt(Offset.zero); + await pumpAndSettle(); + } +}