// Copyright 2014 The Flutter Authors. All rights reserved. // 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'; void main() { test('ButtonThemeData defaults', () { const ButtonThemeData theme = ButtonThemeData(); expect(theme.textTheme, ButtonTextTheme.normal); expect(theme.constraints, const BoxConstraints(minWidth: 88.0, minHeight: 36.0)); expect(theme.padding, const EdgeInsets.symmetric(horizontal: 16.0)); expect(theme.shape, const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(2.0)), )); expect(theme.alignedDropdown, false); expect(theme.layoutBehavior, ButtonBarLayoutBehavior.padded); }); test('ButtonThemeData default overrides', () { const ButtonThemeData theme = ButtonThemeData( textTheme: ButtonTextTheme.primary, minWidth: 100.0, height: 200.0, padding: EdgeInsets.zero, shape: RoundedRectangleBorder(), alignedDropdown: true, ); expect(theme.textTheme, ButtonTextTheme.primary); expect(theme.constraints, const BoxConstraints(minWidth: 100.0, minHeight: 200.0)); expect(theme.padding, EdgeInsets.zero); expect(theme.shape, const RoundedRectangleBorder()); expect(theme.alignedDropdown, true); }); test('ButtonThemeData.copyWith', () { ButtonThemeData theme = const ButtonThemeData().copyWith(); expect(theme.textTheme, ButtonTextTheme.normal); expect(theme.layoutBehavior, ButtonBarLayoutBehavior.padded); expect(theme.constraints, const BoxConstraints(minWidth: 88.0, minHeight: 36.0)); expect(theme.padding, const EdgeInsets.symmetric(horizontal: 16.0)); expect(theme.shape, const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(2.0)), )); expect(theme.alignedDropdown, false); expect(theme.colorScheme, null); theme = const ButtonThemeData().copyWith( textTheme: ButtonTextTheme.primary, layoutBehavior: ButtonBarLayoutBehavior.constrained, minWidth: 100.0, height: 200.0, padding: EdgeInsets.zero, shape: const StadiumBorder(), alignedDropdown: true, colorScheme: const ColorScheme.dark(), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, ); expect(theme.textTheme, ButtonTextTheme.primary); expect(theme.layoutBehavior, ButtonBarLayoutBehavior.constrained); expect(theme.constraints, const BoxConstraints(minWidth: 100.0, minHeight: 200.0)); expect(theme.padding, EdgeInsets.zero); expect(theme.shape, const StadiumBorder()); expect(theme.alignedDropdown, true); expect(theme.colorScheme, const ColorScheme.dark()); }); testWidgets('ButtonTheme alignedDropdown', (WidgetTester tester) async { final Key dropdownKey = UniqueKey(); Widget buildFrame({ required bool alignedDropdown, required TextDirection textDirection }) { return MaterialApp( builder: (BuildContext context, Widget? child) { return Directionality( textDirection: textDirection, child: child!, ); }, home: ButtonTheme( alignedDropdown: alignedDropdown, child: Material( child: Builder( builder: (BuildContext context) { return Container( alignment: Alignment.center, child: DropdownButtonHideUnderline( child: SizedBox( width: 200.0, child: DropdownButton<String>( key: dropdownKey, onChanged: (String? value) { }, value: 'foo', items: const <DropdownMenuItem<String>>[ DropdownMenuItem<String>( value: 'foo', child: Text('foo'), ), DropdownMenuItem<String>( value: 'bar', child: Text('bar'), ), ], ), ), ), ); }, ), ), ), ); } final Finder button = find.byKey(dropdownKey); final Finder menu = find.byWidgetPredicate((Widget w) => '${w.runtimeType}' == '_DropdownMenu<String>'); await tester.pumpWidget( buildFrame( alignedDropdown: false, textDirection: TextDirection.ltr, ), ); await tester.tap(button); await tester.pumpAndSettle(); // 240 = 200.0 (button width) + _kUnalignedMenuMargin (20.0 left and right) expect(tester.getSize(button).width, 200.0); expect(tester.getSize(menu).width, 240.0); // Dismiss the menu. await tester.tapAt(Offset.zero); await tester.pumpAndSettle(); expect(menu, findsNothing); await tester.pumpWidget( buildFrame( alignedDropdown: true, textDirection: TextDirection.ltr, ), ); await tester.tap(button); await tester.pumpAndSettle(); // Aligneddropdown: true means the button and menu widths match expect(tester.getSize(button).width, 200.0); expect(tester.getSize(menu).width, 200.0); // There are two 'foo' widgets: the selected menu item's label and the drop // down button's label. The should both appear at the same location. final Finder fooText = find.text('foo'); expect(fooText, findsNWidgets(2)); expect(tester.getRect(fooText.at(0)), tester.getRect(fooText.at(1))); // Dismiss the menu. await tester.tapAt(Offset.zero); await tester.pumpAndSettle(); expect(menu, findsNothing); // Same test as above except RTL await tester.pumpWidget( buildFrame( alignedDropdown: true, textDirection: TextDirection.rtl, ), ); await tester.tap(button); await tester.pumpAndSettle(); expect(fooText, findsNWidgets(2)); expect(tester.getRect(fooText.at(0)), tester.getRect(fooText.at(1))); }); }