page_selector_test.dart 10.3 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5
// 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';
6
import 'package:flutter_test/flutter_test.dart';
7

8
const Color kSelectedColor = Color(0xFF00FF00);
9
const Color kUnselectedColor = Colors.transparent;
10

11
Widget buildFrame(TabController tabController, { Color? color, Color? selectedColor, double indicatorSize = 12.0, BorderStyle? borderStyle }) {
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
  return Localizations(
    locale: const Locale('en', 'US'),
    delegates: const <LocalizationsDelegate<dynamic>>[
      DefaultMaterialLocalizations.delegate,
      DefaultWidgetsLocalizations.delegate,
    ],
    child: Directionality(
      textDirection: TextDirection.ltr,
      child: Theme(
        data: ThemeData(colorScheme: const ColorScheme.light().copyWith(secondary: kSelectedColor)),
        child: SizedBox.expand(
          child: Center(
            child: SizedBox(
              width: 400.0,
              height: 400.0,
              child: Column(
                children: <Widget>[
                  TabPageSelector(
30
                    controller: tabController,
31 32 33
                    color: color,
                    selectedColor: selectedColor,
                    indicatorSize: indicatorSize,
34
                    borderStyle: borderStyle,
35
                  ),
36 37 38 39 40 41 42 43 44 45 46 47
                  Flexible(
                    child: TabBarView(
                      controller: tabController,
                      children: const <Widget>[
                        Center(child: Text('0')),
                        Center(child: Text('1')),
                        Center(child: Text('2')),
                      ],
                    ),
                  ),
                ],
              ),
48
            ),
49 50 51 52 53 54 55 56 57 58 59
          ),
        ),
      ),
    ),
  );
}

List<Color> indicatorColors(WidgetTester tester) {
  final Iterable<TabPageSelectorIndicator> indicators = tester.widgetList(
    find.descendant(
      of: find.byType(TabPageSelector),
60
      matching: find.byType(TabPageSelectorIndicator),
61
    ),
62
  );
63
  return indicators.map<Color>((TabPageSelectorIndicator indicator) => indicator.backgroundColor).toList();
64 65 66 67
}

void main() {
  testWidgets('PageSelector responds correctly to setting the TabController index', (WidgetTester tester) async {
68
    final TabController tabController = TabController(
69 70 71 72 73 74
      vsync: const TestVSync(),
      length: 3,
    );
    await tester.pumpWidget(buildFrame(tabController));

    expect(tabController.index, 0);
75
    expect(indicatorColors(tester), const <Color>[kSelectedColor, kUnselectedColor, kUnselectedColor]);
76 77 78 79

    tabController.index = 1;
    await tester.pump();
    expect(tabController.index, 1);
80
    expect(indicatorColors(tester), const <Color>[kUnselectedColor, kSelectedColor, kUnselectedColor]);
81 82 83 84

    tabController.index = 2;
    await tester.pump();
    expect(tabController.index, 2);
85
    expect(indicatorColors(tester), const <Color>[kUnselectedColor, kUnselectedColor, kSelectedColor]);
86 87 88
  });

  testWidgets('PageSelector responds correctly to TabController.animateTo()', (WidgetTester tester) async {
89
    final TabController tabController = TabController(
90 91 92 93 94 95
      vsync: const TestVSync(),
      length: 3,
    );
    await tester.pumpWidget(buildFrame(tabController));

    expect(tabController.index, 0);
96
    expect(indicatorColors(tester), const <Color>[kSelectedColor, kUnselectedColor, kUnselectedColor]);
97 98 99 100

    tabController.animateTo(1, duration: const Duration(milliseconds: 200));
    await tester.pump();
    // Verify that indicator 0's color is becoming increasingly transparent,
101
    // and indicator 1's color is becoming increasingly opaque during the
102 103 104 105
    // 200ms animation. Indicator 2 remains transparent throughout.
    await tester.pump(const Duration(milliseconds: 10));
    List<Color> colors = indicatorColors(tester);
    expect(colors[0].alpha, greaterThan(colors[1].alpha));
106
    expect(colors[2], kUnselectedColor);
107 108 109
    await tester.pump(const Duration(milliseconds: 175));
    colors = indicatorColors(tester);
    expect(colors[0].alpha, lessThan(colors[1].alpha));
110
    expect(colors[2], kUnselectedColor);
111 112
    await tester.pumpAndSettle();
    expect(tabController.index, 1);
113
    expect(indicatorColors(tester), const <Color>[kUnselectedColor, kSelectedColor, kUnselectedColor]);
114 115 116 117 118 119 120

    tabController.animateTo(2, duration: const Duration(milliseconds: 200));
    await tester.pump();
    // Same animation test as above for indicators 1 and 2.
    await tester.pump(const Duration(milliseconds: 10));
    colors = indicatorColors(tester);
    expect(colors[1].alpha, greaterThan(colors[2].alpha));
121
    expect(colors[0], kUnselectedColor);
122 123 124
    await tester.pump(const Duration(milliseconds: 175));
    colors = indicatorColors(tester);
    expect(colors[1].alpha, lessThan(colors[2].alpha));
125
    expect(colors[0], kUnselectedColor);
126 127
    await tester.pumpAndSettle();
    expect(tabController.index, 2);
128
    expect(indicatorColors(tester), const <Color>[kUnselectedColor, kUnselectedColor, kSelectedColor]);
129 130 131
  });

  testWidgets('PageSelector responds correctly to TabBarView drags', (WidgetTester tester) async {
132
    final TabController tabController = TabController(
133 134 135 136 137 138 139
      vsync: const TestVSync(),
      initialIndex: 1,
      length: 3,
    );
    await tester.pumpWidget(buildFrame(tabController));

    expect(tabController.index, 1);
140
    expect(indicatorColors(tester), const <Color>[kUnselectedColor, kSelectedColor, kUnselectedColor]);
141 142 143 144 145 146 147 148 149

    final TestGesture gesture = await tester.startGesture(const Offset(200.0, 200.0));

    // Drag to the left moving the selection towards indicator 2. Indicator 2's
    // opacity should increase and Indicator 1's opacity should decrease.
    await gesture.moveBy(const Offset(-100.0, 0.0));
    await tester.pumpAndSettle();
    List<Color> colors = indicatorColors(tester);
    expect(colors[1].alpha, greaterThan(colors[2].alpha));
150
    expect(colors[0], kUnselectedColor);
151 152 153 154 155

    // Drag back to where we started.
    await gesture.moveBy(const Offset(100.0, 0.0));
    await tester.pumpAndSettle();
    colors = indicatorColors(tester);
156
    expect(indicatorColors(tester), const <Color>[kUnselectedColor, kSelectedColor, kUnselectedColor]);
157 158 159 160 161 162 163

    // Drag to the left moving the selection towards indicator 0. Indicator 0's
    // opacity should increase and Indicator 1's opacity should decrease.
    await gesture.moveBy(const Offset(100.0, 0.0));
    await tester.pumpAndSettle();
    colors = indicatorColors(tester);
    expect(colors[1].alpha, greaterThan(colors[0].alpha));
164
    expect(colors[2], kUnselectedColor);
165 166 167 168 169

    // Drag back to where we started.
    await gesture.moveBy(const Offset(-100.0, 0.0));
    await tester.pumpAndSettle();
    colors = indicatorColors(tester);
170
    expect(indicatorColors(tester), const <Color>[kUnselectedColor, kSelectedColor, kUnselectedColor]);
171 172 173 174 175

    // Completing the gesture doesn't change anything
    await gesture.up();
    await tester.pumpAndSettle();
    colors = indicatorColors(tester);
176
    expect(indicatorColors(tester), const <Color>[kUnselectedColor, kSelectedColor, kUnselectedColor]);
177 178 179 180

    // Fling to the left, selects indicator 2
    await tester.fling(find.byType(TabBarView), const Offset(-100.0, 0.0), 1000.0);
    await tester.pumpAndSettle();
181
    expect(indicatorColors(tester), const <Color>[kUnselectedColor, kUnselectedColor, kSelectedColor]);
182 183 184 185

    // Fling to the right, selects indicator 1
    await tester.fling(find.byType(TabBarView), const Offset(100.0, 0.0), 1000.0);
    await tester.pumpAndSettle();
186 187 188 189 190
    expect(indicatorColors(tester), const <Color>[kUnselectedColor, kSelectedColor, kUnselectedColor]);

  });

  testWidgets('PageSelector indicatorColors', (WidgetTester tester) async {
191 192
    const Color kRed = Color(0xFFFF0000);
    const Color kBlue = Color(0xFF0000FF);
193

194
    final TabController tabController = TabController(
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
      vsync: const TestVSync(),
      initialIndex: 1,
      length: 3,
    );
    await tester.pumpWidget(buildFrame(tabController, color: kRed, selectedColor: kBlue));

    expect(tabController.index, 1);
    expect(indicatorColors(tester), const <Color>[kRed, kBlue, kRed]);

    tabController.index = 0;
    await tester.pumpAndSettle();
    expect(indicatorColors(tester), const <Color>[kBlue, kRed, kRed]);
  });

  testWidgets('PageSelector indicatorSize', (WidgetTester tester) async {
210
    final TabController tabController = TabController(
211 212 213 214 215 216 217 218 219 220 221 222
      vsync: const TestVSync(),
      initialIndex: 1,
      length: 3,
    );
    await tester.pumpWidget(buildFrame(tabController, indicatorSize: 16.0));

    final Iterable<Element> indicatorElements = find.descendant(
      of: find.byType(TabPageSelector),
      matching: find.byType(TabPageSelectorIndicator),
    ).evaluate();

    // Indicators get an 8 pixel margin, 16 + 8 = 24.
223
    for (final Element indicatorElement in indicatorElements) {
224
      expect(indicatorElement.size, const Size(24.0, 24.0));
225
    }
226

227
    expect(tester.getSize(find.byType(TabPageSelector)).height, 24.0);
228 229
  });

230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
    testWidgets('PageSelector circle border', (WidgetTester tester) async {
    final TabController tabController = TabController(
      vsync: const TestVSync(),
      initialIndex: 1,
      length: 3,
    );

    Iterable<TabPageSelectorIndicator> indicators;

    // Default border
    await tester.pumpWidget(buildFrame(tabController));
    indicators = tester.widgetList(
      find.descendant(
        of: find.byType(TabPageSelector),
        matching: find.byType(TabPageSelectorIndicator),
      ),
    );
247
    for (final TabPageSelectorIndicator indicator in indicators) {
248
      expect(indicator.borderStyle, BorderStyle.solid);
249
    }
250 251 252 253 254 255 256 257 258

    // No border
    await tester.pumpWidget(buildFrame(tabController, borderStyle: BorderStyle.none));
    indicators = tester.widgetList(
      find.descendant(
        of: find.byType(TabPageSelector),
        matching: find.byType(TabPageSelectorIndicator),
      ),
    );
259
    for (final TabPageSelectorIndicator indicator in indicators) {
260
      expect(indicator.borderStyle, BorderStyle.none);
261
    }
262 263 264 265 266 267 268 269 270

    // Solid border
    await tester.pumpWidget(buildFrame(tabController, borderStyle: BorderStyle.solid));
    indicators = tester.widgetList(
      find.descendant(
        of: find.byType(TabPageSelector),
        matching: find.byType(TabPageSelectorIndicator),
      ),
    );
271
    for (final TabPageSelectorIndicator indicator in indicators) {
272
      expect(indicator.borderStyle, BorderStyle.solid);
273
    }
274
  });
275
}