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

5
import 'package:flutter/rendering.dart';
6 7 8 9
import 'package:flutter/cupertino.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_test/flutter_test.dart';

10 11
import '../widgets/semantics_tester.dart';

12
const TextStyle testStyle = TextStyle(
13 14
  fontFamily: 'Ahem',
  fontSize: 10.0,
xster's avatar
xster committed
15
  letterSpacing: 0.0,
16 17
);

18
void main() {
19
  testWidgets('Default layout minimum size', (WidgetTester tester) async {
20
    await tester.pumpWidget(
Ian Hickson's avatar
Ian Hickson committed
21
      boilerplate(child: const CupertinoButton(
22
        child: Text('X', style: testStyle),
23
        onPressed: null,
24
      )),
25
    );
26
    final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton));
27 28
    expect(
      buttonBox.size,
29 30 31 32 33 34
      // 1 10px character + 16px * 2 is smaller than the default 44px minimum.
      const Size.square(44.0),
    );
  });

  testWidgets('Minimum size parameter', (WidgetTester tester) async {
35
    const double minSize = 60.0;
36
    await tester.pumpWidget(
37
      boilerplate(child: const CupertinoButton(
38
        child: Text('X', style: testStyle),
39 40
        onPressed: null,
        minSize: minSize,
41
      )),
42 43 44 45 46
    );
    final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton));
    expect(
      buttonBox.size,
      // 1 10px character + 16px * 2 is smaller than defined 60.0px minimum
47
      const Size.square(minSize),
48 49 50 51 52
    );
  });

  testWidgets('Size grows with text', (WidgetTester tester) async {
    await tester.pumpWidget(
Ian Hickson's avatar
Ian Hickson committed
53
      boilerplate(child: const CupertinoButton(
54
        child: Text('XXXX', style: testStyle),
55
        onPressed: null,
56
      )),
57
    );
58
    final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton));
59 60
    expect(
      buttonBox.size.width,
61 62
      // 4 10px character + 16px * 2 = 72.
      72.0,
63 64 65 66
    );
  });

  testWidgets('Button with background is wider', (WidgetTester tester) async {
Ian Hickson's avatar
Ian Hickson committed
67
    await tester.pumpWidget(boilerplate(child: const CupertinoButton(
68
      child: Text('X', style: testStyle),
69
      onPressed: null,
70
      color: Color(0xFFFFFFFF),
71
    )));
72
    final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton));
73 74
    expect(
      buttonBox.size.width,
75 76
      // 1 10px character + 64 * 2 = 138 for buttons with background.
      138.0,
77 78 79 80
    );
  });

  testWidgets('Custom padding', (WidgetTester tester) async {
Ian Hickson's avatar
Ian Hickson committed
81
    await tester.pumpWidget(boilerplate(child: const CupertinoButton(
82
      child: Text('X', style: testStyle),
83
      onPressed: null,
84
      padding: EdgeInsets.all(100.0),
85
    )));
86
    final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton));
87 88
    expect(
      buttonBox.size,
89
      const Size.square(210.0),
90 91 92 93 94 95
    );
  });

  testWidgets('Button takes taps', (WidgetTester tester) async {
    bool value = false;
    await tester.pumpWidget(
96
      StatefulBuilder(
97
        builder: (BuildContext context, StateSetter setState) {
Ian Hickson's avatar
Ian Hickson committed
98
          return boilerplate(
99
            child: CupertinoButton(
100
              child: const Text('Tap me'),
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
              onPressed: () {
                setState(() {
                  value = true;
                });
              },
            ),
          );
        },
      ),
    );

    expect(value, isFalse);
    // No animating by default.
    expect(SchedulerBinding.instance.transientCallbackCount, equals(0));
    await tester.tap(find.byType(CupertinoButton));
    expect(value, isTrue);
    // Animates.
    expect(SchedulerBinding.instance.transientCallbackCount, equals(1));
  });

  testWidgets('Disabled button doesn\'t animate', (WidgetTester tester) async {
Ian Hickson's avatar
Ian Hickson committed
122
    await tester.pumpWidget(boilerplate(child: const CupertinoButton(
123
      child: Text('Tap me'),
124 125 126 127 128 129 130
      onPressed: null,
    )));
    expect(SchedulerBinding.instance.transientCallbackCount, equals(0));
    await tester.tap(find.byType(CupertinoButton));
    // Still doesn't animate.
    expect(SchedulerBinding.instance.transientCallbackCount, equals(0));
  });
131 132

  testWidgets('pressedOpacity defaults to 0.1', (WidgetTester tester) async {
133
    await tester.pumpWidget(boilerplate(child: CupertinoButton(
134
      child: const Text('Tap me'),
135 136 137 138
      onPressed: () { },
    )));

    // Keep a "down" gesture on the button
139
    final Offset center = tester.getCenter(find.byType(CupertinoButton));
140 141 142 143
    await tester.startGesture(center);
    await tester.pumpAndSettle();

    // Check opacity
144
    final FadeTransition opacity = tester.widget(find.descendant(
145
      of: find.byType(CupertinoButton),
146
      matching: find.byType(FadeTransition),
147
    ));
148
    expect(opacity.opacity.value, 0.1);
149 150 151
  });

  testWidgets('pressedOpacity parameter', (WidgetTester tester) async {
152
    const double pressedOpacity = 0.5;
153
    await tester.pumpWidget(boilerplate(child: CupertinoButton(
154
      pressedOpacity: pressedOpacity,
155
      child: const Text('Tap me'),
156 157 158 159
      onPressed: () { },
    )));

    // Keep a "down" gesture on the button
160
    final Offset center = tester.getCenter(find.byType(CupertinoButton));
161 162 163 164
    await tester.startGesture(center);
    await tester.pumpAndSettle();

    // Check opacity
165
    final FadeTransition opacity = tester.widget(find.descendant(
166
      of: find.byType(CupertinoButton),
167
      matching: find.byType(FadeTransition),
168
    ));
169
    expect(opacity.opacity.value, pressedOpacity);
170
  });
171 172

  testWidgets('Cupertino button is semantically a button', (WidgetTester tester) async {
173
    final SemanticsTester semantics = SemanticsTester(tester);
174 175
    await tester.pumpWidget(
      boilerplate(
176 177
          child: Center(
            child: CupertinoButton(
178
              onPressed: () { },
179
              child: const Text('ABC'),
180 181 182 183 184 185
            ),
          ),
      ),
    );

    expect(semantics, hasSemantics(
186
      TestSemantics.root(
187
        children: <TestSemantics>[
188
          TestSemantics.rootChild(
189 190
            actions: SemanticsAction.tap.index,
            label: 'ABC',
191
            flags: SemanticsFlag.isButton.index,
192
          ),
193 194 195 196 197 198 199 200 201
        ],
      ),
      ignoreId: true,
      ignoreRect: true,
      ignoreTransform: true,
    ));

    semantics.dispose();
  });
202 203

  testWidgets('Can specify colors', (WidgetTester tester) async {
204
    await tester.pumpWidget(boilerplate(child: CupertinoButton(
205
      child: const Text('Skeuomorph me'),
206 207
      color: const Color(0x000000FF),
      disabledColor: const Color(0x0000FF00),
208 209 210 211 212 213 214
      onPressed: () { },
    )));

    BoxDecoration boxDecoration = tester.widget<DecoratedBox>(
        find.widgetWithText(DecoratedBox, 'Skeuomorph me')
      ).decoration;

215
    expect(boxDecoration.color, const Color(0x000000FF));
216 217

    await tester.pumpWidget(boilerplate(child: const CupertinoButton(
218
      child: Text('Skeuomorph me'),
219 220
      color: Color(0x000000FF),
      disabledColor: Color(0x0000FF00),
221 222 223 224 225 226 227
      onPressed: null,
    )));

    boxDecoration = tester.widget<DecoratedBox>(
        find.widgetWithText(DecoratedBox, 'Skeuomorph me')
      ).decoration;

228
    expect(boxDecoration.color, const Color(0x0000FF00));
229
  });
xster's avatar
xster committed
230

231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
  testWidgets('Can specify dynamic colors', (WidgetTester tester) async {
    const Color bgColor = CupertinoDynamicColor.withBrightness(
      color: Color(0xFF123456),
      darkColor: Color(0xFF654321),
    );

    const Color inactive = CupertinoDynamicColor.withBrightness(
      color: Color(0xFF111111),
      darkColor: Color(0xFF222222),
    );

    await tester.pumpWidget(
      MediaQuery(
        data: const MediaQueryData(platformBrightness: Brightness.dark),
        child: boilerplate(child: CupertinoButton(
          child: const Text('Skeuomorph me'),
          color: bgColor,
          disabledColor: inactive,
          onPressed: () { },
250
        )),
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
      ),
    );

    BoxDecoration boxDecoration = tester.widget<DecoratedBox>(
      find.widgetWithText(DecoratedBox, 'Skeuomorph me')
    ).decoration;

    expect(boxDecoration.color.value, 0xFF654321);

    await tester.pumpWidget(
      MediaQuery(
        data: const MediaQueryData(platformBrightness: Brightness.light),
        child: boilerplate(child: const CupertinoButton(
          child: Text('Skeuomorph me'),
          color: bgColor,
          disabledColor: inactive,
          onPressed: null,
268
        )),
269 270 271 272 273 274 275 276 277 278 279
      ),
    );

    boxDecoration = tester.widget<DecoratedBox>(
      find.widgetWithText(DecoratedBox, 'Skeuomorph me')
    ).decoration;

    // Disabled color.
    expect(boxDecoration.color.value, 0xFF111111);
  });

280
  testWidgets('Button respects themes', (WidgetTester tester) async {
xster's avatar
xster committed
281 282 283 284 285
    TextStyle textStyle;

    await tester.pumpWidget(
      CupertinoApp(
        home: CupertinoButton(
286
          onPressed: () { },
xster's avatar
xster committed
287 288 289 290 291 292 293 294 295 296 297 298 299
          child: Builder(builder: (BuildContext context) {
            textStyle = DefaultTextStyle.of(context).style;
            return const Placeholder();
          }),
        ),
      ),
    );

    expect(textStyle.color, CupertinoColors.activeBlue);

    await tester.pumpWidget(
      CupertinoApp(
        home: CupertinoButton.filled(
300
          onPressed: () { },
xster's avatar
xster committed
301 302 303 304 305 306 307 308 309 310 311 312
          child: Builder(builder: (BuildContext context) {
            textStyle = DefaultTextStyle.of(context).style;
            return const Placeholder();
          }),
        ),
      ),
    );

    expect(textStyle.color, CupertinoColors.white);
    BoxDecoration decoration = tester.widget<DecoratedBox>(
      find.descendant(
        of: find.byType(CupertinoButton),
313
        matching: find.byType(DecoratedBox),
314
      ),
xster's avatar
xster committed
315 316 317 318 319 320 321
    ).decoration;
    expect(decoration.color, CupertinoColors.activeBlue);

    await tester.pumpWidget(
      CupertinoApp(
        theme: const CupertinoThemeData(brightness: Brightness.dark),
        home: CupertinoButton(
322
          onPressed: () { },
xster's avatar
xster committed
323 324 325 326 327 328 329
          child: Builder(builder: (BuildContext context) {
            textStyle = DefaultTextStyle.of(context).style;
            return const Placeholder();
          }),
        ),
      ),
    );
330
    expect(textStyle.color.value, CupertinoColors.activeOrange.darkColor.value);
xster's avatar
xster committed
331 332 333 334 335

    await tester.pumpWidget(
      CupertinoApp(
        theme: const CupertinoThemeData(brightness: Brightness.dark),
        home: CupertinoButton.filled(
336
          onPressed: () { },
xster's avatar
xster committed
337 338 339 340 341 342 343 344 345 346 347
          child: Builder(builder: (BuildContext context) {
            textStyle = DefaultTextStyle.of(context).style;
            return const Placeholder();
          }),
        ),
      ),
    );
    expect(textStyle.color, CupertinoColors.black);
    decoration = tester.widget<DecoratedBox>(
      find.descendant(
        of: find.byType(CupertinoButton),
348
        matching: find.byType(DecoratedBox),
349
      ),
xster's avatar
xster committed
350
    ).decoration;
351
    expect(decoration.color.value, CupertinoColors.activeOrange.darkColor.value);
xster's avatar
xster committed
352
  });
353
}
Ian Hickson's avatar
Ian Hickson committed
354 355

Widget boilerplate({ Widget child }) {
356
  return Directionality(
Ian Hickson's avatar
Ian Hickson committed
357
    textDirection: TextDirection.ltr,
358
    child: Center(child: child),
Ian Hickson's avatar
Ian Hickson committed
359
  );
360
}