scrollable_semantics_traversal_order_test.dart 30.8 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5 6 7 8 9 10 11 12 13 14 15
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:ui';

import 'package:flutter/rendering.dart';
import 'package:flutter/semantics.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';

import 'semantics_tester.dart';

void main() {
  testWidgets('Traversal Order of SliverList', (WidgetTester tester) async {
16
    final SemanticsTester semantics = SemanticsTester(tester);
17

18 19
    final List<Widget> listChildren = List<Widget>.generate(30, (int i) {
      return Container(
20
        height: 200.0,
21
        child: Row(
22 23
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
24
            Semantics(
25
              container: true,
26
              child: Text('Item ${i}a'),
27
            ),
28
            Semantics(
29
              container: true,
30
              child: Text('item ${i}b'),
31 32 33 34 35 36
            ),
          ],
        ),
      );
    });
    await tester.pumpWidget(
37
      Semantics(
38
        textDirection: TextDirection.ltr,
39
        child: Directionality(
40
          textDirection: TextDirection.ltr,
41
          child: MediaQuery(
42
            data: const MediaQueryData(),
43 44
            child: CustomScrollView(
              controller: ScrollController(initialScrollOffset: 3000.0),
45
              semanticChildCount: 30,
46
              slivers: <Widget>[
47 48
                SliverList(
                  delegate: SliverChildListDelegate(listChildren),
49 50 51 52 53 54 55 56 57
                ),
              ],
            ),
          ),
        ),
      ),
    );

    expect(semantics, hasSemantics(
58
      TestSemantics.root(
59
        children: <TestSemantics>[
60
          TestSemantics(
61 62
            textDirection: TextDirection.ltr,
            children: <TestSemantics>[
63
              TestSemantics(
64
                children: <TestSemantics>[
65
                  TestSemantics(
66 67
                    scrollIndex: 15,
                    scrollChildren: 30,
68 69 70
                    flags: <SemanticsFlag>[
                      SemanticsFlag.hasImplicitScrolling,
                    ],
71 72 73 74 75
                    actions: <SemanticsAction>[
                      SemanticsAction.scrollUp,
                      SemanticsAction.scrollDown,
                    ],
                    children: <TestSemantics>[
76
                      TestSemantics(
77
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
78 79 80 81 82 83 84 85 86 87 88 89
                        children: <TestSemantics>[
                          TestSemantics(
                            flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                            label: 'Item 13a',
                            textDirection: TextDirection.ltr,
                          ),
                          TestSemantics(
                            flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                            label: 'item 13b',
                            textDirection: TextDirection.ltr,
                          ),
                        ],
90
                      ),
91
                      TestSemantics(
92
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
93 94 95 96 97 98 99 100 101 102 103
                        children: <TestSemantics>[
                          TestSemantics(
                            flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                            label: 'Item 14a',
                            textDirection: TextDirection.ltr,
                          ),
                          TestSemantics(
                            flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                            label: 'item 14b',
                            textDirection: TextDirection.ltr,
                          ),
104
                        ],
105
                      ),
106
                      TestSemantics(
107 108 109 110 111 112 113 114 115 116
                        children: <TestSemantics>[
                          TestSemantics(
                            label: 'Item 15a',
                            textDirection: TextDirection.ltr,
                          ),
                          TestSemantics(
                            label: 'item 15b',
                            textDirection: TextDirection.ltr,
                          ),
                        ],
117
                      ),
118
                      TestSemantics(
119 120 121 122 123 124 125 126 127 128
                        children: <TestSemantics>[
                          TestSemantics(
                            label: 'Item 16a',
                            textDirection: TextDirection.ltr,
                          ),
                          TestSemantics(
                            label: 'item 16b',
                            textDirection: TextDirection.ltr,
                          ),
                        ],
129
                      ),
130
                      TestSemantics(
131 132 133 134 135 136 137 138 139 140
                        children: <TestSemantics>[
                          TestSemantics(
                            label: 'Item 17a',
                            textDirection: TextDirection.ltr,
                          ),
                          TestSemantics(
                            label: 'item 17b',
                            textDirection: TextDirection.ltr,
                          ),
                        ],
141
                      ),
142
                      TestSemantics(
143
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
144 145 146 147 148 149 150 151 152 153 154 155
                        children: <TestSemantics>[
                          TestSemantics(
                            flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                            label: 'Item 18a',
                            textDirection: TextDirection.ltr,
                          ),
                          TestSemantics(
                            flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                            label: 'item 18b',
                            textDirection: TextDirection.ltr,
                          ),
                        ],
156
                      ),
157
                      TestSemantics(
158
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
159 160 161 162 163 164 165 166 167 168 169 170
                        children: <TestSemantics>[
                          TestSemantics(
                            flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                            label: 'Item 19a',
                            textDirection: TextDirection.ltr,
                          ),
                          TestSemantics(
                            flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                            label: 'item 19b',
                            textDirection: TextDirection.ltr,
                          ),
                        ],
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
                      ),
                    ],
                  ),
                ],
              ),
            ],
          ),
        ],
      ),
      childOrder: DebugSemanticsDumpOrder.traversalOrder,
      ignoreId: true,
      ignoreTransform: true,
      ignoreRect: true,
    ));

    semantics.dispose();
  });

  testWidgets('Traversal Order of SliverFixedExtentList', (WidgetTester tester) async {
190
    final SemanticsTester semantics = SemanticsTester(tester);
191

192 193
    final List<Widget> listChildren = List<Widget>.generate(30, (int i) {
      return Container(
194
        height: 200.0,
195
        child: Row(
196 197
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
198
            Semantics(
199
              container: true,
200
              child: Text('Item ${i}a'),
201
            ),
202
            Semantics(
203
              container: true,
204
              child: Text('item ${i}b'),
205 206 207 208 209 210
            ),
          ],
        ),
      );
    });
    await tester.pumpWidget(
211
      Semantics(
212
        textDirection: TextDirection.ltr,
213
        child: Directionality(
214
          textDirection: TextDirection.ltr,
215
          child: MediaQuery(
216
            data: const MediaQueryData(),
217 218
            child: CustomScrollView(
              controller: ScrollController(initialScrollOffset: 3000.0),
219
              slivers: <Widget>[
220
                SliverFixedExtentList(
221
                  itemExtent: 200.0,
222
                  delegate: SliverChildListDelegate(listChildren, addSemanticIndexes: false),
223 224 225 226 227 228 229 230 231
                ),
              ],
            ),
          ),
        ),
      ),
    );

    expect(semantics, hasSemantics(
232
      TestSemantics.root(
233
        children: <TestSemantics>[
234
          TestSemantics(
235 236
            textDirection: TextDirection.ltr,
            children: <TestSemantics>[
237
              TestSemantics(
238
                children: <TestSemantics>[
239
                  TestSemantics(
240 241 242
                    flags: <SemanticsFlag>[
                      SemanticsFlag.hasImplicitScrolling,
                    ],
243 244 245 246 247
                    actions: <SemanticsAction>[
                      SemanticsAction.scrollUp,
                      SemanticsAction.scrollDown,
                    ],
                    children: <TestSemantics>[
248
                      TestSemantics(
249 250 251 252
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'Item 13a',
                        textDirection: TextDirection.ltr,
                      ),
253
                      TestSemantics(
254 255 256 257
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'item 13b',
                        textDirection: TextDirection.ltr,
                      ),
258
                      TestSemantics(
259 260 261 262
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'Item 14a',
                        textDirection: TextDirection.ltr,
                      ),
263
                      TestSemantics(
264 265 266 267
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'item 14b',
                        textDirection: TextDirection.ltr,
                      ),
268
                      TestSemantics(
269 270 271
                        label: 'Item 15a',
                        textDirection: TextDirection.ltr,
                      ),
272
                      TestSemantics(
273 274 275
                        label: 'item 15b',
                        textDirection: TextDirection.ltr,
                      ),
276
                      TestSemantics(
277 278 279
                        label: 'Item 16a',
                        textDirection: TextDirection.ltr,
                      ),
280
                      TestSemantics(
281 282 283
                        label: 'item 16b',
                        textDirection: TextDirection.ltr,
                      ),
284
                      TestSemantics(
285 286 287
                        label: 'Item 17a',
                        textDirection: TextDirection.ltr,
                      ),
288
                      TestSemantics(
289 290 291
                        label: 'item 17b',
                        textDirection: TextDirection.ltr,
                      ),
292
                      TestSemantics(
293 294 295 296
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'Item 18a',
                        textDirection: TextDirection.ltr,
                      ),
297
                      TestSemantics(
298 299 300 301
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'item 18b',
                        textDirection: TextDirection.ltr,
                      ),
302
                      TestSemantics(
303 304 305 306
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'Item 19a',
                        textDirection: TextDirection.ltr,
                      ),
307
                      TestSemantics(
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'item 19b',
                        textDirection: TextDirection.ltr,
                      ),
                    ],
                  ),
                ],
              ),
            ],
          ),
        ],
      ),
      childOrder: DebugSemanticsDumpOrder.traversalOrder,
      ignoreId: true,
      ignoreTransform: true,
      ignoreRect: true,
    ));

    semantics.dispose();
  });

  testWidgets('Traversal Order of SliverGrid', (WidgetTester tester) async {
330
    final SemanticsTester semantics = SemanticsTester(tester);
331

332 333
    final List<Widget> listChildren = List<Widget>.generate(30, (int i) {
      return Container(
334
        height: 200.0,
335
        child: Text('Item $i'),
336 337 338
      );
    });
    await tester.pumpWidget(
339
      Semantics(
340
        textDirection: TextDirection.ltr,
341
        child: Directionality(
342
          textDirection: TextDirection.ltr,
343
          child: MediaQuery(
344
            data: const MediaQueryData(),
345 346
            child: CustomScrollView(
              controller: ScrollController(initialScrollOffset: 1600.0),
347
              slivers: <Widget>[
348
                SliverGrid.count(
349 350 351 352 353 354 355 356 357 358 359 360
                  crossAxisCount: 2,
                  crossAxisSpacing: 400.0,
                  children: listChildren,
                ),
              ],
            ),
          ),
        ),
      ),
    );

    expect(semantics, hasSemantics(
361
      TestSemantics.root(
362
        children: <TestSemantics>[
363
          TestSemantics(
364 365
            textDirection: TextDirection.ltr,
            children: <TestSemantics>[
366
              TestSemantics(
367
                children: <TestSemantics>[
368
                  TestSemantics(
369 370 371 372 373 374 375
                    flags: <SemanticsFlag>[
                      SemanticsFlag.hasImplicitScrolling,
                    ],
                    actions: <SemanticsAction>[
                      SemanticsAction.scrollUp,
                      SemanticsAction.scrollDown,
                    ],
376
                    children: <TestSemantics>[
377
                      TestSemantics(
378 379 380 381
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'Item 12',
                        textDirection: TextDirection.ltr,
                      ),
382
                      TestSemantics(
383 384 385 386
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'Item 13',
                        textDirection: TextDirection.ltr,
                      ),
387
                      TestSemantics(
388 389 390 391
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'Item 14',
                        textDirection: TextDirection.ltr,
                      ),
392
                      TestSemantics(
393 394 395 396
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'Item 15',
                        textDirection: TextDirection.ltr,
                      ),
397
                      TestSemantics(
398 399 400
                        label: 'Item 16',
                        textDirection: TextDirection.ltr,
                      ),
401
                      TestSemantics(
402 403 404
                        label: 'Item 17',
                        textDirection: TextDirection.ltr,
                      ),
405
                      TestSemantics(
406 407 408
                        label: 'Item 18',
                        textDirection: TextDirection.ltr,
                      ),
409
                      TestSemantics(
410 411 412
                        label: 'Item 19',
                        textDirection: TextDirection.ltr,
                      ),
413
                      TestSemantics(
414 415 416
                        label: 'Item 20',
                        textDirection: TextDirection.ltr,
                      ),
417
                      TestSemantics(
418 419 420
                        label: 'Item 21',
                        textDirection: TextDirection.ltr,
                      ),
421
                      TestSemantics(
422 423 424 425
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'Item 22',
                        textDirection: TextDirection.ltr,
                      ),
426
                      TestSemantics(
427 428 429 430
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'Item 23',
                        textDirection: TextDirection.ltr,
                      ),
431
                      TestSemantics(
432 433 434 435
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'Item 24',
                        textDirection: TextDirection.ltr,
                      ),
436
                      TestSemantics(
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'Item 25',
                        textDirection: TextDirection.ltr,
                      ),
                    ],
                  ),
                ],
              ),
            ],
          ),
        ],
      ),
      childOrder: DebugSemanticsDumpOrder.traversalOrder,
      ignoreId: true,
      ignoreTransform: true,
      ignoreRect: true,
    ));

    semantics.dispose();
  });

  testWidgets('Traversal Order of List of individual slivers', (WidgetTester tester) async {
459
    final SemanticsTester semantics = SemanticsTester(tester);
460

461 462 463
    final List<Widget> listChildren = List<Widget>.generate(30, (int i) {
      return SliverToBoxAdapter(
        child: Container(
464
          height: 200.0,
465
          child: Row(
466 467
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
468
              Semantics(
469
                container: true,
470
                child: Text('Item ${i}a'),
471
              ),
472
              Semantics(
473
                container: true,
474
                child: Text('item ${i}b'),
475 476 477 478 479 480 481
              ),
            ],
          ),
        ),
      );
    });
    await tester.pumpWidget(
482
      Semantics(
483
        textDirection: TextDirection.ltr,
484
        child: Directionality(
485
          textDirection: TextDirection.ltr,
486
          child: MediaQuery(
487
            data: const MediaQueryData(),
488 489
            child: CustomScrollView(
              controller: ScrollController(initialScrollOffset: 3000.0),
490 491 492 493 494 495 496 497
              slivers: listChildren,
            ),
          ),
        ),
      ),
    );

    expect(semantics, hasSemantics(
498
      TestSemantics.root(
499
        children: <TestSemantics>[
500
          TestSemantics(
501 502
            textDirection: TextDirection.ltr,
            children: <TestSemantics>[
503
              TestSemantics(
504
                children: <TestSemantics>[
505
                  TestSemantics(
506 507 508
                    flags: <SemanticsFlag>[
                      SemanticsFlag.hasImplicitScrolling,
                    ],
509 510 511 512 513
                    actions: <SemanticsAction>[
                      SemanticsAction.scrollUp,
                      SemanticsAction.scrollDown,
                    ],
                    children: <TestSemantics>[
514
                      TestSemantics(
515 516 517 518
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'Item 13a',
                        textDirection: TextDirection.ltr,
                      ),
519
                      TestSemantics(
520 521 522 523
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'item 13b',
                        textDirection: TextDirection.ltr,
                      ),
524
                      TestSemantics(
525 526 527 528
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'Item 14a',
                        textDirection: TextDirection.ltr,
                      ),
529
                      TestSemantics(
530 531 532 533
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'item 14b',
                        textDirection: TextDirection.ltr,
                      ),
534
                      TestSemantics(
535 536 537
                        label: 'Item 15a',
                        textDirection: TextDirection.ltr,
                      ),
538
                      TestSemantics(
539 540 541
                        label: 'item 15b',
                        textDirection: TextDirection.ltr,
                      ),
542
                      TestSemantics(
543 544 545
                        label: 'Item 16a',
                        textDirection: TextDirection.ltr,
                      ),
546
                      TestSemantics(
547 548 549
                        label: 'item 16b',
                        textDirection: TextDirection.ltr,
                      ),
550
                      TestSemantics(
551 552 553
                        label: 'Item 17a',
                        textDirection: TextDirection.ltr,
                      ),
554
                      TestSemantics(
555 556 557
                        label: 'item 17b',
                        textDirection: TextDirection.ltr,
                      ),
558
                      TestSemantics(
559 560 561 562
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'Item 18a',
                        textDirection: TextDirection.ltr,
                      ),
563
                      TestSemantics(
564 565 566 567
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'item 18b',
                        textDirection: TextDirection.ltr,
                      ),
568
                      TestSemantics(
569 570 571 572
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'Item 19a',
                        textDirection: TextDirection.ltr,
                      ),
573
                      TestSemantics(
574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: 'item 19b',
                        textDirection: TextDirection.ltr,
                      ),
                    ],
                  ),
                ],
              ),
            ],
          ),
        ],
      ),
      childOrder: DebugSemanticsDumpOrder.traversalOrder,
      ignoreId: true,
      ignoreTransform: true,
      ignoreRect: true,
    ));

    semantics.dispose();
  });

  testWidgets('Traversal Order of in a SingleChildScrollView', (WidgetTester tester) async {
596
    final SemanticsTester semantics = SemanticsTester(tester);
597

598 599
    final List<Widget> listChildren = List<Widget>.generate(30, (int i) {
      return Container(
600
        height: 200.0,
601
        child: Row(
602 603
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
604
            Semantics(
605
              container: true,
606
              child: Text('Item ${i}a'),
607
            ),
608
            Semantics(
609
              container: true,
610
              child: Text('item ${i}b'),
611 612 613 614 615 616
            ),
          ],
        ),
      );
    });
    await tester.pumpWidget(
617
      Semantics(
618
        textDirection: TextDirection.ltr,
619
        child: Directionality(
620
          textDirection: TextDirection.ltr,
621
          child: MediaQuery(
622
            data: const MediaQueryData(),
623 624 625
            child: SingleChildScrollView(
              controller: ScrollController(initialScrollOffset: 3000.0),
              child: Column(
626 627 628 629 630 631 632 633 634
                children: listChildren,
              ),
            ),
          ),
        ),
      ),
    );

    expect(semantics, hasSemantics(
635
      TestSemantics.root(
636
        children: <TestSemantics>[
637
          TestSemantics(
638 639
            textDirection: TextDirection.ltr,
            children: <TestSemantics>[
640
              TestSemantics(
641 642 643
                flags: <SemanticsFlag>[
                  SemanticsFlag.hasImplicitScrolling,
                ],
644 645 646 647 648
                actions: <SemanticsAction>[
                  SemanticsAction.scrollUp,
                  SemanticsAction.scrollDown,
                ],
                children: <TestSemantics>[
649
                  TestSemantics(
650 651 652 653
                    flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                    label: 'Item 13a',
                    textDirection: TextDirection.ltr,
                  ),
654
                  TestSemantics(
655 656 657 658
                    flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                    label: 'item 13b',
                    textDirection: TextDirection.ltr,
                  ),
659
                  TestSemantics(
660 661 662 663
                    flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                    label: 'Item 14a',
                    textDirection: TextDirection.ltr,
                  ),
664
                  TestSemantics(
665 666 667 668
                    flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                    label: 'item 14b',
                    textDirection: TextDirection.ltr,
                  ),
669
                  TestSemantics(
670 671 672
                    label: 'Item 15a',
                    textDirection: TextDirection.ltr,
                  ),
673
                  TestSemantics(
674 675 676
                    label: 'item 15b',
                    textDirection: TextDirection.ltr,
                  ),
677
                  TestSemantics(
678 679 680
                    label: 'Item 16a',
                    textDirection: TextDirection.ltr,
                  ),
681
                  TestSemantics(
682 683 684
                    label: 'item 16b',
                    textDirection: TextDirection.ltr,
                  ),
685
                  TestSemantics(
686 687 688
                    label: 'Item 17a',
                    textDirection: TextDirection.ltr,
                  ),
689
                  TestSemantics(
690 691 692
                    label: 'item 17b',
                    textDirection: TextDirection.ltr,
                  ),
693
                  TestSemantics(
694 695 696 697
                    flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                    label: 'Item 18a',
                    textDirection: TextDirection.ltr,
                  ),
698
                  TestSemantics(
699 700 701 702
                    flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                    label: 'item 18b',
                    textDirection: TextDirection.ltr,
                  ),
703
                  TestSemantics(
704 705 706 707
                    flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                    label: 'Item 19a',
                    textDirection: TextDirection.ltr,
                  ),
708
                  TestSemantics(
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728
                    flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                    label: 'item 19b',
                    textDirection: TextDirection.ltr,
                  ),
                ],
              ),
            ],
          ),
        ],
      ),
      childOrder: DebugSemanticsDumpOrder.traversalOrder,
      ignoreId: true,
      ignoreTransform: true,
      ignoreRect: true,
    ));

    semantics.dispose();
  });

  testWidgets('Traversal Order with center child', (WidgetTester tester) async {
729
    final SemanticsTester semantics = SemanticsTester(tester);
730

731
    await tester.pumpWidget(Semantics(
732
      textDirection: TextDirection.ltr,
733
      child: Directionality(
734
        textDirection: TextDirection.ltr,
735
        child: MediaQuery(
736
          data: const MediaQueryData(),
737
          child: Scrollable(
738
            viewportBuilder: (BuildContext context, ViewportOffset offset) {
739
              return Viewport(
740 741
                offset: offset,
                center: const ValueKey<int>(0),
742
                slivers: List<Widget>.generate(30, (int i) {
743
                  final int item = i - 15;
744 745 746
                  return SliverToBoxAdapter(
                    key: ValueKey<int>(item),
                    child: Container(
747
                      height: 200.0,
748
                      child: Row(
749 750
                        crossAxisAlignment: CrossAxisAlignment.stretch,
                        children: <Widget>[
751
                          Semantics(
752
                            container: true,
753
                            child: Text('${item}a'),
754
                          ),
755
                          Semantics(
756
                            container: true,
757
                            child: Text('${item}b'),
758 759 760 761 762 763 764 765 766 767 768 769 770 771
                          ),
                        ],
                      ),
                    ),
                  );
                }),
              );
            },
          ),
        ),
      ),
    ));

    expect(semantics, hasSemantics(
772
      TestSemantics.root(
773
        children: <TestSemantics>[
774
          TestSemantics(
775 776
            textDirection: TextDirection.ltr,
            children: <TestSemantics>[
777
              TestSemantics(
778
                children: <TestSemantics>[
779
                  TestSemantics(
780 781 782
                    flags: <SemanticsFlag>[
                      SemanticsFlag.hasImplicitScrolling,
                    ],
783 784 785 786 787
                    actions: <SemanticsAction>[
                      SemanticsAction.scrollUp,
                      SemanticsAction.scrollDown,
                    ],
                    children: <TestSemantics>[
788
                      TestSemantics(
789 790 791 792
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: '-2a',
                        textDirection: TextDirection.ltr,
                      ),
793
                      TestSemantics(
794 795 796 797
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: '-2b',
                        textDirection: TextDirection.ltr,
                      ),
798
                      TestSemantics(
799 800 801 802
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: '-1a',
                        textDirection: TextDirection.ltr,
                      ),
803
                      TestSemantics(
804 805 806 807
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: '-1b',
                        textDirection: TextDirection.ltr,
                      ),
808
                      TestSemantics(
809 810 811
                        label: '0a',
                        textDirection: TextDirection.ltr,
                      ),
812
                      TestSemantics(
813 814 815
                        label: '0b',
                        textDirection: TextDirection.ltr,
                      ),
816
                      TestSemantics(
817 818 819
                        label: '1a',
                        textDirection: TextDirection.ltr,
                      ),
820
                      TestSemantics(
821 822 823
                        label: '1b',
                        textDirection: TextDirection.ltr,
                      ),
824
                      TestSemantics(
825 826 827
                        label: '2a',
                        textDirection: TextDirection.ltr,
                      ),
828
                      TestSemantics(
829 830 831
                        label: '2b',
                        textDirection: TextDirection.ltr,
                      ),
832
                      TestSemantics(
833 834 835 836
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: '3a',
                        textDirection: TextDirection.ltr,
                      ),
837
                      TestSemantics(
838 839 840 841
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: '3b',
                        textDirection: TextDirection.ltr,
                      ),
842
                      TestSemantics(
843 844 845 846
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: '4a',
                        textDirection: TextDirection.ltr,
                      ),
847
                      TestSemantics(
848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868
                        flags: <SemanticsFlag>[SemanticsFlag.isHidden],
                        label: '4b',
                        textDirection: TextDirection.ltr,
                      ),
                    ],
                  ),
                ],
              ),
            ],
          ),
        ],
      ),
      ignoreRect: true,
      ignoreTransform: true,
      ignoreId: true,
    ));

    semantics.dispose();

  });
}