blob: b94bb2d5cd47958b11bf1ee5f8f4026265bf57fe [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.
@TestOn('!chrome')
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/semantics.dart';
import 'package:flutter_test/flutter_test.dart';
import 'semantics_tester.dart';
void main() {
group('generateTestSemanticsExpressionForCurrentSemanticsTree', () {
_tests();
});
}
void _tests() {
setUp(() {
debugResetSemanticsIdCounter();
});
Future<void> pumpTestWidget(WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: ListView(
children: <Widget>[
const Text('Plain text'),
Semantics(
selected: true,
checked: true,
onTap: () { },
onDecrease: () { },
value: 'test-value',
increasedValue: 'test-increasedValue',
decreasedValue: 'test-decreasedValue',
hint: 'test-hint',
textDirection: TextDirection.rtl,
child: const Text('Interactive text'),
),
],
),
));
}
// This test generates code using generateTestSemanticsExpressionForCurrentSemanticsTree
// then compares it to the code used in the 'generated code is correct' test
// below. When you update the implementation of generateTestSemanticsExpressionForCurrentSemanticsTree
// also update this code to reflect the new output.
//
// This test is flexible w.r.t. leading and trailing whitespace.
testWidgets('generates code', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await pumpTestWidget(tester);
final String code = semantics
.generateTestSemanticsExpressionForCurrentSemanticsTree(DebugSemanticsDumpOrder.inverseHitTest)
.split('\n')
.map<String>((String line) => line.trim())
.join('\n')
.trim() + ',';
File findThisTestFile(Directory directory) {
for (final FileSystemEntity entity in directory.listSync()) {
if (entity is Directory) {
final File childSearch = findThisTestFile(entity);
if (childSearch != null) {
return childSearch;
}
} else if (entity is File && entity.path.endsWith('semantics_tester_generateTestSemanticsExpressionForCurrentSemanticsTree_test.dart')) {
return entity;
}
}
return null;
}
final File thisTestFile = findThisTestFile(Directory.current);
expect(thisTestFile, isNotNull);
String expectedCode = thisTestFile.readAsStringSync();
expectedCode = expectedCode.substring(
expectedCode.indexOf('v' * 12) + 12,
expectedCode.indexOf('^' * 12) - 3,
)
.split('\n')
.map<String>((String line) => line.trim())
.join('\n')
.trim();
semantics.dispose();
expect(code, expectedCode);
});
testWidgets('generated code is correct', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
await pumpTestWidget(tester);
expect(
semantics,
hasSemantics(
// The code below delimited by "v" and "^" characters is generated by
// generateTestSemanticsExpressionForCurrentSemanticsTree function.
// You must update it when changing the output generated by
// generateTestSemanticsExpressionForCurrentSemanticsTree. Otherwise,
// the test 'generates code', defined above, will fail.
// vvvvvvvvvvvv
TestSemantics.root(
children: <TestSemantics>[
TestSemantics(
id: 1,
textDirection: TextDirection.ltr,
children: <TestSemantics>[
TestSemantics(
id: 2,
flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
children: <TestSemantics>[
TestSemantics(
id: 3,
children: <TestSemantics>[
TestSemantics(
id: 6,
flags: <SemanticsFlag>[SemanticsFlag.hasImplicitScrolling],
children: <TestSemantics>[
TestSemantics(
id: 4,
tags: <SemanticsTag>[const SemanticsTag('RenderViewport.twoPane')],
label: 'Plain text',
textDirection: TextDirection.ltr,
),
TestSemantics(
id: 5,
tags: <SemanticsTag>[const SemanticsTag('RenderViewport.twoPane')],
flags: <SemanticsFlag>[SemanticsFlag.hasCheckedState, SemanticsFlag.isChecked, SemanticsFlag.isSelected],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.decrease],
label: '‪Interactive text‬',
value: 'test-value',
increasedValue: 'test-increasedValue',
decreasedValue: 'test-decreasedValue',
hint: 'test-hint',
textDirection: TextDirection.rtl,
),
],
),
],
),
],
),
],
),
],
),
// ^^^^^^^^^^^^
ignoreRect: true,
ignoreTransform: true,
ignoreId: true,
),
);
semantics.dispose();
});
}