grid_view_test.dart 14.7 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';

Adam Barth's avatar
Adam Barth committed
8
import '../rendering/mock_canvas.dart';
9 10 11
import 'states.dart';

void main() {
12
  testWidgets('Empty GridView', (WidgetTester tester) async {
13
    await tester.pumpWidget(
14
      Directionality(
15
        textDirection: TextDirection.ltr,
16
        child: GridView.count(
17 18 19 20 21
          crossAxisCount: 4,
          children: const <Widget>[],
        ),
      ),
    );
22 23
  });

24
  testWidgets('GridView.count control test', (WidgetTester tester) async {
25
    final List<String> log = <String>[];
26

27
    await tester.pumpWidget(
28
      Directionality(
29
        textDirection: TextDirection.ltr,
30
        child: GridView.count(
31
          crossAxisCount: 4,
32
          children: kStates.map<Widget>((String state) {
33
            return GestureDetector(
34 35 36
              onTap: () {
                log.add(state);
              },
37
              child: Container(
38
                color: const Color(0xFF0000FF),
39
                child: Text(state),
40 41 42 43 44 45
              ),
            );
          }).toList(),
        ),
      ),
    );
46 47 48 49 50 51 52 53 54 55 56 57

    expect(tester.getSize(find.text('Arkansas')), equals(const Size(200.0, 200.0)));

    for (int i = 0; i < 8; ++i) {
      await tester.tap(find.text(kStates[i]));
      expect(log, equals(<String>[kStates[i]]));
      log.clear();
    }

    expect(find.text(kStates[12]), findsNothing);
    expect(find.text('Nevada'), findsNothing);

58
    await tester.drag(find.text('Arkansas'), const Offset(0.0, -200.0));
59 60 61 62 63 64 65 66 67 68 69
    await tester.pump();

    for (int i = 0; i < 4; ++i)
      expect(find.text(kStates[i]), findsNothing);

    for (int i = 4; i < 12; ++i) {
      await tester.tap(find.text(kStates[i]));
      expect(log, equals(<String>[kStates[i]]));
      log.clear();
    }

70
    await tester.drag(find.text('Delaware'), const Offset(0.0, -4000.0));
71 72 73 74 75 76
    await tester.pump();

    expect(find.text('Alabama'), findsNothing);
    expect(find.text('Pennsylvania'), findsNothing);

    expect(tester.getCenter(find.text('Tennessee')),
77
        equals(const Offset(300.0, 100.0)));
78 79 80 81 82

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

83
    await tester.drag(find.text('Tennessee'), const Offset(0.0, 200.0));
84 85 86 87 88 89 90 91 92 93 94
    await tester.pump();

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

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

95
  testWidgets('GridView.extent control test', (WidgetTester tester) async {
96
    final List<String> log = <String>[];
97

98
    await tester.pumpWidget(
99
      Directionality(
100
        textDirection: TextDirection.ltr,
101
        child: GridView.extent(
102
          maxCrossAxisExtent: 200.0,
103
          children: kStates.map<Widget>((String state) {
104
            return GestureDetector(
105 106 107
              onTap: () {
                log.add(state);
              },
108
              child: Container(
109
                color: const Color(0xFF0000FF),
110
                child: Text(state),
111 112 113 114 115 116
              ),
            );
          }).toList(),
        ),
      ),
    );
117 118 119 120 121 122 123 124 125 126 127

    expect(tester.getSize(find.text('Arkansas')), equals(const Size(200.0, 200.0)));

    for (int i = 0; i < 8; ++i) {
      await tester.tap(find.text(kStates[i]));
      expect(log, equals(<String>[kStates[i]]));
      log.clear();
    }

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

128
    await tester.drag(find.text('Arkansas'), const Offset(0.0, -4000.0));
129 130 131 132 133
    await tester.pump();

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

    expect(tester.getCenter(find.text('Tennessee')),
134
        equals(const Offset(300.0, 100.0)));
135 136 137 138 139 140

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

141
  testWidgets('GridView large scroll jump', (WidgetTester tester) async {
142
    final List<int> log = <int>[];
143

144
    await tester.pumpWidget(
145
      Directionality(
146
        textDirection: TextDirection.ltr,
147
        child: GridView.extent(
148 149 150
          scrollDirection: Axis.horizontal,
          maxCrossAxisExtent: 200.0,
          childAspectRatio: 0.75,
151 152
          children: List<Widget>.generate(80, (int i) {
            return Builder(
153 154
              builder: (BuildContext context) {
                log.add(i);
155 156
                return Container(
                  child: Text('$i'),
157 158 159 160 161
                );
              }
            );
          }),
        ),
162
      ),
163
    );
164 165 166 167 168 169 170

    expect(tester.getSize(find.text('4')), equals(const Size(200.0 / 0.75, 200.0)));

    expect(log, equals(<int>[
      0, 1, 2, // col 0
      3, 4, 5, // col 1
      6, 7, 8, // col 2
171
      9, 10, 11, // col 3 (in cached area)
172 173 174
    ]));
    log.clear();

175 176 177 178 179 180 181
    for (int i = 0; i < 9; i++) {
      expect(find.text('$i'), findsOneWidget);
    }
    for (int i = 9; i < 80; i++) {
      expect(find.text('$i'), findsNothing);
    }

182 183
    final ScrollableState state = tester.state(find.byType(Scrollable));
    final ScrollPosition position = state.position;
184 185 186 187 188 189
    position.jumpTo(3025.0);

    expect(log, isEmpty);
    await tester.pump();

    expect(log, equals(<int>[
190
      30, 31, 32, // col 10 (in cached area)
191 192 193 194
      33, 34, 35, // col 11
      36, 37, 38, // col 12
      39, 40, 41, // col 13
      42, 43, 44, // col 14
195
      45, 46, 47, // col 15 (in cached area)
196 197 198
    ]));
    log.clear();

199 200 201 202 203 204 205 206 207 208
    for (int i = 0; i < 33; i++) {
      expect(find.text('$i'), findsNothing);
    }
    for (int i = 33; i < 45; i++) {
      expect(find.text('$i'), findsOneWidget);
    }
    for (int i = 45; i < 80; i++) {
      expect(find.text('$i'), findsNothing);
    }

209 210 211 212 213 214
    position.jumpTo(975.0);

    expect(log, isEmpty);
    await tester.pump();

    expect(log, equals(<int>[
215
      6, 7, 8, // col2 (in cached area)
216 217 218 219
      9, 10, 11, // col 3
      12, 13, 14, // col 4
      15, 16, 17, // col 5
      18, 19, 20, // col 6
220
      21, 22, 23, // col 7 (in cached area)
221 222
    ]));
    log.clear();
223 224 225 226 227 228 229 230 231 232

    for (int i = 0; i < 9; i++) {
      expect(find.text('$i'), findsNothing);
    }
    for (int i = 9; i < 21; i++) {
      expect(find.text('$i'), findsOneWidget);
    }
    for (int i = 21; i < 80; i++) {
      expect(find.text('$i'), findsNothing);
    }
233 234
  });

235
  testWidgets('GridView - change crossAxisCount', (WidgetTester tester) async {
236
    final List<int> log = <int>[];
237 238

    await tester.pumpWidget(
239
      Directionality(
240
        textDirection: TextDirection.ltr,
241
        child: GridView(
242 243 244
          gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 4,
          ),
245 246
          children: List<Widget>.generate(40, (int i) {
            return Builder(
247 248
              builder: (BuildContext context) {
                log.add(i);
249 250
                return Container(
                  child: Text('$i'),
251 252 253 254
                );
              }
            );
          }),
255 256 257 258 259 260 261 262 263 264
        ),
      ),
    );

    expect(tester.getSize(find.text('4')), equals(const Size(200.0, 200.0)));

    expect(log, equals(<int>[
      0, 1, 2, 3, // row 0
      4, 5, 6, 7, // row 1
      8, 9, 10, 11, // row 2
265 266
      12, 13, 14, 15, // row 3 (in cached area)
      16, 17, 18, 19, // row 4 (in cached area)
267
    ]));
268 269 270 271 272 273
    for (int i = 0; i < 12; i++) {
      expect(find.text('$i'), findsOneWidget);
    }
    for (int i = 12; i < 40; i++) {
      expect(find.text('$i'), findsNothing);
    }
274 275 276
    log.clear();

    await tester.pumpWidget(
277
      Directionality(
278
        textDirection: TextDirection.ltr,
279
        child: GridView(
280 281 282
          gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 2,
          ),
283 284
          children: List<Widget>.generate(40, (int i) {
            return Builder(
285 286
              builder: (BuildContext context) {
                log.add(i);
287 288
                return Container(
                  child: Text('$i'),
289 290 291 292
                );
              }
            );
          }),
293 294 295 296 297 298 299 300
        ),
      ),
    );

    expect(log, equals(<int>[
      0, 1, 2, 3, // row 0
      4, 5, 6, 7, // row 1
      8, 9, 10, 11, // row 2
301 302
      12, 13, 14, 15, // row 3 (in cached area)
      16, 17, 18, 19, // row 4 (in cached area)
303 304 305 306 307 308 309
    ]));
    log.clear();

    expect(tester.getSize(find.text('3')), equals(const Size(400.0, 400.0)));
    expect(find.text('4'), findsNothing);
  });

310
  testWidgets('GridView - change maxChildCrossAxisExtent', (WidgetTester tester) async {
311
    final List<int> log = <int>[];
312 313

    await tester.pumpWidget(
314
      Directionality(
315
        textDirection: TextDirection.ltr,
316
        child: GridView(
317 318 319
          gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
            maxCrossAxisExtent: 200.0,
          ),
320 321
          children: List<Widget>.generate(40, (int i) {
            return Builder(
322 323
              builder: (BuildContext context) {
                log.add(i);
324 325
                return Container(
                  child: Text('$i'),
326 327 328 329
                );
              }
            );
          }),
330 331 332 333 334 335 336 337 338 339
        ),
      ),
    );

    expect(tester.getSize(find.text('4')), equals(const Size(200.0, 200.0)));

    expect(log, equals(<int>[
      0, 1, 2, 3, // row 0
      4, 5, 6, 7, // row 1
      8, 9, 10, 11, // row 2
340 341
      12, 13, 14, 15, // row 3 (in cached area)
      16, 17, 18, 19, // row 4 (in cached area)
342
    ]));
343 344 345 346 347 348
    for (int i = 0; i < 12; i++) {
      expect(find.text('$i'), findsOneWidget);
    }
    for (int i = 12; i < 40; i++) {
      expect(find.text('$i'), findsNothing);
    }
349 350 351
    log.clear();

    await tester.pumpWidget(
352
      Directionality(
353
        textDirection: TextDirection.ltr,
354
        child: GridView(
355 356 357
          gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
            maxCrossAxisExtent: 400.0,
          ),
358 359
          children: List<Widget>.generate(40, (int i) {
            return Builder(
360 361
              builder: (BuildContext context) {
                log.add(i);
362 363
                return Container(
                  child: Text('$i'),
364 365 366 367
                );
              }
            );
          }),
368 369 370 371 372 373 374 375
        ),
      ),
    );

    expect(log, equals(<int>[
      0, 1, 2, 3, // row 0
      4, 5, 6, 7, // row 1
      8, 9, 10, 11, // row 2
376 377
      12, 13, 14, 15, // row 3 (in cached area)
      16, 17, 18, 19, // row 4 (in cached area)
378 379 380 381 382 383
    ]));
    log.clear();

    expect(tester.getSize(find.text('3')), equals(const Size(400.0, 400.0)));
    expect(find.text('4'), findsNothing);
  });
384

Adam Barth's avatar
Adam Barth committed
385
  testWidgets('One-line GridView paints', (WidgetTester tester) async {
386
    const Color green = Color(0xFF00FF00);
Adam Barth's avatar
Adam Barth committed
387

388
    final Container container = Container(
Adam Barth's avatar
Adam Barth committed
389
      decoration: const BoxDecoration(
390
        color: green,
Adam Barth's avatar
Adam Barth committed
391 392 393
      ),
    );

394
    await tester.pumpWidget(
395
      Directionality(
396
        textDirection: TextDirection.ltr,
397 398
        child: Center(
          child: SizedBox(
399
            height: 200.0,
400
            child: GridView.count(
401
              cacheExtent: 0.0,
402 403 404 405
              crossAxisCount: 2,
              children: <Widget>[ container, container, container, container ],
            ),
          ),
Adam Barth's avatar
Adam Barth committed
406 407
        ),
      ),
408
    );
Adam Barth's avatar
Adam Barth committed
409 410 411 412 413

    expect(find.byType(GridView), paints..rect(color: green)..rect(color: green));
    expect(find.byType(GridView), isNot(paints..rect(color: green)..rect(color: green)..rect(color: green)));
  });

414 415
  testWidgets('GridView in zero context', (WidgetTester tester) async {
    await tester.pumpWidget(
416
      Directionality(
417
        textDirection: TextDirection.ltr,
418 419
        child: Center(
          child: SizedBox(
420 421
            width: 0.0,
            height: 0.0,
422
            child: GridView.count(
423
              crossAxisCount: 4,
424 425 426
              children: List<Widget>.generate(20, (int i) {
                return Container(
                  child: Text('$i'),
427 428 429 430 431 432 433 434
                );
              }),
            ),
          ),
        ),
      ),
    );

435
    expect(find.text('0'), findsNothing);
436 437 438 439 440
    expect(find.text('1'), findsNothing);
  });

  testWidgets('GridView in unbounded context', (WidgetTester tester) async {
    await tester.pumpWidget(
441
      Directionality(
442
        textDirection: TextDirection.ltr,
443 444
        child: SingleChildScrollView(
          child: GridView.count(
445
            crossAxisCount: 4,
446
            shrinkWrap: true,
447 448 449
            children: List<Widget>.generate(20, (int i) {
              return Container(
                child: Text('$i'),
450 451 452 453 454 455 456 457
              );
            }),
          ),
        ),
      ),
    );

    expect(find.text('0'), findsOneWidget);
458
    expect(find.text('19'), findsOneWidget);
459 460
  });

461
  testWidgets('GridView.builder control test', (WidgetTester tester) async {
462
    await tester.pumpWidget(
463
      Directionality(
464
        textDirection: TextDirection.ltr,
465
        child: GridView.builder(
466 467 468
          gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 4,
          ),
469
          shrinkWrap: true,
470 471
          itemCount: 20,
          itemBuilder: (BuildContext context, int index) {
472 473
            return Container(
              child: Text('$index'),
474
            );
475
          },
476 477 478
        ),
      ),
    );
479 480 481 482 483
    expect(find.text('0'), findsOneWidget);
    expect(find.text('11'), findsOneWidget);
    expect(find.text('12'), findsNothing);
  });

484 485
  testWidgets('GridView.builder with undefined itemCount', (WidgetTester tester) async {
    await tester.pumpWidget(
486
      Directionality(
487
        textDirection: TextDirection.ltr,
488
        child: GridView.builder(
489 490 491 492 493
          gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 4,
          ),
          shrinkWrap: true,
          itemBuilder: (BuildContext context, int index) {
494 495
            return Container(
              child: Text('$index'),
496 497 498 499 500 501 502 503 504 505 506 507
            );
          },
        ),
      ),
    );
    expect(find.text('0'), findsOneWidget);
    expect(find.text('11'), findsOneWidget);
    await tester.drag(find.byType(GridView), const Offset(0.0, -300.0));
    await tester.pump(const Duration(milliseconds: 200));
    expect(find.text('13'), findsOneWidget);
  });

508
  testWidgets('GridView cross axis layout', (WidgetTester tester) async {
509
    final Key target = UniqueKey();
510 511

    Widget build(TextDirection textDirection) {
512
      return Directionality(
513
        textDirection: textDirection,
514
        child: GridView.count(
515 516
          crossAxisCount: 4,
          children: <Widget>[
517
            Container(key: target),
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
          ],
        ),
      );
    }

    await tester.pumpWidget(build(TextDirection.ltr));

    expect(tester.getTopLeft(find.byKey(target)), Offset.zero);
    expect(tester.getBottomRight(find.byKey(target)), const Offset(200.0, 200.0));

    await tester.pumpWidget(build(TextDirection.rtl));

    expect(tester.getTopLeft(find.byKey(target)), const Offset(600.0, 0.0));
    expect(tester.getBottomRight(find.byKey(target)), const Offset(800.0, 200.0));
  });
533
}