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
// 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/widgets.dart';
9
import 'package:flutter_test/flutter_test.dart';
10 11 12 13 14

import 'semantics_tester.dart';

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

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

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

    semantics.dispose();
  });

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

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

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

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

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

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

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

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

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

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

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

    semantics.dispose();

  });
}