floating_action_button_theme_test.dart 14.3 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
// 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/rendering.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  test('FloatingActionButtonThemeData copyWith, ==, hashCode basics', () {
    expect(const FloatingActionButtonThemeData(), const FloatingActionButtonThemeData().copyWith());
    expect(const FloatingActionButtonThemeData().hashCode, const FloatingActionButtonThemeData().copyWith().hashCode);
  });

  testWidgets('Default values are used when no FloatingActionButton or FloatingActionButtonThemeData properties are specified', (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(
      home: Scaffold(
        floatingActionButton: FloatingActionButton(
          onPressed: () { },
          child: const Icon(Icons.add),
        ),
      ),
    ));

    // The color scheme values are guaranteed to be non null since the default
    // [ThemeData] creates it with [ColorScheme.fromSwatch].
    expect(_getRawMaterialButton(tester).fillColor, ThemeData().colorScheme.secondary);
28
    expect(_getRichText(tester).text.style!.color, ThemeData().colorScheme.onSecondary);
29 30 31 32 33

    // These defaults come directly from the [FloatingActionButton].
    expect(_getRawMaterialButton(tester).elevation, 6);
    expect(_getRawMaterialButton(tester).highlightElevation, 12);
    expect(_getRawMaterialButton(tester).shape, const CircleBorder());
34
    expect(_getRawMaterialButton(tester).splashColor, ThemeData().splashColor);
35
    expect(_getRawMaterialButton(tester).constraints, const BoxConstraints.tightFor(width: 56.0, height: 56.0));
36 37
    expect(_getIconSize(tester).width, 24.0);
    expect(_getIconSize(tester).height, 24.0);
38 39 40 41 42
  });

  testWidgets('FloatingActionButtonThemeData values are used when no FloatingActionButton properties are specified', (WidgetTester tester) async {
    const Color backgroundColor = Color(0xBEEFBEEF);
    const Color foregroundColor = Color(0xFACEFACE);
43
    const Color splashColor = Color(0xCAFEFEED);
44 45 46 47
    const double elevation = 7;
    const double disabledElevation = 1;
    const double highlightElevation = 13;
    const ShapeBorder shape = StadiumBorder();
48
    const BoxConstraints constraints = BoxConstraints.tightFor(width: 100.0, height: 100.0);
49 50 51 52 53 54

    await tester.pumpWidget(MaterialApp(
      theme: ThemeData().copyWith(
        floatingActionButtonTheme: const FloatingActionButtonThemeData(
          backgroundColor: backgroundColor,
          foregroundColor: foregroundColor,
55
          splashColor: splashColor,
56 57 58 59
          elevation: elevation,
          disabledElevation: disabledElevation,
          highlightElevation: highlightElevation,
          shape: shape,
60
          sizeConstraints: constraints,
61
        ),
62 63 64 65 66 67 68 69 70 71
      ),
      home: Scaffold(
        floatingActionButton: FloatingActionButton(
          onPressed: () { },
          child: const Icon(Icons.add),
        ),
      ),
    ));

    expect(_getRawMaterialButton(tester).fillColor, backgroundColor);
72
    expect(_getRichText(tester).text.style!.color, foregroundColor);
73 74 75 76
    expect(_getRawMaterialButton(tester).elevation, elevation);
    expect(_getRawMaterialButton(tester).disabledElevation, disabledElevation);
    expect(_getRawMaterialButton(tester).highlightElevation, highlightElevation);
    expect(_getRawMaterialButton(tester).shape, shape);
77
    expect(_getRawMaterialButton(tester).splashColor, splashColor);
78
    expect(_getRawMaterialButton(tester).constraints, constraints);
79 80 81
  });

  testWidgets('FloatingActionButton values take priority over FloatingActionButtonThemeData values when both properties are specified', (WidgetTester tester) async {
82 83 84
    const Color backgroundColor = Color(0x00000001);
    const Color foregroundColor = Color(0x00000002);
    const Color splashColor = Color(0x00000003);
85 86 87 88 89 90 91 92
    const double elevation = 7;
    const double disabledElevation = 1;
    const double highlightElevation = 13;
    const ShapeBorder shape = StadiumBorder();

    await tester.pumpWidget(MaterialApp(
      theme: ThemeData().copyWith(
        floatingActionButtonTheme: const FloatingActionButtonThemeData(
93 94 95
          backgroundColor: Color(0x00000004),
          foregroundColor: Color(0x00000005),
          splashColor: Color(0x00000006),
96 97 98 99 100 101 102 103 104 105 106
          elevation: 23,
          disabledElevation: 11,
          highlightElevation: 43,
          shape: BeveledRectangleBorder(),
        ),
      ),
      home: Scaffold(
        floatingActionButton: FloatingActionButton(
          onPressed: () { },
          backgroundColor: backgroundColor,
          foregroundColor: foregroundColor,
107
          splashColor: splashColor,
108 109 110 111
          elevation: elevation,
          disabledElevation: disabledElevation,
          highlightElevation: highlightElevation,
          shape: shape,
112
          child: const Icon(Icons.add),
113 114 115 116 117
        ),
      ),
    ));

    expect(_getRawMaterialButton(tester).fillColor, backgroundColor);
118
    expect(_getRichText(tester).text.style!.color, foregroundColor);
119 120 121 122
    expect(_getRawMaterialButton(tester).elevation, elevation);
    expect(_getRawMaterialButton(tester).disabledElevation, disabledElevation);
    expect(_getRawMaterialButton(tester).highlightElevation, highlightElevation);
    expect(_getRawMaterialButton(tester).shape, shape);
123
    expect(_getRawMaterialButton(tester).splashColor, splashColor);
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
  });

  testWidgets('FloatingActionButton uses a custom shape when specified in the theme', (WidgetTester tester) async {
    const ShapeBorder customShape = BeveledRectangleBorder();

    await tester.pumpWidget(MaterialApp(
      home: Scaffold(
        floatingActionButton: FloatingActionButton(
          onPressed: () { },
          shape: customShape,
        ),
      ),
    ));

    expect(_getRawMaterialButton(tester).shape, customShape);
  });

141 142
  testWidgets('FloatingActionButton.small uses custom constraints when specified in the theme', (WidgetTester tester) async {
    const BoxConstraints constraints = BoxConstraints.tightFor(width: 100.0, height: 100.0);
143
    const double iconSize = 24.0;
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159

    await tester.pumpWidget(MaterialApp(
      theme: ThemeData().copyWith(
        floatingActionButtonTheme: const FloatingActionButtonThemeData(
          smallSizeConstraints: constraints,
        ),
      ),
      home: Scaffold(
        floatingActionButton: FloatingActionButton.small(
          onPressed: () { },
          child: const Icon(Icons.add),
        ),
      ),
    ));

    expect(_getRawMaterialButton(tester).constraints, constraints);
160 161
    expect(_getIconSize(tester).width, iconSize);
    expect(_getIconSize(tester).height, iconSize);
162 163 164 165
  });

  testWidgets('FloatingActionButton.large uses custom constraints when specified in the theme', (WidgetTester tester) async {
    const BoxConstraints constraints = BoxConstraints.tightFor(width: 100.0, height: 100.0);
166
    const double iconSize = 36.0;
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182

    await tester.pumpWidget(MaterialApp(
      theme: ThemeData().copyWith(
        floatingActionButtonTheme: const FloatingActionButtonThemeData(
          largeSizeConstraints: constraints,
        ),
      ),
      home: Scaffold(
        floatingActionButton: FloatingActionButton.large(
          onPressed: () { },
          child: const Icon(Icons.add),
        ),
      ),
    ));

    expect(_getRawMaterialButton(tester).constraints, constraints);
183 184
    expect(_getIconSize(tester).width, iconSize);
    expect(_getIconSize(tester).height, iconSize);
185 186
  });

187
  testWidgets('FloatingActionButton.extended uses custom properties when specified in the theme', (WidgetTester tester) async {
188 189 190
    const Key iconKey = Key('icon');
    const Key labelKey = Key('label');
    const BoxConstraints constraints = BoxConstraints.tightFor(height: 100.0);
191 192
    const double iconLabelSpacing = 33.0;
    const EdgeInsetsDirectional padding = EdgeInsetsDirectional.only(start: 5.0, end: 6.0);
193
    const TextStyle textStyle = TextStyle(letterSpacing: 2.0);
194 195 196 197 198

    await tester.pumpWidget(MaterialApp(
      theme: ThemeData().copyWith(
        floatingActionButtonTheme: const FloatingActionButtonThemeData(
          extendedSizeConstraints: constraints,
199 200
          extendedIconLabelSpacing: iconLabelSpacing,
          extendedPadding: padding,
201
          extendedTextStyle: textStyle,
202 203 204 205 206 207 208 209 210 211 212 213
        ),
      ),
      home: Scaffold(
        floatingActionButton: FloatingActionButton.extended(
          onPressed: () { },
          label: const Text('Extended', key: labelKey),
          icon: const Icon(Icons.add, key: iconKey),
        ),
      ),
    ));

    expect(_getRawMaterialButton(tester).constraints, constraints);
214 215 216
    expect(tester.getTopLeft(find.byKey(labelKey)).dx - tester.getTopRight(find.byKey(iconKey)).dx, iconLabelSpacing);
    expect(tester.getTopLeft(find.byKey(iconKey)).dx - tester.getTopLeft(find.byType(FloatingActionButton)).dx, padding.start);
    expect(tester.getTopRight(find.byType(FloatingActionButton)).dx - tester.getTopRight(find.byKey(labelKey)).dx, padding.end);
217 218
    // The color comes from the default color scheme's onSecondary value.
    expect(_getRawMaterialButton(tester).textStyle, textStyle.copyWith(color: const Color(0xffffffff)));
219 220
  });

221
  testWidgets('FloatingActionButton.extended custom properties takes priority over FloatingActionButtonThemeData spacing', (WidgetTester tester) async {
222 223
    const Key iconKey = Key('icon');
    const Key labelKey = Key('label');
224 225
    const double iconLabelSpacing = 33.0;
    const EdgeInsetsDirectional padding = EdgeInsetsDirectional.only(start: 5.0, end: 6.0);
226
    const TextStyle textStyle = TextStyle(letterSpacing: 2.0);
227 228 229 230 231

    await tester.pumpWidget(MaterialApp(
      theme: ThemeData().copyWith(
        floatingActionButtonTheme: const FloatingActionButtonThemeData(
          extendedIconLabelSpacing: 25.0,
232
          extendedPadding: EdgeInsetsDirectional.only(start: 7.0, end: 8.0),
233
          extendedTextStyle: TextStyle(letterSpacing: 3.0),
234 235 236 237 238 239 240
        ),
      ),
      home: Scaffold(
        floatingActionButton: FloatingActionButton.extended(
          onPressed: () { },
          label: const Text('Extended', key: labelKey),
          icon: const Icon(Icons.add, key: iconKey),
241 242
          extendedIconLabelSpacing: iconLabelSpacing,
          extendedPadding: padding,
243
          extendedTextStyle: textStyle,
244 245 246 247
        ),
      ),
    ));

248 249 250
    expect(tester.getTopLeft(find.byKey(labelKey)).dx - tester.getTopRight(find.byKey(iconKey)).dx, iconLabelSpacing);
    expect(tester.getTopLeft(find.byKey(iconKey)).dx - tester.getTopLeft(find.byType(FloatingActionButton)).dx, padding.start);
    expect(tester.getTopRight(find.byType(FloatingActionButton)).dx - tester.getTopRight(find.byKey(labelKey)).dx, padding.end);
251 252
    // The color comes from the default color scheme's onSecondary value.
    expect(_getRawMaterialButton(tester).textStyle, textStyle.copyWith(color: const Color(0xffffffff)));
253 254
  });

255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
  testWidgets('default FloatingActionButton debugFillProperties', (WidgetTester tester) async {
    final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
    const FloatingActionButtonThemeData ().debugFillProperties(builder);

    final List<String> description = builder.properties
      .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
      .map((DiagnosticsNode node) => node.toString())
      .toList();

    expect(description, <String>[]);
  });

  testWidgets('Material implements debugFillProperties', (WidgetTester tester) async {
    final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
    const FloatingActionButtonThemeData(
      foregroundColor: Color(0xFEEDFEED),
271 272 273 274
      backgroundColor: Color(0xCAFECAFE),
      focusColor: Color(0xFEEDFEE1),
      hoverColor: Color(0xFEEDFEE2),
      splashColor: Color(0xFEEDFEE3),
275
      elevation: 23,
276 277
      focusElevation: 9,
      hoverElevation: 10,
278 279 280
      disabledElevation: 11,
      highlightElevation: 43,
      shape: BeveledRectangleBorder(),
281
      enableFeedback: true,
282
      iconSize: 42,
283 284 285 286 287
      sizeConstraints: BoxConstraints.tightFor(width: 100.0, height: 100.0),
      smallSizeConstraints: BoxConstraints.tightFor(width: 101.0, height: 101.0),
      largeSizeConstraints: BoxConstraints.tightFor(width: 102.0, height: 102.0),
      extendedSizeConstraints: BoxConstraints(minHeight: 103.0, maxHeight: 103.0),
      extendedIconLabelSpacing: 12,
288
      extendedPadding: EdgeInsetsDirectional.only(start: 7.0, end: 8.0),
289
      extendedTextStyle: TextStyle(letterSpacing: 2.0),
290 291 292 293 294 295 296 297 298
    ).debugFillProperties(builder);

    final List<String> description = builder.properties
      .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
      .map((DiagnosticsNode node) => node.toString())
      .toList();

    expect(description, <String>[
      'foregroundColor: Color(0xfeedfeed)',
299
      'backgroundColor: Color(0xcafecafe)',
300 301 302
      'focusColor: Color(0xfeedfee1)',
      'hoverColor: Color(0xfeedfee2)',
      'splashColor: Color(0xfeedfee3)',
303
      'elevation: 23.0',
304 305
      'focusElevation: 9.0',
      'hoverElevation: 10.0',
306 307 308
      'disabledElevation: 11.0',
      'highlightElevation: 43.0',
      'shape: BeveledRectangleBorder(BorderSide(Color(0xff000000), 0.0, BorderStyle.none), BorderRadius.zero)',
309
      'enableFeedback: true',
310
      'iconSize: 42.0',
311 312 313 314
      'sizeConstraints: BoxConstraints(w=100.0, h=100.0)',
      'smallSizeConstraints: BoxConstraints(w=101.0, h=101.0)',
      'largeSizeConstraints: BoxConstraints(w=102.0, h=102.0)',
      'extendedSizeConstraints: BoxConstraints(0.0<=w<=Infinity, h=103.0)',
315 316
      'extendedIconLabelSpacing: 12.0',
      'extendedPadding: EdgeInsetsDirectional(7.0, 0.0, 8.0, 0.0)',
317
      'extendedTextStyle: TextStyle(inherit: true, letterSpacing: 2.0)',
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
    ]);
  });
}

RawMaterialButton _getRawMaterialButton(WidgetTester tester) {
  return tester.widget<RawMaterialButton>(
    find.descendant(
      of: find.byType(FloatingActionButton),
      matching: find.byType(RawMaterialButton),
    ),
  );
}

RichText _getRichText(WidgetTester tester) {
  return tester.widget<RichText>(
    find.descendant(
      of: find.byType(FloatingActionButton),
      matching: find.byType(RichText),
    ),
  );
}
339 340 341 342 343 344 345 346 347 348 349 350

SizedBox _getIconSize(WidgetTester tester) {
  return tester.widget<SizedBox>(
    find.descendant(
      of: find.descendant(
        of: find.byType(FloatingActionButton),
        matching: find.byType(Icon),
      ),
      matching: find.byType(SizedBox),
    ),
  );
}