scroll_view_test.dart 13.9 KB
Newer Older
1 2 3 4 5 6 7
// 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.

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

8
import 'states.dart';
9 10

void main() {
11
  testWidgets('ListView control test', (WidgetTester tester) async {
12
    final List<String> log = <String>[];
13

14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
    await tester.pumpWidget(
      new Directionality(
        textDirection: TextDirection.ltr,
        child: new ListView(
          children: kStates.map<Widget>((String state) {
            return new GestureDetector(
              onTap: () {
                log.add(state);
              },
              child: new Container(
                height: 200.0,
                color: const Color(0xFF0000FF),
                child: new Text(state),
              ),
            );
          }).toList(),
        ),
      ),
    );
33 34 35 36 37 38 39

    await tester.tap(find.text('Alabama'));
    expect(log, equals(<String>['Alabama']));
    log.clear();

    expect(find.text('Nevada'), findsNothing);

40
    await tester.drag(find.text('Alabama'), const Offset(0.0, -4000.0));
41 42 43
    await tester.pump();

    expect(find.text('Alabama'), findsNothing);
44
    expect(tester.getCenter(find.text('Massachusetts')), equals(const Offset(400.0, 100.0)));
45 46 47 48 49

    await tester.tap(find.text('Massachusetts'));
    expect(log, equals(<String>['Massachusetts']));
    log.clear();
  });
50

51 52
  testWidgets('ListView restart ballistic activity out of range', (WidgetTester tester) async {
    Widget buildListView(int n) {
53 54 55 56 57 58 59 60 61 62 63
      return new Directionality(
        textDirection: TextDirection.ltr,
        child: new ListView(
          children: kStates.take(n).map<Widget>((String state) {
            return new Container(
              height: 200.0,
              color: const Color(0xFF0000FF),
              child: new Text(state),
            );
          }).toList(),
        ),
64 65 66
      );
    }

67 68 69
    await tester.pumpWidget(buildListView(30));
    await tester.fling(find.byType(ListView), const Offset(0.0, -4000.0), 4000.0);
    await tester.pumpWidget(buildListView(15));
70 71 72 73
    await tester.pump(const Duration(milliseconds: 10));
    await tester.pump(const Duration(milliseconds: 10));
    await tester.pump(const Duration(milliseconds: 10));
    await tester.pump(const Duration(milliseconds: 10));
74
    await tester.pumpAndSettle(const Duration(milliseconds: 100));
75

76
    final Viewport viewport = tester.widget(find.byType(Viewport));
77 78
    expect(viewport.offset.pixels, equals(2400.0));
  });
Adam Barth's avatar
Adam Barth committed
79 80

  testWidgets('CustomScrollView control test', (WidgetTester tester) async {
81
    final List<String> log = <String>[];
Adam Barth's avatar
Adam Barth committed
82

83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
    await tester.pumpWidget(
      new Directionality(
        textDirection: TextDirection.ltr,
        child: new CustomScrollView(
          slivers: <Widget>[
            new SliverList(
              delegate: new SliverChildListDelegate(
                kStates.map<Widget>((String state) {
                  return new GestureDetector(
                    onTap: () {
                      log.add(state);
                    },
                    child: new Container(
                      height: 200.0,
                      color: const Color(0xFF0000FF),
                      child: new Text(state),
                    ),
                  );
                }).toList(),
              ),
            ),
          ],
Adam Barth's avatar
Adam Barth committed
105
        ),
106 107
      ),
    );
Adam Barth's avatar
Adam Barth committed
108 109 110 111 112 113 114

    await tester.tap(find.text('Alabama'));
    expect(log, equals(<String>['Alabama']));
    log.clear();

    expect(find.text('Nevada'), findsNothing);

115
    await tester.drag(find.text('Alabama'), const Offset(0.0, -4000.0));
Adam Barth's avatar
Adam Barth committed
116 117 118
    await tester.pump();

    expect(find.text('Alabama'), findsNothing);
119
    expect(tester.getCenter(find.text('Massachusetts')), equals(const Offset(400.0, 100.0)));
Adam Barth's avatar
Adam Barth committed
120 121 122 123 124

    await tester.tap(find.text('Massachusetts'));
    expect(log, equals(<String>['Massachusetts']));
    log.clear();
  });
125 126 127 128 129

  testWidgets('Can jumpTo during drag', (WidgetTester tester) async {
    final List<Type> log = <Type>[];
    final ScrollController controller = new ScrollController();

130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
    await tester.pumpWidget(
      new Directionality(
        textDirection: TextDirection.ltr,
        child: new NotificationListener<ScrollNotification>(
          onNotification: (ScrollNotification notification) {
            log.add(notification.runtimeType);
            return false;
          },
          child: new ListView(
            controller: controller,
            children: kStates.map<Widget>((String state) {
              return new Container(
                height: 200.0,
                child: new Text(state),
              );
            }).toList(),
          ),
        ),
148
      ),
149
    );
150 151 152

    expect(log, isEmpty);

153
    final TestGesture gesture = await tester.startGesture(const Offset(100.0, 100.0));
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
    await gesture.moveBy(const Offset(0.0, -100.0));

    expect(log, equals(<Type>[
      ScrollStartNotification,
      UserScrollNotification,
      ScrollUpdateNotification,
    ]));
    log.clear();

    await tester.pump();

    controller.jumpTo(550.0);

    expect(controller.offset, equals(550.0));
    expect(log, equals(<Type>[
      ScrollEndNotification,
      UserScrollNotification,
      ScrollStartNotification,
      ScrollUpdateNotification,
      ScrollEndNotification,
    ]));
    log.clear();

    await tester.pump();
    await gesture.moveBy(const Offset(0.0, -100.0));

    expect(controller.offset, equals(550.0));
    expect(log, isEmpty);
  });
183

184
  testWidgets('Vertical CustomScrollViews are primary by default', (WidgetTester tester) async {
185
    final CustomScrollView view = new CustomScrollView(scrollDirection: Axis.vertical);
186 187 188 189
    expect(view.primary, isTrue);
  });

  testWidgets('Vertical ListViews are primary by default', (WidgetTester tester) async {
190
    final ListView view = new ListView(scrollDirection: Axis.vertical);
191 192 193 194
    expect(view.primary, isTrue);
  });

  testWidgets('Vertical GridViews are primary by default', (WidgetTester tester) async {
195
    final GridView view = new GridView.count(
196 197 198 199 200 201 202
      scrollDirection: Axis.vertical,
      crossAxisCount: 1,
    );
    expect(view.primary, isTrue);
  });

  testWidgets('Horizontal CustomScrollViews are non-primary by default', (WidgetTester tester) async {
203
    final CustomScrollView view = new CustomScrollView(scrollDirection: Axis.horizontal);
204 205 206 207
    expect(view.primary, isFalse);
  });

  testWidgets('Horizontal ListViews are non-primary by default', (WidgetTester tester) async {
208
    final ListView view = new ListView(scrollDirection: Axis.horizontal);
209 210 211 212
    expect(view.primary, isFalse);
  });

  testWidgets('Horizontal GridViews are non-primary by default', (WidgetTester tester) async {
213
    final GridView view = new GridView.count(
214 215 216 217 218 219 220
      scrollDirection: Axis.horizontal,
      crossAxisCount: 1,
    );
    expect(view.primary, isFalse);
  });

  testWidgets('CustomScrollViews with controllers are non-primary by default', (WidgetTester tester) async {
221
    final CustomScrollView view = new CustomScrollView(
222 223 224 225 226 227 228
      controller: new ScrollController(),
      scrollDirection: Axis.vertical,
    );
    expect(view.primary, isFalse);
  });

  testWidgets('ListViews with controllers are non-primary by default', (WidgetTester tester) async {
229
    final ListView view = new ListView(
230 231 232 233 234 235 236
      controller: new ScrollController(),
      scrollDirection: Axis.vertical,
    );
    expect(view.primary, isFalse);
  });

  testWidgets('GridViews with controllers are non-primary by default', (WidgetTester tester) async {
237
    final GridView view = new GridView.count(
238 239 240 241 242 243 244
      controller: new ScrollController(),
      scrollDirection: Axis.vertical,
      crossAxisCount: 1,
    );
    expect(view.primary, isFalse);
  });

245
  testWidgets('CustomScrollView sets PrimaryScrollController when primary', (WidgetTester tester) async {
246
    final ScrollController primaryScrollController = new ScrollController();
247 248 249 250 251 252 253 254 255
    await tester.pumpWidget(
      new Directionality(
        textDirection: TextDirection.ltr,
        child: new PrimaryScrollController(
          controller: primaryScrollController,
          child: new CustomScrollView(primary: true),
        ),
      ),
    );
256
    final Scrollable scrollable = tester.widget(find.byType(Scrollable));
257 258 259 260
    expect(scrollable.controller, primaryScrollController);
  });

  testWidgets('ListView sets PrimaryScrollController when primary', (WidgetTester tester) async {
261
    final ScrollController primaryScrollController = new ScrollController();
262 263 264 265 266 267 268 269 270
    await tester.pumpWidget(
      new Directionality(
        textDirection: TextDirection.ltr,
        child: new PrimaryScrollController(
          controller: primaryScrollController,
          child: new ListView(primary: true),
        ),
      ),
    );
271
    final Scrollable scrollable = tester.widget(find.byType(Scrollable));
272 273 274 275
    expect(scrollable.controller, primaryScrollController);
  });

  testWidgets('GridView sets PrimaryScrollController when primary', (WidgetTester tester) async {
276
    final ScrollController primaryScrollController = new ScrollController();
277 278 279 280 281 282 283 284 285
    await tester.pumpWidget(
      new Directionality(
        textDirection: TextDirection.ltr,
        child: new PrimaryScrollController(
          controller: primaryScrollController,
          child: new GridView.count(primary: true, crossAxisCount: 1),
        ),
      ),
    );
286
    final Scrollable scrollable = tester.widget(find.byType(Scrollable));
287 288
    expect(scrollable.controller, primaryScrollController);
  });
289 290 291

  testWidgets('Nested scrollables have a null PrimaryScrollController', (WidgetTester tester) async {
    const Key innerKey = const Key('inner');
292
    final ScrollController primaryScrollController = new ScrollController();
293 294 295 296 297 298 299 300 301 302 303 304 305
    await tester.pumpWidget(
      new Directionality(
        textDirection: TextDirection.ltr,
        child: new PrimaryScrollController(
          controller: primaryScrollController,
          child: new ListView(
            primary: true,
            children: <Widget>[
              new Container(
                constraints: const BoxConstraints(maxHeight: 200.0),
                child: new ListView(key: innerKey, primary: true),
              ),
            ],
306
          ),
307
        ),
308
      ),
309
    );
310

311
    final Scrollable innerScrollable = tester.widget(
312 313 314 315 316 317 318
      find.descendant(
        of: find.byKey(innerKey),
        matching: find.byType(Scrollable),
      ),
    );
    expect(innerScrollable.controller, isNull);
  });
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342

  testWidgets('Primary ListViews are always scrollable', (WidgetTester tester) async {
    final ListView view = new ListView(primary: true);
    expect(view.physics, const isInstanceOf<AlwaysScrollableScrollPhysics>());
  });

  testWidgets('Non-primary ListViews are not always scrollable', (WidgetTester tester) async {
    final ListView view = new ListView(primary: false);
    expect(view.physics, isNot(const isInstanceOf<AlwaysScrollableScrollPhysics>()));
  });

  testWidgets('Defaulting-to-primary ListViews are always scrollable', (WidgetTester tester) async {
    final ListView view = new ListView(scrollDirection: Axis.vertical);
    expect(view.physics, const isInstanceOf<AlwaysScrollableScrollPhysics>());
  });

  testWidgets('Defaulting-to-not-primary ListViews are not always scrollable', (WidgetTester tester) async {
    final ListView view = new ListView(scrollDirection: Axis.horizontal);
    expect(view.physics, isNot(const isInstanceOf<AlwaysScrollableScrollPhysics>()));
  });

  testWidgets('primary:true leads to scrolling', (WidgetTester tester) async {
    bool scrolled = false;
    await tester.pumpWidget(
343 344 345 346 347 348 349 350
      new Directionality(
        textDirection: TextDirection.ltr,
        child: new NotificationListener<OverscrollNotification>(
          onNotification: (OverscrollNotification message) { scrolled = true; return false; },
          child: new ListView(
            primary: true,
            children: <Widget>[],
          ),
351 352 353 354 355 356 357 358 359 360
        ),
      ),
    );
    await tester.dragFrom(const Offset(100.0, 100.0), const Offset(0.0, 100.0));
    expect(scrolled, isTrue);
  });

  testWidgets('primary:false leads to no scrolling', (WidgetTester tester) async {
    bool scrolled = false;
    await tester.pumpWidget(
361 362 363 364 365 366 367 368
      new Directionality(
        textDirection: TextDirection.ltr,
        child: new NotificationListener<OverscrollNotification>(
          onNotification: (OverscrollNotification message) { scrolled = true; return false; },
          child: new ListView(
            primary: false,
            children: <Widget>[],
          ),
369 370 371 372 373 374 375
        ),
      ),
    );
    await tester.dragFrom(const Offset(100.0, 100.0), const Offset(0.0, 100.0));
    expect(scrolled, isFalse);
  });

Ian Hickson's avatar
Ian Hickson committed
376
  testWidgets('physics:AlwaysScrollableScrollPhysics actually overrides primary:false default behavior', (WidgetTester tester) async {
377 378
    bool scrolled = false;
    await tester.pumpWidget(
379 380 381 382 383 384 385 386 387
      new Directionality(
        textDirection: TextDirection.ltr,
        child: new NotificationListener<OverscrollNotification>(
          onNotification: (OverscrollNotification message) { scrolled = true; return false; },
          child: new ListView(
            primary: false,
            physics: const AlwaysScrollableScrollPhysics(),
            children: <Widget>[],
          ),
388 389 390 391 392 393 394
        ),
      ),
    );
    await tester.dragFrom(const Offset(100.0, 100.0), const Offset(0.0, 100.0));
    expect(scrolled, isTrue);
  });

Ian Hickson's avatar
Ian Hickson committed
395
  testWidgets('physics:ScrollPhysics actually overrides primary:true default behavior', (WidgetTester tester) async {
396 397
    bool scrolled = false;
    await tester.pumpWidget(
398 399 400 401 402 403 404 405 406
      new Directionality(
        textDirection: TextDirection.ltr,
        child: new NotificationListener<OverscrollNotification>(
          onNotification: (OverscrollNotification message) { scrolled = true; return false; },
          child: new ListView(
            primary: true,
            physics: const ScrollPhysics(),
            children: <Widget>[],
          ),
407 408 409 410 411 412
        ),
      ),
    );
    await tester.dragFrom(const Offset(100.0, 100.0), const Offset(0.0, 100.0));
    expect(scrolled, isFalse);
  });
413
}