flutter/packages/flutter_test/test/multi_view_controller_test.dart
Michael Goderbauer 5491c8c146
Auto-format Framework (#160545)
This auto-formats all *.dart files in the repository outside of the
`engine` subdirectory and enforces that these files stay formatted with
a presubmit check.

**Reviewers:** Please carefully review all the commits except for the
one titled "formatted". The "formatted" commit was auto-generated by
running `dev/tools/format.sh -a -f`. The other commits were hand-crafted
to prepare the repo for the formatting change. I recommend reviewing the
commits one-by-one via the "Commits" tab and avoiding Github's "Files
changed" tab as it will likely slow down your browser because of the
size of this PR.

---------

Co-authored-by: Kate Lovett <katelovett@google.com>
Co-authored-by: LongCatIsLooong <31859944+LongCatIsLooong@users.noreply.github.com>
2024-12-19 20:06:21 +00:00

250 lines
8.0 KiB
Dart

// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'multi_view_testing.dart';
void main() {
testWidgets('simulatedAccessibilityTraversal - start and end in same view', (
WidgetTester tester,
) async {
await pumpViews(tester: tester);
expect(
tester.semantics
.simulatedAccessibilityTraversal(
start: find.text('View2Child1'),
end: find.text('View2Child3'),
)
.map((SemanticsNode node) => node.label),
<String>['View2Child1', 'View2Child2', 'View2Child3'],
);
});
testWidgets('simulatedAccessibilityTraversal - start not specified', (WidgetTester tester) async {
await pumpViews(tester: tester);
expect(
tester.semantics
.simulatedAccessibilityTraversal(end: find.text('View2Child3'))
.map((SemanticsNode node) => node.label),
<String>['View2Child0', 'View2Child1', 'View2Child2', 'View2Child3'],
);
});
testWidgets('simulatedAccessibilityTraversal - end not specified', (WidgetTester tester) async {
await pumpViews(tester: tester);
expect(
tester.semantics
.simulatedAccessibilityTraversal(start: find.text('View2Child1'))
.map((SemanticsNode node) => node.label),
<String>['View2Child1', 'View2Child2', 'View2Child3', 'View2Child4'],
);
});
testWidgets('simulatedAccessibilityTraversal - nothing specified', (WidgetTester tester) async {
await pumpViews(tester: tester);
expect(
tester.semantics.simulatedAccessibilityTraversal().map((SemanticsNode node) => node.label),
<String>['View1Child0', 'View1Child1', 'View1Child2', 'View1Child3', 'View1Child4'],
);
// Should be traversing over tester.view.
expect(tester.viewOf(find.text('View1Child0')), tester.view);
});
testWidgets('simulatedAccessibilityTraversal - only view specified', (WidgetTester tester) async {
await pumpViews(tester: tester);
expect(
tester.semantics
.simulatedAccessibilityTraversal(view: tester.viewOf(find.text('View2Child1')))
.map((SemanticsNode node) => node.label),
<String>['View2Child0', 'View2Child1', 'View2Child2', 'View2Child3', 'View2Child4'],
);
});
testWidgets('simulatedAccessibilityTraversal - everything specified', (
WidgetTester tester,
) async {
await pumpViews(tester: tester);
expect(
tester.semantics
.simulatedAccessibilityTraversal(
start: find.text('View2Child1'),
end: find.text('View2Child3'),
view: tester.viewOf(find.text('View2Child1')),
)
.map((SemanticsNode node) => node.label),
<String>['View2Child1', 'View2Child2', 'View2Child3'],
);
});
testWidgets('simulatedAccessibilityTraversal - start and end not in same view', (
WidgetTester tester,
) async {
await pumpViews(tester: tester);
expect(
() => tester.semantics.simulatedAccessibilityTraversal(
start: find.text('View2Child1'),
end: find.text('View1Child3'),
),
throwsA(
isStateError.having(
(StateError e) => e.message,
'message',
contains('The start and end node are in different views.'),
),
),
);
});
testWidgets('simulatedAccessibilityTraversal - start is not in view', (
WidgetTester tester,
) async {
await pumpViews(tester: tester);
expect(
() => tester.semantics.simulatedAccessibilityTraversal(
start: find.text('View2Child1'),
end: find.text('View1Child3'),
view: tester.viewOf(find.text('View1Child3')),
),
throwsA(
isStateError.having(
(StateError e) => e.message,
'message',
contains('The start node is not part of the provided view.'),
),
),
);
});
testWidgets('simulatedAccessibilityTraversal - end is not in view', (WidgetTester tester) async {
await pumpViews(tester: tester);
expect(
() => tester.semantics.simulatedAccessibilityTraversal(
start: find.text('View2Child1'),
end: find.text('View1Child3'),
view: tester.viewOf(find.text('View2Child1')),
),
throwsA(
isStateError.having(
(StateError e) => e.message,
'message',
contains('The end node is not part of the provided view.'),
),
),
);
});
testWidgets('viewOf', (WidgetTester tester) async {
await pumpViews(tester: tester);
expect(tester.viewOf(find.text('View0Child0')).viewId, 100);
expect(tester.viewOf(find.text('View1Child1')).viewId, tester.view.viewId);
expect(tester.viewOf(find.text('View2Child2')).viewId, 102);
});
testWidgets('layers includes layers from all views', (WidgetTester tester) async {
await pumpViews(tester: tester);
const int numberOfViews = 3;
expect(
tester.binding.renderViews.length,
numberOfViews,
); // One RenderView for each FlutterView.
final List<Layer> layers = tester.layers;
// Each RenderView contributes a TransformLayer and a PictureLayer.
expect(layers, hasLength(numberOfViews * 2));
expect(layers.whereType<TransformLayer>(), hasLength(numberOfViews));
expect(layers.whereType<PictureLayer>(), hasLength(numberOfViews));
expect(
layers.whereType<TransformLayer>().map((TransformLayer l) => l.owner),
containsAll(tester.binding.renderViews),
);
});
testWidgets('hitTestOnBinding', (WidgetTester tester) async {
await pumpViews(tester: tester);
// Not specifying a viewId hit tests on tester.view:
HitTestResult result = tester.hitTestOnBinding(Offset.zero);
expect(
result.path.map((HitTestEntry h) => h.target).whereType<RenderView>().single.flutterView,
tester.view,
);
// Specifying a viewId is respected:
result = tester.hitTestOnBinding(Offset.zero, viewId: 100);
expect(
result.path
.map((HitTestEntry h) => h.target)
.whereType<RenderView>()
.single
.flutterView
.viewId,
100,
);
result = tester.hitTestOnBinding(Offset.zero, viewId: 102);
expect(
result.path
.map((HitTestEntry h) => h.target)
.whereType<RenderView>()
.single
.flutterView
.viewId,
102,
);
});
testWidgets('hitTestable works in different Views', (WidgetTester tester) async {
await pumpViews(tester: tester);
expect(
(find.text('View0Child0').hitTestable().evaluate().single.widget as Text).data,
'View0Child0',
);
expect(
(find.text('View1Child1').hitTestable().evaluate().single.widget as Text).data,
'View1Child1',
);
expect(
(find.text('View2Child2').hitTestable().evaluate().single.widget as Text).data,
'View2Child2',
);
});
testWidgets('simulatedAccessibilityTraversal - startNode and endNode in same view', (
WidgetTester tester,
) async {
await pumpViews(tester: tester);
expect(
tester.semantics
.simulatedAccessibilityTraversal(
startNode: find.semantics.byLabel('View2Child1'),
endNode: find.semantics.byLabel('View2Child3'),
)
.map((SemanticsNode node) => node.label),
<String>['View2Child1', 'View2Child2', 'View2Child3'],
);
});
}
Future<void> pumpViews({required WidgetTester tester}) {
final List<Widget> views = <Widget>[
for (int i = 0; i < 3; i++)
View(
view: i == 1 ? tester.view : FakeView(tester.view, viewId: i + 100),
child: Center(
child: Column(
children: <Widget>[
for (int c = 0; c < 5; c++)
Semantics(container: true, child: Text('View${i}Child$c')),
],
),
),
),
];
return tester.pumpWidget(
wrapWithView: false,
Directionality(textDirection: TextDirection.ltr, child: ViewCollection(views: views)),
);
}