button_bar_test.dart 25.1 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5 6
// 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';
7
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
8

9
void main() {
10
  testWidgetsWithLeakTracking('ButtonBar default control smoketest', (WidgetTester tester) async {
11
    await tester.pumpWidget(
12
      const Directionality(
13
        textDirection: TextDirection.ltr,
14
        child: ButtonBar(),
15 16
      ),
    );
17
  });
18

19 20
  group('alignment', () {

21
    testWidgetsWithLeakTracking('default alignment is MainAxisAlignment.end', (WidgetTester tester) async {
22 23 24 25 26 27 28
      await tester.pumpWidget(
        const MaterialApp(
          home: ButtonBar(
            children: <Widget>[
              SizedBox(width: 10.0, height: 10.0),
            ],
          ),
29
        ),
30 31 32 33 34 35 36 37
      );

      final Finder child = find.byType(SizedBox);
      // Should be positioned to the right of the bar,
      expect(tester.getRect(child).left, 782.0);  // bar width - default padding - 10
      expect(tester.getRect(child).right, 792.0); // bar width - default padding
    });

38
    testWidgetsWithLeakTracking('ButtonBarTheme.alignment overrides default', (WidgetTester tester) async {
39 40 41 42 43
      await tester.pumpWidget(
        const MaterialApp(
          home: ButtonBarTheme(
            data: ButtonBarThemeData(
              alignment: MainAxisAlignment.center,
44
            ),
45 46 47 48 49 50
            child: ButtonBar(
              children: <Widget>[
                SizedBox(width: 10.0, height: 10.0),
              ],
            ),
          ),
51
        ),
52 53 54 55 56 57 58 59
      );

      final Finder child = find.byType(SizedBox);
      // Should be positioned in the center
      expect(tester.getRect(child).left, 395.0);  // (bar width - padding) / 2 - 10 / 2
      expect(tester.getRect(child).right, 405.0); // (bar width - padding) / 2 - 10 / 2 + 10
    });

60
    testWidgetsWithLeakTracking('ButtonBar.alignment overrides ButtonBarTheme.alignment and default', (WidgetTester tester) async {
61 62 63 64 65 66 67 68 69 70 71 72 73
      await tester.pumpWidget(
        const MaterialApp(
          home: ButtonBarTheme(
            data: ButtonBarThemeData(
              alignment: MainAxisAlignment.center,
            ),
            child: ButtonBar(
              alignment: MainAxisAlignment.start,
              children: <Widget>[
                SizedBox(width: 10.0, height: 10.0),
              ],
            ),
          ),
74
        ),
75 76 77 78 79 80 81
      );

      final Finder child = find.byType(SizedBox);
      // Should be positioned on the left
      expect(tester.getRect(child).left, 8.0);   // padding
      expect(tester.getRect(child).right, 18.0); // padding + 10
    });
82 83 84

  });

85 86
  group('mainAxisSize', () {

87
    testWidgetsWithLeakTracking('Default mainAxisSize is MainAxisSize.max', (WidgetTester tester) async {
88 89 90 91 92
      const Key buttonBarKey = Key('row');
      const Key child0Key = Key('child0');
      const Key child1Key = Key('child1');
      const Key child2Key = Key('child2');

93
      await tester.pumpWidget(
94
        const MaterialApp(
95 96 97 98 99 100
          home: Center(
            child: ButtonBar(
              key: buttonBarKey,
              // buttonPadding set to zero to simplify test calculations.
              buttonPadding: EdgeInsets.zero,
              children: <Widget>[
101 102 103
                SizedBox(key: child0Key, width: 100.0, height: 100.0),
                SizedBox(key: child1Key, width: 100.0, height: 100.0),
                SizedBox(key: child2Key, width: 100.0, height: 100.0),
104 105
              ],
            ),
106
          ),
107
        ),
108 109
      );

110 111 112 113 114
      // ButtonBar should take up all the space it is provided by its parent.
      final Rect buttonBarRect = tester.getRect(find.byKey(buttonBarKey));
      expect(buttonBarRect.size.width, equals(800.0));
      expect(buttonBarRect.size.height, equals(100.0));

115
      // The children of [ButtonBar] are aligned by [MainAxisAlignment.end] by
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
      // default.
      Rect childRect;
      childRect = tester.getRect(find.byKey(child0Key));
      expect(childRect.size.width, equals(100.0));
      expect(childRect.size.height, equals(100.0));
      expect(childRect.right, 800.0 - 200.0);

      childRect = tester.getRect(find.byKey(child1Key));
      expect(childRect.size.width, equals(100.0));
      expect(childRect.size.height, equals(100.0));
      expect(childRect.right, 800.0 - 100.0);

      childRect = tester.getRect(find.byKey(child2Key));
      expect(childRect.size.width, equals(100.0));
      expect(childRect.size.height, equals(100.0));
      expect(childRect.right, 800.0);
132 133
    });

134
    testWidgetsWithLeakTracking('ButtonBarTheme.mainAxisSize overrides default', (WidgetTester tester) async {
135 136 137 138
      const Key buttonBarKey = Key('row');
      const Key child0Key = Key('child0');
      const Key child1Key = Key('child1');
      const Key child2Key = Key('child2');
139
      await tester.pumpWidget(
140
        const MaterialApp(
141
          home: ButtonBarTheme(
142
            data: ButtonBarThemeData(
143 144
              mainAxisSize: MainAxisSize.min,
            ),
145 146 147 148 149 150
            child: Center(
              child: ButtonBar(
                key: buttonBarKey,
                // buttonPadding set to zero to simplify test calculations.
                buttonPadding: EdgeInsets.zero,
                children: <Widget>[
151 152 153
                  SizedBox(key: child0Key, width: 100.0, height: 100.0),
                  SizedBox(key: child1Key, width: 100.0, height: 100.0),
                  SizedBox(key: child2Key, width: 100.0, height: 100.0),
154 155
                ],
              ),
156 157
            ),
          ),
158
        ),
159 160
      );

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
      // ButtonBar should take up minimum space it requires.
      final Rect buttonBarRect = tester.getRect(find.byKey(buttonBarKey));
      expect(buttonBarRect.size.width, equals(300.0));
      expect(buttonBarRect.size.height, equals(100.0));

      Rect childRect;
      childRect = tester.getRect(find.byKey(child0Key));
      expect(childRect.size.width, equals(100.0));
      expect(childRect.size.height, equals(100.0));
      // Should be a center aligned because of [Center] widget.
      // First child is on the left side of the button bar.
      expect(childRect.left, (800.0 - buttonBarRect.width) / 2.0);

      childRect = tester.getRect(find.byKey(child1Key));
      expect(childRect.size.width, equals(100.0));
      expect(childRect.size.height, equals(100.0));
      // Should be a center aligned because of [Center] widget.
      // Second child is on the center the button bar.
      expect(childRect.left, ((800.0 - buttonBarRect.width) / 2.0) + 100.0);

      childRect = tester.getRect(find.byKey(child2Key));
      expect(childRect.size.width, equals(100.0));
      expect(childRect.size.height, equals(100.0));
      // Should be a center aligned because of [Center] widget.
      // Third child is on the right side of the button bar.
      expect(childRect.left, ((800.0 - buttonBarRect.width) / 2.0) + 200.0);
187 188
    });

189
    testWidgetsWithLeakTracking('ButtonBar.mainAxisSize overrides ButtonBarTheme.mainAxisSize and default', (WidgetTester tester) async {
190 191 192 193
      const Key buttonBarKey = Key('row');
      const Key child0Key = Key('child0');
      const Key child1Key = Key('child1');
      const Key child2Key = Key('child2');
194
      await tester.pumpWidget(
195
        const MaterialApp(
196
          home: ButtonBarTheme(
197
            data: ButtonBarThemeData(
198 199
              mainAxisSize: MainAxisSize.min,
            ),
200 201 202 203 204 205 206
            child: Center(
              child: ButtonBar(
                key: buttonBarKey,
                // buttonPadding set to zero to simplify test calculations.
                buttonPadding: EdgeInsets.zero,
                mainAxisSize: MainAxisSize.max,
                children: <Widget>[
207 208 209
                  SizedBox(key: child0Key, width: 100.0, height: 100.0),
                  SizedBox(key: child1Key, width: 100.0, height: 100.0),
                  SizedBox(key: child2Key, width: 100.0, height: 100.0),
210 211
                ],
              ),
212 213
            ),
          ),
214
        ),
215 216
      );

217 218 219 220 221
      // ButtonBar should take up all the space it is provided by its parent.
      final Rect buttonBarRect = tester.getRect(find.byKey(buttonBarKey));
      expect(buttonBarRect.size.width, equals(800.0));
      expect(buttonBarRect.size.height, equals(100.0));

222
      // The children of [ButtonBar] are aligned by [MainAxisAlignment.end] by
223 224 225 226 227 228 229 230 231 232 233
      // default.
      Rect childRect;
      childRect = tester.getRect(find.byKey(child0Key));
      expect(childRect.size.width, equals(100.0));
      expect(childRect.size.height, equals(100.0));
      expect(childRect.right, 800.0 - 200.0);

      childRect = tester.getRect(find.byKey(child1Key));
      expect(childRect.size.width, equals(100.0));
      expect(childRect.size.height, equals(100.0));
      expect(childRect.right, 800.0 - 100.0);
234

235 236 237 238 239
      childRect = tester.getRect(find.byKey(child2Key));
      expect(childRect.size.width, equals(100.0));
      expect(childRect.size.height, equals(100.0));
      expect(childRect.right, 800.0);
    });
240 241
  });

242
  group('button properties override ButtonTheme', () {
243

244
    testWidgetsWithLeakTracking('default button properties override ButtonTheme properties', (WidgetTester tester) async {
245
      late BuildContext capturedContext;
246 247 248 249 250 251 252
      await tester.pumpWidget(
        MaterialApp(
          home: ButtonBar(
            children: <Widget>[
              Builder(builder: (BuildContext context) {
                capturedContext = context;
                return Container();
253
              }),
254 255
            ],
          ),
256
        ),
257 258 259 260 261 262 263 264 265 266
      );
      final ButtonThemeData buttonTheme = ButtonTheme.of(capturedContext);
      expect(buttonTheme.textTheme, equals(ButtonTextTheme.primary));
      expect(buttonTheme.minWidth, equals(64.0));
      expect(buttonTheme.height, equals(36.0));
      expect(buttonTheme.padding, equals(const EdgeInsets.symmetric(horizontal: 8.0)));
      expect(buttonTheme.alignedDropdown, equals(false));
      expect(buttonTheme.layoutBehavior, equals(ButtonBarLayoutBehavior.padded));
    });

267
    testWidgetsWithLeakTracking('ButtonBarTheme button properties override defaults and ButtonTheme properties', (WidgetTester tester) async {
268
      late BuildContext capturedContext;
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
      await tester.pumpWidget(
        MaterialApp(
          home: ButtonBarTheme(
            data: const ButtonBarThemeData(
              buttonTextTheme: ButtonTextTheme.primary,
              buttonMinWidth: 42.0,
              buttonHeight: 84.0,
              buttonPadding: EdgeInsets.fromLTRB(10, 20, 30, 40),
              buttonAlignedDropdown: true,
              layoutBehavior: ButtonBarLayoutBehavior.constrained,
            ),
            child: ButtonBar(
              children: <Widget>[
                Builder(builder: (BuildContext context) {
                  capturedContext = context;
                  return Container();
285
                }),
286 287 288
              ],
            ),
          ),
289
        ),
290 291 292 293 294 295 296 297 298 299
      );
      final ButtonThemeData buttonTheme = ButtonTheme.of(capturedContext);
      expect(buttonTheme.textTheme, equals(ButtonTextTheme.primary));
      expect(buttonTheme.minWidth, equals(42.0));
      expect(buttonTheme.height, equals(84.0));
      expect(buttonTheme.padding, equals(const EdgeInsets.fromLTRB(10, 20, 30, 40)));
      expect(buttonTheme.alignedDropdown, equals(true));
      expect(buttonTheme.layoutBehavior, equals(ButtonBarLayoutBehavior.constrained));
    });

300
    testWidgetsWithLeakTracking('ButtonBar button properties override ButtonBarTheme, defaults and ButtonTheme properties', (WidgetTester tester) async {
301
      late BuildContext capturedContext;
302 303 304 305 306 307 308 309 310
      await tester.pumpWidget(
        MaterialApp(
          home: ButtonBarTheme(
            data: const ButtonBarThemeData(
              buttonTextTheme: ButtonTextTheme.accent,
              buttonMinWidth: 4242.0,
              buttonHeight: 8484.0,
              buttonPadding: EdgeInsets.fromLTRB(50, 60, 70, 80),
              buttonAlignedDropdown: false,
311
              layoutBehavior: ButtonBarLayoutBehavior.padded,
312 313 314 315 316 317 318 319 320 321 322 323
            ),
            child: ButtonBar(
              buttonTextTheme: ButtonTextTheme.primary,
              buttonMinWidth: 42.0,
              buttonHeight: 84.0,
              buttonPadding: const EdgeInsets.fromLTRB(10, 20, 30, 40),
              buttonAlignedDropdown: true,
              layoutBehavior: ButtonBarLayoutBehavior.constrained,
              children: <Widget>[
                Builder(builder: (BuildContext context) {
                  capturedContext = context;
                  return Container();
324
                }),
325 326 327
              ],
            ),
          ),
328
        ),
329 330 331 332 333 334 335 336 337 338 339 340 341 342
      );
      final ButtonThemeData buttonTheme = ButtonTheme.of(capturedContext);
      expect(buttonTheme.textTheme, equals(ButtonTextTheme.primary));
      expect(buttonTheme.minWidth, equals(42.0));
      expect(buttonTheme.height, equals(84.0));
      expect(buttonTheme.padding, equals(const EdgeInsets.fromLTRB(10, 20, 30, 40)));
      expect(buttonTheme.alignedDropdown, equals(true));
      expect(buttonTheme.layoutBehavior, equals(ButtonBarLayoutBehavior.constrained));
    });

  });

  group('layoutBehavior', () {

343
    testWidgetsWithLeakTracking('ButtonBar has a min height of 52 when using ButtonBarLayoutBehavior.constrained', (WidgetTester tester) async {
344
      await tester.pumpWidget(
345
        const SingleChildScrollView(
346
          child: ListBody(
347
            children: <Widget>[
348
              Directionality(
349 350
                textDirection: TextDirection.ltr,
                child: ButtonBar(
351
                  layoutBehavior: ButtonBarLayoutBehavior.constrained,
352 353 354 355 356
                  children: <Widget>[
                    SizedBox(width: 10.0, height: 10.0),
                  ],
                ),
              ),
357 358
            ],
          ),
359
        ),
360
      );
361

362 363 364
      final Finder buttonBar = find.byType(ButtonBar);
      expect(tester.getBottomRight(buttonBar).dy - tester.getTopRight(buttonBar).dy, 52.0);
    });
365

366
    testWidgetsWithLeakTracking('ButtonBar has padding applied when using ButtonBarLayoutBehavior.padded', (WidgetTester tester) async {
367
      await tester.pumpWidget(
368
        const SingleChildScrollView(
369
          child: ListBody(
370
            children: <Widget>[
371 372
              Directionality(
                textDirection: TextDirection.ltr,
373
                child: ButtonBar(
374
                  layoutBehavior: ButtonBarLayoutBehavior.padded,
375
                  children: <Widget>[
376
                    SizedBox(width: 10.0, height: 10.0),
377 378 379
                  ],
                ),
              ),
380 381
            ],
          ),
382
        ),
383
      );
384

385 386 387
      final Finder buttonBar = find.byType(ButtonBar);
      expect(tester.getBottomRight(buttonBar).dy - tester.getTopRight(buttonBar).dy, 26.0);
    });
388
  });
389

390
  group("ButtonBar's children wrap when they overflow horizontally", () {
391
    testWidgetsWithLeakTracking("ButtonBar's children wrap when buttons overflow", (WidgetTester tester) async {
392 393 394 395 396 397
      final Key keyOne = UniqueKey();
      final Key keyTwo = UniqueKey();
      await tester.pumpWidget(
        MaterialApp(
          home: ButtonBar(
            children: <Widget>[
398 399
              SizedBox(key: keyOne, height: 50.0, width: 800.0),
              SizedBox(key: keyTwo, height: 50.0, width: 800.0),
400 401 402 403 404 405 406 407 408 409 410 411 412
            ],
          ),
        ),
      );

      // Second [Container] should wrap around to the next column since
      // they take up max width constraint.
      final Rect containerOneRect = tester.getRect(find.byKey(keyOne));
      final Rect containerTwoRect = tester.getRect(find.byKey(keyTwo));
      expect(containerOneRect.bottom, containerTwoRect.top);
      expect(containerOneRect.left, containerTwoRect.left);
    });

413
    testWidgetsWithLeakTracking(
414 415 416 417 418 419 420 421 422
      "ButtonBar's children overflow defaults - MainAxisAlignment.end", (WidgetTester tester) async {
        final Key keyOne = UniqueKey();
        final Key keyTwo = UniqueKey();
        await tester.pumpWidget(
          MaterialApp(
            home: ButtonBar(
              // Set padding to zero to align buttons with edge of button bar.
              buttonPadding: EdgeInsets.zero,
              children: <Widget>[
423 424
                SizedBox(key: keyOne, height: 50.0, width: 500.0),
                SizedBox(key: keyTwo, height: 50.0, width: 500.0),
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
              ],
            ),
          ),
        );

        final Rect buttonBarRect = tester.getRect(find.byType(ButtonBar));
        final Rect containerOneRect = tester.getRect(find.byKey(keyOne));
        final Rect containerTwoRect = tester.getRect(find.byKey(keyTwo));
        // Second [Container] should wrap around to the next row.
        expect(containerOneRect.bottom, containerTwoRect.top);
        // Second [Container] should align to the start of the ButtonBar.
        expect(containerOneRect.right, containerTwoRect.right);
        expect(containerOneRect.right, buttonBarRect.right);
      },
    );

441
    testWidgetsWithLeakTracking("ButtonBar's children overflow - MainAxisAlignment.start", (WidgetTester tester) async {
442 443 444 445 446 447 448 449 450
      final Key keyOne = UniqueKey();
      final Key keyTwo = UniqueKey();
      await tester.pumpWidget(
        MaterialApp(
          home: ButtonBar(
            alignment: MainAxisAlignment.start,
            // Set padding to zero to align buttons with edge of button bar.
            buttonPadding: EdgeInsets.zero,
            children: <Widget>[
451 452
              SizedBox(key: keyOne, height: 50.0, width: 500.0),
              SizedBox(key: keyTwo, height: 50.0, width: 500.0),
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
            ],
          ),
        ),
      );

      final Rect buttonBarRect = tester.getRect(find.byType(ButtonBar));
      final Rect containerOneRect = tester.getRect(find.byKey(keyOne));
      final Rect containerTwoRect = tester.getRect(find.byKey(keyTwo));
      // Second [Container] should wrap around to the next row.
      expect(containerOneRect.bottom, containerTwoRect.top);
      // [Container]s should align to the end of the ButtonBar.
      expect(containerOneRect.left, containerTwoRect.left);
      expect(containerOneRect.left, buttonBarRect.left);
    });

468
    testWidgetsWithLeakTracking("ButtonBar's children overflow - MainAxisAlignment.center", (WidgetTester tester) async {
469 470 471 472 473 474 475 476 477
      final Key keyOne = UniqueKey();
      final Key keyTwo = UniqueKey();
      await tester.pumpWidget(
        MaterialApp(
          home: ButtonBar(
            alignment: MainAxisAlignment.center,
            // Set padding to zero to align buttons with edge of button bar.
            buttonPadding: EdgeInsets.zero,
            children: <Widget>[
478 479
              SizedBox(key: keyOne, height: 50.0, width: 500.0),
              SizedBox(key: keyTwo, height: 50.0, width: 500.0),
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
            ],
          ),
        ),
      );

      final Rect buttonBarRect = tester.getRect(find.byType(ButtonBar));
      final Rect containerOneRect = tester.getRect(find.byKey(keyOne));
      final Rect containerTwoRect = tester.getRect(find.byKey(keyTwo));
      // Second [Container] should wrap around to the next row.
      expect(containerOneRect.bottom, containerTwoRect.top);
      // [Container]s should center themselves in the ButtonBar.
      expect(containerOneRect.center.dx, containerTwoRect.center.dx);
      expect(containerOneRect.center.dx, buttonBarRect.center.dx);
    });

495
    testWidgetsWithLeakTracking(
496 497 498 499 500 501 502 503 504 505 506 507
      "ButtonBar's children default to MainAxisAlignment.start for horizontal "
      'alignment when overflowing in spaceBetween, spaceAround and spaceEvenly '
      'cases when overflowing.', (WidgetTester tester) async {
        final Key keyOne = UniqueKey();
        final Key keyTwo = UniqueKey();
        await tester.pumpWidget(
          MaterialApp(
            home: ButtonBar(
              alignment: MainAxisAlignment.spaceEvenly,
              // Set padding to zero to align buttons with edge of button bar.
              buttonPadding: EdgeInsets.zero,
              children: <Widget>[
508 509
                SizedBox(key: keyOne, height: 50.0, width: 500.0),
                SizedBox(key: keyTwo, height: 50.0, width: 500.0),
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
              ],
            ),
          ),
        );

        Rect buttonBarRect = tester.getRect(find.byType(ButtonBar));
        Rect containerOneRect = tester.getRect(find.byKey(keyOne));
        Rect containerTwoRect = tester.getRect(find.byKey(keyTwo));
        // Second [Container] should wrap around to the next row.
        expect(containerOneRect.bottom, containerTwoRect.top);
        // Should align horizontally to the start of the button bar.
        expect(containerOneRect.left, containerTwoRect.left);
        expect(containerOneRect.left, buttonBarRect.left);

        await tester.pumpWidget(
          MaterialApp(
            home: ButtonBar(
              alignment: MainAxisAlignment.spaceAround,
              // Set padding to zero to align buttons with edge of button bar.
              buttonPadding: EdgeInsets.zero,
              children: <Widget>[
531 532
                SizedBox(key: keyOne, height: 50.0, width: 500.0),
                SizedBox(key: keyTwo, height: 50.0, width: 500.0),
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
              ],
            ),
          ),
        );

        buttonBarRect = tester.getRect(find.byType(ButtonBar));
        containerOneRect = tester.getRect(find.byKey(keyOne));
        containerTwoRect = tester.getRect(find.byKey(keyTwo));
        // Second [Container] should wrap around to the next row.
        expect(containerOneRect.bottom, containerTwoRect.top);
        // Should align horizontally to the start of the button bar.
        expect(containerOneRect.left, containerTwoRect.left);
        expect(containerOneRect.left, buttonBarRect.left);
      },
    );
548

549
    testWidgetsWithLeakTracking(
550 551 552 553 554 555 556 557 558 559 560 561 562 563
      "ButtonBar's children respects verticalDirection when overflowing",
      (WidgetTester tester) async {
        final Key keyOne = UniqueKey();
        final Key keyTwo = UniqueKey();
        await tester.pumpWidget(
          MaterialApp(
            home: ButtonBar(
              alignment: MainAxisAlignment.center,
              // Set padding to zero to align buttons with edge of button bar.
              buttonPadding: EdgeInsets.zero,
              // Set the vertical direction to start from the bottom and lay
              // out upwards.
              overflowDirection: VerticalDirection.up,
              children: <Widget>[
564 565
                SizedBox(key: keyOne, height: 50.0, width: 500.0),
                SizedBox(key: keyTwo, height: 50.0, width: 500.0),
566 567 568 569 570 571 572 573
              ],
            ),
          ),
        );

        final Rect containerOneRect = tester.getRect(find.byKey(keyOne));
        final Rect containerTwoRect = tester.getRect(find.byKey(keyTwo));
        // Second [Container] should appear above first container.
574 575 576 577
        expect(containerTwoRect.bottom, lessThanOrEqualTo(containerOneRect.top));
      },
    );

578
    testWidgetsWithLeakTracking(
579 580 581 582 583 584 585 586 587 588 589
      'ButtonBar has no spacing by default when overflowing',
      (WidgetTester tester) async {
        final Key keyOne = UniqueKey();
        final Key keyTwo = UniqueKey();
        await tester.pumpWidget(
          MaterialApp(
            home: ButtonBar(
              alignment: MainAxisAlignment.center,
              // Set padding to zero to align buttons with edge of button bar.
              buttonPadding: EdgeInsets.zero,
              children: <Widget>[
590 591
                SizedBox(key: keyOne, height: 50.0, width: 500.0),
                SizedBox(key: keyTwo, height: 50.0, width: 500.0),
592 593 594 595 596 597 598 599 600 601 602
              ],
            ),
          ),
        );

        final Rect containerOneRect = tester.getRect(find.byKey(keyOne));
        final Rect containerTwoRect = tester.getRect(find.byKey(keyTwo));
        expect(containerOneRect.bottom, containerTwoRect.top);
      },
    );

603
    testWidgetsWithLeakTracking(
604 605 606 607 608 609 610 611 612 613 614 615 616 617
      "ButtonBar's children respects overflowButtonSpacing when overflowing",
      (WidgetTester tester) async {
        final Key keyOne = UniqueKey();
        final Key keyTwo = UniqueKey();
        await tester.pumpWidget(
          MaterialApp(
            home: ButtonBar(
              alignment: MainAxisAlignment.center,
              // Set padding to zero to align buttons with edge of button bar.
              buttonPadding: EdgeInsets.zero,
              // Set the overflow button spacing to ensure add some space between
              // buttons in an overflow case.
              overflowButtonSpacing: 10.0,
              children: <Widget>[
618 619
                SizedBox(key: keyOne, height: 50.0, width: 500.0),
                SizedBox(key: keyTwo, height: 50.0, width: 500.0),
620 621 622 623 624 625 626 627
              ],
            ),
          ),
        );

        final Rect containerOneRect = tester.getRect(find.byKey(keyOne));
        final Rect containerTwoRect = tester.getRect(find.byKey(keyTwo));
        expect(containerOneRect.bottom, containerTwoRect.top - 10.0);
628 629
      },
    );
630
  });
631

632
  testWidgetsWithLeakTracking('_RenderButtonBarRow.constraints does not work before layout', (WidgetTester tester) async {
633 634 635 636 637 638 639 640 641 642
    await tester.pumpWidget(
      const MaterialApp(home: ButtonBar()),
      Duration.zero,
      EnginePhase.build,
    );

    final Finder buttonBar = find.byWidgetPredicate((Widget w) => '${w.runtimeType}' == '_ButtonBarRow');
    final RenderBox renderButtonBar = tester.renderObject(buttonBar) as RenderBox;

    expect(renderButtonBar.debugNeedsLayout, isTrue);
643
    expect(() => renderButtonBar.constraints, throwsStateError);
644
  });
645
}