blob: 6c530e785f1a0dfbb9067346c01fbbc55ab2f49c [file] [log] [blame]
// 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/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import '../widgets/semantics_tester.dart';
void main() {
testWidgets('SemanticsNodes overlapping in z', (WidgetTester tester) async {
// Cards are semantic boundaries that always own their own SemanticNode,
// PhysicalModels merge their semantics information into parent.
//
// Side view of the widget tree:
//
// Card('abs. elevation: 30') ---------------
// | 8 ----------- Card('abs. elevation 25')
// Card('abs. elevation: 22') --------------- |
// | 7 |
// PhysicalModel('abs. elevation: 15') --------------- | 15
// | 5 |
// --------------------------------------- Card('abs. elevation: 10')
// | 10
// |
// --------------------------------------- 'ground'
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(MaterialApp(
home: Column(
children: <Widget>[
const Text('ground'),
Card(
elevation: 10.0,
child: Column(
children: <Widget>[
const Text('absolute elevation: 10'),
PhysicalModel(
elevation: 5.0,
color: Colors.black,
child: Column(
children: <Widget>[
const Text('absolute elevation: 15'),
Card(
elevation: 7.0,
child: Column(
children: const <Widget>[
Text('absolute elevation: 22'),
Card(
elevation: 8.0,
child: Text('absolute elevation: 30'),
),
],
),
),
],
),
),
const Card(
elevation: 15.0,
child: Text('absolute elevation: 25'),
),
],
),
),
],
),
));
final SemanticsNode ground = tester.getSemantics(find.text('ground'));
expect(ground.thickness, 0.0);
expect(ground.elevation, 0.0);
expect(ground.label, 'ground');
final SemanticsNode elevation10 = tester.getSemantics(find.text('absolute elevation: 10'));
final SemanticsNode elevation15 = tester.getSemantics(find.text('absolute elevation: 15'));
expect(elevation10, same(elevation15)); // configs got merged into each other.
expect(elevation10.thickness, 15.0);
expect(elevation10.elevation, 0.0);
expect(elevation10.label, 'absolute elevation: 10\nabsolute elevation: 15');
final SemanticsNode elevation22 = tester.getSemantics(find.text('absolute elevation: 22'));
expect(elevation22.thickness, 7.0);
expect(elevation22.elevation, 15.0);
expect(elevation22.label, 'absolute elevation: 22');
final SemanticsNode elevation25 = tester.getSemantics(find.text('absolute elevation: 25'));
expect(elevation25.thickness, 15.0);
expect(elevation25.elevation, 10.0);
expect(elevation22.label, 'absolute elevation: 22');
final SemanticsNode elevation30 = tester.getSemantics(find.text('absolute elevation: 30'));
expect(elevation30.thickness, 8.0);
expect(elevation30.elevation, 7.0);
expect(elevation30.label, 'absolute elevation: 30');
semantics.dispose();
});
testWidgets('SemanticsNodes overlapping in z with switched children', (WidgetTester tester) async {
// Same as 'SemanticsNodes overlapping in z', but the order of children
// is reversed
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(MaterialApp(
home: Column(
children: <Widget>[
const Text('ground'),
Card(
elevation: 10.0,
child: Column(
children: <Widget>[
const Card(
elevation: 15.0,
child: Text('absolute elevation: 25'),
),
PhysicalModel(
elevation: 5.0,
color: Colors.black,
child: Column(
children: <Widget>[
const Text('absolute elevation: 15'),
Card(
elevation: 7.0,
child: Column(
children: const <Widget>[
Text('absolute elevation: 22'),
Card(
elevation: 8.0,
child: Text('absolute elevation: 30'),
),
],
),
),
],
),
),
const Text('absolute elevation: 10'),
],
),
),
],
),
));
final SemanticsNode ground = tester.getSemantics(find.text('ground'));
expect(ground.thickness, 0.0);
expect(ground.elevation, 0.0);
expect(ground.label, 'ground');
final SemanticsNode elevation10 = tester.getSemantics(find.text('absolute elevation: 10'));
final SemanticsNode elevation15 = tester.getSemantics(find.text('absolute elevation: 15'));
expect(elevation10, same(elevation15)); // configs got merged into each other.
expect(elevation10.thickness, 15.0);
expect(elevation10.elevation, 0.0);
expect(elevation10.label, 'absolute elevation: 15\nabsolute elevation: 10');
final SemanticsNode elevation22 = tester.getSemantics(find.text('absolute elevation: 22'));
expect(elevation22.thickness, 7.0);
expect(elevation22.elevation, 15.0);
expect(elevation22.label, 'absolute elevation: 22');
final SemanticsNode elevation25 = tester.getSemantics(find.text('absolute elevation: 25'));
expect(elevation25.thickness, 15.0);
expect(elevation25.elevation, 10.0);
expect(elevation22.label, 'absolute elevation: 22');
final SemanticsNode elevation30 = tester.getSemantics(find.text('absolute elevation: 30'));
expect(elevation30.thickness, 8.0);
expect(elevation30.elevation, 7.0);
expect(elevation30.label, 'absolute elevation: 30');
semantics.dispose();
});
testWidgets('single node thickness', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(const MaterialApp(
home: Center(
child: Material(
elevation: 24.0,
child: Text('Hello'),
),
),
));
final SemanticsNode node = tester.getSemantics(find.text('Hello'));
expect(node.thickness, 0.0);
expect(node.elevation, 24.0);
expect(node.label, 'Hello');
semantics.dispose();
});
testWidgets('force-merge', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(MaterialApp(
home: Card(
elevation: 10.0,
child: Column(
children: <Widget>[
const Text('abs. elevation: 10.0'),
MergeSemantics(
child: Semantics(
explicitChildNodes: true, // just to be sure that it's going to be an explicit merge
child: Column(
children: const <Widget>[
Card(
elevation: 15.0,
child: Text('abs. elevation 25.0'),
),
Card(
elevation: 5.0,
child: Text('abs. elevation 15.0'),
),
],
),
),
),
],
),
),
));
final SemanticsNode elevation10 = tester.getSemantics(find.text('abs. elevation: 10.0'));
expect(elevation10.thickness, 10.0);
expect(elevation10.elevation, 0.0);
expect(elevation10.label, 'abs. elevation: 10.0');
expect(elevation10.childrenCount, 1);
// TODO(goderbauer): remove awkward workaround when accessing force-merged
// SemanticsData becomes easier, https://github.com/flutter/flutter/issues/25669
SemanticsData? mergedChildData;
elevation10.visitChildren((SemanticsNode child) {
expect(mergedChildData, isNull);
mergedChildData = child.getSemanticsData();
return true;
});
expect(mergedChildData!.thickness, 15.0);
expect(mergedChildData!.elevation, 10.0);
expect(mergedChildData!.label, 'abs. elevation 25.0\nabs. elevation 15.0');
semantics.dispose();
});
testWidgets('force-merge with inversed children', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await tester.pumpWidget(MaterialApp(
home: Card(
elevation: 10.0,
child: Column(
children: <Widget>[
const Text('abs. elevation: 10.0'),
MergeSemantics(
child: Semantics(
explicitChildNodes: true, // just to be sure that it's going to be an explicit merge
child: Column(
children: const <Widget>[
Card(
elevation: 5.0,
child: Text('abs. elevation 15.0'),
),
Card(
elevation: 15.0,
child: Text('abs. elevation 25.0'),
),
],
),
),
),
],
),
),
));
final SemanticsNode elevation10 = tester.getSemantics(find.text('abs. elevation: 10.0'));
expect(elevation10.thickness, 10.0);
expect(elevation10.elevation, 0.0);
expect(elevation10.label, 'abs. elevation: 10.0');
expect(elevation10.childrenCount, 1);
// TODO(goderbauer): remove awkward workaround when accessing force-merged
// SemanticsData becomes easier, https://github.com/flutter/flutter/issues/25669
SemanticsData? mergedChildData;
elevation10.visitChildren((SemanticsNode child) {
expect(mergedChildData, isNull);
mergedChildData = child.getSemanticsData();
return true;
});
expect(mergedChildData!.thickness, 15.0);
expect(mergedChildData!.elevation, 10.0);
expect(mergedChildData!.label, 'abs. elevation 15.0\nabs. elevation 25.0');
semantics.dispose();
});
}