semantics_10_test.dart 3.29 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// Copyright 2017 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/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';

import 'semantics_tester.dart';

List<String> callLog = <String>[];

void main() {
  testWidgets('can call markNeedsSemanticsUpdate(onlyChanges: true) followed by markNeedsSemanticsUpdate(onlyChanges: false)', (WidgetTester tester) async {
    final SemanticsTester semantics = new SemanticsTester(tester);

    await tester.pumpWidget(
Ian Hickson's avatar
Ian Hickson committed
19 20 21 22 23
      buildTestWidgets(
        excludeSemantics: false,
        label: 'label',
        isSemanticsBoundary: true,
      ),
24 25 26 27 28 29
    );

    callLog.clear();

    // The following should not trigger an assert.
    await tester.pumpWidget(
Ian Hickson's avatar
Ian Hickson committed
30 31 32 33 34
      buildTestWidgets(
        excludeSemantics: true,
        label: 'label CHANGED',
        isSemanticsBoundary: false,
      ),
35 36 37 38 39 40 41 42 43
    );

    expect(callLog, <String>['markNeedsSemanticsUpdate(onlyChanges: true)', 'markNeedsSemanticsUpdate(onlyChanges: false)']);

    semantics.dispose();
  });
}

Widget buildTestWidgets({bool excludeSemantics, String label, bool isSemanticsBoundary}) {
Ian Hickson's avatar
Ian Hickson committed
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
  return new Directionality(
    textDirection: TextDirection.ltr,
    child: new Semantics(
      label: 'container',
      container: true,
      child: new ExcludeSemantics(
        excluding: excludeSemantics,
        child: new TestWidget(
          label: label,
          isSemanticBoundary: isSemanticsBoundary,
          child: new Column(
            children: <Widget>[
              const Semantics(
                label: 'child1',
              ),
              const Semantics(
                label: 'child2',
              ),
            ],
          ),
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
        ),
      ),
    ),
  );
}

class TestWidget extends SingleChildRenderObjectWidget {
  const TestWidget({
    Key key,
    Widget child,
    this.label,
    this.isSemanticBoundary,
  }) : super(key: key, child: child);

  final String label;
  final bool isSemanticBoundary;

  @override
  RenderTest createRenderObject(BuildContext context) {
    return new RenderTest()
      ..label = label
      ..isSemanticBoundary = isSemanticBoundary;
  }

  @override
  void updateRenderObject(BuildContext context, RenderTest renderObject) {
    renderObject
      ..label = label
      ..isSemanticBoundary = isSemanticBoundary;
  }
}

class RenderTest extends RenderProxyBox {
97

98
  @override
99 100 101 102 103 104 105 106 107 108
  void describeSemanticsConfiguration(SemanticsConfiguration config) {
    super.describeSemanticsConfiguration(config);

    if (!_isSemanticBoundary)
      return;

    config
      ..isSemanticBoundary = _isSemanticBoundary
      ..label = _label
      ..textDirection = TextDirection.ltr;
109 110 111 112 113 114 115 116

  }

  String _label;
  set label(String value) {
    if (value == _label)
      return;
    _label = value;
117
    markNeedsSemanticsUpdate(onlyLocalUpdates: true);
118 119 120
    callLog.add('markNeedsSemanticsUpdate(onlyChanges: true)');
  }

121

122 123 124 125 126
  bool _isSemanticBoundary;
  set isSemanticBoundary(bool value) {
    if (_isSemanticBoundary == value)
      return;
    _isSemanticBoundary = value;
127
    markNeedsSemanticsUpdate(onlyLocalUpdates: false);
128 129 130
    callLog.add('markNeedsSemanticsUpdate(onlyChanges: false)');
  }
}