Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

@Skip(
'This file is skipped due to a cross-import that needs to be fixed. Tracked in https://github.com/flutter/flutter/issues/177028.',
)
import 'package:cupertino_ui/cupertino_ui.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

import '../widgets/semantics_tester.dart';

/// A [CustomPainter] that calls a callback when it paints.
class TestCallbackPainter extends CustomPainter {
/// Creates a [TestCallbackPainter] that calls [onPaint] when it paints.
Expand Down Expand Up @@ -73,7 +68,7 @@ void main() {
});

testWidgets('Picker semantics', (WidgetTester tester) async {
final semantics = SemanticsTester(tester);
final SemanticsHandle handle = tester.ensureSemantics();

await tester.pumpWidget(
CupertinoApp(
Expand All @@ -90,11 +85,16 @@ void main() {
),
);
expect(
semantics,
includesNodeWith(
tester.getSemantics(
find.byWidgetPredicate(
(Widget widget) => widget.runtimeType.toString() == '_CupertinoPickerSemantics',
),
),
Comment on lines +88 to +92

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of finding the private _CupertinoPickerSemantics widget by matching its runtimeType.toString(), we can find the public ListWheelScrollView widget. Since ListWheelScrollView is a direct descendant of _CupertinoPickerSemantics, tester.getSemantics will automatically walk up the tree and return the semantics node of _CupertinoPickerSemantics (which is the nearest ancestor semantics boundary). This is cleaner, more robust, and avoids relying on private class name strings.

Suggested change
tester.getSemantics(
find.byWidgetPredicate(
(Widget widget) => widget.runtimeType.toString() == '_CupertinoPickerSemantics',
),
),
tester.getSemantics(find.byType(ListWheelScrollView)),

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried the suggestion but it does not work, tester.getSemantics(find.byType(ListWheelScrollView) does not return the node of _CupertinoPickerSemantics (ancestor).

isSemantics(
value: '0',
increasedValue: '1',
actions: <SemanticsAction>[SemanticsAction.increase],
hasIncreaseAction: true,
hasDecreaseAction: false,
),
);

Expand All @@ -105,23 +105,29 @@ void main() {
hourListController.jumpToItem(11);
await tester.pumpAndSettle();
expect(
semantics,
includesNodeWith(
tester.getSemantics(
find.byWidgetPredicate(
(Widget widget) => widget.runtimeType.toString() == '_CupertinoPickerSemantics',
),
),
Comment on lines +108 to +112

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of finding the private _CupertinoPickerSemantics widget by matching its runtimeType.toString(), we can find the public ListWheelScrollView widget. Since ListWheelScrollView is a direct descendant of _CupertinoPickerSemantics, tester.getSemantics will automatically walk up the tree and return the semantics node of _CupertinoPickerSemantics (which is the nearest ancestor semantics boundary). This is cleaner, more robust, and avoids relying on private class name strings.

Suggested change
tester.getSemantics(
find.byWidgetPredicate(
(Widget widget) => widget.runtimeType.toString() == '_CupertinoPickerSemantics',
),
),
tester.getSemantics(find.byType(ListWheelScrollView)),

isSemantics(
value: '11',
increasedValue: '12',
decreasedValue: '10',
actions: <SemanticsAction>[SemanticsAction.increase, SemanticsAction.decrease],
hasIncreaseAction: true,
hasDecreaseAction: true,
),
);
semantics.dispose();

handle.dispose();
});

testWidgets('Picker semantics excludes current item with empty label', (
WidgetTester tester,
) async {
// When the current item has an empty label (e.g., wrapped with ExcludeSemantics),
// the picker should not set any value, increasedValue, decreasedValue, or actions.
final semantics = SemanticsTester(tester);
final SemanticsHandle handle = tester.ensureSemantics();
final controller = FixedExtentScrollController(initialItem: 1);
addTearDown(controller.dispose);

Expand All @@ -146,15 +152,13 @@ void main() {

// When the current item (index 1) has an empty label due to ExcludeSemantics,
// the picker should not have any value or actions set.
expect(semantics, isNot(includesNodeWith(value: '1')));
// Also verify that no increase/decrease actions are set for this item.
expect(
semantics,
isNot(includesNodeWith(actions: <SemanticsAction>[SemanticsAction.increase])),
);
expect(
semantics,
isNot(includesNodeWith(actions: <SemanticsAction>[SemanticsAction.decrease])),
tester.getSemantics(
find.byWidgetPredicate(
(Widget widget) => widget.runtimeType.toString() == '_CupertinoPickerSemantics',
),
),
Comment on lines +156 to +160

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of finding the private _CupertinoPickerSemantics widget by matching its runtimeType.toString(), we can find the public ListWheelScrollView widget. Since ListWheelScrollView is a direct descendant of _CupertinoPickerSemantics, tester.getSemantics will automatically walk up the tree and return the semantics node of _CupertinoPickerSemantics (which is the nearest ancestor semantics boundary). This is cleaner, more robust, and avoids relying on private class name strings.

Suggested change
tester.getSemantics(
find.byWidgetPredicate(
(Widget widget) => widget.runtimeType.toString() == '_CupertinoPickerSemantics',
),
),
tester.getSemantics(find.byType(ListWheelScrollView)),

isSemantics(value: '', hasIncreaseAction: false, hasDecreaseAction: false),
);

// Scroll to item 0 which has a valid label.
Expand All @@ -163,10 +167,13 @@ void main() {

// Now the picker should have value '0' but no increase action
// because the next item (1) has an empty label.
expect(semantics, includesNodeWith(value: '0'));
expect(
semantics,
isNot(includesNodeWith(value: '0', actions: <SemanticsAction>[SemanticsAction.increase])),
tester.getSemantics(
find.byWidgetPredicate(
(Widget widget) => widget.runtimeType.toString() == '_CupertinoPickerSemantics',
),
),
Comment on lines +171 to +175

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of finding the private _CupertinoPickerSemantics widget by matching its runtimeType.toString(), we can find the public ListWheelScrollView widget. Since ListWheelScrollView is a direct descendant of _CupertinoPickerSemantics, tester.getSemantics will automatically walk up the tree and return the semantics node of _CupertinoPickerSemantics (which is the nearest ancestor semantics boundary). This is cleaner, more robust, and avoids relying on private class name strings.

Suggested change
tester.getSemantics(
find.byWidgetPredicate(
(Widget widget) => widget.runtimeType.toString() == '_CupertinoPickerSemantics',
),
),
tester.getSemantics(find.byType(ListWheelScrollView)),

isSemantics(value: '0', hasIncreaseAction: false, hasDecreaseAction: false),
);

// Scroll to item 2 which has a valid label.
Expand All @@ -175,13 +182,15 @@ void main() {

// Now the picker should have value '2' but no decrease action
// because the previous item (1) has an empty label.
expect(semantics, includesNodeWith(value: '2'));
expect(
semantics,
isNot(includesNodeWith(value: '2', actions: <SemanticsAction>[SemanticsAction.decrease])),
tester.getSemantics(
find.byWidgetPredicate(
(Widget widget) => widget.runtimeType.toString() == '_CupertinoPickerSemantics',
),
),
Comment on lines +186 to +190

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of finding the private _CupertinoPickerSemantics widget by matching its runtimeType.toString(), we can find the public ListWheelScrollView widget. Since ListWheelScrollView is a direct descendant of _CupertinoPickerSemantics, tester.getSemantics will automatically walk up the tree and return the semantics node of _CupertinoPickerSemantics (which is the nearest ancestor semantics boundary). This is cleaner, more robust, and avoids relying on private class name strings.

Suggested change
tester.getSemantics(
find.byWidgetPredicate(
(Widget widget) => widget.runtimeType.toString() == '_CupertinoPickerSemantics',
),
),
tester.getSemantics(find.byType(ListWheelScrollView)),

isSemantics(value: '2', hasDecreaseAction: false, hasIncreaseAction: false),
);

semantics.dispose();
handle.dispose();
});

group('layout', () {
Expand Down
Loading