| // 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: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_generate_test_semantics_expression_for_current_semantics_tree_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, |
| children: <TestSemantics>[ |
| TestSemantics( |
| id: 3, |
| flags: <SemanticsFlag>[SemanticsFlag.scopesRoute], |
| children: <TestSemantics>[ |
| TestSemantics( |
| id: 4, |
| children: <TestSemantics>[ |
| TestSemantics( |
| id: 7, |
| flags: <SemanticsFlag>[SemanticsFlag.hasImplicitScrolling], |
| children: <TestSemantics>[ |
| TestSemantics( |
| id: 5, |
| tags: <SemanticsTag>[const SemanticsTag('RenderViewport.twoPane')], |
| label: 'Plain text', |
| textDirection: TextDirection.ltr, |
| ), |
| TestSemantics( |
| id: 6, |
| tags: <SemanticsTag>[const SemanticsTag('RenderViewport.twoPane')], |
| flags: <SemanticsFlag>[SemanticsFlag.hasCheckedState, SemanticsFlag.isChecked, SemanticsFlag.isSelected], |
| actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.decrease], |
| label: '\u202aInteractive text\u202c', |
| value: 'test-value', |
| increasedValue: 'test-increasedValue', |
| decreasedValue: 'test-decreasedValue', |
| hint: 'test-hint', |
| textDirection: TextDirection.rtl, |
| ), |
| ], |
| ), |
| ], |
| ), |
| ], |
| ), |
| ], |
| ), |
| ], |
| ), |
| ], |
| ), |
| // ^^^^^^^^^^^^ |
| ignoreRect: true, |
| ignoreTransform: true, |
| ignoreId: true, |
| ), |
| ); |
| semantics.dispose(); |
| }); |
| } |