scroll_view_test.dart 12.5 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
    await tester.pumpWidget(new ListView(
15
      children: kStates.map<Widget>((String state) {
16 17 18 19 20 21
        return new GestureDetector(
          onTap: () {
            log.add(state);
          },
          child: new Container(
            height: 200.0,
22
            color: const Color(0xFF0000FF),
23 24 25 26
            child: new Text(state),
          ),
        );
      }).toList()
27
    ));
28 29 30 31 32 33 34

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

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

35
    await tester.drag(find.text('Alabama'), const Offset(0.0, -4000.0));
36 37 38
    await tester.pump();

    expect(find.text('Alabama'), findsNothing);
39
    expect(tester.getCenter(find.text('Massachusetts')), equals(const Offset(400.0, 100.0)));
40 41 42 43 44

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

46 47 48
  testWidgets('ListView restart ballistic activity out of range', (WidgetTester tester) async {
    Widget buildListView(int n) {
      return new ListView(
49
        children: kStates.take(n).map<Widget>((String state) {
50 51
          return new Container(
            height: 200.0,
52
            color: const Color(0xFF0000FF),
53 54 55 56 57 58
            child: new Text(state),
          );
        }).toList()
      );
    }

59 60 61
    await tester.pumpWidget(buildListView(30));
    await tester.fling(find.byType(ListView), const Offset(0.0, -4000.0), 4000.0);
    await tester.pumpWidget(buildListView(15));
62 63 64 65
    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));
66
    await tester.pumpAndSettle(const Duration(milliseconds: 100));
67

68
    final Viewport viewport = tester.widget(find.byType(Viewport));
69 70
    expect(viewport.offset.pixels, equals(2400.0));
  });
Adam Barth's avatar
Adam Barth committed
71 72

  testWidgets('CustomScrollView control test', (WidgetTester tester) async {
73
    final List<String> log = <String>[];
Adam Barth's avatar
Adam Barth committed
74 75 76 77 78 79 80 81 82 83 84 85

    await tester.pumpWidget(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,
86
                  color: const Color(0xFF0000FF),
Adam Barth's avatar
Adam Barth committed
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
                  child: new Text(state),
                ),
              );
            }).toList(),
          ),
        ),
      ],
    ));

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

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

102
    await tester.drag(find.text('Alabama'), const Offset(0.0, -4000.0));
Adam Barth's avatar
Adam Barth committed
103 104 105
    await tester.pump();

    expect(find.text('Alabama'), findsNothing);
106
    expect(tester.getCenter(find.text('Massachusetts')), equals(const Offset(400.0, 100.0)));
Adam Barth's avatar
Adam Barth committed
107 108 109 110 111

    await tester.tap(find.text('Massachusetts'));
    expect(log, equals(<String>['Massachusetts']));
    log.clear();
  });
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134

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

    await tester.pumpWidget(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(),
      ),
    ));

    expect(log, isEmpty);

135
    final TestGesture gesture = await tester.startGesture(const Offset(100.0, 100.0));
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
    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);
  });
165

166
  testWidgets('Vertical CustomScrollViews are primary by default', (WidgetTester tester) async {
167
    final CustomScrollView view = new CustomScrollView(scrollDirection: Axis.vertical);
168 169 170 171
    expect(view.primary, isTrue);
  });

  testWidgets('Vertical ListViews are primary by default', (WidgetTester tester) async {
172
    final ListView view = new ListView(scrollDirection: Axis.vertical);
173 174 175 176
    expect(view.primary, isTrue);
  });

  testWidgets('Vertical GridViews are primary by default', (WidgetTester tester) async {
177
    final GridView view = new GridView.count(
178 179 180 181 182 183 184
      scrollDirection: Axis.vertical,
      crossAxisCount: 1,
    );
    expect(view.primary, isTrue);
  });

  testWidgets('Horizontal CustomScrollViews are non-primary by default', (WidgetTester tester) async {
185
    final CustomScrollView view = new CustomScrollView(scrollDirection: Axis.horizontal);
186 187 188 189
    expect(view.primary, isFalse);
  });

  testWidgets('Horizontal ListViews are non-primary by default', (WidgetTester tester) async {
190
    final ListView view = new ListView(scrollDirection: Axis.horizontal);
191 192 193 194
    expect(view.primary, isFalse);
  });

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

  testWidgets('CustomScrollViews with controllers are non-primary by default', (WidgetTester tester) async {
203
    final CustomScrollView view = new CustomScrollView(
204 205 206 207 208 209 210
      controller: new ScrollController(),
      scrollDirection: Axis.vertical,
    );
    expect(view.primary, isFalse);
  });

  testWidgets('ListViews with controllers are non-primary by default', (WidgetTester tester) async {
211
    final ListView view = new ListView(
212 213 214 215 216 217 218
      controller: new ScrollController(),
      scrollDirection: Axis.vertical,
    );
    expect(view.primary, isFalse);
  });

  testWidgets('GridViews with controllers are non-primary by default', (WidgetTester tester) async {
219
    final GridView view = new GridView.count(
220 221 222 223 224 225 226
      controller: new ScrollController(),
      scrollDirection: Axis.vertical,
      crossAxisCount: 1,
    );
    expect(view.primary, isFalse);
  });

227
  testWidgets('CustomScrollView sets PrimaryScrollController when primary', (WidgetTester tester) async {
228
    final ScrollController primaryScrollController = new ScrollController();
229 230 231 232
    await tester.pumpWidget(new PrimaryScrollController(
      controller: primaryScrollController,
      child: new CustomScrollView(primary: true),
    ));
233
    final Scrollable scrollable = tester.widget(find.byType(Scrollable));
234 235 236 237
    expect(scrollable.controller, primaryScrollController);
  });

  testWidgets('ListView sets PrimaryScrollController when primary', (WidgetTester tester) async {
238
    final ScrollController primaryScrollController = new ScrollController();
239 240 241 242
    await tester.pumpWidget(new PrimaryScrollController(
      controller: primaryScrollController,
      child: new ListView(primary: true),
    ));
243
    final Scrollable scrollable = tester.widget(find.byType(Scrollable));
244 245 246 247
    expect(scrollable.controller, primaryScrollController);
  });

  testWidgets('GridView sets PrimaryScrollController when primary', (WidgetTester tester) async {
248
    final ScrollController primaryScrollController = new ScrollController();
249 250 251 252
    await tester.pumpWidget(new PrimaryScrollController(
      controller: primaryScrollController,
      child: new GridView.count(primary: true, crossAxisCount: 1),
    ));
253
    final Scrollable scrollable = tester.widget(find.byType(Scrollable));
254 255
    expect(scrollable.controller, primaryScrollController);
  });
256 257 258

  testWidgets('Nested scrollables have a null PrimaryScrollController', (WidgetTester tester) async {
    const Key innerKey = const Key('inner');
259
    final ScrollController primaryScrollController = new ScrollController();
260 261 262 263 264 265
    await tester.pumpWidget(new PrimaryScrollController(
      controller: primaryScrollController,
      child: new ListView(
        primary: true,
        children: <Widget>[
          new Container(
266
            constraints: const BoxConstraints(maxHeight: 200.0),
267 268 269 270 271 272
            child: new ListView(key: innerKey, primary: true),
          ),
        ],
      ),
    ));

273
    final Scrollable innerScrollable = tester.widget(
274 275 276 277 278 279 280
      find.descendant(
        of: find.byKey(innerKey),
        matching: find.byType(Scrollable),
      ),
    );
    expect(innerScrollable.controller, isNull);
  });
281 282 283 284 285 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 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362

  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(
      new NotificationListener<OverscrollNotification>(
        onNotification: (OverscrollNotification message) { scrolled = true; return false; },
        child: new ListView(
          primary: true,
          children: <Widget>[],
        ),
      ),
    );
    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(
      new NotificationListener<OverscrollNotification>(
        onNotification: (OverscrollNotification message) { scrolled = true; return false; },
        child: new ListView(
          primary: false,
          children: <Widget>[],
        ),
      ),
    );
    await tester.dragFrom(const Offset(100.0, 100.0), const Offset(0.0, 100.0));
    expect(scrolled, isFalse);
  });

  testWidgets('physics:AlwaysScrollableScrollPhysics actually overrides primary:false default behaviour', (WidgetTester tester) async {
    bool scrolled = false;
    await tester.pumpWidget(
      new NotificationListener<OverscrollNotification>(
        onNotification: (OverscrollNotification message) { scrolled = true; return false; },
        child: new ListView(
          primary: false,
          physics: const AlwaysScrollableScrollPhysics(),
          children: <Widget>[],
        ),
      ),
    );
    await tester.dragFrom(const Offset(100.0, 100.0), const Offset(0.0, 100.0));
    expect(scrolled, isTrue);
  });

  testWidgets('physics:ScrollPhysics actually overrides primary:true default behaviour', (WidgetTester tester) async {
    bool scrolled = false;
    await tester.pumpWidget(
      new NotificationListener<OverscrollNotification>(
        onNotification: (OverscrollNotification message) { scrolled = true; return false; },
        child: new ListView(
          primary: true,
          physics: const ScrollPhysics(),
          children: <Widget>[],
        ),
      ),
    );
    await tester.dragFrom(const Offset(100.0, 100.0), const Offset(0.0, 100.0));
    expect(scrolled, isFalse);
  });
363
}