Skip to content

Commit

Permalink
Fixes page.onPopInvoked type mismatches (flutter#153593)
Browse files Browse the repository at this point in the history
  • Loading branch information
chunhtai authored Aug 20, 2024
1 parent cdab9d5 commit e7da16d
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 1 deletion.
2 changes: 1 addition & 1 deletion packages/flutter/lib/src/widgets/navigator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ abstract class Route<T> extends _RoutePlaceholder {
@mustCallSuper
void onPopInvokedWithResult(bool didPop, T? result) {
if (_isPageBased) {
final Page<Object?> page = settings as Page<Object?>;
final Page<T> page = settings as Page<T>;
page.onPopInvoked(didPop, result);
}
}
Expand Down
80 changes: 80 additions & 0 deletions packages/flutter/test/widgets/navigator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5352,6 +5352,56 @@ void main() {
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }),
skip: isBrowser, // [intended] only non-web Android supports predictive back.
);

testWidgets('canPop and onPopInvoked', (WidgetTester tester) async {
bool page2CanPop = false;
bool page3CanPop = false;
final CanPopPage<int> page1 = CanPopPage<int>(name: 'page1', pageCanPop: () => false);
final CanPopPage<String> page2 = CanPopPage<String>(name: 'page2', pageCanPop: () => page2CanPop);
final CanPopPage<bool> page3 = CanPopPage<bool>(name: 'page3', pageCanPop: () => page3CanPop);
final List<Page<Object?>> pages = <Page<Object?>>[page1, page2, page3];
final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
await tester.pumpWidget(
MaterialApp(
home: Navigator(
key: key,
pages: pages,
onDidRemovePage: (Page<Object?> page) => pages.remove(page),
),
),
);

expect(find.text('page3'), findsOneWidget);

key.currentState!.maybePop(true);
await tester.pumpAndSettle();
expect(find.text('page3'), findsOneWidget);
expect(page3.popInvoked, <CanPopPageInvoke>[(false, true)]);

page3CanPop = true;
key.currentState!.maybePop(false);
await tester.pumpAndSettle();
expect(find.text('page3'), findsNothing);
expect(find.text('page2'), findsOneWidget);
expect(page3.popInvoked, <CanPopPageInvoke>[(false, true), (true, false)]);

key.currentState!.maybePop('some string');
await tester.pumpAndSettle();
expect(find.text('page2'), findsOneWidget);
expect(page2.popInvoked, <CanPopPageInvoke>[(false, 'some string')]);

page2CanPop = true;
key.currentState!.maybePop('another string');
await tester.pumpAndSettle();
expect(find.text('page2'), findsNothing);
expect(find.text('page1'), findsOneWidget);
expect(page2.popInvoked, <CanPopPageInvoke>[(false, 'some string'), (true, 'another string')]);

key.currentState!.maybePop(1);
await tester.pumpAndSettle();
expect(find.text('page1'), findsOneWidget);
expect(page1.popInvoked, <CanPopPageInvoke>[(false, 1)]);
});
});
});
}
Expand Down Expand Up @@ -5487,6 +5537,36 @@ class ZeroTransitionPage extends Page<void> {
}
}

typedef CanPopPageInvoke = (bool didPop, Object? result);

class CanPopPage<T> extends Page<T> {
CanPopPage({
super.key,
super.name,
required this.pageCanPop,
super.arguments,
});

final List<CanPopPageInvoke> popInvoked = <CanPopPageInvoke>[];

@override
bool get canPop => pageCanPop();
final ValueGetter<bool> pageCanPop;

@override
PopInvokedWithResultCallback<T> get onPopInvoked => (bool didPop, T? result) {
popInvoked.add((didPop, result));
};

@override
Route<T> createRoute(BuildContext context) {
return MaterialPageRoute<T>(
builder: (BuildContext context) => Text(name!),
settings: this,
);
}
}

class TestPage extends Page<void> {
const TestPage({
super.key,
Expand Down

0 comments on commit e7da16d

Please sign in to comment.