1// Copyright 2018 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5import 'package:flutter/widgets.dart'; 6import 'package:flutter/cupertino.dart'; 7import 'package:flutter_test/flutter_test.dart'; 8 9import '../widgets/semantics_tester.dart'; 10 11dynamic getRenderSegmentedControl(WidgetTester tester) { 12 return tester.allRenderObjects.firstWhere( 13 (RenderObject currentObject) { 14 return currentObject.toStringShort().contains('_RenderSegmentedControl'); 15 }, 16 ); 17} 18 19StatefulBuilder setupSimpleSegmentedControl() { 20 final Map<int, Widget> children = <int, Widget>{}; 21 children[0] = const Text('Child 1'); 22 children[1] = const Text('Child 2'); 23 int sharedValue = 0; 24 25 return StatefulBuilder( 26 builder: (BuildContext context, StateSetter setState) { 27 return boilerplate( 28 child: CupertinoSegmentedControl<int>( 29 children: children, 30 onValueChanged: (int newValue) { 31 setState(() { 32 sharedValue = newValue; 33 }); 34 }, 35 groupValue: sharedValue, 36 ), 37 ); 38 }, 39 ); 40} 41 42Widget boilerplate({ Widget child }) { 43 return Directionality( 44 textDirection: TextDirection.ltr, 45 child: Center(child: child), 46 ); 47} 48 49Color getBackgroundColor(WidgetTester tester, int childIndex) { 50 return getRenderSegmentedControl(tester).backgroundColors[childIndex]; 51} 52 53void main() { 54 testWidgets('Tap changes toggle state', (WidgetTester tester) async { 55 final Map<int, Widget> children = <int, Widget>{}; 56 children[0] = const Text('Child 1'); 57 children[1] = const Text('Child 2'); 58 children[2] = const Text('Child 3'); 59 60 int sharedValue = 0; 61 62 await tester.pumpWidget( 63 StatefulBuilder( 64 builder: (BuildContext context, StateSetter setState) { 65 return boilerplate( 66 child: CupertinoSegmentedControl<int>( 67 key: const ValueKey<String>('Segmented Control'), 68 children: children, 69 onValueChanged: (int newValue) { 70 setState(() { 71 sharedValue = newValue; 72 }); 73 }, 74 groupValue: sharedValue, 75 ), 76 ); 77 }, 78 ), 79 ); 80 81 expect(sharedValue, 0); 82 83 await tester.tap(find.byKey(const ValueKey<String>('Segmented Control'))); 84 85 expect(sharedValue, 1); 86 }); 87 88 testWidgets('Need at least 2 children', (WidgetTester tester) async { 89 final Map<int, Widget> children = <int, Widget>{}; 90 try { 91 await tester.pumpWidget( 92 boilerplate( 93 child: CupertinoSegmentedControl<int>( 94 children: children, 95 onValueChanged: (int newValue) { }, 96 ), 97 ), 98 ); 99 fail('Should not be possible to create a segmented control with no children'); 100 } on AssertionError catch (e) { 101 expect(e.toString(), contains('children.length')); 102 } 103 try { 104 children[0] = const Text('Child 1'); 105 106 await tester.pumpWidget( 107 boilerplate( 108 child: CupertinoSegmentedControl<int>( 109 children: children, 110 onValueChanged: (int newValue) { }, 111 ), 112 ), 113 ); 114 fail('Should not be possible to create a segmented control with just one child'); 115 } on AssertionError catch (e) { 116 expect(e.toString(), contains('children.length')); 117 } 118 }); 119 120 testWidgets('Padding works', (WidgetTester tester) async { 121 const Key key = Key('Container'); 122 123 final Map<int, Widget> children = <int, Widget>{}; 124 children[0] = const SizedBox( 125 height: double.infinity, 126 child: Text('Child 1'), 127 ) ; 128 children[1] = const SizedBox( 129 height: double.infinity, 130 child: Text('Child 2'), 131 ) ; 132 133 Future<void> verifyPadding({ EdgeInsets padding }) async { 134 final EdgeInsets effectivePadding = padding ?? const EdgeInsets.symmetric(horizontal: 16); 135 final Rect segmentedControlRect = tester.getRect(find.byKey(key)); 136 expect( 137 tester.getTopLeft(find.byWidget(children[0])), 138 segmentedControlRect.topLeft.translate( 139 effectivePadding.topLeft.dx, 140 effectivePadding.topLeft.dy, 141 ) 142 ); 143 expect( 144 tester.getBottomLeft(find.byWidget(children[0])), 145 segmentedControlRect.bottomLeft.translate( 146 effectivePadding.bottomLeft.dx, 147 effectivePadding.bottomLeft.dy, 148 ), 149 ); 150 151 expect( 152 tester.getTopRight(find.byWidget(children[1])), 153 segmentedControlRect.topRight.translate( 154 effectivePadding.topRight.dx, 155 effectivePadding.topRight.dy, 156 ), 157 ); 158 expect( 159 tester.getBottomRight(find.byWidget(children[1])), 160 segmentedControlRect.bottomRight.translate( 161 effectivePadding.bottomRight.dx, 162 effectivePadding.bottomRight.dy, 163 ), 164 ); 165 } 166 167 await tester.pumpWidget( 168 boilerplate( 169 child: CupertinoSegmentedControl<int>( 170 key: key, 171 children: children, 172 onValueChanged: (int newValue) { }, 173 ), 174 ) 175 ); 176 177 // Default padding works. 178 await verifyPadding(); 179 180 // Switch to Child 2 padding should remain the same. 181 await tester.tap(find.text('Child 2')); 182 await tester.pumpAndSettle(); 183 184 await verifyPadding(); 185 186 await tester.pumpWidget( 187 boilerplate( 188 child: CupertinoSegmentedControl<int>( 189 key: key, 190 padding: const EdgeInsets.fromLTRB(1, 3, 5, 7), 191 children: children, 192 onValueChanged: (int newValue) { }, 193 ), 194 ) 195 ); 196 197 // Custom padding works. 198 await verifyPadding(padding: const EdgeInsets.fromLTRB(1, 3, 5, 7)); 199 200 // Switch back to Child 1 padding should remain the same. 201 await tester.tap(find.text('Child 1')); 202 await tester.pumpAndSettle(); 203 204 await verifyPadding(padding: const EdgeInsets.fromLTRB(1, 3, 5, 7)); 205 }); 206 207 testWidgets('Value attribute must be the key of one of the children widgets', (WidgetTester tester) async { 208 final Map<int, Widget> children = <int, Widget>{}; 209 children[0] = const Text('Child 1'); 210 children[1] = const Text('Child 2'); 211 212 try { 213 await tester.pumpWidget( 214 boilerplate( 215 child: CupertinoSegmentedControl<int>( 216 children: children, 217 onValueChanged: (int newValue) { }, 218 groupValue: 2, 219 ), 220 ), 221 ); 222 fail('Should not be possible to create segmented control in which ' 223 'value is not the key of one of the children widgets'); 224 } on AssertionError catch (e) { 225 expect(e.toString(), contains('children')); 226 } 227 }); 228 229 testWidgets('Children and onValueChanged arguments can not be null', (WidgetTester tester) async { 230 try { 231 await tester.pumpWidget( 232 boilerplate( 233 child: CupertinoSegmentedControl<int>( 234 children: null, 235 onValueChanged: (int newValue) { }, 236 ), 237 ), 238 ); 239 fail('Should not be possible to create segmented control with null children'); 240 } on AssertionError catch (e) { 241 expect(e.toString(), contains('children')); 242 } 243 244 final Map<int, Widget> children = <int, Widget>{}; 245 children[0] = const Text('Child 1'); 246 children[1] = const Text('Child 2'); 247 248 try { 249 await tester.pumpWidget( 250 boilerplate( 251 child: CupertinoSegmentedControl<int>( 252 children: children, 253 onValueChanged: null, 254 ), 255 ), 256 ); 257 fail('Should not be possible to create segmented control with null onValueChanged'); 258 } on AssertionError catch (e) { 259 expect(e.toString(), contains('onValueChanged')); 260 } 261 }); 262 263 testWidgets('Widgets have correct default text/icon styles, change correctly on selection', (WidgetTester tester) async { 264 final Map<int, Widget> children = <int, Widget>{}; 265 children[0] = const Text('Child 1'); 266 children[1] = const Icon(IconData(1)); 267 268 int sharedValue = 0; 269 270 await tester.pumpWidget( 271 StatefulBuilder( 272 builder: (BuildContext context, StateSetter setState) { 273 return boilerplate( 274 child: CupertinoSegmentedControl<int>( 275 children: children, 276 onValueChanged: (int newValue) { 277 setState(() { 278 sharedValue = newValue; 279 }); 280 }, 281 groupValue: sharedValue, 282 ), 283 ); 284 }, 285 ), 286 ); 287 288 await tester.pumpAndSettle(); 289 290 DefaultTextStyle textStyle = tester.widget(find.widgetWithText(DefaultTextStyle, 'Child 1')); 291 IconTheme iconTheme = tester.widget(find.widgetWithIcon(IconTheme, const IconData(1))); 292 293 expect(textStyle.style.color, CupertinoColors.white); 294 expect(iconTheme.data.color, CupertinoColors.activeBlue); 295 296 await tester.tap(find.widgetWithIcon(IconTheme, const IconData(1))); 297 await tester.pumpAndSettle(); 298 299 textStyle = tester.widget(find.widgetWithText(DefaultTextStyle, 'Child 1')); 300 iconTheme = tester.widget(find.widgetWithIcon(IconTheme, const IconData(1))); 301 302 expect(textStyle.style.color, CupertinoColors.activeBlue); 303 expect(iconTheme.data.color, CupertinoColors.white); 304 }); 305 306 testWidgets( 307 'Segmented controls respects themes', 308 (WidgetTester tester) async { 309 final Map<int, Widget> children = <int, Widget>{}; 310 children[0] = const Text('Child 1'); 311 children[1] = const Icon(IconData(1)); 312 313 int sharedValue = 0; 314 315 await tester.pumpWidget( 316 CupertinoApp( 317 theme: const CupertinoThemeData(brightness: Brightness.dark), 318 home: StatefulBuilder( 319 builder: (BuildContext context, StateSetter setState) { 320 return CupertinoSegmentedControl<int>( 321 children: children, 322 onValueChanged: (int newValue) { 323 setState(() { 324 sharedValue = newValue; 325 }); 326 }, 327 groupValue: sharedValue, 328 ); 329 }, 330 ), 331 ), 332 ); 333 334 DefaultTextStyle textStyle = tester.widget(find.widgetWithText(DefaultTextStyle, 'Child 1').first); 335 IconThemeData iconTheme = IconTheme.of(tester.element(find.byIcon(const IconData(1)))); 336 337 expect(textStyle.style.color, CupertinoColors.black); 338 expect(iconTheme.color, CupertinoColors.activeOrange); 339 340 await tester.tap(find.byIcon(const IconData(1))); 341 await tester.pump(); 342 await tester.pump(const Duration(milliseconds: 500)); 343 344 textStyle = tester.widget(find.widgetWithText(DefaultTextStyle, 'Child 1').first); 345 iconTheme = IconTheme.of(tester.element(find.byIcon(const IconData(1)))); 346 347 expect(textStyle.style.color, CupertinoColors.activeOrange); 348 expect(iconTheme.color, CupertinoColors.black); 349 }, 350 ); 351 352 testWidgets('SegmentedControl is correct when user provides custom colors', (WidgetTester tester) async { 353 final Map<int, Widget> children = <int, Widget>{}; 354 children[0] = const Text('Child 1'); 355 children[1] = const Icon(IconData(1)); 356 357 int sharedValue = 0; 358 359 await tester.pumpWidget( 360 StatefulBuilder( 361 builder: (BuildContext context, StateSetter setState) { 362 return boilerplate( 363 child: CupertinoSegmentedControl<int>( 364 children: children, 365 onValueChanged: (int newValue) { 366 setState(() { 367 sharedValue = newValue; 368 }); 369 }, 370 groupValue: sharedValue, 371 unselectedColor: CupertinoColors.lightBackgroundGray, 372 selectedColor: CupertinoColors.activeGreen, 373 borderColor: CupertinoColors.black, 374 pressedColor: const Color(0x638CFC7B), 375 ), 376 ); 377 }, 378 ), 379 ); 380 381 DefaultTextStyle textStyle = tester.widget(find.widgetWithText(DefaultTextStyle, 'Child 1')); 382 IconTheme iconTheme = tester.widget(find.widgetWithIcon(IconTheme, const IconData(1))); 383 384 expect(getRenderSegmentedControl(tester).borderColor, CupertinoColors.black); 385 expect(textStyle.style.color, CupertinoColors.lightBackgroundGray); 386 expect(iconTheme.data.color, CupertinoColors.activeGreen); 387 expect(getBackgroundColor(tester, 0), CupertinoColors.activeGreen); 388 expect(getBackgroundColor(tester, 1), CupertinoColors.lightBackgroundGray); 389 390 await tester.tap(find.widgetWithIcon(IconTheme, const IconData(1))); 391 await tester.pumpAndSettle(); 392 393 textStyle = tester.widget(find.widgetWithText(DefaultTextStyle, 'Child 1')); 394 iconTheme = tester.widget(find.widgetWithIcon(IconTheme, const IconData(1))); 395 396 expect(textStyle.style.color, CupertinoColors.activeGreen); 397 expect(iconTheme.data.color, CupertinoColors.lightBackgroundGray); 398 expect(getBackgroundColor(tester, 0), CupertinoColors.lightBackgroundGray); 399 expect(getBackgroundColor(tester, 1), CupertinoColors.activeGreen); 400 401 final Offset center = tester.getCenter(find.text('Child 1')); 402 await tester.startGesture(center); 403 await tester.pumpAndSettle(); 404 405 expect(getBackgroundColor(tester, 0), const Color(0x638CFC7B)); 406 expect(getBackgroundColor(tester, 1), CupertinoColors.activeGreen); 407 }); 408 409 testWidgets('Widgets are centered within segments', (WidgetTester tester) async { 410 final Map<int, Widget> children = <int, Widget>{}; 411 children[0] = const Text('Child 1'); 412 children[1] = const Text('Child 2'); 413 414 await tester.pumpWidget( 415 Directionality( 416 textDirection: TextDirection.ltr, 417 child: Align( 418 alignment: Alignment.topLeft, 419 child: SizedBox( 420 width: 200.0, 421 height: 200.0, 422 child: CupertinoSegmentedControl<int>( 423 children: children, 424 onValueChanged: (int newValue) { }, 425 ), 426 ), 427 ), 428 ), 429 ); 430 431 // Widgets are centered taking into account 16px of horizontal padding 432 expect(tester.getCenter(find.text('Child 1')), const Offset(58.0, 100.0)); 433 expect(tester.getCenter(find.text('Child 2')), const Offset(142.0, 100.0)); 434 }); 435 436 testWidgets('Tap calls onValueChanged', (WidgetTester tester) async { 437 final Map<int, Widget> children = <int, Widget>{}; 438 children[0] = const Text('Child 1'); 439 children[1] = const Text('Child 2'); 440 441 bool value = false; 442 443 await tester.pumpWidget( 444 StatefulBuilder( 445 builder: (BuildContext context, StateSetter setState) { 446 return boilerplate( 447 child: CupertinoSegmentedControl<int>( 448 children: children, 449 onValueChanged: (int newValue) { 450 value = true; 451 }, 452 ), 453 ); 454 }, 455 ), 456 ); 457 458 expect(value, isFalse); 459 460 await tester.tap(find.text('Child 2')); 461 462 expect(value, isTrue); 463 }); 464 465 testWidgets('State does not change if onValueChanged does not call setState()', (WidgetTester tester) async { 466 final Map<int, Widget> children = <int, Widget>{}; 467 children[0] = const Text('Child 1'); 468 children[1] = const Text('Child 2'); 469 470 const int sharedValue = 0; 471 472 await tester.pumpWidget( 473 StatefulBuilder( 474 builder: (BuildContext context, StateSetter setState) { 475 return boilerplate( 476 child: CupertinoSegmentedControl<int>( 477 children: children, 478 onValueChanged: (int newValue) { }, 479 groupValue: sharedValue, 480 ), 481 ); 482 }, 483 ), 484 ); 485 486 expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue); 487 expect(getBackgroundColor(tester, 1), CupertinoColors.white); 488 489 await tester.tap(find.text('Child 2')); 490 await tester.pump(); 491 492 expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue); 493 expect(getBackgroundColor(tester, 1), CupertinoColors.white); 494 }); 495 496 testWidgets( 497 'Background color of child should change on selection, ' 498 'and should not change when tapped again', (WidgetTester tester) async { 499 await tester.pumpWidget(setupSimpleSegmentedControl()); 500 501 expect(getBackgroundColor(tester, 1), CupertinoColors.white); 502 503 await tester.tap(find.text('Child 2')); 504 await tester.pumpAndSettle(const Duration(milliseconds: 200)); 505 506 expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue); 507 508 await tester.tap(find.text('Child 2')); 509 await tester.pump(); 510 511 expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue); 512 }); 513 514 testWidgets( 515 'Children can be non-Text or Icon widgets (in this case, ' 516 'a Container or Placeholder widget)', 517 (WidgetTester tester) async { 518 final Map<int, Widget> children = <int, Widget>{}; 519 children[0] = const Text('Child 1'); 520 children[1] = Container( 521 constraints: const BoxConstraints.tightFor(width: 50.0, height: 50.0), 522 ); 523 children[2] = const Placeholder(); 524 525 int sharedValue = 0; 526 527 await tester.pumpWidget( 528 StatefulBuilder( 529 builder: (BuildContext context, StateSetter setState) { 530 return boilerplate( 531 child: CupertinoSegmentedControl<int>( 532 children: children, 533 onValueChanged: (int newValue) { 534 setState(() { 535 sharedValue = newValue; 536 }); 537 }, 538 groupValue: sharedValue, 539 ), 540 ); 541 }, 542 ), 543 ); 544 }, 545 ); 546 547 testWidgets('Passed in value is child initially selected', (WidgetTester tester) async { 548 await tester.pumpWidget(setupSimpleSegmentedControl()); 549 550 expect(getRenderSegmentedControl(tester).selectedIndex, 0); 551 552 expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue); 553 expect(getBackgroundColor(tester, 1), CupertinoColors.white); 554 }); 555 556 testWidgets('Null input for value results in no child initially selected', (WidgetTester tester) async { 557 final Map<int, Widget> children = <int, Widget>{}; 558 children[0] = const Text('Child 1'); 559 children[1] = const Text('Child 2'); 560 561 int sharedValue; 562 563 await tester.pumpWidget( 564 StatefulBuilder( 565 builder: (BuildContext context, StateSetter setState) { 566 return boilerplate( 567 child: CupertinoSegmentedControl<int>( 568 children: children, 569 onValueChanged: (int newValue) { 570 setState(() { 571 sharedValue = newValue; 572 }); 573 }, 574 groupValue: sharedValue, 575 ), 576 ); 577 }, 578 ), 579 ); 580 581 expect(getRenderSegmentedControl(tester).selectedIndex, null); 582 583 expect(getBackgroundColor(tester, 0), CupertinoColors.white); 584 expect(getBackgroundColor(tester, 1), CupertinoColors.white); 585 }); 586 587 testWidgets('Long press changes background color of not-selected child', (WidgetTester tester) async { 588 await tester.pumpWidget(setupSimpleSegmentedControl()); 589 590 expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue); 591 expect(getBackgroundColor(tester, 1), CupertinoColors.white); 592 593 final Offset center = tester.getCenter(find.text('Child 2')); 594 await tester.startGesture(center); 595 await tester.pumpAndSettle(); 596 597 expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue); 598 expect(getBackgroundColor(tester, 1), const Color(0x33007aff)); 599 }); 600 601 testWidgets('Long press does not change background color of currently-selected child', (WidgetTester tester) async { 602 await tester.pumpWidget(setupSimpleSegmentedControl()); 603 604 expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue); 605 expect(getBackgroundColor(tester, 1), CupertinoColors.white); 606 607 final Offset center = tester.getCenter(find.text('Child 1')); 608 await tester.startGesture(center); 609 await tester.pumpAndSettle(); 610 611 expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue); 612 expect(getBackgroundColor(tester, 1), CupertinoColors.white); 613 }); 614 615 testWidgets('Height of segmented control is determined by tallest widget', (WidgetTester tester) async { 616 final Map<int, Widget> children = <int, Widget>{}; 617 children[0] = Container( 618 constraints: const BoxConstraints.tightFor(height: 100.0), 619 ); 620 children[1] = Container( 621 constraints: const BoxConstraints.tightFor(height: 400.0), 622 ); 623 children[2] = Container( 624 constraints: const BoxConstraints.tightFor(height: 200.0), 625 ); 626 627 await tester.pumpWidget( 628 StatefulBuilder( 629 builder: (BuildContext context, StateSetter setState) { 630 return boilerplate( 631 child: CupertinoSegmentedControl<int>( 632 key: const ValueKey<String>('Segmented Control'), 633 children: children, 634 onValueChanged: (int newValue) { }, 635 ), 636 ); 637 }, 638 ), 639 ); 640 641 final RenderBox buttonBox = tester.renderObject( 642 find.byKey(const ValueKey<String>('Segmented Control'))); 643 644 expect(buttonBox.size.height, 400.0); 645 }); 646 647 testWidgets('Width of each segmented control segment is determined by widest widget', (WidgetTester tester) async { 648 final Map<int, Widget> children = <int, Widget>{}; 649 children[0] = Container( 650 constraints: const BoxConstraints.tightFor(width: 50.0), 651 ); 652 children[1] = Container( 653 constraints: const BoxConstraints.tightFor(width: 100.0), 654 ); 655 children[2] = Container( 656 constraints: const BoxConstraints.tightFor(width: 200.0), 657 ); 658 659 await tester.pumpWidget( 660 StatefulBuilder( 661 builder: (BuildContext context, StateSetter setState) { 662 return boilerplate( 663 child: CupertinoSegmentedControl<int>( 664 key: const ValueKey<String>('Segmented Control'), 665 children: children, 666 onValueChanged: (int newValue) { }, 667 ), 668 ); 669 }, 670 ), 671 ); 672 673 final RenderBox segmentedControl = tester.renderObject( 674 find.byKey(const ValueKey<String>('Segmented Control'))); 675 676 // Subtract the 16.0px from each side. Remaining width should be allocated 677 // to each child equally. 678 final double childWidth = (segmentedControl.size.width - 32.0) / 3; 679 680 expect(childWidth, 200.0); 681 682 expect(childWidth, 683 getRenderSegmentedControl(tester).getChildrenAsList()[0].parentData.surroundingRect.width); 684 expect(childWidth, 685 getRenderSegmentedControl(tester).getChildrenAsList()[1].parentData.surroundingRect.width); 686 expect(childWidth, 687 getRenderSegmentedControl(tester).getChildrenAsList()[2].parentData.surroundingRect.width); 688 }); 689 690 testWidgets('Width is finite in unbounded space', (WidgetTester tester) async { 691 final Map<int, Widget> children = <int, Widget>{}; 692 children[0] = const Text('Child 1'); 693 children[1] = const Text('Child 2'); 694 695 await tester.pumpWidget( 696 StatefulBuilder( 697 builder: (BuildContext context, StateSetter setState) { 698 return boilerplate( 699 child: Row( 700 children: <Widget>[ 701 CupertinoSegmentedControl<int>( 702 key: const ValueKey<String>('Segmented Control'), 703 children: children, 704 onValueChanged: (int newValue) { }, 705 ), 706 ], 707 ), 708 ); 709 }, 710 ), 711 ); 712 713 final RenderBox segmentedControl = tester.renderObject( 714 find.byKey(const ValueKey<String>('Segmented Control'))); 715 716 expect(segmentedControl.size.width.isFinite, isTrue); 717 }); 718 719 testWidgets('Directionality test - RTL should reverse order of widgets', (WidgetTester tester) async { 720 final Map<int, Widget> children = <int, Widget>{}; 721 children[0] = const Text('Child 1'); 722 children[1] = const Text('Child 2'); 723 724 await tester.pumpWidget( 725 Directionality( 726 textDirection: TextDirection.rtl, 727 child: Center( 728 child: CupertinoSegmentedControl<int>( 729 children: children, 730 onValueChanged: (int newValue) { }, 731 ), 732 ), 733 ), 734 ); 735 736 expect(tester.getTopRight(find.text('Child 1')).dx > 737 tester.getTopRight(find.text('Child 2')).dx, isTrue); 738 }); 739 740 testWidgets('Correct initial selection and toggling behavior - RTL', (WidgetTester tester) async { 741 final Map<int, Widget> children = <int, Widget>{}; 742 children[0] = const Text('Child 1'); 743 children[1] = const Text('Child 2'); 744 745 int sharedValue = 0; 746 747 await tester.pumpWidget( 748 StatefulBuilder( 749 builder: (BuildContext context, StateSetter setState) { 750 return Directionality( 751 textDirection: TextDirection.rtl, 752 child: Center( 753 child: CupertinoSegmentedControl<int>( 754 children: children, 755 onValueChanged: (int newValue) { 756 setState(() { 757 sharedValue = newValue; 758 }); 759 }, 760 groupValue: sharedValue, 761 ), 762 ), 763 ); 764 }, 765 ), 766 ); 767 768 expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue); 769 expect(getBackgroundColor(tester, 1), CupertinoColors.white); 770 771 await tester.tap(find.text('Child 2')); 772 await tester.pumpAndSettle(); 773 774 expect(getBackgroundColor(tester, 0), CupertinoColors.white); 775 expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue); 776 777 await tester.tap(find.text('Child 2')); 778 await tester.pump(); 779 780 expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue); 781 }); 782 783 testWidgets('Segmented control semantics', (WidgetTester tester) async { 784 final SemanticsTester semantics = SemanticsTester(tester); 785 786 final Map<int, Widget> children = <int, Widget>{}; 787 children[0] = const Text('Child 1'); 788 children[1] = const Text('Child 2'); 789 int sharedValue = 0; 790 791 await tester.pumpWidget( 792 StatefulBuilder( 793 builder: (BuildContext context, StateSetter setState) { 794 return Directionality( 795 textDirection: TextDirection.ltr, 796 child: Center( 797 child: CupertinoSegmentedControl<int>( 798 children: children, 799 onValueChanged: (int newValue) { 800 setState(() { 801 sharedValue = newValue; 802 }); 803 }, 804 groupValue: sharedValue, 805 ), 806 ), 807 ); 808 }, 809 ), 810 ); 811 812 expect( 813 semantics, 814 hasSemantics( 815 TestSemantics.root( 816 children: <TestSemantics>[ 817 TestSemantics.rootChild( 818 label: 'Child 1', 819 flags: <SemanticsFlag>[ 820 SemanticsFlag.isButton, 821 SemanticsFlag.isInMutuallyExclusiveGroup, 822 SemanticsFlag.isSelected, 823 ], 824 actions: <SemanticsAction>[ 825 SemanticsAction.tap, 826 ], 827 ), 828 TestSemantics.rootChild( 829 label: 'Child 2', 830 flags: <SemanticsFlag>[ 831 SemanticsFlag.isButton, 832 SemanticsFlag.isInMutuallyExclusiveGroup, 833 ], 834 actions: <SemanticsAction>[ 835 SemanticsAction.tap, 836 ], 837 ), 838 ], 839 ), 840 ignoreId: true, 841 ignoreRect: true, 842 ignoreTransform: true, 843 ), 844 ); 845 846 await tester.tap(find.text('Child 2')); 847 await tester.pump(); 848 849 expect( 850 semantics, 851 hasSemantics( 852 TestSemantics.root( 853 children: <TestSemantics>[ 854 TestSemantics.rootChild( 855 label: 'Child 1', 856 flags: <SemanticsFlag>[ 857 SemanticsFlag.isButton, 858 SemanticsFlag.isInMutuallyExclusiveGroup, 859 ], 860 actions: <SemanticsAction>[ 861 SemanticsAction.tap, 862 ], 863 ), 864 TestSemantics.rootChild( 865 label: 'Child 2', 866 flags: <SemanticsFlag>[ 867 SemanticsFlag.isButton, 868 SemanticsFlag.isInMutuallyExclusiveGroup, 869 SemanticsFlag.isSelected, 870 ], 871 actions: <SemanticsAction>[ 872 SemanticsAction.tap, 873 ], 874 ), 875 ], 876 ), 877 ignoreId: true, 878 ignoreRect: true, 879 ignoreTransform: true, 880 )); 881 882 semantics.dispose(); 883 }); 884 885 testWidgets('Non-centered taps work on smaller widgets', (WidgetTester tester) async { 886 final Map<int, Widget> children = <int, Widget>{}; 887 children[0] = const Text('Child 1'); 888 children[1] = const Text('Child 2'); 889 890 int sharedValue = 1; 891 892 await tester.pumpWidget( 893 StatefulBuilder( 894 builder: (BuildContext context, StateSetter setState) { 895 return boilerplate( 896 child: CupertinoSegmentedControl<int>( 897 key: const ValueKey<String>('Segmented Control'), 898 children: children, 899 onValueChanged: (int newValue) { 900 setState(() { 901 sharedValue = newValue; 902 }); 903 }, 904 groupValue: sharedValue, 905 ), 906 ); 907 }, 908 ), 909 ); 910 911 expect(sharedValue, 1); 912 913 final double childWidth = getRenderSegmentedControl(tester).firstChild.size.width; 914 final Offset centerOfSegmentedControl = tester.getCenter(find.text('Child 1')); 915 916 // Tap just inside segment bounds 917 await tester.tapAt( 918 Offset( 919 centerOfSegmentedControl.dx + (childWidth / 2) - 10.0, 920 centerOfSegmentedControl.dy, 921 ), 922 ); 923 924 expect(sharedValue, 0); 925 }); 926 927 testWidgets('Animation is correct when the selected segment changes', (WidgetTester tester) async { 928 await tester.pumpWidget(setupSimpleSegmentedControl()); 929 930 await tester.tap(find.text('Child 2')); 931 932 await tester.pump(); 933 expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue); 934 expect(getBackgroundColor(tester, 1), const Color(0x33007aff)); 935 936 await tester.pump(const Duration(milliseconds: 40)); 937 expect(getBackgroundColor(tester, 0), const Color(0xff3d9aff)); 938 expect(getBackgroundColor(tester, 1), const Color(0x64007aff)); 939 940 await tester.pump(const Duration(milliseconds: 40)); 941 expect(getBackgroundColor(tester, 0), const Color(0xff7bbaff)); 942 expect(getBackgroundColor(tester, 1), const Color(0x95007aff)); 943 944 await tester.pump(const Duration(milliseconds: 40)); 945 expect(getBackgroundColor(tester, 0), const Color(0xffb9daff)); 946 expect(getBackgroundColor(tester, 1), const Color(0xc7007aff)); 947 948 await tester.pump(const Duration(milliseconds: 40)); 949 expect(getBackgroundColor(tester, 0), const Color(0xfff7faff)); 950 expect(getBackgroundColor(tester, 1), const Color(0xf8007aff)); 951 952 await tester.pump(const Duration(milliseconds: 40)); 953 expect(getBackgroundColor(tester, 0), CupertinoColors.white); 954 expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue); 955 }); 956 957 testWidgets('Animation is correct when widget is rebuilt', (WidgetTester tester) async { 958 final Map<int, Widget> children = <int, Widget>{}; 959 children[0] = const Text('Child 1'); 960 children[1] = const Text('Child 2'); 961 int sharedValue = 0; 962 963 await tester.pumpWidget( 964 StatefulBuilder( 965 builder: (BuildContext context, StateSetter setState) { 966 return boilerplate( 967 child: CupertinoSegmentedControl<int>( 968 children: children, 969 onValueChanged: (int newValue) { 970 setState(() { 971 sharedValue = newValue; 972 }); 973 }, 974 groupValue: sharedValue, 975 ), 976 ); 977 }, 978 ), 979 ); 980 981 await tester.tap(find.text('Child 2')); 982 983 await tester.pumpWidget( 984 StatefulBuilder( 985 builder: (BuildContext context, StateSetter setState) { 986 return boilerplate( 987 child: CupertinoSegmentedControl<int>( 988 children: children, 989 onValueChanged: (int newValue) { 990 setState(() { 991 sharedValue = newValue; 992 }); 993 }, 994 groupValue: sharedValue, 995 ), 996 ); 997 }, 998 ), 999 ); 1000 expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue); 1001 expect(getBackgroundColor(tester, 1), const Color(0x33007aff)); 1002 1003 await tester.pumpWidget( 1004 StatefulBuilder( 1005 builder: (BuildContext context, StateSetter setState) { 1006 return boilerplate( 1007 child: CupertinoSegmentedControl<int>( 1008 children: children, 1009 onValueChanged: (int newValue) { 1010 setState(() { 1011 sharedValue = newValue; 1012 }); 1013 }, 1014 groupValue: sharedValue, 1015 ), 1016 ); 1017 }, 1018 ), 1019 const Duration(milliseconds: 40), 1020 ); 1021 expect(getBackgroundColor(tester, 0), const Color(0xff3d9aff)); 1022 expect(getBackgroundColor(tester, 1), const Color(0x64007aff)); 1023 1024 await tester.pumpWidget( 1025 StatefulBuilder( 1026 builder: (BuildContext context, StateSetter setState) { 1027 return boilerplate( 1028 child: CupertinoSegmentedControl<int>( 1029 children: children, 1030 onValueChanged: (int newValue) { 1031 setState(() { 1032 sharedValue = newValue; 1033 }); 1034 }, 1035 groupValue: sharedValue, 1036 ), 1037 ); 1038 }, 1039 ), 1040 const Duration(milliseconds: 40), 1041 ); 1042 expect(getBackgroundColor(tester, 0), const Color(0xff7bbaff)); 1043 expect(getBackgroundColor(tester, 1), const Color(0x95007aff)); 1044 1045 await tester.pumpWidget( 1046 StatefulBuilder( 1047 builder: (BuildContext context, StateSetter setState) { 1048 return boilerplate( 1049 child: CupertinoSegmentedControl<int>( 1050 children: children, 1051 onValueChanged: (int newValue) { 1052 setState(() { 1053 sharedValue = newValue; 1054 }); 1055 }, 1056 groupValue: sharedValue, 1057 ), 1058 ); 1059 }, 1060 ), 1061 const Duration(milliseconds: 40), 1062 ); 1063 expect(getBackgroundColor(tester, 0), const Color(0xffb9daff)); 1064 expect(getBackgroundColor(tester, 1), const Color(0xc7007aff)); 1065 1066 await tester.pumpWidget( 1067 StatefulBuilder( 1068 builder: (BuildContext context, StateSetter setState) { 1069 return boilerplate( 1070 child: CupertinoSegmentedControl<int>( 1071 children: children, 1072 onValueChanged: (int newValue) { 1073 setState(() { 1074 sharedValue = newValue; 1075 }); 1076 }, 1077 groupValue: sharedValue, 1078 ), 1079 ); 1080 }, 1081 ), 1082 const Duration(milliseconds: 40), 1083 ); 1084 expect(getBackgroundColor(tester, 0), const Color(0xfff7faff)); 1085 expect(getBackgroundColor(tester, 1), const Color(0xf8007aff)); 1086 1087 await tester.pumpWidget( 1088 StatefulBuilder( 1089 builder: (BuildContext context, StateSetter setState) { 1090 return boilerplate( 1091 child: CupertinoSegmentedControl<int>( 1092 children: children, 1093 onValueChanged: (int newValue) { 1094 setState(() { 1095 sharedValue = newValue; 1096 }); 1097 }, 1098 groupValue: sharedValue, 1099 ), 1100 ); 1101 }, 1102 ), 1103 const Duration(milliseconds: 40), 1104 ); 1105 expect(getBackgroundColor(tester, 0), CupertinoColors.white); 1106 expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue); 1107 }); 1108 1109 testWidgets('Multiple segments are pressed', (WidgetTester tester) async { 1110 final Map<int, Widget> children = <int, Widget>{}; 1111 children[0] = const Text('A'); 1112 children[1] = const Text('B'); 1113 children[2] = const Text('C'); 1114 int sharedValue = 0; 1115 1116 await tester.pumpWidget( 1117 StatefulBuilder( 1118 builder: (BuildContext context, StateSetter setState) { 1119 return boilerplate( 1120 child: CupertinoSegmentedControl<int>( 1121 key: const ValueKey<String>('Segmented Control'), 1122 children: children, 1123 onValueChanged: (int newValue) { 1124 setState(() { 1125 sharedValue = newValue; 1126 }); 1127 }, 1128 groupValue: sharedValue, 1129 ), 1130 ); 1131 }, 1132 ), 1133 ); 1134 1135 expect(getBackgroundColor(tester, 1), CupertinoColors.white); 1136 1137 await tester.startGesture(tester.getCenter(find.text('B'))); 1138 await tester.pumpAndSettle(const Duration(milliseconds: 200)); 1139 1140 expect(getBackgroundColor(tester, 1), const Color(0x33007aff)); 1141 expect(getBackgroundColor(tester, 2), CupertinoColors.white); 1142 1143 await tester.startGesture(tester.getCenter(find.text('C'))); 1144 await tester.pumpAndSettle(const Duration(milliseconds: 200)); 1145 1146 // Press on C has no effect while B is held down. 1147 expect(getBackgroundColor(tester, 1), const Color(0x33007aff)); 1148 expect(getBackgroundColor(tester, 2), CupertinoColors.white); 1149 }); 1150 1151 testWidgets('Transition is triggered while a transition is already occurring', (WidgetTester tester) async { 1152 final Map<int, Widget> children = <int, Widget>{}; 1153 children[0] = const Text('A'); 1154 children[1] = const Text('B'); 1155 children[2] = const Text('C'); 1156 int sharedValue = 0; 1157 1158 await tester.pumpWidget( 1159 StatefulBuilder( 1160 builder: (BuildContext context, StateSetter setState) { 1161 return boilerplate( 1162 child: CupertinoSegmentedControl<int>( 1163 key: const ValueKey<String>('Segmented Control'), 1164 children: children, 1165 onValueChanged: (int newValue) { 1166 setState(() { 1167 sharedValue = newValue; 1168 }); 1169 }, 1170 groupValue: sharedValue, 1171 ), 1172 ); 1173 }, 1174 ), 1175 ); 1176 1177 await tester.tap(find.text('B')); 1178 1179 await tester.pump(); 1180 expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue); 1181 expect(getBackgroundColor(tester, 1), const Color(0x33007aff)); 1182 1183 await tester.pump(const Duration(milliseconds: 40)); 1184 expect(getBackgroundColor(tester, 0), const Color(0xff3d9aff)); 1185 expect(getBackgroundColor(tester, 1), const Color(0x64007aff)); 1186 1187 // While A to B transition is occurring, press on C. 1188 await tester.tap(find.text('C')); 1189 1190 await tester.pump(); 1191 1192 // A and B are now both transitioning to white. 1193 expect(getBackgroundColor(tester, 0), const Color(0xff3d9aff)); 1194 expect(getBackgroundColor(tester, 1), const Color(0xffc1deff)); 1195 expect(getBackgroundColor(tester, 2), const Color(0x33007aff)); 1196 1197 await tester.pump(const Duration(milliseconds: 40)); 1198 // B background color has reached unselected state. 1199 expect(getBackgroundColor(tester, 0), const Color(0xff7bbaff)); 1200 expect(getBackgroundColor(tester, 1), CupertinoColors.white); 1201 expect(getBackgroundColor(tester, 2), const Color(0x64007aff)); 1202 1203 await tester.pump(const Duration(milliseconds: 100)); 1204 // A background color has reached unselected state. 1205 expect(getBackgroundColor(tester, 0), CupertinoColors.white); 1206 expect(getBackgroundColor(tester, 2), const Color(0xe0007aff)); 1207 1208 await tester.pump(const Duration(milliseconds: 40)); 1209 // C background color has reached selected state. 1210 expect(getBackgroundColor(tester, 2), CupertinoColors.activeBlue); 1211 }); 1212 1213 testWidgets('Segment is selected while it is transitioning to unselected state', (WidgetTester tester) async { 1214 await tester.pumpWidget(setupSimpleSegmentedControl()); 1215 1216 await tester.tap(find.text('Child 2')); 1217 1218 await tester.pump(); 1219 expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue); 1220 expect(getBackgroundColor(tester, 1), const Color(0x33007aff)); 1221 1222 await tester.pump(const Duration(milliseconds: 40)); 1223 expect(getBackgroundColor(tester, 0), const Color(0xff3d9aff)); 1224 expect(getBackgroundColor(tester, 1), const Color(0x64007aff)); 1225 1226 // While A to B transition is occurring, press on A again. 1227 await tester.tap(find.text('Child 1')); 1228 1229 await tester.pump(); 1230 1231 // Both transitions start to reverse. 1232 expect(getBackgroundColor(tester, 0), const Color(0xcd007aff)); 1233 expect(getBackgroundColor(tester, 1), const Color(0xffc1deff)); 1234 1235 await tester.pump(const Duration(milliseconds: 40)); 1236 // A and B finish transitioning. 1237 expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue); 1238 expect(getBackgroundColor(tester, 1), CupertinoColors.white); 1239 }); 1240 1241 testWidgets('Add segment while animation is running', (WidgetTester tester) async { 1242 Map<int, Widget> children = <int, Widget>{}; 1243 children[0] = const Text('A'); 1244 children[1] = const Text('B'); 1245 children[2] = const Text('C'); 1246 int sharedValue = 0; 1247 1248 await tester.pumpWidget( 1249 StatefulBuilder( 1250 builder: (BuildContext context, StateSetter setState) { 1251 return boilerplate( 1252 child: CupertinoSegmentedControl<int>( 1253 key: const ValueKey<String>('Segmented Control'), 1254 children: children, 1255 onValueChanged: (int newValue) { 1256 setState(() { 1257 sharedValue = newValue; 1258 }); 1259 if (sharedValue == 1) { 1260 children = Map<int, Widget>.from(children); 1261 children[3] = const Text('D'); 1262 } 1263 }, 1264 groupValue: sharedValue, 1265 ), 1266 ); 1267 }, 1268 ), 1269 ); 1270 1271 await tester.tap(find.text('B')); 1272 1273 await tester.pump(); 1274 expect(getBackgroundColor(tester, 0), CupertinoColors.white); 1275 expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue); 1276 expect(getBackgroundColor(tester, 3), CupertinoColors.white); 1277 1278 await tester.pump(const Duration(milliseconds: 40)); 1279 expect(getBackgroundColor(tester, 0), CupertinoColors.white); 1280 expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue); 1281 expect(getBackgroundColor(tester, 3), CupertinoColors.white); 1282 1283 await tester.pump(const Duration(milliseconds: 150)); 1284 expect(getBackgroundColor(tester, 0), CupertinoColors.white); 1285 expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue); 1286 expect(getBackgroundColor(tester, 3), CupertinoColors.white); 1287 }); 1288 1289 testWidgets('Remove segment while animation is running', (WidgetTester tester) async { 1290 Map<int, Widget> children = <int, Widget>{}; 1291 children[0] = const Text('A'); 1292 children[1] = const Text('B'); 1293 children[2] = const Text('C'); 1294 int sharedValue = 0; 1295 1296 await tester.pumpWidget( 1297 StatefulBuilder( 1298 builder: (BuildContext context, StateSetter setState) { 1299 return boilerplate( 1300 child: CupertinoSegmentedControl<int>( 1301 key: const ValueKey<String>('Segmented Control'), 1302 children: children, 1303 onValueChanged: (int newValue) { 1304 setState(() { 1305 sharedValue = newValue; 1306 }); 1307 if (sharedValue == 1) { 1308 children.remove(2); 1309 children = Map<int, Widget>.from(children); 1310 } 1311 }, 1312 groupValue: sharedValue, 1313 ), 1314 ); 1315 }, 1316 ), 1317 ); 1318 1319 expect(getRenderSegmentedControl(tester).getChildrenAsList().length, 3); 1320 1321 await tester.tap(find.text('B')); 1322 1323 await tester.pump(); 1324 expect(getBackgroundColor(tester, 1), const Color(0x33007aff)); 1325 expect(getRenderSegmentedControl(tester).getChildrenAsList().length, 2); 1326 1327 await tester.pump(const Duration(milliseconds: 40)); 1328 expect(getBackgroundColor(tester, 1), const Color(0x64007aff)); 1329 1330 await tester.pump(const Duration(milliseconds: 150)); 1331 expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue); 1332 }); 1333 1334 testWidgets('Remove currently animating segment', (WidgetTester tester) async { 1335 Map<int, Widget> children = <int, Widget>{}; 1336 children[0] = const Text('A'); 1337 children[1] = const Text('B'); 1338 children[2] = const Text('C'); 1339 int sharedValue = 0; 1340 1341 await tester.pumpWidget( 1342 StatefulBuilder( 1343 builder: (BuildContext context, StateSetter setState) { 1344 return boilerplate( 1345 child: CupertinoSegmentedControl<int>( 1346 key: const ValueKey<String>('Segmented Control'), 1347 children: children, 1348 onValueChanged: (int newValue) { 1349 setState(() { 1350 sharedValue = newValue; 1351 }); 1352 if (sharedValue == 1) { 1353 children.remove(1); 1354 children = Map<int, Widget>.from(children); 1355 sharedValue = null; 1356 } 1357 }, 1358 groupValue: sharedValue, 1359 ), 1360 ); 1361 }, 1362 ), 1363 ); 1364 1365 expect(getRenderSegmentedControl(tester).getChildrenAsList().length, 3); 1366 1367 await tester.tap(find.text('B')); 1368 1369 await tester.pump(); 1370 expect(getRenderSegmentedControl(tester).getChildrenAsList().length, 2); 1371 1372 await tester.pump(const Duration(milliseconds: 40)); 1373 expect(getBackgroundColor(tester, 0), const Color(0xff3d9aff)); 1374 expect(getBackgroundColor(tester, 1), CupertinoColors.white); 1375 1376 await tester.pump(const Duration(milliseconds: 40)); 1377 expect(getBackgroundColor(tester, 0), const Color(0xff7bbaff)); 1378 expect(getBackgroundColor(tester, 1), CupertinoColors.white); 1379 1380 await tester.pump(const Duration(milliseconds: 100)); 1381 expect(getBackgroundColor(tester, 0), CupertinoColors.white); 1382 expect(getBackgroundColor(tester, 1), CupertinoColors.white); 1383 }); 1384 1385 testWidgets('Golden Test Placeholder Widget', (WidgetTester tester) async { 1386 final Map<int, Widget> children = <int, Widget>{}; 1387 children[0] = Container(); 1388 children[1] = const Placeholder(); 1389 children[2] = Container(); 1390 1391 const int currentValue = 0; 1392 1393 await tester.pumpWidget( 1394 RepaintBoundary( 1395 child: StatefulBuilder( 1396 builder: (BuildContext context, StateSetter setState) { 1397 return boilerplate( 1398 child: SizedBox( 1399 width: 800.0, 1400 child: CupertinoSegmentedControl<int>( 1401 key: const ValueKey<String>('Segmented Control'), 1402 children: children, 1403 onValueChanged: (int newValue) { }, 1404 groupValue: currentValue, 1405 ), 1406 ), 1407 ); 1408 }, 1409 ), 1410 ), 1411 ); 1412 1413 await expectLater( 1414 find.byType(RepaintBoundary), 1415 matchesGoldenFile( 1416 'segmented_control_test.0.png', 1417 version: 0, 1418 ), 1419 ); 1420 }); 1421 1422 testWidgets('Golden Test Pressed State', (WidgetTester tester) async { 1423 final Map<int, Widget> children = <int, Widget>{}; 1424 children[0] = const Text('A'); 1425 children[1] = const Text('B'); 1426 children[2] = const Text('C'); 1427 1428 const int currentValue = 0; 1429 1430 await tester.pumpWidget( 1431 RepaintBoundary( 1432 child: StatefulBuilder( 1433 builder: (BuildContext context, StateSetter setState) { 1434 return boilerplate( 1435 child: SizedBox( 1436 width: 800.0, 1437 child: CupertinoSegmentedControl<int>( 1438 key: const ValueKey<String>('Segmented Control'), 1439 children: children, 1440 onValueChanged: (int newValue) { }, 1441 groupValue: currentValue, 1442 ), 1443 ), 1444 ); 1445 }, 1446 ), 1447 ), 1448 ); 1449 1450 final Offset center = tester.getCenter(find.text('B')); 1451 await tester.startGesture(center); 1452 await tester.pumpAndSettle(); 1453 1454 await expectLater( 1455 find.byType(RepaintBoundary), 1456 matchesGoldenFile( 1457 'segmented_control_test.1.png', 1458 version: 0, 1459 ), 1460 ); 1461 }); 1462} 1463