semantics_debugger_test.dart 10.3 KB
Newer Older
1 2 3 4
// 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.

5 6
import 'dart:ui' show window;

7 8
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
Ian Hickson's avatar
Ian Hickson committed
9
import 'package:flutter/rendering.dart';
10 11 12 13
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('SemanticsDebugger smoke test', (WidgetTester tester) async {
Ian Hickson's avatar
Ian Hickson committed
14

15 16
    // This is a smoketest to verify that adding a debugger doesn't crash.
    await tester.pumpWidget(
17
      Directionality(
18
        textDirection: TextDirection.ltr,
19
        child: Stack(
20
          children: <Widget>[
21 22
            Semantics(),
            Semantics(
23
              container: true,
24
            ),
25
            Semantics(
26
              label: 'label',
Ian Hickson's avatar
Ian Hickson committed
27
              textDirection: TextDirection.ltr,
28
            ),
29 30 31
          ],
        ),
      ),
32 33
    );

34
    await tester.pumpWidget(
35
      Directionality(
36
        textDirection: TextDirection.ltr,
37 38
        child: SemanticsDebugger(
          child: Stack(
39
            children: <Widget>[
40 41
              Semantics(),
              Semantics(
42 43
                container: true,
              ),
44
              Semantics(
45 46 47 48 49 50 51 52 53
                label: 'label',
                textDirection: TextDirection.ltr,
              ),
            ],
          ),
        ),
      ),
    );

54 55 56
    expect(true, isTrue); // expect that we reach here without crashing
  });

57
  testWidgets('SemanticsDebugger reparents subtree', (WidgetTester tester) async {
58
    final GlobalKey key = GlobalKey();
59 60

    await tester.pumpWidget(
61
      Directionality(
62
        textDirection: TextDirection.ltr,
63 64
        child: SemanticsDebugger(
          child: Stack(
65
            children: <Widget>[
66 67
              Semantics(label: 'label1', textDirection: TextDirection.ltr),
              Positioned(
68 69 70 71 72
                key: key,
                left: 0.0,
                top: 0.0,
                width: 100.0,
                height: 100.0,
73
                child: Semantics(label: 'label2', textDirection: TextDirection.ltr),
74
              ),
75 76
            ],
          ),
77 78
        ),
      ),
79 80 81
    );

    await tester.pumpWidget(
82
      Directionality(
83
        textDirection: TextDirection.ltr,
84 85
        child: SemanticsDebugger(
          child: Stack(
86
            children: <Widget>[
87 88
              Semantics(label: 'label1', textDirection: TextDirection.ltr),
              Semantics(
89
                container: true,
90
                child: Stack(
91
                  children: <Widget>[
92
                    Positioned(
93 94 95 96 97
                      key: key,
                      left: 0.0,
                      top: 0.0,
                      width: 100.0,
                      height: 100.0,
98
                      child: Semantics(label: 'label2', textDirection: TextDirection.ltr),
99
                    ),
100
                    Semantics(label: 'label3', textDirection: TextDirection.ltr),
101 102
                  ],
                ),
103
              ),
104 105 106 107 108 109 110
            ],
          ),
        ),
      ),
    );

    await tester.pumpWidget(
111
      Directionality(
112
        textDirection: TextDirection.ltr,
113 114
        child: SemanticsDebugger(
          child: Stack(
115
            children: <Widget>[
116 117
              Semantics(label: 'label1', textDirection: TextDirection.ltr),
              Semantics(
118
                container: true,
119
                child: Stack(
120
                  children: <Widget>[
121
                    Positioned(
122 123 124 125 126
                        key: key,
                        left: 0.0,
                        top: 0.0,
                        width: 100.0,
                        height: 100.0,
127 128 129
                        child: Semantics(label: 'label2', textDirection: TextDirection.ltr)),
                    Semantics(label: 'label3', textDirection: TextDirection.ltr),
                    Semantics(label: 'label4', textDirection: TextDirection.ltr),
130 131 132 133 134
                  ],
                ),
              ),
            ],
          ),
135 136
        ),
      ),
137 138 139 140
    );

    expect(tester.takeException(), isNull);
  });
141

142
  testWidgets('SemanticsDebugger interaction test', (WidgetTester tester) async {
143 144 145
    final List<String> log = <String>[];

    await tester.pumpWidget(
146
      Directionality(
147
        textDirection: TextDirection.ltr,
148 149 150
        child: SemanticsDebugger(
          child: Material(
            child: ListView(
151
              children: <Widget>[
152
                RaisedButton(
153 154 155 156 157
                  onPressed: () {
                    log.add('top');
                  },
                  child: const Text('TOP'),
                ),
158
                RaisedButton(
159 160 161 162 163 164 165
                  onPressed: () {
                    log.add('bottom');
                  },
                  child: const Text('BOTTOM'),
                ),
              ],
            ),
166
          ),
167 168 169 170 171 172 173 174 175 176 177 178 179
        ),
      ),
    );

    await tester.tap(find.text('TOP'));
    expect(log, equals(<String>['top']));
    log.clear();

    await tester.tap(find.text('BOTTOM'));
    expect(log, equals(<String>['bottom']));
    log.clear();
  });

180
  testWidgets('SemanticsDebugger interaction test - negative', (WidgetTester tester) async {
Ian Hickson's avatar
Ian Hickson committed
181 182 183
    final List<String> log = <String>[];

    await tester.pumpWidget(
184
      Directionality(
Ian Hickson's avatar
Ian Hickson committed
185
        textDirection: TextDirection.ltr,
186 187 188
        child: SemanticsDebugger(
          child: Material(
            child: ListView(
Ian Hickson's avatar
Ian Hickson committed
189
              children: <Widget>[
190
                RaisedButton(
Ian Hickson's avatar
Ian Hickson committed
191 192 193 194 195
                  onPressed: () {
                    log.add('top');
                  },
                  child: const Text('TOP', textDirection: TextDirection.ltr),
                ),
196 197
                ExcludeSemantics(
                  child: RaisedButton(
Ian Hickson's avatar
Ian Hickson committed
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
                    onPressed: () {
                      log.add('bottom');
                    },
                    child: const Text('BOTTOM', textDirection: TextDirection.ltr),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );

    await tester.tap(find.text('TOP'));
    expect(log, equals(<String>['top']));
    log.clear();

    await tester.tap(find.text('BOTTOM'));
    expect(log, equals(<String>[]));
    log.clear();
  });

220
  testWidgets('SemanticsDebugger scroll test', (WidgetTester tester) async {
221
    final Key childKey = UniqueKey();
222 223

    await tester.pumpWidget(
224
      Directionality(
225
        textDirection: TextDirection.ltr,
226 227
        child: SemanticsDebugger(
          child: ListView(
228
            children: <Widget>[
229
              Container(
230 231 232 233 234 235
                key: childKey,
                height: 5000.0,
                color: Colors.green[500],
              ),
            ],
          ),
236 237 238 239
        ),
      ),
    );

240
    expect(tester.getTopLeft(find.byKey(childKey)).dy, equals(0.0));
241

242
    await tester.fling(find.byType(ListView), const Offset(0.0, -200.0), 200.0);
243 244
    await tester.pump();

245
    expect(tester.getTopLeft(find.byKey(childKey)).dy, equals(-480.0));
246

247
    await tester.fling(find.byType(ListView), const Offset(200.0, 0.0), 200.0);
248 249
    await tester.pump();

250
    expect(tester.getTopLeft(find.byKey(childKey)).dy, equals(-480.0));
251

252
    await tester.fling(find.byType(ListView), const Offset(-200.0, 0.0), 200.0);
253 254
    await tester.pump();

255
    expect(tester.getTopLeft(find.byKey(childKey)).dy, equals(-480.0));
256

257
    await tester.fling(find.byType(ListView), const Offset(0.0, 200.0), 200.0);
258 259
    await tester.pump();

260
    expect(tester.getTopLeft(find.byKey(childKey)).dy, equals(0.0));
261 262 263 264 265 266
  });

  testWidgets('SemanticsDebugger long press', (WidgetTester tester) async {
    bool didLongPress = false;

    await tester.pumpWidget(
267
      Directionality(
268
        textDirection: TextDirection.ltr,
269 270
        child: SemanticsDebugger(
          child: GestureDetector(
271 272 273 274 275 276
            onLongPress: () {
              expect(didLongPress, isFalse);
              didLongPress = true;
            },
            child: const Text('target', textDirection: TextDirection.ltr),
          ),
277 278 279 280 281 282 283 284 285 286 287 288
        ),
      ),
    );

    await tester.longPress(find.text('target'));
    expect(didLongPress, isTrue);
  });

  testWidgets('SemanticsDebugger slider', (WidgetTester tester) async {
    double value = 0.75;

    await tester.pumpWidget(
289
      Directionality(
290
        textDirection: TextDirection.ltr,
291 292
        child: SemanticsDebugger(
          child: Directionality(
293
            textDirection: TextDirection.ltr,
294 295 296 297 298
            child: MediaQuery(
              data: MediaQueryData.fromWindow(window),
              child: Material(
                child: Center(
                  child: Slider(
299 300 301 302 303
                    value: value,
                    onChanged: (double newValue) {
                      value = newValue;
                    },
                  ),
304
                ),
305
              ),
306 307 308 309 310 311
            ),
          ),
        ),
      ),
    );

312 313 314 315 316 317
    // The fling below must be such that the velocity estimation examines an
    // offset greater than the kTouchSlop. Too slow or too short a distance, and
    // it won't trigger. The actual distance moved doesn't matter since this is
    // interpreted as a gesture by the semantics debugger and sent to the widget
    // as a semantic action that always moves by 10% of the complete track.
    await tester.fling(find.byType(Slider), const Offset(-100.0, 0.0), 2000.0);
318
    expect(value, equals(0.70));
319 320 321
  });

  testWidgets('SemanticsDebugger checkbox', (WidgetTester tester) async {
322 323
    final Key keyTop = UniqueKey();
    final Key keyBottom = UniqueKey();
324 325

    bool valueTop = false;
326
    const bool valueBottom = true;
327 328

    await tester.pumpWidget(
329
      Directionality(
330
        textDirection: TextDirection.ltr,
331 332 333
        child: SemanticsDebugger(
          child: Material(
            child: ListView(
334
              children: <Widget>[
335
                Checkbox(
336 337 338 339 340 341
                  key: keyTop,
                  value: valueTop,
                  onChanged: (bool newValue) {
                    valueTop = newValue;
                  },
                ),
342
                Checkbox(
343 344 345 346 347 348
                  key: keyBottom,
                  value: valueBottom,
                  onChanged: null,
                ),
              ],
            ),
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
          ),
        ),
      ),
    );

    await tester.tap(find.byKey(keyTop));

    expect(valueTop, isTrue);
    valueTop = false;
    expect(valueTop, isFalse);

    await tester.tap(find.byKey(keyBottom));

    expect(valueTop, isFalse);
    expect(valueTop, isFalse);
  });
365
}