scrollable_semantics_traversal_order_test.dart 30.5 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
                      ),
                    ],
                  ),
                ],
              ),
            ],
          ),
        ],
      ),
      ignoreId: true,
      ignoreTransform: true,
      ignoreRect: true,
    ));

    semantics.dispose();
  });

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

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

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

    semantics.dispose();
  });

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

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

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

    semantics.dispose();
  });

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

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

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

    semantics.dispose();
  });

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

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

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

    semantics.dispose();
  });

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

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

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

    semantics.dispose();

  });
}