Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more to error message of RestorationScope.of #126444

Merged
merged 3 commits into from
May 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 20 additions & 9 deletions packages/flutter/lib/src/widgets/restoration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,26 @@ class RestorationScope extends StatefulWidget {
final RestorationBucket? bucket = maybeOf(context);
assert(() {
if (bucket == null) {
throw FlutterError(
'RestorationScope.of() was called with a context that does not contain a '
'RestorationScope widget.\n'
'No RestorationScope widget ancestor could be found starting from the '
'context that was passed to RestorationScope.of(). This can happen '
'because you are using a widget that looks for a RestorationScope '
'ancestor, but no such ancestor exists.\n'
'The context used was:\n'
' $context',
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary(
'RestorationScope.of() was called with a context that does not '
'contain a RestorationScope widget. '
),
ErrorDescription(
'No RestorationScope widget ancestor could be found starting from '
'the context that was passed to RestorationScope.of(). This can '
'happen because you are using a widget that looks for a '
'RestorationScope ancestor, but no such ancestor exists.\n'
'The context used was:\n'
' $context'
),
ErrorHint(
'State restoration must be enabled for a RestorationScope to exist. '
'This can be done by passing a restorationScopeId to MaterialApp, '
'CupertinoApp, or WidgetsApp at the root of the widget tree or by '
'wrapping the widget tree in a RootRestorationScope.'
),
],
);
}
return true;
Expand Down
46 changes: 46 additions & 0 deletions packages/flutter/test/widgets/restoration_scope_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,52 @@ void main() {
});

group('RestorationScope', () {
testWidgets('asserts when none is found', (WidgetTester tester) async {
late BuildContext capturedContext;
await tester.pumpWidget(WidgetsApp(
color: const Color(0xD0FF0000),
builder: (_, __) {
return RestorationScope(
restorationId: 'test',
child: Builder(
builder: (BuildContext context) {
capturedContext = context;
return Container();
}
)
);
},
));
expect(
() {
RestorationScope.of(capturedContext);
},
throwsA(isA<FlutterError>().having(
(FlutterError error) => error.message,
'message',
contains('State restoration must be enabled for a RestorationScope'),
)),
);

await tester.pumpWidget(WidgetsApp(
restorationScopeId: 'test scope',
color: const Color(0xD0FF0000),
builder: (_, __) {
return RestorationScope(
restorationId: 'test',
child: Builder(
builder: (BuildContext context) {
capturedContext = context;
return Container();
}
)
);
},
));
final UnmanagedRestorationScope scope = tester.widget(find.byType(UnmanagedRestorationScope).last);
expect(RestorationScope.of(capturedContext), scope.bucket);
});

testWidgets('makes bucket available to descendants', (WidgetTester tester) async {
const String id = 'hello world 1234';
final MockRestorationManager manager = MockRestorationManager();
Expand Down