refresh_indicator_test.dart 12.3 KB
Newer Older
1 2 3 4 5 6 7 8 9
// Copyright 2015 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.

import 'dart:async';

import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';

10
bool refreshCalled = false;
11

12 13 14 15
Future<Null> refresh() {
  refreshCalled = true;
  return new Future<Null>.value();
}
16

17 18 19 20 21 22
Future<Null> holdRefresh() {
  refreshCalled = true;
  return new Completer<Null>().future;
}

void main() {
23
  testWidgets('RefreshIndicator', (WidgetTester tester) async {
24
    refreshCalled = false;
25
    await tester.pumpWidget(
Ian Hickson's avatar
Ian Hickson committed
26 27
      new MaterialApp(
        home: new RefreshIndicator(
28 29 30 31 32 33 34 35 36 37
          onRefresh: refresh,
          child: new ListView(
            physics: const AlwaysScrollableScrollPhysics(),
            children: <String>['A', 'B', 'C', 'D', 'E', 'F'].map((String item) {
              return new SizedBox(
                height: 200.0,
                child: new Text(item),
              );
            }).toList(),
          ),
38 39
        ),
      ),
40
    );
41

42
    await tester.fling(find.text('A'), const Offset(0.0, 300.0), 1000.0);
43 44 45 46
    await tester.pump();
    await tester.pump(const Duration(seconds: 1)); // finish the scroll animation
    await tester.pump(const Duration(seconds: 1)); // finish the indicator settle animation
    await tester.pump(const Duration(seconds: 1)); // finish the indicator hide animation
47
    expect(refreshCalled, true);
48
  });
49

50 51 52 53 54 55 56 57 58 59 60
  testWidgets('Refresh Indicator - nested', (WidgetTester tester) async {
    refreshCalled = false;
    await tester.pumpWidget(
      new MaterialApp(
        home: new RefreshIndicator(
          notificationPredicate: (ScrollNotification notification) => notification.depth == 1,
          onRefresh: refresh,
          child: new SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: new Container(
              width: 600.0,
61
              child: new ListView(
62 63 64 65 66 67 68 69 70 71 72 73 74
                physics: const AlwaysScrollableScrollPhysics(),
                children: <String>['A', 'B', 'C', 'D', 'E', 'F'].map((String item) {
                  return new SizedBox(
                    height: 200.0,
                    child: new Text(item),
                  );
                }).toList(),
              ),
            ),
          ),
        ),
      ),
    );
75

76 77 78 79 80
    await tester.fling(find.text('A'), const Offset(300.0, 0.0), 1000.0); // horizontal fling
    await tester.pump();
    await tester.pump(const Duration(seconds: 1)); // finish the scroll animation
    await tester.pump(const Duration(seconds: 1)); // finish the indicator settle animation
    await tester.pump(const Duration(seconds: 1)); // finish the indicator hide animation
81 82
    expect(refreshCalled, false);

83 84 85 86 87 88

    await tester.fling(find.text('A'), const Offset(0.0, 300.0), 1000.0); // vertical fling
    await tester.pump();
    await tester.pump(const Duration(seconds: 1)); // finish the scroll animation
    await tester.pump(const Duration(seconds: 1)); // finish the indicator settle animation
    await tester.pump(const Duration(seconds: 1)); // finish the indicator hide animation
89
    expect(refreshCalled, true);
90
  });
91 92 93 94

  testWidgets('RefreshIndicator - bottom', (WidgetTester tester) async {
    refreshCalled = false;
    await tester.pumpWidget(
Ian Hickson's avatar
Ian Hickson committed
95 96
      new MaterialApp(
        home: new RefreshIndicator(
97 98 99 100
          onRefresh: refresh,
          child: new ListView(
            reverse: true,
            physics: const AlwaysScrollableScrollPhysics(),
101
            children: const <Widget>[
102 103 104 105 106 107
              const SizedBox(
                height: 200.0,
                child: const Text('X'),
              ),
            ],
          ),
108 109 110 111 112 113 114 115 116 117 118 119
        ),
      ),
    );

    await tester.fling(find.text('X'), const Offset(0.0, -300.0), 1000.0);
    await tester.pump();
    await tester.pump(const Duration(seconds: 1)); // finish the scroll animation
    await tester.pump(const Duration(seconds: 1)); // finish the indicator settle animation
    await tester.pump(const Duration(seconds: 1)); // finish the indicator hide animation
    expect(refreshCalled, true);
  });

120 121 122
  testWidgets('RefreshIndicator - top - position', (WidgetTester tester) async {
    refreshCalled = false;
    await tester.pumpWidget(
Ian Hickson's avatar
Ian Hickson committed
123 124
      new MaterialApp(
        home: new RefreshIndicator(
125 126 127
          onRefresh: holdRefresh,
          child: new ListView(
            physics: const AlwaysScrollableScrollPhysics(),
128
            children: const <Widget>[
129 130 131 132 133 134
              const SizedBox(
                height: 200.0,
                child: const Text('X'),
              ),
            ],
          ),
135 136 137 138
        ),
      ),
    );

139
    await tester.fling(find.text('X'), const Offset(0.0, 300.0), 1000.0);
140 141 142
    await tester.pump();
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
143
    expect(tester.getCenter(find.byType(RefreshProgressIndicator)).dy, lessThan(300.0));
144 145 146 147 148
  });

  testWidgets('RefreshIndicator - bottom - position', (WidgetTester tester) async {
    refreshCalled = false;
    await tester.pumpWidget(
Ian Hickson's avatar
Ian Hickson committed
149 150
      new MaterialApp(
        home: new RefreshIndicator(
151 152 153 154
          onRefresh: holdRefresh,
          child: new ListView(
            reverse: true,
            physics: const AlwaysScrollableScrollPhysics(),
155
            children: const <Widget>[
156 157 158 159 160 161
              const SizedBox(
                height: 200.0,
                child: const Text('X'),
              ),
            ],
          ),
162 163 164 165 166 167 168 169
        ),
      ),
    );

    await tester.fling(find.text('X'), const Offset(0.0, -300.0), 1000.0);
    await tester.pump();
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
170
    expect(tester.getCenter(find.byType(RefreshProgressIndicator)).dy, greaterThan(300.0));
171 172 173 174 175
  });

  testWidgets('RefreshIndicator - no movement', (WidgetTester tester) async {
    refreshCalled = false;
    await tester.pumpWidget(
Ian Hickson's avatar
Ian Hickson committed
176 177
      new MaterialApp(
        home: new RefreshIndicator(
178 179 180
          onRefresh: refresh,
          child: new ListView(
            physics: const AlwaysScrollableScrollPhysics(),
181
            children: const <Widget>[
182 183 184 185 186 187
              const SizedBox(
                height: 200.0,
                child: const Text('X'),
              ),
            ],
          ),
188 189 190 191 192 193 194 195 196 197 198 199 200
        ),
      ),
    );

    // this fling is horizontal, not up or down
    await tester.fling(find.text('X'), const Offset(1.0, 0.0), 1000.0);
    await tester.pump();
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    expect(refreshCalled, false);
  });

201 202 203
  testWidgets('RefreshIndicator - not enough', (WidgetTester tester) async {
    refreshCalled = false;
    await tester.pumpWidget(
Ian Hickson's avatar
Ian Hickson committed
204 205
      new MaterialApp(
        home: new RefreshIndicator(
206 207 208
          onRefresh: refresh,
          child: new ListView(
            physics: const AlwaysScrollableScrollPhysics(),
209
            children: const <Widget>[
210 211 212 213 214 215
              const SizedBox(
                height: 200.0,
                child: const Text('X'),
              ),
            ],
          ),
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
        ),
      ),
    );

    await tester.fling(find.text('X'), const Offset(0.0, 100.0), 1000.0);
    await tester.pump();
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    expect(refreshCalled, false);
  });

  testWidgets('RefreshIndicator - show - slow', (WidgetTester tester) async {
    refreshCalled = false;
    await tester.pumpWidget(
Ian Hickson's avatar
Ian Hickson committed
231 232
      new MaterialApp(
        home: new RefreshIndicator(
233 234 235
          onRefresh: holdRefresh, // this one never returns
          child: new ListView(
            physics: const AlwaysScrollableScrollPhysics(),
236
            children: const <Widget>[
237 238 239 240 241 242
              const SizedBox(
                height: 200.0,
                child: const Text('X'),
              ),
            ],
          ),
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
        ),
      ),
    );

    bool completed = false;
    tester.state<RefreshIndicatorState>(find.byType(RefreshIndicator))
      .show()
      .then<Null>((Null value) { completed = true; });
    await tester.pump();
    expect(completed, false);
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    expect(refreshCalled, true);
    expect(completed, false);
    completed = false;
    refreshCalled = false;
    tester.state<RefreshIndicatorState>(find.byType(RefreshIndicator))
      .show()
      .then<Null>((Null value) { completed = true; });
    await tester.pump();
    expect(completed, false);
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    expect(refreshCalled, false);
  });

  testWidgets('RefreshIndicator - show - fast', (WidgetTester tester) async {
    refreshCalled = false;
    await tester.pumpWidget(
Ian Hickson's avatar
Ian Hickson committed
274 275
      new MaterialApp(
        home: new RefreshIndicator(
276 277 278
          onRefresh: refresh,
          child: new ListView(
            physics: const AlwaysScrollableScrollPhysics(),
279
            children: const <Widget>[
280 281 282 283 284 285
              const SizedBox(
                height: 200.0,
                child: const Text('X'),
              ),
            ],
          ),
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
        ),
      ),
    );

    bool completed = false;
    tester.state<RefreshIndicatorState>(find.byType(RefreshIndicator))
      .show()
      .then<Null>((Null value) { completed = true; });
    await tester.pump();
    expect(completed, false);
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    expect(refreshCalled, true);
    expect(completed, true);
    completed = false;
    refreshCalled = false;
    tester.state<RefreshIndicatorState>(find.byType(RefreshIndicator))
      .show()
      .then<Null>((Null value) { completed = true; });
    await tester.pump();
    expect(completed, false);
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    expect(refreshCalled, true);
    expect(completed, true);
  });

  testWidgets('RefreshIndicator - show - fast - twice', (WidgetTester tester) async {
    refreshCalled = false;
    await tester.pumpWidget(
Ian Hickson's avatar
Ian Hickson committed
318 319
      new MaterialApp(
        home: new RefreshIndicator(
320 321 322
          onRefresh: refresh,
          child: new ListView(
            physics: const AlwaysScrollableScrollPhysics(),
323
            children: const <Widget>[
324 325 326 327 328 329
              const SizedBox(
                height: 200.0,
                child: const Text('X'),
              ),
            ],
          ),
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
        ),
      ),
    );

    bool completed1 = false;
    tester.state<RefreshIndicatorState>(find.byType(RefreshIndicator))
      .show()
      .then<Null>((Null value) { completed1 = true; });
    bool completed2 = false;
    tester.state<RefreshIndicatorState>(find.byType(RefreshIndicator))
      .show()
      .then<Null>((Null value) { completed2 = true; });
    await tester.pump();
    expect(completed1, false);
    expect(completed2, false);
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    await tester.pump(const Duration(seconds: 1));
    expect(refreshCalled, true);
    expect(completed1, true);
    expect(completed2, true);
  });
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380

  testWidgets('RefreshIndicator - onRefresh asserts', (WidgetTester tester) async {
    refreshCalled = false;
    await tester.pumpWidget(
      new MaterialApp(
        home: new RefreshIndicator(
          onRefresh: () {
            refreshCalled = true;
            // Missing a returned Future value here.
          },
          child: new ListView(
            physics: const AlwaysScrollableScrollPhysics(),
            children: <String>['A', 'B', 'C', 'D', 'E', 'F'].map((String item) {
              return new SizedBox(
                height: 200.0,
                child: new Text(item),
              );
            }).toList(),
          ),
        ),
      ),
    );

    await tester.fling(find.text('A'), const Offset(0.0, 300.0), 1000.0);
    await tester.pump();
    await tester.pump(const Duration(seconds: 1)); // finish the scroll animation
    expect(refreshCalled, true);
    expect(tester.takeException(), isFlutterError);
  });
381
}