Skip to content

Commit

Permalink
Improve some scrollbar error messages (#143279)
Browse files Browse the repository at this point in the history
Adds some missing spaces, rewords some errors, and splits some errors into more lines.
  • Loading branch information
loic-sharma authored Feb 13, 2024
1 parent 14bce28 commit b4270f7
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 28 deletions.
60 changes: 36 additions & 24 deletions packages/flutter/lib/src/widgets/scrollbar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1466,18 +1466,24 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
ErrorHint(
'The Scrollbar attempted to use the $controllerForError. This '
'ScrollController should be associated with the ScrollView that '
'the Scrollbar is being applied to.'
'${tryPrimary
? 'When ScrollView.scrollDirection is Axis.vertical on mobile '
'platforms will automatically use the '
'PrimaryScrollController if the user has not provided a '
'ScrollController. To use the PrimaryScrollController '
'explicitly, set ScrollView.primary to true for the Scrollable '
'widget.'
: 'When providing your own ScrollController, ensure both the '
'Scrollbar and the Scrollable widget use the same one.'
}',
'the Scrollbar is being applied to.',
),
if (tryPrimary) ...<ErrorHint>[
ErrorHint(
'If a ScrollController has not been provided, the '
'PrimaryScrollController is used by default on mobile platforms '
'for ScrollViews with an Axis.vertical scroll direction.',
),
ErrorHint(
'To use the PrimaryScrollController explicitly, '
'set ScrollView.primary to true on the Scrollable widget.',
),
]
else
ErrorHint(
'When providing your own ScrollController, ensure both the '
'Scrollbar and the Scrollable widget use the same one.',
),
]);
}
return true;
Expand All @@ -1491,26 +1497,32 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
}
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary(
'The $controllerForError is currently attached to more than one '
'ScrollPosition.',
'The $controllerForError is attached to more than one ScrollPosition.',
),
ErrorDescription(
'The Scrollbar requires a single ScrollPosition in order to be painted.',
),
ErrorHint(
'When $when, the associated ScrollController must only have one '
'ScrollPosition attached.'
'${tryPrimary
? 'If a ScrollController has not been provided, the '
'PrimaryScrollController is used by default on mobile platforms '
'for ScrollViews with an Axis.vertical scroll direction. More '
'than one ScrollView may have tried to use the '
'PrimaryScrollController of the current context. '
'ScrollView.primary can override this behavior.'
: 'The provided ScrollController must be unique to one '
'ScrollView widget.'
}',
'ScrollPosition attached.',
),
if (tryPrimary) ...<ErrorHint>[
ErrorHint(
'If a ScrollController has not been provided, the '
'PrimaryScrollController is used by default on mobile platforms '
'for ScrollViews with an Axis.vertical scroll direction.'
),
ErrorHint(
'More than one ScrollView may have tried to use the '
'PrimaryScrollController of the current context. '
'ScrollView.primary can override this behavior.'
),
]
else
ErrorHint(
'The provided ScrollController cannot be shared by multiple '
'ScrollView widgets.'
),
]);
}
return true;
Expand Down
13 changes: 11 additions & 2 deletions packages/flutter/test/material/scrollbar_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1810,7 +1810,12 @@ void main() {
FlutterError error = tester.takeException() as FlutterError;
expect(
error.message,
contains('The PrimaryScrollController is currently attached to more than one ScrollPosition.'),
'''
The PrimaryScrollController is attached to more than one ScrollPosition.
The Scrollbar requires a single ScrollPosition in order to be painted.
When Scrollbar.thumbVisibility is true, the associated ScrollController must only have one ScrollPosition attached.
If a ScrollController has not been provided, the PrimaryScrollController is used by default on mobile platforms for ScrollViews with an Axis.vertical scroll direction.
More than one ScrollView may have tried to use the PrimaryScrollController of the current context. ScrollView.primary can override this behavior.''',
);

// Asserts when using the ScrollController provided by the user.
Expand All @@ -1829,7 +1834,11 @@ void main() {
error = tester.takeException() as FlutterError;
expect(
error.message,
contains('The provided ScrollController is currently attached to more than one ScrollPosition.'),
'''
The provided ScrollController is attached to more than one ScrollPosition.
The Scrollbar requires a single ScrollPosition in order to be painted.
When Scrollbar.thumbVisibility is true, the associated ScrollController must only have one ScrollPosition attached.
The provided ScrollController cannot be shared by multiple ScrollView widgets.''',
);

scrollController.dispose();
Expand Down
60 changes: 58 additions & 2 deletions packages/flutter/test/widgets/scrollbar_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1514,7 +1514,63 @@ void main() {
expect(exception, isAssertionError);
expect(
exception.message,
contains("The Scrollbar's ScrollController has no ScrollPosition attached."),
'''
The Scrollbar's ScrollController has no ScrollPosition attached.
A Scrollbar cannot be painted without a ScrollPosition.
The Scrollbar attempted to use the PrimaryScrollController. This ScrollController should be associated with the ScrollView that the Scrollbar is being applied to.
If a ScrollController has not been provided, the PrimaryScrollController is used by default on mobile platforms for ScrollViews with an Axis.vertical scroll direction.
To use the PrimaryScrollController explicitly, set ScrollView.primary to true on the Scrollable widget.''',
);
});

testWidgets('Scrollbars assert on multiple scroll positions', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: MediaQuery(
data: const MediaQueryData(),
child: PrimaryScrollController(
controller: scrollController,
child: Row(
children: <Widget>[
RawScrollbar(
controller: scrollController,
child: const SingleChildScrollView(
child: SizedBox(width: 10.0, height: 4000.0),
),
),
RawScrollbar(
controller: scrollController,
child: const SingleChildScrollView(
child: SizedBox(width: 10.0, height: 4000.0),
),
),
],
),
),
),
),
);
await tester.pumpAndSettle();

AssertionError? exception = tester.takeException() as AssertionError?;
// The scrollbar is not visible and cannot be interacted with, so no assertion.
expect(exception, isNull);
// Scroll to trigger the scrollbar to come into view.
final Finder scrollViews = find.byType(SingleChildScrollView);
final TestGesture gesture = await tester.startGesture(tester.getCenter(scrollViews.first));
await gesture.moveBy(const Offset(0.0, -20.0));
exception = tester.takeException() as AssertionError;
expect(exception, isAssertionError);
expect(
exception.message,
'''
The provided ScrollController is attached to more than one ScrollPosition.
The Scrollbar requires a single ScrollPosition in order to be painted.
When the scrollbar is interactive, the associated ScrollController must only have one ScrollPosition attached.
The provided ScrollController cannot be shared by multiple ScrollView widgets.''',
);
});

Expand Down Expand Up @@ -2892,7 +2948,7 @@ void main() {
expect(scrollController.offset, greaterThan(lastPosition));
});

testWidgets('The bar support mouse wheel event', (WidgetTester tester) async {
testWidgets('The bar supports mouse wheel event', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/pull/109659
final ScrollController scrollController = ScrollController();
addTearDown(scrollController.dispose);
Expand Down

0 comments on commit b4270f7

Please sign in to comment.