mergeable_material_test.dart 35.6 KB
Newer Older
1
  // Copyright 2016 The Chromium Authors. All rights reserved.
2 3 4 5 6 7
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

8 9
import '../rendering/mock_canvas.dart';

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
enum RadiusType {
  Sharp,
  Shifting,
  Round
}

void matches(BorderRadius borderRadius, RadiusType top, RadiusType bottom) {
  final Radius cardRadius = kMaterialEdges[MaterialType.card].topLeft;

  if (top == RadiusType.Sharp) {
    expect(borderRadius.topLeft, equals(Radius.zero));
    expect(borderRadius.topRight, equals(Radius.zero));
  } else if (top == RadiusType.Shifting) {
    expect(borderRadius.topLeft.x, greaterThan(0.0));
    expect(borderRadius.topLeft.x, lessThan(cardRadius.x));
    expect(borderRadius.topLeft.y, greaterThan(0.0));
    expect(borderRadius.topLeft.y, lessThan(cardRadius.y));
    expect(borderRadius.topRight.x, greaterThan(0.0));
    expect(borderRadius.topRight.x, lessThan(cardRadius.x));
    expect(borderRadius.topRight.y, greaterThan(0.0));
    expect(borderRadius.topRight.y, lessThan(cardRadius.y));
  } else {
    expect(borderRadius.topLeft, equals(cardRadius));
    expect(borderRadius.topRight, equals(cardRadius));
  }

  if (bottom == RadiusType.Sharp) {
    expect(borderRadius.bottomLeft, equals(Radius.zero));
    expect(borderRadius.bottomRight, equals(Radius.zero));
  } else if (bottom == RadiusType.Shifting) {
    expect(borderRadius.bottomLeft.x, greaterThan(0.0));
    expect(borderRadius.bottomLeft.x, lessThan(cardRadius.x));
    expect(borderRadius.bottomLeft.y, greaterThan(0.0));
    expect(borderRadius.bottomLeft.y, lessThan(cardRadius.y));
    expect(borderRadius.bottomRight.x, greaterThan(0.0));
    expect(borderRadius.bottomRight.x, lessThan(cardRadius.x));
    expect(borderRadius.bottomRight.y, greaterThan(0.0));
    expect(borderRadius.bottomRight.y, lessThan(cardRadius.y));
  } else {
    expect(borderRadius.bottomLeft, equals(cardRadius));
    expect(borderRadius.bottomRight, equals(cardRadius));
  }
}

54 55 56
// Returns the border radius decoration of an item within a MergeableMaterial.
// This depends on the exact structure of objects built by the Material and
// MergeableMaterial widgets.
57
BorderRadius getBorderRadius(WidgetTester tester, int index) {
58
  final List<Element> containers = tester.elementList(find.byType(Container))
59 60
                                   .toList();

61
  final Container container = containers[index].widget;
62
  final BoxDecoration boxDecoration = container.decoration;
63 64 65 66 67 68 69

  return boxDecoration.borderRadius;
}

void main() {
  testWidgets('MergeableMaterial empty', (WidgetTester tester) async {
    await tester.pumpWidget(
70 71 72 73 74 75 76
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
            child: const MergeableMaterial()
          ),
        ),
      ),
77 78
    );

79
    final RenderBox box = tester.renderObject(find.byType(MergeableMaterial));
80 81 82 83 84
    expect(box.size.height, equals(0));
  });

  testWidgets('MergeableMaterial update slice', (WidgetTester tester) async {
    await tester.pumpWidget(
85 86 87
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
88
            child: const MergeableMaterial(
89 90 91 92
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
93 94 95 96 97 98 99 100 101
                    width: 100.0,
                    height: 100.0
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
102 103 104 105 106 107
    );

    RenderBox box = tester.renderObject(find.byType(MergeableMaterial));
    expect(box.size.height, equals(100.0));

    await tester.pumpWidget(
108 109 110
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
111
            child: const MergeableMaterial(
112 113 114 115
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
116 117 118 119 120 121 122 123 124
                    width: 100.0,
                    height: 200.0
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
125 126 127 128 129 130 131 132
    );

    box = tester.renderObject(find.byType(MergeableMaterial));
    expect(box.size.height, equals(200.0));
  });

  testWidgets('MergeableMaterial swap slices', (WidgetTester tester) async {
    await tester.pumpWidget(
133 134 135
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
136
            child: const MergeableMaterial(
137 138 139 140
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
141 142 143 144
                    width: 100.0,
                    height: 100.0
                  )
                ),
145 146 147
                MaterialSlice(
                  key: ValueKey<String>('B'),
                  child: SizedBox(
148 149 150 151 152 153 154 155 156
                    width: 100.0,
                    height: 100.0
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
157 158 159 160 161 162 163 164
    );

    RenderBox box = tester.renderObject(find.byType(MergeableMaterial));
    expect(box.size.height, equals(200.0));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round);

    await tester.pumpWidget(
165 166 167
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
168
            child: const MergeableMaterial(
169 170 171 172
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('B'),
                  child: SizedBox(
173 174 175 176
                    width: 100.0,
                    height: 100.0
                  )
                ),
177 178 179
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
180 181 182 183 184 185 186 187 188
                    width: 100.0,
                    height: 100.0
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
189 190 191 192 193 194 195 196 197 198 199 200
    );

    box = tester.renderObject(find.byType(MergeableMaterial));
    expect(box.size.height, equals(200.0));

    await tester.pump(const Duration(milliseconds: 100));
    expect(box.size.height, equals(200.0));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round);
  });

  testWidgets('MergeableMaterial paints shadows', (WidgetTester tester) async {
201
    debugDisableShadows = false;
202
    await tester.pumpWidget(
203 204 205
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
206
            child: const MergeableMaterial(
207 208 209 210
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
211 212 213 214 215 216 217 218 219
                    width: 100.0,
                    height: 100.0
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
220 221 222 223 224 225
    );

    final BoxShadow boxShadow = kElevationToShadow[2][0];
    final RRect rrect = kMaterialEdges[MaterialType.card].toRRect(
      new Rect.fromLTRB(0.0, 0.0, 800.0, 100.0)
    );
226 227 228 229
    expect(
      find.byType(MergeableMaterial),
      paints..rrect(rrect: rrect, color: boxShadow.color, hasMaskFilter: true),
    );
230
    debugDisableShadows = true;
231 232 233 234
  });

  testWidgets('MergeableMaterial merge gap', (WidgetTester tester) async {
    await tester.pumpWidget(
235 236 237
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
238
            child: const MergeableMaterial(
239 240 241 242
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
243 244 245 246
                    width: 100.0,
                    height: 100.0
                  )
                ),
247 248
                MaterialGap(
                  key: ValueKey<String>('x')
249
                ),
250 251 252
                MaterialSlice(
                  key: ValueKey<String>('B'),
                  child: SizedBox(
253 254 255 256 257 258 259 260 261
                    width: 100.0,
                    height: 100.0
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
262 263
    );

264
    final RenderBox box = tester.renderObject(find.byType(MergeableMaterial));
265 266 267 268 269 270
    expect(box.size.height, equals(216));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round);
    matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round);

    await tester.pumpWidget(
271 272 273
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
274
            child: const MergeableMaterial(
275 276 277 278
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
279 280 281 282
                    width: 100.0,
                    height: 100.0
                  )
                ),
283 284 285
                MaterialSlice(
                  key: ValueKey<String>('B'),
                  child: SizedBox(
286 287 288 289 290 291 292 293 294
                    width: 100.0,
                    height: 100.0
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
    );

    await tester.pump(const Duration(milliseconds: 100));
    expect(box.size.height, lessThan(216));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Shifting);
    matches(getBorderRadius(tester, 1), RadiusType.Shifting, RadiusType.Round);

    await tester.pump(const Duration(milliseconds: 100));
    expect(box.size.height, equals(200));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Sharp);
    matches(getBorderRadius(tester, 1), RadiusType.Sharp, RadiusType.Round);
  });

  testWidgets('MergeableMaterial separate slices', (WidgetTester tester) async {
    await tester.pumpWidget(
312 313 314
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
315
            child: const MergeableMaterial(
316 317 318 319
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
320 321 322 323
                    width: 100.0,
                    height: 100.0
                  )
                ),
324 325 326
                MaterialSlice(
                  key: ValueKey<String>('B'),
                  child: SizedBox(
327 328 329 330 331 332 333 334 335
                    width: 100.0,
                    height: 100.0
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
336 337
    );

338
    final RenderBox box = tester.renderObject(find.byType(MergeableMaterial));
339 340 341 342 343
    expect(box.size.height, equals(200));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round);

    await tester.pumpWidget(
344 345 346
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
347
            child: const MergeableMaterial(
348 349 350 351
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
352 353 354 355
                    width: 100.0,
                    height: 100.0
                  )
                ),
356 357
                MaterialGap(
                  key: ValueKey<String>('x')
358
                ),
359 360 361
                MaterialSlice(
                  key: ValueKey<String>('B'),
                  child: SizedBox(
362 363 364 365 366 367 368 369 370
                    width: 100.0,
                    height: 100.0
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
    );

    await tester.pump(const Duration(milliseconds: 100));
    expect(box.size.height, lessThan(216));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Shifting);
    matches(getBorderRadius(tester, 1), RadiusType.Shifting, RadiusType.Round);

    await tester.pump(const Duration(milliseconds: 100));
    expect(box.size.height, equals(216));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round);
    matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round);
  });

Josh Soref's avatar
Josh Soref committed
386
  testWidgets('MergeableMaterial separate merge separate', (WidgetTester tester) async {
387
    await tester.pumpWidget(
388 389 390
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
391
            child: const MergeableMaterial(
392 393 394 395
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
396 397 398 399
                    width: 100.0,
                    height: 100.0
                  )
                ),
400 401 402
                MaterialSlice(
                  key: ValueKey<String>('B'),
                  child: SizedBox(
403 404 405
                    width: 100.0,
                    height: 100.0
                  )
406
                )
407 408
              ]
            )
409 410 411 412 413
          )
        )
      )
    );

414
    final RenderBox box = tester.renderObject(find.byType(MergeableMaterial));
415 416 417 418 419
    expect(box.size.height, equals(200));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round);

    await tester.pumpWidget(
420 421 422
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
423
            child: const MergeableMaterial(
424 425 426 427
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
428 429 430 431
                    width: 100.0,
                    height: 100.0
                  )
                ),
432 433
                MaterialGap(
                  key: ValueKey<String>('x')
434
                ),
435 436 437
                MaterialSlice(
                  key: ValueKey<String>('B'),
                  child: SizedBox(
438 439 440
                    width: 100.0,
                    height: 100.0
                  )
441
                )
442 443
              ]
            )
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
          )
        )
      )
    );

    await tester.pump(const Duration(milliseconds: 100));
    expect(box.size.height, lessThan(216));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Shifting);
    matches(getBorderRadius(tester, 1), RadiusType.Shifting, RadiusType.Round);

    await tester.pump(const Duration(milliseconds: 100));
    expect(box.size.height, equals(216));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round);
    matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round);

    await tester.pumpWidget(
462 463 464
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
465
            child: const MergeableMaterial(
466 467 468 469
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
470 471 472 473
                    width: 100.0,
                    height: 100.0
                  )
                ),
474 475 476
                MaterialSlice(
                  key: ValueKey<String>('B'),
                  child: SizedBox(
477 478 479
                    width: 100.0,
                    height: 100.0
                  )
480
                )
481 482
              ]
            )
483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
          )
        )
      )
    );

    await tester.pump(const Duration(milliseconds: 100));
    expect(box.size.height, lessThan(216));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Shifting);
    matches(getBorderRadius(tester, 1), RadiusType.Shifting, RadiusType.Round);

    await tester.pump(const Duration(milliseconds: 100));
    expect(box.size.height, equals(200));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Sharp);
    matches(getBorderRadius(tester, 1), RadiusType.Sharp, RadiusType.Round);

    await tester.pumpWidget(
501 502 503
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
504
            child: const MergeableMaterial(
505 506 507 508
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
509 510 511 512
                    width: 100.0,
                    height: 100.0
                  )
                ),
513 514
                MaterialGap(
                  key: ValueKey<String>('x')
515
                ),
516 517 518
                MaterialSlice(
                  key: ValueKey<String>('B'),
                  child: SizedBox(
519 520 521
                    width: 100.0,
                    height: 100.0
                  )
522
                )
523 524
              ]
            )
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
          )
        )
      )
    );

    await tester.pump(const Duration(milliseconds: 100));
    expect(box.size.height, lessThan(216));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Shifting);
    matches(getBorderRadius(tester, 1), RadiusType.Shifting, RadiusType.Round);

    await tester.pump(const Duration(milliseconds: 100));
    expect(box.size.height, equals(216));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round);
    matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round);
  });

  testWidgets('MergeableMaterial insert slice', (WidgetTester tester) async {
    await tester.pumpWidget(
545 546 547
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
548
            child: const MergeableMaterial(
549 550 551 552
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
553 554 555 556
                    width: 100.0,
                    height: 100.0
                  )
                ),
557 558 559
                MaterialSlice(
                  key: ValueKey<String>('C'),
                  child: SizedBox(
560 561 562
                    width: 100.0,
                    height: 100.0
                  )
563
                )
564 565
              ]
            )
566 567 568 569 570
          )
        )
      )
    );

571
    final RenderBox box = tester.renderObject(find.byType(MergeableMaterial));
572 573 574 575 576
    expect(box.size.height, equals(200));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round);

    await tester.pumpWidget(
577 578 579
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
580
            child: const MergeableMaterial(
581 582 583 584
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
585 586 587 588
                    width: 100.0,
                    height: 100.0
                  )
                ),
589 590 591
                MaterialSlice(
                  key: ValueKey<String>('B'),
                  child: SizedBox(
592 593 594 595
                    width: 100.0,
                    height: 100.0
                  )
                ),
596 597 598
                MaterialSlice(
                  key: ValueKey<String>('C'),
                  child: SizedBox(
599 600 601
                    width: 100.0,
                    height: 100.0
                  )
602
                )
603 604
              ]
            )
605 606 607 608 609 610 611 612 613 614 615 616
          )
        )
      )
    );

    expect(box.size.height, equals(300));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round);
  });

  testWidgets('MergeableMaterial remove slice', (WidgetTester tester) async {
    await tester.pumpWidget(
617 618 619
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
620
            child: const MergeableMaterial(
621 622 623 624
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
625 626 627 628
                    width: 100.0,
                    height: 100.0
                  )
                ),
629 630 631
                MaterialSlice(
                  key: ValueKey<String>('B'),
                  child: SizedBox(
632 633 634 635
                    width: 100.0,
                    height: 100.0
                  )
                ),
636 637 638
                MaterialSlice(
                  key: ValueKey<String>('C'),
                  child: SizedBox(
639 640 641
                    width: 100.0,
                    height: 100.0
                  )
642
                )
643 644
              ]
            )
645 646 647 648 649
          )
        )
      )
    );

650
    final RenderBox box = tester.renderObject(find.byType(MergeableMaterial));
651 652 653 654 655
    expect(box.size.height, equals(300));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round);

    await tester.pumpWidget(
656 657 658
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
659
            child: const MergeableMaterial(
660 661 662 663
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
664 665 666 667
                    width: 100.0,
                    height: 100.0
                  )
                ),
668 669 670
                MaterialSlice(
                  key: ValueKey<String>('C'),
                  child: SizedBox(
671 672 673
                    width: 100.0,
                    height: 100.0
                  )
674
                )
675 676
              ]
            )
677 678 679 680 681 682 683 684 685 686 687 688 689
          )
        )
      )
    );

    await tester.pump();
    expect(box.size.height, equals(200));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round);
  });

  testWidgets('MergeableMaterial insert chunk', (WidgetTester tester) async {
    await tester.pumpWidget(
690 691 692
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
693
            child: const MergeableMaterial(
694 695 696 697
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
698 699 700 701
                    width: 100.0,
                    height: 100.0
                  )
                ),
702 703 704
                MaterialSlice(
                  key: ValueKey<String>('C'),
                  child: SizedBox(
705 706 707
                    width: 100.0,
                    height: 100.0
                  )
708
                )
709 710
              ]
            )
711 712 713 714 715
          )
        )
      )
    );

716
    final RenderBox box = tester.renderObject(find.byType(MergeableMaterial));
717 718 719 720 721
    expect(box.size.height, equals(200));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round);

    await tester.pumpWidget(
722 723 724
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
725
            child: const MergeableMaterial(
726 727 728 729
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
730 731 732 733
                    width: 100.0,
                    height: 100.0
                  )
                ),
734 735
                MaterialGap(
                  key: ValueKey<String>('x')
736
                ),
737 738 739
                MaterialSlice(
                  key: ValueKey<String>('B'),
                  child: SizedBox(
740 741 742 743
                    width: 100.0,
                    height: 100.0
                  )
                ),
744 745
                MaterialGap(
                  key: ValueKey<String>('y')
746
                ),
747 748 749
                MaterialSlice(
                  key: ValueKey<String>('C'),
                  child: SizedBox(
750 751 752
                    width: 100.0,
                    height: 100.0
                  )
753
                )
754 755
              ]
            )
756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777
          )
        )
      )
    );

    await tester.pump(const Duration(milliseconds: 100));
    expect(box.size.height, lessThan(332));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Shifting);
    matches(getBorderRadius(tester, 1), RadiusType.Shifting, RadiusType.Shifting);
    matches(getBorderRadius(tester, 2), RadiusType.Shifting, RadiusType.Round);

    await tester.pump(const Duration(milliseconds: 100));
    expect(box.size.height, equals(332));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round);
    matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round);
    matches(getBorderRadius(tester, 2), RadiusType.Round, RadiusType.Round);
  });

  testWidgets('MergeableMaterial remove chunk', (WidgetTester tester) async {
    await tester.pumpWidget(
778 779 780
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
781
            child: const MergeableMaterial(
782 783 784 785
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
786 787 788 789
                    width: 100.0,
                    height: 100.0
                  )
                ),
790 791
                MaterialGap(
                  key: ValueKey<String>('x')
792
                ),
793 794 795
                MaterialSlice(
                  key: ValueKey<String>('B'),
                  child: SizedBox(
796 797 798 799
                    width: 100.0,
                    height: 100.0
                  )
                ),
800 801
                MaterialGap(
                  key: ValueKey<String>('y')
802
                ),
803 804 805
                MaterialSlice(
                  key: ValueKey<String>('C'),
                  child: SizedBox(
806 807 808
                    width: 100.0,
                    height: 100.0
                  )
809
                )
810 811
              ]
            )
812 813 814 815 816
          )
        )
      )
    );

817
    final RenderBox box = tester.renderObject(find.byType(MergeableMaterial));
818 819 820 821 822 823 824
    expect(box.size.height, equals(332));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round);
    matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round);
    matches(getBorderRadius(tester, 2), RadiusType.Round, RadiusType.Round);

    await tester.pumpWidget(
825 826 827
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
828
            child: const MergeableMaterial(
829 830 831 832
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
833 834 835 836
                    width: 100.0,
                    height: 100.0
                  )
                ),
837 838 839
                MaterialSlice(
                  key: ValueKey<String>('C'),
                  child: SizedBox(
840 841 842
                    width: 100.0,
                    height: 100.0
                  )
843
                )
844 845
              ]
            )
846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
          )
        )
      )
    );

    await tester.pump(const Duration(milliseconds: 100));
    expect(box.size.height, lessThan(332));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Shifting);
    matches(getBorderRadius(tester, 1), RadiusType.Shifting, RadiusType.Round);

    await tester.pump(const Duration(milliseconds: 100));
    expect(box.size.height, equals(200));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Sharp);
    matches(getBorderRadius(tester, 1), RadiusType.Sharp, RadiusType.Round);
  });

  testWidgets('MergeableMaterial replace gap with chunk', (WidgetTester tester) async {
    await tester.pumpWidget(
866 867 868
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
869
            child: const MergeableMaterial(
870 871 872 873
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
874 875 876 877
                    width: 100.0,
                    height: 100.0
                  )
                ),
878 879
                MaterialGap(
                  key: ValueKey<String>('x')
880
                ),
881 882 883
                MaterialSlice(
                  key: ValueKey<String>('C'),
                  child: SizedBox(
884 885 886
                    width: 100.0,
                    height: 100.0
                  )
887
                )
888 889
              ]
            )
890 891 892 893 894
          )
        )
      )
    );

895
    final RenderBox box = tester.renderObject(find.byType(MergeableMaterial));
896 897 898 899 900 901
    expect(box.size.height, equals(216));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round);
    matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round);

    await tester.pumpWidget(
902 903 904
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
905
            child: const MergeableMaterial(
906 907 908 909
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
910 911 912 913
                    width: 100.0,
                    height: 100.0
                  )
                ),
914 915
                MaterialGap(
                  key: ValueKey<String>('y')
916
                ),
917 918 919
                MaterialSlice(
                  key: ValueKey<String>('B'),
                  child: SizedBox(
920 921 922 923
                    width: 100.0,
                    height: 100.0
                  )
                ),
924 925
                MaterialGap(
                  key: ValueKey<String>('z')
926
                ),
927 928 929
                MaterialSlice(
                  key: ValueKey<String>('C'),
                  child: SizedBox(
930 931 932
                    width: 100.0,
                    height: 100.0
                  )
933
                )
934 935
              ]
            )
936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957
          )
        )
      )
    );

    await tester.pump(const Duration(milliseconds: 100));
    expect(box.size.height, lessThan(332));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Shifting);
    matches(getBorderRadius(tester, 1), RadiusType.Shifting, RadiusType.Shifting);
    matches(getBorderRadius(tester, 2), RadiusType.Shifting, RadiusType.Round);

    await tester.pump(const Duration(milliseconds: 100));
    expect(box.size.height, equals(332));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round);
    matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round);
    matches(getBorderRadius(tester, 2), RadiusType.Round, RadiusType.Round);
  });

  testWidgets('MergeableMaterial replace chunk with gap', (WidgetTester tester) async {
    await tester.pumpWidget(
958 959 960
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
961
            child: const MergeableMaterial(
962 963 964 965
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
966 967 968 969
                    width: 100.0,
                    height: 100.0
                  )
                ),
970 971
                MaterialGap(
                  key: ValueKey<String>('x')
972
                ),
973 974 975
                MaterialSlice(
                  key: ValueKey<String>('B'),
                  child: SizedBox(
976 977 978 979
                    width: 100.0,
                    height: 100.0
                  )
                ),
980 981
                MaterialGap(
                  key: ValueKey<String>('y')
982
                ),
983 984 985
                MaterialSlice(
                  key: ValueKey<String>('C'),
                  child: SizedBox(
986 987 988
                    width: 100.0,
                    height: 100.0
                  )
989
                )
990 991
              ]
            )
992 993 994 995 996
          )
        )
      )
    );

997
    final RenderBox box = tester.renderObject(find.byType(MergeableMaterial));
998 999 1000 1001 1002 1003 1004
    expect(box.size.height, equals(332));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round);
    matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round);
    matches(getBorderRadius(tester, 2), RadiusType.Round, RadiusType.Round);

    await tester.pumpWidget(
1005 1006 1007
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
1008
            child: const MergeableMaterial(
1009 1010 1011 1012
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
1013 1014 1015 1016
                    width: 100.0,
                    height: 100.0
                  )
                ),
1017 1018
                MaterialGap(
                  key: ValueKey<String>('z')
1019
                ),
1020 1021 1022
                MaterialSlice(
                  key: ValueKey<String>('C'),
                  child: SizedBox(
1023 1024 1025
                    width: 100.0,
                    height: 100.0
                  )
1026
                )
1027 1028
              ]
            )
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
          )
        )
      )
    );

    await tester.pump(const Duration(milliseconds: 100));
    expect(box.size.height, lessThan(332));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Shifting);
    matches(getBorderRadius(tester, 1), RadiusType.Shifting, RadiusType.Round);

    await tester.pump(const Duration(milliseconds: 100));
    expect(box.size.height, equals(216));

    matches(getBorderRadius(tester, 0), RadiusType.Round, RadiusType.Round);
    matches(getBorderRadius(tester, 1), RadiusType.Round, RadiusType.Round);
  });
1046

1047
  bool isDivider(Widget widget, bool top, bool bottom) {
1048
    final DecoratedBox box = widget;
1049
    const BorderSide side = BorderSide(color: Color(0x1F000000), width: 0.5);
1050 1051 1052

    return box.decoration == new BoxDecoration(
      border: new Border(
1053 1054
        top: top ? side : BorderSide.none,
        bottom: bottom ? side : BorderSide.none
1055 1056 1057 1058 1059 1060
      )
    );
  }

  testWidgets('MergeableMaterial dividers', (WidgetTester tester) async {
    await tester.pumpWidget(
1061 1062 1063
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
1064
            child: const MergeableMaterial(
1065
              hasDividers: true,
1066 1067 1068 1069
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
1070 1071 1072 1073
                    width: 100.0,
                    height: 100.0
                  )
                ),
1074 1075 1076
                MaterialSlice(
                  key: ValueKey<String>('B'),
                  child: SizedBox(
1077 1078 1079 1080
                    width: 100.0,
                    height: 100.0
                  )
                ),
1081 1082 1083
                MaterialSlice(
                  key: ValueKey<String>('C'),
                  child: SizedBox(
1084 1085 1086 1087
                    width: 100.0,
                    height: 100.0
                  )
                ),
1088 1089 1090
                MaterialSlice(
                  key: ValueKey<String>('D'),
                  child: SizedBox(
1091 1092 1093
                    width: 100.0,
                    height: 100.0
                  )
1094
                )
1095 1096
              ]
            )
1097 1098 1099 1100 1101 1102
          )
        )
      )
    );

    List<Widget> boxes = tester.widgetList(find.byType(DecoratedBox)).toList();
1103
    int offset = 1;
1104

1105 1106 1107 1108
    expect(isDivider(boxes[offset], false, true), isTrue);
    expect(isDivider(boxes[offset + 1], true, true), isTrue);
    expect(isDivider(boxes[offset + 2], true, true), isTrue);
    expect(isDivider(boxes[offset + 3], true, false), isTrue);
1109 1110

    await tester.pumpWidget(
1111 1112 1113
      new MaterialApp(
        home: new Scaffold(
          body: new SingleChildScrollView(
1114
            child: const MergeableMaterial(
1115
              hasDividers: true,
1116 1117 1118 1119
              children: <MergeableMaterialItem>[
                MaterialSlice(
                  key: ValueKey<String>('A'),
                  child: SizedBox(
1120 1121 1122 1123
                    width: 100.0,
                    height: 100.0
                  )
                ),
1124 1125 1126
                MaterialSlice(
                  key: ValueKey<String>('B'),
                  child: SizedBox(
1127 1128 1129 1130
                    width: 100.0,
                    height: 100.0
                  )
                ),
1131 1132
                MaterialGap(
                  key: ValueKey<String>('x')
1133
                ),
1134 1135 1136
                MaterialSlice(
                  key: ValueKey<String>('C'),
                  child: SizedBox(
1137 1138 1139 1140
                    width: 100.0,
                    height: 100.0
                  )
                ),
1141 1142 1143
                MaterialSlice(
                  key: ValueKey<String>('D'),
                  child: SizedBox(
1144 1145 1146
                    width: 100.0,
                    height: 100.0
                  )
1147
                )
1148 1149
              ]
            )
1150 1151 1152 1153 1154
          )
        )
      )
    );

1155 1156 1157
    // Wait for dividers to shrink.
    await tester.pump(const Duration(milliseconds: 200));

1158
    boxes = tester.widgetList(find.byType(DecoratedBox)).toList();
1159
    offset = 1;
1160

1161 1162
    expect(isDivider(boxes[offset], false, true), isTrue);
    expect(isDivider(boxes[offset + 1], true, false), isTrue);
1163
    // offset + 2 is gap
1164 1165
    expect(isDivider(boxes[offset + 3], false, true), isTrue);
    expect(isDivider(boxes[offset + 4], true, false), isTrue);
1166
  });
1167
}