mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
This match switches the framework to use the semantics backend in `dart:ui` rather than the Mojo backend.
165 lines
5.9 KiB
Dart
165 lines
5.9 KiB
Dart
// Copyright 2015 The Chromium 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_test/flutter_test.dart';
|
|
import 'package:meta/meta.dart';
|
|
|
|
export 'package:flutter/rendering.dart' show SemanticsData;
|
|
|
|
/// Test semantics data that is compared against real semantics tree.
|
|
///
|
|
/// Useful with [hasSemantics] and [SemanticsTester] to test the contents of the
|
|
/// semantics tree.
|
|
class TestSemantics {
|
|
/// Creates an object witht some test semantics data.
|
|
///
|
|
/// If [rect] argument is null, the [rect] field with ve initialized with
|
|
/// `new Rect.fromLTRB(0.0, 0.0, 800.0, 600.0)`, which is the default size of
|
|
/// the screen during unit testing.
|
|
TestSemantics({
|
|
this.id,
|
|
this.flags: 0,
|
|
this.actions: 0,
|
|
this.label: '',
|
|
Rect rect,
|
|
this.transform,
|
|
this.children: const <TestSemantics>[],
|
|
}) : rect = rect ?? new Rect.fromLTRB(0.0, 0.0, 800.0, 600.0);
|
|
|
|
/// The unique identifier for this node.
|
|
///
|
|
/// The root node has an id of zero. Other nodes are given a unique id when
|
|
/// they are created.
|
|
final int id;
|
|
|
|
/// A bit field of [SemanticsFlags] that apply to this node.
|
|
final int flags;
|
|
|
|
/// A bit field of [SemanticsActions] that apply to this node.
|
|
final int actions;
|
|
|
|
/// A textual description of this node.
|
|
final String label;
|
|
|
|
/// The bounding box for this node in its coordinate system.
|
|
final Rect rect;
|
|
|
|
/// The transform from this node's coordinate system to its parent's coordinate system.
|
|
///
|
|
/// By default, the transform is null, which represents the identity
|
|
/// transformation (i.e., that this node has the same coorinate system as its
|
|
/// parent).
|
|
final Matrix4 transform;
|
|
|
|
/// The children of this node.
|
|
final List<TestSemantics> children;
|
|
|
|
SemanticsData _getSemanticsData() {
|
|
return new SemanticsData(
|
|
flags: flags,
|
|
actions: actions,
|
|
label: label,
|
|
rect: rect,
|
|
transform: transform
|
|
);
|
|
}
|
|
|
|
bool _matches(SemanticsNode node, Map<dynamic, dynamic> matchState) {
|
|
if (node == null || id != node.id
|
|
|| _getSemanticsData() != node.getSemanticsData()
|
|
|| children.length != (node.mergeAllDescendantsIntoThisNode ? 0 : node.childrenCount)) {
|
|
matchState[TestSemantics] = this;
|
|
matchState[SemanticsNode] = node;
|
|
return false;
|
|
}
|
|
if (children.isEmpty)
|
|
return true;
|
|
bool result = true;
|
|
Iterator<TestSemantics> it = children.iterator;
|
|
node.visitChildren((SemanticsNode node) {
|
|
it.moveNext();
|
|
if (!it.current._matches(node, matchState)) {
|
|
result = false;
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// Ensures that the given widget tester has a semantics tree to test.
|
|
///
|
|
/// Useful with [hasSemantics] to test the contents of the semantics tree.
|
|
class SemanticsTester {
|
|
/// Creates a semantics tester for the given widget tester.
|
|
///
|
|
/// You should call [dispose] at the end of a test that creates a semantics
|
|
/// tester.
|
|
SemanticsTester(this.tester) {
|
|
_semanticsHandle = tester.binding.pipelineOwner.ensureSemantics();
|
|
}
|
|
|
|
/// The widget tester that this object is testing the semantics of.
|
|
final WidgetTester tester;
|
|
SemanticsHandle _semanticsHandle;
|
|
|
|
/// Release resources held by this semantics tester.
|
|
///
|
|
/// Call this function at the end of any test that uses a semantics tester.
|
|
@mustCallSuper
|
|
void dispose() {
|
|
_semanticsHandle.dispose();
|
|
_semanticsHandle = null;
|
|
}
|
|
|
|
@override
|
|
String toString() => 'SemanticsTester';
|
|
}
|
|
|
|
class _HasSemantics extends Matcher {
|
|
const _HasSemantics(this._semantics);
|
|
|
|
final TestSemantics _semantics;
|
|
|
|
@override
|
|
bool matches(@checked SemanticsTester item, Map<dynamic, dynamic> matchState) {
|
|
return _semantics._matches(item.tester.binding.pipelineOwner.semanticsOwner.rootSemanticsNode, matchState);
|
|
}
|
|
|
|
@override
|
|
Description describe(Description description) {
|
|
return description.add('semantics node id ${_semantics.id}');
|
|
}
|
|
|
|
@override
|
|
Description describeMismatch(dynamic item, Description mismatchDescription, Map<dynamic, dynamic> matchState, bool verbose) {
|
|
TestSemantics testNode = matchState[TestSemantics];
|
|
SemanticsNode node = matchState[SemanticsNode];
|
|
if (node == null)
|
|
return mismatchDescription.add('could not find node with id ${testNode.id}');
|
|
if (testNode.id != node.id)
|
|
return mismatchDescription.add('expected node id ${testNode.id} but found id ${node.id}');
|
|
final SemanticsData data = node.getSemanticsData();
|
|
if (testNode.flags != data.flags)
|
|
return mismatchDescription.add('expected node id ${testNode.id} to have flags ${testNode.flags} but found flags ${data.flags}');
|
|
if (testNode.actions != data.actions)
|
|
return mismatchDescription.add('expected node id ${testNode.id} to have actions ${testNode.actions} but found actions ${data.actions}');
|
|
if (testNode.label != data.label)
|
|
return mismatchDescription.add('expected node id ${testNode.id} to have label "${testNode.label}" but found label "${data.label}"');
|
|
if (testNode.rect != data.rect)
|
|
return mismatchDescription.add('expected node id ${testNode.id} to have rect ${testNode.rect} but found rect ${data.rect}');
|
|
if (testNode.transform != data.transform)
|
|
return mismatchDescription.add('expected node id ${testNode.id} to have transform ${testNode.transform} but found transform ${data.transform}');
|
|
final int childrenCount = node.mergeAllDescendantsIntoThisNode ? 0 : node.childrenCount;
|
|
if (testNode.children.length != childrenCount)
|
|
return mismatchDescription.add('expected node id ${testNode.id} to have ${testNode.children.length} but found $childrenCount children');
|
|
return mismatchDescription;
|
|
}
|
|
}
|
|
|
|
/// Asserts that a [SemanticsTester] has a semantics tree that exactly matches the given semantics.
|
|
Matcher hasSemantics(TestSemantics semantics) => new _HasSemantics(semantics);
|