page_view_test.dart 23.1 KB
Newer Older
Adam Barth's avatar
Adam Barth committed
1 2 3 4 5
// 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';
6
import 'package:flutter/material.dart';
7
import 'package:flutter/rendering.dart';
Adam Barth's avatar
Adam Barth committed
8 9
import 'package:flutter/widgets.dart';

10
import 'semantics_tester.dart';
Adam Barth's avatar
Adam Barth committed
11 12
import 'states.dart';

13
const Duration _frameDuration = Duration(milliseconds: 100);
Adam Barth's avatar
Adam Barth committed
14 15 16

void main() {
  testWidgets('PageView control test', (WidgetTester tester) async {
17
    final List<String> log = <String>[];
Adam Barth's avatar
Adam Barth committed
18

19
    await tester.pumpWidget(Directionality(
20
      textDirection: TextDirection.ltr,
21
      child: PageView(
22
        children: kStates.map<Widget>((String state) {
23
          return GestureDetector(
24 25 26
            onTap: () {
              log.add(state);
            },
27
            child: Container(
28 29
              height: 200.0,
              color: const Color(0xFF0000FF),
30
              child: Text(state),
31 32 33 34
            ),
          );
        }).toList(),
      ),
Adam Barth's avatar
Adam Barth committed
35 36 37 38 39 40 41 42
    ));

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

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

43
    await tester.drag(find.byType(PageView), const Offset(-20.0, 0.0));
Adam Barth's avatar
Adam Barth committed
44 45 46 47 48 49
    await tester.pump();

    expect(find.text('Alabama'), findsOneWidget);
    expect(find.text('Alaska'), findsOneWidget);
    expect(find.text('Arizona'), findsNothing);

50
    await tester.pumpAndSettle(_frameDuration);
Adam Barth's avatar
Adam Barth committed
51 52 53 54

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

55 56
    await tester.drag(find.byType(PageView), const Offset(-401.0, 0.0));
    await tester.pumpAndSettle(_frameDuration);
Adam Barth's avatar
Adam Barth committed
57 58 59 60 61 62 63 64 65

    expect(find.text('Alabama'), findsNothing);
    expect(find.text('Alaska'), findsOneWidget);
    expect(find.text('Arizona'), findsNothing);

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

66
    await tester.fling(find.byType(PageView), const Offset(-200.0, 0.0), 1000.0);
67
    await tester.pumpAndSettle(_frameDuration);
Adam Barth's avatar
Adam Barth committed
68 69 70 71 72 73

    expect(find.text('Alabama'), findsNothing);
    expect(find.text('Alaska'), findsNothing);
    expect(find.text('Arizona'), findsOneWidget);

    await tester.fling(find.byType(PageView), const Offset(200.0, 0.0), 1000.0);
74
    await tester.pumpAndSettle(_frameDuration);
Adam Barth's avatar
Adam Barth committed
75 76 77 78 79

    expect(find.text('Alabama'), findsNothing);
    expect(find.text('Alaska'), findsOneWidget);
    expect(find.text('Arizona'), findsNothing);
  });
80

81 82
  testWidgets('PageView does not squish when overscrolled',
      (WidgetTester tester) async {
83 84 85 86 87 88
    await tester.pumpWidget(MaterialApp(
      theme: ThemeData(platform: TargetPlatform.iOS),
      home: PageView(
        children: List<Widget>.generate(10, (int i) {
          return Container(
            key: ValueKey<int>(i),
89
            color: const Color(0xFF0000FF),
90 91 92 93 94
          );
        }),
      ),
    ));

95 96
    Size sizeOf(int i) => tester.getSize(find.byKey(ValueKey<int>(i)));
    double leftOf(int i) => tester.getTopLeft(find.byKey(ValueKey<int>(i))).dx;
97 98 99 100

    expect(leftOf(0), equals(0.0));
    expect(sizeOf(0), equals(const Size(800.0, 600.0)));

101
    // Going into overscroll.
102
    await tester.drag(find.byType(PageView), const Offset(100.0, 0.0));
103 104
    await tester.pump();

105
    expect(leftOf(0), greaterThan(0.0));
106 107
    expect(sizeOf(0), equals(const Size(800.0, 600.0)));

108
    // Easing overscroll past overscroll limit.
109
    await tester.drag(find.byType(PageView), const Offset(-200.0, 0.0));
110 111
    await tester.pump();

112
    expect(leftOf(0), lessThan(0.0));
113 114
    expect(sizeOf(0), equals(const Size(800.0, 600.0)));
  });
115 116

  testWidgets('PageController control test', (WidgetTester tester) async {
117
    final PageController controller = PageController(initialPage: 4);
118

119
    await tester.pumpWidget(Directionality(
120
      textDirection: TextDirection.ltr,
121 122
      child: Center(
        child: SizedBox(
123 124
          width: 600.0,
          height: 400.0,
125
          child: PageView(
126
            controller: controller,
127
            children: kStates.map<Widget>((String state) => Text(state)).toList(),
128
          ),
129 130 131 132 133 134
        ),
      ),
    ));

    expect(find.text('California'), findsOneWidget);

135 136
    controller.nextPage(duration: const Duration(milliseconds: 150), curve: Curves.ease);
    await tester.pumpAndSettle(const Duration(milliseconds: 100));
137 138 139

    expect(find.text('Colorado'), findsOneWidget);

140
    await tester.pumpWidget(Directionality(
141
      textDirection: TextDirection.ltr,
142 143
      child: Center(
        child: SizedBox(
144 145
          width: 300.0,
          height: 400.0,
146
          child: PageView(
147
            controller: controller,
148
            children: kStates.map<Widget>((String state) => Text(state)).toList(),
149
          ),
150 151 152 153 154 155
        ),
      ),
    ));

    expect(find.text('Colorado'), findsOneWidget);

156 157
    controller.previousPage(duration: const Duration(milliseconds: 150), curve: Curves.ease);
    await tester.pumpAndSettle(const Duration(milliseconds: 100));
158 159 160 161 162

    expect(find.text('California'), findsOneWidget);
  });

  testWidgets('PageController page stability', (WidgetTester tester) async {
163
    await tester.pumpWidget(Directionality(
164
      textDirection: TextDirection.ltr,
165 166
      child: Center(
        child: SizedBox(
167 168
          width: 600.0,
          height: 400.0,
169 170
          child: PageView(
            children: kStates.map<Widget>((String state) => Text(state)).toList(),
171 172
          ),
        )
173 174 175 176 177
      ),
    ));

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

178 179
    await tester.drag(find.byType(PageView), const Offset(-1250.0, 0.0));
    await tester.pumpAndSettle(const Duration(milliseconds: 100));
180 181 182

    expect(find.text('Arizona'), findsOneWidget);

183
    await tester.pumpWidget(Directionality(
184
      textDirection: TextDirection.ltr,
185 186
      child: Center(
        child: SizedBox(
187 188
          width: 250.0,
          height: 100.0,
189 190
          child: PageView(
            children: kStates.map<Widget>((String state) => Text(state)).toList(),
191
          ),
192 193 194 195 196 197
        ),
      ),
    ));

    expect(find.text('Arizona'), findsOneWidget);

198
    await tester.pumpWidget(Directionality(
199
      textDirection: TextDirection.ltr,
200 201
      child: Center(
        child: SizedBox(
202 203
          width: 450.0,
          height: 400.0,
204 205
          child: PageView(
            children: kStates.map<Widget>((String state) => Text(state)).toList(),
206
          ),
207 208 209 210 211 212
        ),
      ),
    ));

    expect(find.text('Arizona'), findsOneWidget);
  });
213

214
  testWidgets('PageController nextPage and previousPage return Futures that resolve', (WidgetTester tester) async {
215 216
    final PageController controller = PageController();
    await tester.pumpWidget(Directionality(
217
        textDirection: TextDirection.ltr,
218
        child: PageView(
219
          controller: controller,
220
          children: kStates.map<Widget>((String state) => Text(state)).toList(),
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
        ),
    ));

    bool nextPageCompleted = false;
    controller.nextPage(duration: const Duration(milliseconds: 150), curve: Curves.ease)
        .then((_) => nextPageCompleted = true);

    expect(nextPageCompleted, false);
    await tester.pump(const Duration(milliseconds: 200));
    expect(nextPageCompleted, false);
    await tester.pump(const Duration(milliseconds: 200));
    expect(nextPageCompleted, true);


    bool previousPageCompleted = false;
    controller.previousPage(duration: const Duration(milliseconds: 150), curve: Curves.ease)
        .then((_) => previousPageCompleted = true);

    expect(previousPageCompleted, false);
    await tester.pump(const Duration(milliseconds: 200));
    expect(previousPageCompleted, false);
    await tester.pump(const Duration(milliseconds: 200));
    expect(previousPageCompleted, true);
  });

246
  testWidgets('PageView in zero-size container', (WidgetTester tester) async {
247
    await tester.pumpWidget(Directionality(
248
      textDirection: TextDirection.ltr,
249 250
      child: Center(
        child: SizedBox(
251 252
          width: 0.0,
          height: 0.0,
253 254
          child: PageView(
            children: kStates.map<Widget>((String state) => Text(state)).toList(),
255
          ),
256 257 258 259
        ),
      ),
    ));

260
    expect(find.text('Alabama', skipOffstage: false), findsOneWidget);
261

262
    await tester.pumpWidget(Directionality(
263
      textDirection: TextDirection.ltr,
264 265
      child: Center(
        child: SizedBox(
266 267
          width: 200.0,
          height: 200.0,
268 269
          child: PageView(
            children: kStates.map<Widget>((String state) => Text(state)).toList(),
270
          ),
271 272 273 274 275
        ),
      ),
    ));

    expect(find.text('Alabama'), findsOneWidget);
276
  });
277 278 279

  testWidgets('Page changes at halfway point', (WidgetTester tester) async {
    final List<int> log = <int>[];
280
    await tester.pumpWidget(Directionality(
281
      textDirection: TextDirection.ltr,
282
      child: PageView(
283
        onPageChanged: log.add,
284
        children: kStates.map<Widget>((String state) => Text(state)).toList(),
285
      ),
286 287 288 289
    ));

    expect(log, isEmpty);

290
    final TestGesture gesture =
291
        await tester.startGesture(const Offset(100.0, 100.0));
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
    // The page view is 800.0 wide, so this move is just short of halfway.
    await gesture.moveBy(const Offset(-380.0, 0.0));

    expect(log, isEmpty);

    // We've crossed the halfway mark.
    await gesture.moveBy(const Offset(-40.0, 0.0));

    expect(log, equals(const <int>[1]));
    log.clear();

    // Moving a bit more should not generate redundant notifications.
    await gesture.moveBy(const Offset(-40.0, 0.0));

    expect(log, isEmpty);

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

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

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

    expect(log, isEmpty);

    await gesture.up();
320
    await tester.pumpAndSettle();
321 322 323 324 325 326 327

    expect(log, isEmpty);

    expect(find.text('Alabama'), findsNothing);
    expect(find.text('Alaska'), findsOneWidget);
  });

328 329
  testWidgets('Bouncing scroll physics ballistics does not overshoot', (WidgetTester tester) async {
    final List<int> log = <int>[];
330
    final PageController controller = PageController(viewportFraction: 0.9);
331 332

    Widget build(PageController controller, {Size size}) {
333
      final Widget pageView = Directionality(
334
        textDirection: TextDirection.ltr,
335
        child: PageView(
336 337 338
          controller: controller,
          onPageChanged: log.add,
          physics: const BouncingScrollPhysics(),
339
          children: kStates.map<Widget>((String state) => Text(state)).toList(),
340 341 342 343
        ),
      );

      if (size != null) {
344
        return OverflowBox(
345 346 347 348 349 350 351 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 381
          child: pageView,
          minWidth: size.width,
          minHeight: size.height,
          maxWidth: size.width,
          maxHeight: size.height,
        );
      } else {
        return pageView;
      }
    }

    await tester.pumpWidget(build(controller));
    expect(log, isEmpty);

    // Fling right to move to a non-existent page at the beginning of the
    // PageView, and confirm that the PageView settles back on the first page.
    await tester.fling(find.byType(PageView), const Offset(100.0, 0.0), 800.0);
    await tester.pumpAndSettle();
    expect(log, isEmpty);

    expect(find.text('Alabama'), findsOneWidget);
    expect(find.text('Alaska'), findsOneWidget);
    expect(find.text('Arizona'), findsNothing);

    // Try again with a Cupertino "Plus" device size.
    await tester.pumpWidget(build(controller, size: const Size(414.0, 736.0)));
    expect(log, isEmpty);

    await tester.fling(find.byType(PageView), const Offset(100.0, 0.0), 800.0);
    await tester.pumpAndSettle();
    expect(log, isEmpty);

    expect(find.text('Alabama'), findsOneWidget);
    expect(find.text('Alaska'), findsOneWidget);
    expect(find.text('Arizona'), findsNothing);
  });

382
  testWidgets('PageView viewportFraction', (WidgetTester tester) async {
383
    PageController controller = PageController(viewportFraction: 7/8);
384 385

    Widget build(PageController controller) {
386
      return Directionality(
387
        textDirection: TextDirection.ltr,
388
        child: PageView.builder(
389 390 391
          controller: controller,
          itemCount: kStates.length,
          itemBuilder: (BuildContext context, int index) {
392
            return Container(
393 394 395 396
              height: 200.0,
              color: index % 2 == 0
                  ? const Color(0xFF0000FF)
                  : const Color(0xFF00FF00),
397
              child: Text(kStates[index]),
398 399 400
            );
          },
        ),
401 402 403 404 405
      );
    }

    await tester.pumpWidget(build(controller));

406 407
    expect(tester.getTopLeft(find.text('Alabama')), const Offset(50.0, 0.0));
    expect(tester.getTopLeft(find.text('Alaska')), const Offset(750.0, 0.0));
408 409 410 411

    controller.jumpToPage(10);
    await tester.pump();

412 413 414
    expect(tester.getTopLeft(find.text('Georgia')), const Offset(-650.0, 0.0));
    expect(tester.getTopLeft(find.text('Hawaii')), const Offset(50.0, 0.0));
    expect(tester.getTopLeft(find.text('Idaho')), const Offset(750.0, 0.0));
415

416
    controller = PageController(viewportFraction: 39/40);
417 418 419

    await tester.pumpWidget(build(controller));

420 421 422
    expect(tester.getTopLeft(find.text('Georgia')), const Offset(-770.0, 0.0));
    expect(tester.getTopLeft(find.text('Hawaii')), const Offset(10.0, 0.0));
    expect(tester.getTopLeft(find.text('Idaho')), const Offset(790.0, 0.0));
423 424
  });

425 426 427 428
  testWidgets('Page snapping disable and reenable', (WidgetTester tester) async {
    final List<int> log = <int>[];

    Widget build({ bool pageSnapping }) {
429
      return Directionality(
430
        textDirection: TextDirection.ltr,
431
        child: PageView(
432 433 434
          pageSnapping: pageSnapping,
          onPageChanged: log.add,
          children:
435
              kStates.map<Widget>((String state) => Text(state)).toList(),
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
        ),
      );
    }

    await tester.pumpWidget(build(pageSnapping: true));
    expect(log, isEmpty);

    // Drag more than halfway to the next page, to confirm the default behavior.
    TestGesture gesture = await tester.startGesture(const Offset(100.0, 100.0));
    // The page view is 800.0 wide, so this move is just beyond halfway.
    await gesture.moveBy(const Offset(-420.0, 0.0));

    expect(log, equals(const <int>[1]));
    log.clear();

    // Release the gesture, confirm that the page settles on the next.
    await gesture.up();
    await tester.pumpAndSettle();

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

    // Disable page snapping, and try moving halfway. Confirm it doesn't snap.
    await tester.pumpWidget(build(pageSnapping: false));
    gesture = await tester.startGesture(const Offset(100.0, 100.0));
    // Move just beyond halfway, again.
    await gesture.moveBy(const Offset(-420.0, 0.0));

    // Page notifications still get sent.
    expect(log, equals(const <int>[2]));
    log.clear();

    // Release the gesture, confirm that both pages are visible.
    await gesture.up();
    await tester.pumpAndSettle();

    expect(find.text('Alabama'), findsNothing);
    expect(find.text('Alaska'), findsOneWidget);
    expect(find.text('Arizona'), findsOneWidget);
    expect(find.text('Arkansas'), findsNothing);

    // Now re-enable snapping, confirm that we've settled on a page.
    await tester.pumpWidget(build(pageSnapping: true));
    await tester.pumpAndSettle();

    expect(log, isEmpty);

    expect(find.text('Alaska'), findsNothing);
    expect(find.text('Arizona'), findsOneWidget);
    expect(find.text('Arkansas'), findsNothing);
  });

488
  testWidgets('PageView small viewportFraction', (WidgetTester tester) async {
489
    final PageController controller = PageController(viewportFraction: 1/8);
490 491

    Widget build(PageController controller) {
492
      return Directionality(
493
        textDirection: TextDirection.ltr,
494
        child: PageView.builder(
495 496 497
          controller: controller,
          itemCount: kStates.length,
          itemBuilder: (BuildContext context, int index) {
498
            return Container(
499 500 501 502
              height: 200.0,
              color: index % 2 == 0
                  ? const Color(0xFF0000FF)
                  : const Color(0xFF00FF00),
503
              child: Text(kStates[index]),
504 505 506
            );
          },
        ),
507 508 509 510 511
      );
    }

    await tester.pumpWidget(build(controller));

512 513 514 515 516
    expect(tester.getTopLeft(find.text('Alabama')), const Offset(350.0, 0.0));
    expect(tester.getTopLeft(find.text('Alaska')), const Offset(450.0, 0.0));
    expect(tester.getTopLeft(find.text('Arizona')), const Offset(550.0, 0.0));
    expect(tester.getTopLeft(find.text('Arkansas')), const Offset(650.0, 0.0));
    expect(tester.getTopLeft(find.text('California')), const Offset(750.0, 0.0));
517 518 519 520

    controller.jumpToPage(10);
    await tester.pump();

521 522 523 524 525 526 527 528 529
    expect(tester.getTopLeft(find.text('Connecticut')), const Offset(-50.0, 0.0));
    expect(tester.getTopLeft(find.text('Delaware')), const Offset(50.0, 0.0));
    expect(tester.getTopLeft(find.text('Florida')), const Offset(150.0, 0.0));
    expect(tester.getTopLeft(find.text('Georgia')), const Offset(250.0, 0.0));
    expect(tester.getTopLeft(find.text('Hawaii')), const Offset(350.0, 0.0));
    expect(tester.getTopLeft(find.text('Idaho')), const Offset(450.0, 0.0));
    expect(tester.getTopLeft(find.text('Illinois')), const Offset(550.0, 0.0));
    expect(tester.getTopLeft(find.text('Indiana')), const Offset(650.0, 0.0));
    expect(tester.getTopLeft(find.text('Iowa')), const Offset(750.0, 0.0));
530 531 532
  });

  testWidgets('PageView large viewportFraction', (WidgetTester tester) async {
533
    final PageController controller =
534
        PageController(viewportFraction: 5/4);
535 536

    Widget build(PageController controller) {
537
      return Directionality(
538
        textDirection: TextDirection.ltr,
539
        child: PageView.builder(
540 541 542
          controller: controller,
          itemCount: kStates.length,
          itemBuilder: (BuildContext context, int index) {
543
            return Container(
544 545 546 547
              height: 200.0,
              color: index % 2 == 0
                  ? const Color(0xFF0000FF)
                  : const Color(0xFF00FF00),
548
              child: Text(kStates[index]),
549 550 551
            );
          },
        ),
552 553 554 555 556
      );
    }

    await tester.pumpWidget(build(controller));

557 558
    expect(tester.getTopLeft(find.text('Alabama')), const Offset(-100.0, 0.0));
    expect(tester.getBottomRight(find.text('Alabama')), const Offset(900.0, 600.0));
559 560 561 562

    controller.jumpToPage(10);
    await tester.pump();

563
    expect(tester.getTopLeft(find.text('Hawaii')), const Offset(-100.0, 0.0));
564
  });
565 566 567

  testWidgets('PageView does not report page changed on overscroll',
      (WidgetTester tester) async {
568
    final PageController controller = PageController(
569 570
      initialPage: kStates.length - 1,
    );
571 572
    int changeIndex = 0;
    Widget build() {
573
      return Directionality(
574
        textDirection: TextDirection.ltr,
575
        child: PageView(
576
          children:
577
              kStates.map<Widget>((String state) => Text(state)).toList(),
578 579 580 581 582
          controller: controller,
          onPageChanged: (int page) {
            changeIndex = page;
          },
        ),
583 584 585 586 587 588 589 590 591 592
      );
    }

    await tester.pumpWidget(build());
    controller.jumpToPage(kStates.length * 2); // try to move beyond max range
    // change index should be zero, shouldn't fire onPageChanged
    expect(changeIndex, 0);
    await tester.pump();
    expect(changeIndex, 0);
  });
593 594 595

  testWidgets('PageView can restore page',
      (WidgetTester tester) async {
596
    final PageController controller = PageController();
597 598 599 600 601 602 603 604 605
    try {
      controller.page;
      fail('Accessing page before attaching should fail.');
    } on AssertionError catch (e) {
      expect(
        e.message,
        'PageController.page cannot be accessed before a PageView is built with it.',
      );
    }
606 607
    final PageStorageBucket bucket = PageStorageBucket();
    await tester.pumpWidget(Directionality(
608
      textDirection: TextDirection.ltr,
609
      child: PageStorage(
610
        bucket: bucket,
611
        child: PageView(
612
          key: const PageStorageKey<String>('PageView'),
613
          controller: controller,
614
          children: const <Widget>[
615 616 617
            Placeholder(),
            Placeholder(),
            Placeholder(),
618 619 620
          ],
        ),
      ),
621
    ));
622 623 624 625 626
    expect(controller.page, 0);
    controller.jumpToPage(2);
    expect(await tester.pumpAndSettle(const Duration(minutes: 1)), 1);
    expect(controller.page, 2);
    await tester.pumpWidget(
627
      PageStorage(
628
        bucket: bucket,
629
        child: Container(),
630 631
      ),
    );
632 633 634 635 636 637 638 639 640
    try {
      controller.page;
      fail('Accessing page after detaching all PageViews should fail.');
    } on AssertionError catch (e) {
      expect(
        e.message,
        'PageController.page cannot be accessed before a PageView is built with it.',
      );
    }
641
    await tester.pumpWidget(Directionality(
642
      textDirection: TextDirection.ltr,
643
      child: PageStorage(
644
        bucket: bucket,
645
        child: PageView(
646
          key: const PageStorageKey<String>('PageView'),
647
          controller: controller,
648
          children: const <Widget>[
649 650 651
            Placeholder(),
            Placeholder(),
            Placeholder(),
652 653 654
          ],
        ),
      ),
655
    ));
656
    expect(controller.page, 2);
657

658 659
    final PageController controller2 = PageController(keepPage: false);
    await tester.pumpWidget(Directionality(
660
      textDirection: TextDirection.ltr,
661
      child: PageStorage(
662
        bucket: bucket,
663
        child: PageView(
664
          key: const PageStorageKey<String>('Check it again against your list and see consistency!'),
665
          controller: controller2,
666
          children: const <Widget>[
667 668 669
            Placeholder(),
            Placeholder(),
            Placeholder(),
670 671 672
          ],
        ),
      ),
673
    ));
674
    expect(controller2.page, 0);
675
  });
676 677

  testWidgets('PageView exposes semantics of children', (WidgetTester tester) async {
678
    final SemanticsTester semantics = SemanticsTester(tester);
679

680 681
    final PageController controller = PageController();
    await tester.pumpWidget(Directionality(
682
      textDirection: TextDirection.ltr,
683
      child: PageView(
684
          controller: controller,
685 686 687
          children: List<Widget>.generate(3, (int i) {
            return Semantics(
              child: Text('Page #$i'),
688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714
              container: true,
            );
          })
        ),
    ));
    expect(controller.page, 0);

    expect(semantics, includesNodeWith(label: 'Page #0'));
    expect(semantics, isNot(includesNodeWith(label: 'Page #1')));
    expect(semantics, isNot(includesNodeWith(label: 'Page #2')));

    controller.jumpToPage(1);
    await tester.pumpAndSettle();

    expect(semantics, isNot(includesNodeWith(label: 'Page #0')));
    expect(semantics, includesNodeWith(label: 'Page #1'));
    expect(semantics, isNot(includesNodeWith(label: 'Page #2')));

    controller.jumpToPage(2);
    await tester.pumpAndSettle();

    expect(semantics, isNot(includesNodeWith(label: 'Page #0')));
    expect(semantics, isNot(includesNodeWith(label: 'Page #1')));
    expect(semantics, includesNodeWith(label: 'Page #2'));

    semantics.dispose();
  });
715 716

  testWidgets('PageMetrics', (WidgetTester tester) async {
717
    final PageMetrics page = PageMetrics(
718 719 720 721 722 723 724 725 726 727 728 729 730
      minScrollExtent: 100.0,
      maxScrollExtent: 200.0,
      pixels: 150.0,
      viewportDimension: 25.0,
      axisDirection: AxisDirection.right,
      viewportFraction: 1.0,
    );
    expect(page.page, 6);
    final PageMetrics page2 = page.copyWith(
      pixels: page.pixels - 100.0,
    );
    expect(page2.page, 4.0);
  });
Adam Barth's avatar
Adam Barth committed
731
}