ensure_visible_test.dart 27.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 'dart:math' as math;

import 'package:flutter_test/flutter_test.dart';
8
import 'package:flutter/rendering.dart';
9 10 11 12 13
import 'package:flutter/widgets.dart';

Finder findKey(int i) => find.byKey(new ValueKey<int>(i));

Widget buildSingleChildScrollView(Axis scrollDirection, { bool reverse: false }) {
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
  return new Directionality(
    textDirection: TextDirection.ltr,
    child: new Center(
      child: new SizedBox(
        width: 600.0,
        height: 400.0,
        child: new SingleChildScrollView(
          scrollDirection: scrollDirection,
          reverse: reverse,
          child: new ListBody(
            mainAxis: scrollDirection,
            children: <Widget>[
              new Container(key: const ValueKey<int>(0), width: 200.0, height: 200.0),
              new Container(key: const ValueKey<int>(1), width: 200.0, height: 200.0),
              new Container(key: const ValueKey<int>(2), width: 200.0, height: 200.0),
              new Container(key: const ValueKey<int>(3), width: 200.0, height: 200.0),
              new Container(key: const ValueKey<int>(4), width: 200.0, height: 200.0),
              new Container(key: const ValueKey<int>(5), width: 200.0, height: 200.0),
              new Container(key: const ValueKey<int>(6), width: 200.0, height: 200.0),
            ],
          ),
        ),
      ),
    ),
  );
}

Widget buildListView(Axis scrollDirection, { bool reverse: false, bool shrinkWrap: false }) {
  return new Directionality(
    textDirection: TextDirection.ltr,
    child: new Center(
      child: new SizedBox(
        width: 600.0,
        height: 400.0,
        child: new ListView(
          scrollDirection: scrollDirection,
          reverse: reverse,
          shrinkWrap: shrinkWrap,
52
          children: <Widget>[
53 54 55 56 57 58 59
            new Container(key: const ValueKey<int>(0), width: 200.0, height: 200.0),
            new Container(key: const ValueKey<int>(1), width: 200.0, height: 200.0),
            new Container(key: const ValueKey<int>(2), width: 200.0, height: 200.0),
            new Container(key: const ValueKey<int>(3), width: 200.0, height: 200.0),
            new Container(key: const ValueKey<int>(4), width: 200.0, height: 200.0),
            new Container(key: const ValueKey<int>(5), width: 200.0, height: 200.0),
            new Container(key: const ValueKey<int>(6), width: 200.0, height: 200.0),
60 61 62 63 64 65 66
          ],
        ),
      ),
    ),
  );
}

67
void main() {
68

69 70 71
  group('SingleChildScollView', () {
    testWidgets('SingleChildScollView ensureVisible Axis.vertical', (WidgetTester tester) async {
      BuildContext findContext(int i) => tester.element(findKey(i));
72

73
      await tester.pumpWidget(buildSingleChildScrollView(Axis.vertical));
74

Adam Barth's avatar
Adam Barth committed
75
      Scrollable.ensureVisible(findContext(3));
76
      await tester.pump();
77
      expect(tester.getTopLeft(findKey(3)).dy, equals(100.0));
78

Adam Barth's avatar
Adam Barth committed
79
      Scrollable.ensureVisible(findContext(6));
80
      await tester.pump();
81
      expect(tester.getTopLeft(findKey(6)).dy, equals(300.0));
82

Adam Barth's avatar
Adam Barth committed
83
      Scrollable.ensureVisible(findContext(4), alignment: 1.0);
84
      await tester.pump();
85
      expect(tester.getBottomRight(findKey(4)).dy, equals(500.0));
86

Adam Barth's avatar
Adam Barth committed
87
      Scrollable.ensureVisible(findContext(0), alignment: 1.0);
88
      await tester.pump();
89
      expect(tester.getTopLeft(findKey(0)).dy, equals(100.0));
90

Adam Barth's avatar
Adam Barth committed
91
      Scrollable.ensureVisible(findContext(3), duration: const Duration(seconds: 1));
92 93
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 1020));
94
      expect(tester.getTopLeft(findKey(3)).dy, equals(100.0));
95 96 97 98 99 100 101
    });

    testWidgets('SingleChildScollView ensureVisible Axis.horizontal', (WidgetTester tester) async {
      BuildContext findContext(int i) => tester.element(findKey(i));

      await tester.pumpWidget(buildSingleChildScrollView(Axis.horizontal));

Adam Barth's avatar
Adam Barth committed
102
      Scrollable.ensureVisible(findContext(3));
103
      await tester.pump();
104
      expect(tester.getTopLeft(findKey(3)).dx, equals(100.0));
105

Adam Barth's avatar
Adam Barth committed
106
      Scrollable.ensureVisible(findContext(6));
107
      await tester.pump();
108
      expect(tester.getTopLeft(findKey(6)).dx, equals(500.0));
109

Adam Barth's avatar
Adam Barth committed
110
      Scrollable.ensureVisible(findContext(4), alignment: 1.0);
111
      await tester.pump();
112
      expect(tester.getBottomRight(findKey(4)).dx, equals(700.0));
113

Adam Barth's avatar
Adam Barth committed
114
      Scrollable.ensureVisible(findContext(0), alignment: 1.0);
115
      await tester.pump();
116
      expect(tester.getTopLeft(findKey(0)).dx, equals(100.0));
117

Adam Barth's avatar
Adam Barth committed
118
      Scrollable.ensureVisible(findContext(3), duration: const Duration(seconds: 1));
119 120
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 1020));
121
      expect(tester.getTopLeft(findKey(3)).dx, equals(100.0));
122 123 124 125 126 127 128
    });

    testWidgets('SingleChildScollView ensureVisible Axis.vertical reverse', (WidgetTester tester) async {
      BuildContext findContext(int i) => tester.element(findKey(i));

      await tester.pumpWidget(buildSingleChildScrollView(Axis.vertical, reverse: true));

Adam Barth's avatar
Adam Barth committed
129
      Scrollable.ensureVisible(findContext(3));
130
      await tester.pump();
131
      expect(tester.getBottomRight(findKey(3)).dy, equals(500.0));
132

Adam Barth's avatar
Adam Barth committed
133
      Scrollable.ensureVisible(findContext(0));
134
      await tester.pump();
135
      expect(tester.getBottomRight(findKey(0)).dy, equals(300.0));
136

Adam Barth's avatar
Adam Barth committed
137
      Scrollable.ensureVisible(findContext(2), alignment: 1.0);
138
      await tester.pump();
139
      expect(tester.getTopLeft(findKey(2)).dy, equals(100.0));
140

Adam Barth's avatar
Adam Barth committed
141
      Scrollable.ensureVisible(findContext(6), alignment: 1.0);
142
      await tester.pump();
143
      expect(tester.getBottomRight(findKey(6)).dy, equals(500.0));
144

Adam Barth's avatar
Adam Barth committed
145
      Scrollable.ensureVisible(findContext(3), duration: const Duration(seconds: 1));
146 147
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 1020));
148
      expect(tester.getBottomRight(findKey(3)).dy, equals(500.0));
149 150 151 152 153 154 155
    });

    testWidgets('SingleChildScollView ensureVisible Axis.horizontal reverse', (WidgetTester tester) async {
      BuildContext findContext(int i) => tester.element(findKey(i));

      await tester.pumpWidget(buildSingleChildScrollView(Axis.horizontal, reverse: true));

Adam Barth's avatar
Adam Barth committed
156
      Scrollable.ensureVisible(findContext(3));
157
      await tester.pump();
158
      expect(tester.getBottomRight(findKey(3)).dx, equals(700.0));
159

Adam Barth's avatar
Adam Barth committed
160
      Scrollable.ensureVisible(findContext(0));
161
      await tester.pump();
162
      expect(tester.getBottomRight(findKey(0)).dx, equals(300.0));
163

Adam Barth's avatar
Adam Barth committed
164
      Scrollable.ensureVisible(findContext(2), alignment: 1.0);
165
      await tester.pump();
166
      expect(tester.getTopLeft(findKey(2)).dx, equals(100.0));
167

Adam Barth's avatar
Adam Barth committed
168
      Scrollable.ensureVisible(findContext(6), alignment: 1.0);
169
      await tester.pump();
170
      expect(tester.getBottomRight(findKey(6)).dx, equals(700.0));
171

Adam Barth's avatar
Adam Barth committed
172
      Scrollable.ensureVisible(findContext(3), duration: const Duration(seconds: 1));
173 174
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 1020));
175
      expect(tester.getBottomRight(findKey(3)).dx, equals(700.0));
176 177 178 179 180 181 182 183 184 185 186
    });

    testWidgets('SingleChildScollView ensureVisible rotated child', (WidgetTester tester) async {
      BuildContext findContext(int i) => tester.element(findKey(i));

      await tester.pumpWidget(
        new Center(
          child: new SizedBox(
            width: 600.0,
            height: 400.0,
            child: new SingleChildScrollView(
187
              child: new ListBody(
188 189 190 191 192 193 194 195 196 197
                children: <Widget>[
                  new Container(height: 200.0),
                  new Container(height: 200.0),
                  new Container(height: 200.0),
                  new Container(
                    height: 200.0,
                    child: new Center(
                      child: new Transform(
                        transform: new Matrix4.rotationZ(math.PI),
                        child: new Container(
198
                          key: const ValueKey<int>(0),
199 200
                          width: 100.0,
                          height: 100.0,
201
                          color: const Color(0xFFFFFFFF),
202 203 204 205 206 207 208 209 210 211 212 213 214
                        ),
                      ),
                    ),
                  ),
                  new Container(height: 200.0),
                  new Container(height: 200.0),
                  new Container(height: 200.0),
                ],
              ),
            ),
          ),
        )
      );
215

Adam Barth's avatar
Adam Barth committed
216
      Scrollable.ensureVisible(findContext(0));
217
      await tester.pump();
218
      expect(tester.getBottomRight(findKey(0)).dy, closeTo(100.0, 0.1));
219

Adam Barth's avatar
Adam Barth committed
220
      Scrollable.ensureVisible(findContext(0), alignment: 1.0);
221
      await tester.pump();
222
      expect(tester.getTopLeft(findKey(0)).dy, closeTo(500.0, 0.1));
223
    });
224 225
  });

226 227 228 229
  group('ListView', () {
    testWidgets('ListView ensureVisible Axis.vertical', (WidgetTester tester) async {
      BuildContext findContext(int i) => tester.element(findKey(i));
      Future<Null> prepare(double offset) async {
Adam Barth's avatar
Adam Barth committed
230
        tester.state<ScrollableState>(find.byType(Scrollable)).position.jumpTo(offset);
231 232 233 234 235 236
        await tester.pump();
      }

      await tester.pumpWidget(buildListView(Axis.vertical));

      await prepare(480.0);
Adam Barth's avatar
Adam Barth committed
237
      Scrollable.ensureVisible(findContext(3));
238
      await tester.pump();
239
      expect(tester.getTopLeft(findKey(3)).dy, equals(100.0));
240 241

      await prepare(1083.0);
Adam Barth's avatar
Adam Barth committed
242
      Scrollable.ensureVisible(findContext(6));
243
      await tester.pump();
244
      expect(tester.getTopLeft(findKey(6)).dy, equals(300.0));
245 246

      await prepare(735.0);
Adam Barth's avatar
Adam Barth committed
247
      Scrollable.ensureVisible(findContext(4), alignment: 1.0);
248
      await tester.pump();
249
      expect(tester.getBottomRight(findKey(4)).dy, equals(500.0));
250 251

      await prepare(123.0);
Adam Barth's avatar
Adam Barth committed
252
      Scrollable.ensureVisible(findContext(0), alignment: 1.0);
253
      await tester.pump();
254
      expect(tester.getTopLeft(findKey(0)).dy, equals(100.0));
255 256

      await prepare(523.0);
Adam Barth's avatar
Adam Barth committed
257
      Scrollable.ensureVisible(findContext(3), duration: const Duration(seconds: 1));
258 259
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 1020));
260
      expect(tester.getTopLeft(findKey(3)).dy, equals(100.0));
261 262 263 264 265
    });

    testWidgets('ListView ensureVisible Axis.horizontal', (WidgetTester tester) async {
      BuildContext findContext(int i) => tester.element(findKey(i));
      Future<Null> prepare(double offset) async {
Adam Barth's avatar
Adam Barth committed
266
        tester.state<ScrollableState>(find.byType(Scrollable)).position.jumpTo(offset);
267 268 269 270 271 272
        await tester.pump();
      }

      await tester.pumpWidget(buildListView(Axis.horizontal));

      await prepare(23.0);
Adam Barth's avatar
Adam Barth committed
273
      Scrollable.ensureVisible(findContext(3));
274
      await tester.pump();
275
      expect(tester.getTopLeft(findKey(3)).dx, equals(100.0));
276 277

      await prepare(843.0);
Adam Barth's avatar
Adam Barth committed
278
      Scrollable.ensureVisible(findContext(6));
279
      await tester.pump();
280
      expect(tester.getTopLeft(findKey(6)).dx, equals(500.0));
281 282

      await prepare(415.0);
Adam Barth's avatar
Adam Barth committed
283
      Scrollable.ensureVisible(findContext(4), alignment: 1.0);
284
      await tester.pump();
285
      expect(tester.getBottomRight(findKey(4)).dx, equals(700.0));
286 287

      await prepare(46.0);
Adam Barth's avatar
Adam Barth committed
288
      Scrollable.ensureVisible(findContext(0), alignment: 1.0);
289
      await tester.pump();
290
      expect(tester.getTopLeft(findKey(0)).dx, equals(100.0));
291 292

      await prepare(211.0);
Adam Barth's avatar
Adam Barth committed
293
      Scrollable.ensureVisible(findContext(3), duration: const Duration(seconds: 1));
294 295
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 1020));
296
      expect(tester.getTopLeft(findKey(3)).dx, equals(100.0));
297 298 299 300 301
    });

    testWidgets('ListView ensureVisible Axis.vertical reverse', (WidgetTester tester) async {
      BuildContext findContext(int i) => tester.element(findKey(i));
      Future<Null> prepare(double offset) async {
Adam Barth's avatar
Adam Barth committed
302
        tester.state<ScrollableState>(find.byType(Scrollable)).position.jumpTo(offset);
303 304 305 306 307 308
        await tester.pump();
      }

      await tester.pumpWidget(buildListView(Axis.vertical, reverse: true));

      await prepare(211.0);
Adam Barth's avatar
Adam Barth committed
309
      Scrollable.ensureVisible(findContext(3));
310
      await tester.pump();
311
      expect(tester.getBottomRight(findKey(3)).dy, equals(500.0));
312 313

      await prepare(23.0);
Adam Barth's avatar
Adam Barth committed
314
      Scrollable.ensureVisible(findContext(0));
315
      await tester.pump();
316
      expect(tester.getBottomRight(findKey(0)).dy, equals(500.0));
317 318

      await prepare(230.0);
Adam Barth's avatar
Adam Barth committed
319
      Scrollable.ensureVisible(findContext(2), alignment: 1.0);
320
      await tester.pump();
321
      expect(tester.getTopLeft(findKey(2)).dy, equals(100.0));
322 323

      await prepare(1083.0);
Adam Barth's avatar
Adam Barth committed
324
      Scrollable.ensureVisible(findContext(6), alignment: 1.0);
325
      await tester.pump();
326
      expect(tester.getBottomRight(findKey(6)).dy, equals(300.0));
327 328

      await prepare(345.0);
Adam Barth's avatar
Adam Barth committed
329
      Scrollable.ensureVisible(findContext(3), duration: const Duration(seconds: 1));
330 331
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 1020));
332
      expect(tester.getBottomRight(findKey(3)).dy, equals(500.0));
333 334 335 336 337
    });

    testWidgets('ListView ensureVisible Axis.horizontal reverse', (WidgetTester tester) async {
      BuildContext findContext(int i) => tester.element(findKey(i));
      Future<Null> prepare(double offset) async {
Adam Barth's avatar
Adam Barth committed
338
        tester.state<ScrollableState>(find.byType(Scrollable)).position.jumpTo(offset);
339 340 341 342 343 344
        await tester.pump();
      }

      await tester.pumpWidget(buildListView(Axis.horizontal, reverse: true));

      await prepare(211.0);
Adam Barth's avatar
Adam Barth committed
345
      Scrollable.ensureVisible(findContext(3));
346
      await tester.pump();
347
      expect(tester.getBottomRight(findKey(3)).dx, equals(700.0));
348 349

      await prepare(23.0);
Adam Barth's avatar
Adam Barth committed
350
      Scrollable.ensureVisible(findContext(0));
351
      await tester.pump();
352
      expect(tester.getBottomRight(findKey(0)).dx, equals(700.0));
353 354

      await prepare(230.0);
Adam Barth's avatar
Adam Barth committed
355
      Scrollable.ensureVisible(findContext(2), alignment: 1.0);
356
      await tester.pump();
357
      expect(tester.getTopLeft(findKey(2)).dx, equals(100.0));
358 359

      await prepare(1083.0);
Adam Barth's avatar
Adam Barth committed
360
      Scrollable.ensureVisible(findContext(6), alignment: 1.0);
361
      await tester.pump();
362
      expect(tester.getBottomRight(findKey(6)).dx, equals(300.0));
363 364

      await prepare(345.0);
Adam Barth's avatar
Adam Barth committed
365
      Scrollable.ensureVisible(findContext(3), duration: const Duration(seconds: 1));
366 367
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 1020));
368
      expect(tester.getBottomRight(findKey(3)).dx, equals(700.0));
369 370 371 372 373 374
    });

    // TODO(abarth): Unskip this test. See https://github.com/flutter/flutter/issues/7919
    testWidgets('ListView ensureVisible negative child', (WidgetTester tester) async {
      BuildContext findContext(int i) => tester.element(findKey(i));
      Future<Null> prepare(double offset) async {
Adam Barth's avatar
Adam Barth committed
375
        tester.state<ScrollableState>(find.byType(Scrollable)).position.jumpTo(offset);
376 377 378 379
        await tester.pump();
      }

      double getOffset() {
Adam Barth's avatar
Adam Barth committed
380
        return tester.state<ScrollableState>(find.byType(Scrollable)).position.pixels;
381 382 383 384 385 386 387 388 389
      }

      Widget buildSliver(int i) {
        return new SliverToBoxAdapter(
          key: new ValueKey<int>(i),
          child: new Container(width: 200.0, height: 200.0),
        );
      }

390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
      await tester.pumpWidget(
        new Directionality(
          textDirection: TextDirection.ltr,
          child: new Center(
            child: new SizedBox(
              width: 600.0,
              height: 400.0,
              child: new Scrollable(
                viewportBuilder: (BuildContext context, ViewportOffset offset) {
                  return new Viewport(
                    offset: offset,
                    center: const ValueKey<int>(4),
                    slivers: <Widget>[
                      buildSliver(0),
                      buildSliver(1),
                      buildSliver(2),
                      buildSliver(3),
                      buildSliver(4),
                      buildSliver(5),
                      buildSliver(6),
                    ],
                  );
                },
              ),
            ),
415 416
          ),
        ),
417
      );
418 419

      await prepare(-125.0);
Adam Barth's avatar
Adam Barth committed
420
      Scrollable.ensureVisible(findContext(3));
421 422 423 424
      await tester.pump();
      expect(getOffset(), equals(-200.0));

      await prepare(-225.0);
Adam Barth's avatar
Adam Barth committed
425
      Scrollable.ensureVisible(findContext(2));
426 427 428 429 430 431 432
      await tester.pump();
      expect(getOffset(), equals(-400.0));
    }, skip: true);

    testWidgets('ListView ensureVisible rotated child', (WidgetTester tester) async {
      BuildContext findContext(int i) => tester.element(findKey(i));
      Future<Null> prepare(double offset) async {
Adam Barth's avatar
Adam Barth committed
433
        tester.state<ScrollableState>(find.byType(Scrollable)).position.jumpTo(offset);
434 435 436
        await tester.pump();
      }

437 438 439
      await tester.pumpWidget(new Directionality(
        textDirection: TextDirection.ltr,
        child: new Center(
440 441 442 443
          child: new SizedBox(
            width: 600.0,
            height: 400.0,
            child: new ListView(
444 445 446 447 448 449 450 451 452 453
              children: <Widget>[
                new Container(height: 200.0),
                new Container(height: 200.0),
                new Container(height: 200.0),
                new Container(
                  height: 200.0,
                  child: new Center(
                    child: new Transform(
                      transform: new Matrix4.rotationZ(math.PI),
                      child: new Container(
454
                        key: const ValueKey<int>(0),
455 456
                        width: 100.0,
                        height: 100.0,
457
                        color: const Color(0xFFFFFFFF),
458 459 460 461 462 463 464 465 466 467
                      ),
                    ),
                  ),
                ),
                new Container(height: 200.0),
                new Container(height: 200.0),
                new Container(height: 200.0),
              ],
            ),
          ),
468
        )
469
      ));
470 471

      await prepare(321.0);
Adam Barth's avatar
Adam Barth committed
472
      Scrollable.ensureVisible(findContext(0));
473
      await tester.pump();
474
      expect(tester.getBottomRight(findKey(0)).dy, closeTo(100.0, 0.1));
475

Adam Barth's avatar
Adam Barth committed
476
      Scrollable.ensureVisible(findContext(0), alignment: 1.0);
477
      await tester.pump();
478
      expect(tester.getTopLeft(findKey(0)).dy, closeTo(500.0, 0.1));
479
    });
480 481
  });

482 483 484 485
  group('ListView shrinkWrap', () {
    testWidgets('ListView ensureVisible Axis.vertical', (WidgetTester tester) async {
      BuildContext findContext(int i) => tester.element(findKey(i));
      Future<Null> prepare(double offset) async {
Adam Barth's avatar
Adam Barth committed
486
        tester.state<ScrollableState>(find.byType(Scrollable)).position.jumpTo(offset);
487 488 489 490 491 492
        await tester.pump();
      }

      await tester.pumpWidget(buildListView(Axis.vertical, shrinkWrap: true));

      await prepare(480.0);
Adam Barth's avatar
Adam Barth committed
493
      Scrollable.ensureVisible(findContext(3));
494
      await tester.pump();
495
      expect(tester.getTopLeft(findKey(3)).dy, equals(100.0));
496 497

      await prepare(1083.0);
Adam Barth's avatar
Adam Barth committed
498
      Scrollable.ensureVisible(findContext(6));
499
      await tester.pump();
500
      expect(tester.getTopLeft(findKey(6)).dy, equals(300.0));
501 502

      await prepare(735.0);
Adam Barth's avatar
Adam Barth committed
503
      Scrollable.ensureVisible(findContext(4), alignment: 1.0);
504
      await tester.pump();
505
      expect(tester.getBottomRight(findKey(4)).dy, equals(500.0));
506 507

      await prepare(123.0);
Adam Barth's avatar
Adam Barth committed
508
      Scrollable.ensureVisible(findContext(0), alignment: 1.0);
509
      await tester.pump();
510
      expect(tester.getTopLeft(findKey(0)).dy, equals(100.0));
511 512

      await prepare(523.0);
Adam Barth's avatar
Adam Barth committed
513
      Scrollable.ensureVisible(findContext(3), duration: const Duration(seconds: 1));
514 515
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 1020));
516
      expect(tester.getTopLeft(findKey(3)).dy, equals(100.0));
517 518 519 520 521
    });

    testWidgets('ListView ensureVisible Axis.horizontal', (WidgetTester tester) async {
      BuildContext findContext(int i) => tester.element(findKey(i));
      Future<Null> prepare(double offset) async {
Adam Barth's avatar
Adam Barth committed
522
        tester.state<ScrollableState>(find.byType(Scrollable)).position.jumpTo(offset);
523 524 525 526 527 528
        await tester.pump();
      }

      await tester.pumpWidget(buildListView(Axis.horizontal, shrinkWrap: true));

      await prepare(23.0);
Adam Barth's avatar
Adam Barth committed
529
      Scrollable.ensureVisible(findContext(3));
530
      await tester.pump();
531
      expect(tester.getTopLeft(findKey(3)).dx, equals(100.0));
532 533

      await prepare(843.0);
Adam Barth's avatar
Adam Barth committed
534
      Scrollable.ensureVisible(findContext(6));
535
      await tester.pump();
536
      expect(tester.getTopLeft(findKey(6)).dx, equals(500.0));
537 538

      await prepare(415.0);
Adam Barth's avatar
Adam Barth committed
539
      Scrollable.ensureVisible(findContext(4), alignment: 1.0);
540
      await tester.pump();
541
      expect(tester.getBottomRight(findKey(4)).dx, equals(700.0));
542 543

      await prepare(46.0);
Adam Barth's avatar
Adam Barth committed
544
      Scrollable.ensureVisible(findContext(0), alignment: 1.0);
545
      await tester.pump();
546
      expect(tester.getTopLeft(findKey(0)).dx, equals(100.0));
547 548

      await prepare(211.0);
Adam Barth's avatar
Adam Barth committed
549
      Scrollable.ensureVisible(findContext(3), duration: const Duration(seconds: 1));
550 551
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 1020));
552
      expect(tester.getTopLeft(findKey(3)).dx, equals(100.0));
553 554 555 556 557
    });

    testWidgets('ListView ensureVisible Axis.vertical reverse', (WidgetTester tester) async {
      BuildContext findContext(int i) => tester.element(findKey(i));
      Future<Null> prepare(double offset) async {
Adam Barth's avatar
Adam Barth committed
558
        tester.state<ScrollableState>(find.byType(Scrollable)).position.jumpTo(offset);
559 560 561 562 563 564
        await tester.pump();
      }

      await tester.pumpWidget(buildListView(Axis.vertical, reverse: true, shrinkWrap: true));

      await prepare(211.0);
Adam Barth's avatar
Adam Barth committed
565
      Scrollable.ensureVisible(findContext(3));
566
      await tester.pump();
567
      expect(tester.getBottomRight(findKey(3)).dy, equals(500.0));
568 569

      await prepare(23.0);
Adam Barth's avatar
Adam Barth committed
570
      Scrollable.ensureVisible(findContext(0));
571
      await tester.pump();
572
      expect(tester.getBottomRight(findKey(0)).dy, equals(500.0));
573 574

      await prepare(230.0);
Adam Barth's avatar
Adam Barth committed
575
      Scrollable.ensureVisible(findContext(2), alignment: 1.0);
576
      await tester.pump();
577
      expect(tester.getTopLeft(findKey(2)).dy, equals(100.0));
578 579

      await prepare(1083.0);
Adam Barth's avatar
Adam Barth committed
580
      Scrollable.ensureVisible(findContext(6), alignment: 1.0);
581
      await tester.pump();
582
      expect(tester.getBottomRight(findKey(6)).dy, equals(300.0));
583 584

      await prepare(345.0);
Adam Barth's avatar
Adam Barth committed
585
      Scrollable.ensureVisible(findContext(3), duration: const Duration(seconds: 1));
586 587
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 1020));
588
      expect(tester.getBottomRight(findKey(3)).dy, equals(500.0));
589 590 591 592 593
    });

    testWidgets('ListView ensureVisible Axis.horizontal reverse', (WidgetTester tester) async {
      BuildContext findContext(int i) => tester.element(findKey(i));
      Future<Null> prepare(double offset) async {
Adam Barth's avatar
Adam Barth committed
594
        tester.state<ScrollableState>(find.byType(Scrollable)).position.jumpTo(offset);
595 596 597 598 599 600
        await tester.pump();
      }

      await tester.pumpWidget(buildListView(Axis.horizontal, reverse: true, shrinkWrap: true));

      await prepare(211.0);
Adam Barth's avatar
Adam Barth committed
601
      Scrollable.ensureVisible(findContext(3));
602
      await tester.pump();
603
      expect(tester.getBottomRight(findKey(3)).dx, equals(700.0));
604 605

      await prepare(23.0);
Adam Barth's avatar
Adam Barth committed
606
      Scrollable.ensureVisible(findContext(0));
607
      await tester.pump();
608
      expect(tester.getBottomRight(findKey(0)).dx, equals(700.0));
609 610

      await prepare(230.0);
Adam Barth's avatar
Adam Barth committed
611
      Scrollable.ensureVisible(findContext(2), alignment: 1.0);
612
      await tester.pump();
613
      expect(tester.getTopLeft(findKey(2)).dx, equals(100.0));
614 615

      await prepare(1083.0);
Adam Barth's avatar
Adam Barth committed
616
      Scrollable.ensureVisible(findContext(6), alignment: 1.0);
617
      await tester.pump();
618
      expect(tester.getBottomRight(findKey(6)).dx, equals(300.0));
619 620

      await prepare(345.0);
Adam Barth's avatar
Adam Barth committed
621
      Scrollable.ensureVisible(findContext(3), duration: const Duration(seconds: 1));
622 623
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 1020));
624
      expect(tester.getBottomRight(findKey(3)).dx, equals(700.0));
625 626
    });
  });
627 628 629 630 631 632 633 634 635

  group('Scrollable with center', () {
    testWidgets('ensureVisible', (WidgetTester tester) async {
      BuildContext findContext(int i) => tester.element(findKey(i));
      Future<Null> prepare(double offset) async {
        tester.state<ScrollableState>(find.byType(Scrollable)).position.jumpTo(offset);
        await tester.pump();
      }

636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666
      await tester.pumpWidget(
        new Directionality(
          textDirection: TextDirection.ltr,
          child: new Center(
            child: new SizedBox(
              width: 600.0,
              height: 400.0,
              child: new Scrollable(
                viewportBuilder: (BuildContext context, ViewportOffset offset) {
                  return new Viewport(
                    offset: offset,
                    center: const ValueKey<String>('center'),
                    slivers: <Widget>[
                      new SliverToBoxAdapter(child: new Container(key: const ValueKey<int>(-6), width: 200.0, height: 200.0)),
                      new SliverToBoxAdapter(child: new Container(key: const ValueKey<int>(-5), width: 200.0, height: 200.0)),
                      new SliverToBoxAdapter(child: new Container(key: const ValueKey<int>(-4), width: 200.0, height: 200.0)),
                      new SliverToBoxAdapter(child: new Container(key: const ValueKey<int>(-3), width: 200.0, height: 200.0)),
                      new SliverToBoxAdapter(child: new Container(key: const ValueKey<int>(-2), width: 200.0, height: 200.0)),
                      new SliverToBoxAdapter(child: new Container(key: const ValueKey<int>(-1), width: 200.0, height: 200.0)),
                      new SliverToBoxAdapter(child: new Container(key: const ValueKey<int>(0), width: 200.0, height: 200.0), key: const ValueKey<String>('center')),
                      new SliverToBoxAdapter(child: new Container(key: const ValueKey<int>(1), width: 200.0, height: 200.0)),
                      new SliverToBoxAdapter(child: new Container(key: const ValueKey<int>(2), width: 200.0, height: 200.0)),
                      new SliverToBoxAdapter(child: new Container(key: const ValueKey<int>(3), width: 200.0, height: 200.0)),
                      new SliverToBoxAdapter(child: new Container(key: const ValueKey<int>(4), width: 200.0, height: 200.0)),
                      new SliverToBoxAdapter(child: new Container(key: const ValueKey<int>(5), width: 200.0, height: 200.0)),
                      new SliverToBoxAdapter(child: new Container(key: const ValueKey<int>(6), width: 200.0, height: 200.0)),
                    ],
                  );
                },
              ),
            ),
667 668
          ),
        ),
669
      );
670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 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 715 716 717 718 719

      await prepare(480.0);
      Scrollable.ensureVisible(findContext(3));
      await tester.pump();
      expect(tester.getTopLeft(findKey(3)).dy, equals(100.0));

      await prepare(1083.0);
      Scrollable.ensureVisible(findContext(6));
      await tester.pump();
      expect(tester.getTopLeft(findKey(6)).dy, equals(300.0));

      await prepare(735.0);
      Scrollable.ensureVisible(findContext(4), alignment: 1.0);
      await tester.pump();
      expect(tester.getBottomRight(findKey(4)).dy, equals(500.0));

      await prepare(123.0);
      Scrollable.ensureVisible(findContext(0), alignment: 1.0);
      await tester.pump();
      expect(tester.getBottomRight(findKey(0)).dy, equals(500.0));

      await prepare(523.0);
      Scrollable.ensureVisible(findContext(3), duration: const Duration(seconds: 1));
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 1020));
      expect(tester.getTopLeft(findKey(3)).dy, equals(100.0));


      await prepare(-480.0);
      Scrollable.ensureVisible(findContext(-3));
      await tester.pump();
      expect(tester.getTopLeft(findKey(-3)).dy, equals(100.0));

      await prepare(-1083.0);
      Scrollable.ensureVisible(findContext(-6));
      await tester.pump();
      expect(tester.getTopLeft(findKey(-6)).dy, equals(100.0));

      await prepare(-735.0);
      Scrollable.ensureVisible(findContext(-4), alignment: 1.0);
      await tester.pump();
      expect(tester.getBottomRight(findKey(-4)).dy, equals(500.0));

      await prepare(-523.0);
      Scrollable.ensureVisible(findContext(-3), duration: const Duration(seconds: 1));
      await tester.pump();
      await tester.pump(const Duration(milliseconds: 1020));
      expect(tester.getTopLeft(findKey(-3)).dy, equals(100.0));
    });
  });
720
}