semantics_9_test.dart 4.67 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5 6
// 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';
7
import 'package:flutter/widgets.dart';
8 9 10 11 12 13 14
import 'package:flutter_test/flutter_test.dart';

import 'semantics_tester.dart';

void main() {
  group('BlockSemantics', () {
    testWidgets('hides semantic nodes of siblings', (WidgetTester tester) async {
15
      final SemanticsTester semantics = SemanticsTester(tester);
16

17
      await tester.pumpWidget(Stack(
18
        textDirection: TextDirection.ltr,
19
        children: <Widget>[
20
          Semantics(
21
            label: 'layer#1',
Ian Hickson's avatar
Ian Hickson committed
22
            textDirection: TextDirection.ltr,
23
            child: Container(),
24 25
          ),
          const BlockSemantics(),
26
          Semantics(
27
            label: 'layer#2',
Ian Hickson's avatar
Ian Hickson committed
28
            textDirection: TextDirection.ltr,
29
            child: Container(),
30 31 32 33
          ),
        ],
      ));

34
      expect(semantics, isNot(includesNodeWith(label: 'layer#1')));
35

36
      await tester.pumpWidget(Stack(
37
        textDirection: TextDirection.ltr,
38
        children: <Widget>[
39
          Semantics(
40
            label: 'layer#1',
Ian Hickson's avatar
Ian Hickson committed
41
            textDirection: TextDirection.ltr,
42
            child: Container(),
43 44 45 46
          ),
        ],
      ));

47
      expect(semantics, includesNodeWith(label: 'layer#1'));
48 49 50 51 52

      semantics.dispose();
    });

    testWidgets('does not hides semantic nodes of siblings outside the current semantic boundary', (WidgetTester tester) async {
53
      final SemanticsTester semantics = SemanticsTester(tester);
54

55
      await tester.pumpWidget(Directionality(textDirection: TextDirection.ltr, child: Stack(
56
        children: <Widget>[
57
          Semantics(
58
            label: '#1',
59
            child: Container(),
60
          ),
61
          Semantics(
62 63
            label: '#2',
            container: true,
64
            explicitChildNodes: true,
65
            child: Stack(
66
              children: <Widget>[
67
                Semantics(
68
                  label: 'NOT#2.1',
69
                  child: Container(),
70
                ),
71
                Semantics(
72
                  label: '#2.2',
73 74
                  child: BlockSemantics(
                    child: Semantics(
75 76
                      container: true,
                      label: '#2.2.1',
77
                      child: Container(),
78 79 80
                    ),
                  ),
                ),
81
                Semantics(
82
                  label: '#2.3',
83
                  child: Container(),
84 85 86 87
                ),
              ],
            ),
          ),
88
          Semantics(
89
            label: '#3',
90
            child: Container(),
91 92
          ),
        ],
Ian Hickson's avatar
Ian Hickson committed
93
      )));
94

95 96 97 98 99 100 101
      expect(semantics, includesNodeWith(label: '#1'));
      expect(semantics, includesNodeWith(label: '#2'));
      expect(semantics, isNot(includesNodeWith(label:'NOT#2.1')));
      expect(semantics, includesNodeWith(label: '#2.2'));
      expect(semantics, includesNodeWith(label: '#2.2.1'));
      expect(semantics, includesNodeWith(label: '#2.3'));
      expect(semantics, includesNodeWith(label: '#3'));
102 103 104 105 106

      semantics.dispose();
    });

    testWidgets('node is semantic boundary and blocking previously painted nodes', (WidgetTester tester) async {
107 108
      final SemanticsTester semantics = SemanticsTester(tester);
      final GlobalKey stackKey = GlobalKey();
109

110
      await tester.pumpWidget(Directionality(textDirection: TextDirection.ltr, child: Stack(
111 112
        key: stackKey,
        children: <Widget>[
113
          Semantics(
114
            label: 'NOT#1',
115
            child: Container(),
116
          ),
117 118
          BoundaryBlockSemantics(
            child: Semantics(
119
              label: '#2.1',
120
              child: Container(),
121
            ),
122
          ),
123
          Semantics(
124
            label: '#3',
125
            child: Container(),
126 127
          ),
        ],
Ian Hickson's avatar
Ian Hickson committed
128
      )));
129

130 131 132
      expect(semantics, isNot(includesNodeWith(label: 'NOT#1')));
      expect(semantics, includesNodeWith(label: '#2.1'));
      expect(semantics, includesNodeWith(label: '#3'));
133 134 135 136 137 138 139

      semantics.dispose();
    });
  });
}

class BoundaryBlockSemantics extends SingleChildRenderObjectWidget {
140
  const BoundaryBlockSemantics({ Key? key, required Widget child }) : super(key: key, child: child);
141 142

  @override
143
  RenderBoundaryBlockSemantics createRenderObject(BuildContext context) => RenderBoundaryBlockSemantics();
144 145 146
}

class RenderBoundaryBlockSemantics extends RenderProxyBox {
147
  RenderBoundaryBlockSemantics();
148 149

  @override
150 151
  void describeSemanticsConfiguration(SemanticsConfiguration config) {
    super.describeSemanticsConfiguration(config);
152

153 154 155 156
    config
      ..isBlockingSemanticsOfPreviouslyPaintedNodes = true
      ..isSemanticBoundary = true;
  }
157
}