button_test.dart 6.3 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 'dart:ui' show SemanticsFlag;
6 7

import 'package:flutter/rendering.dart';
8 9 10 11
import 'package:flutter/cupertino.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_test/flutter_test.dart';

12 13
import '../widgets/semantics_tester.dart';

14 15 16 17 18
const TextStyle testStyle = const TextStyle(
  fontFamily: 'Ahem',
  fontSize: 10.0,
);

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

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

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

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

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

  testWidgets('Button takes taps', (WidgetTester tester) async {
    bool value = false;
    await tester.pumpWidget(
      new StatefulBuilder(
        builder: (BuildContext context, StateSetter setState) {
Ian Hickson's avatar
Ian Hickson committed
99
          return boilerplate(
100
            child: new CupertinoButton(
101
              child: const Text('Tap me'),
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
              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
123
    await tester.pumpWidget(boilerplate(child: const CupertinoButton(
124
      child: const Text('Tap me'),
125 126 127 128 129 130 131
      onPressed: null,
    )));
    expect(SchedulerBinding.instance.transientCallbackCount, equals(0));
    await tester.tap(find.byType(CupertinoButton));
    // Still doesn't animate.
    expect(SchedulerBinding.instance.transientCallbackCount, equals(0));
  });
132 133

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

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

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

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

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

    // Check opacity
166
    final FadeTransition opacity = tester.widget(find.descendant(
167
      of: find.byType(CupertinoButton),
168
      matching: find.byType(FadeTransition),
169
    ));
170
    expect(opacity.opacity.value, pressedOpacity);
171
  });
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191

  testWidgets('Cupertino button is semantically a button', (WidgetTester tester) async {
    final SemanticsTester semantics = new SemanticsTester(tester);
    await tester.pumpWidget(
      boilerplate(
          child: new Center(
            child: new CupertinoButton(
              onPressed: () { },
              child: const Text('ABC')
            ),
          ),
      ),
    );

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

    semantics.dispose();
  });
203
}
Ian Hickson's avatar
Ian Hickson committed
204 205 206 207 208 209

Widget boilerplate({ Widget child }) {
  return new Directionality(
    textDirection: TextDirection.ltr,
    child: new Center(child: child),
  );
210
}