scrollbar_test.dart 5.23 KB
Newer Older
1 2 3 4 5 6 7 8
// Copyright 2016 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/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_test/flutter_test.dart';

9 10
import '../rendering/mock_canvas.dart';

11 12 13 14 15 16 17 18 19 20 21
class TestCanvas implements Canvas {
  TestCanvas([this.invocations]);

  final List<Invocation> invocations;

  @override
  void noSuchMethod(Invocation invocation) {
    invocations?.add(invocation);
  }
}

22 23
void main() {
  testWidgets('Scrollbar doesn\'t show when tapping list', (WidgetTester tester) async {
24 25 26
    await tester.pumpWidget(new Directionality(
      textDirection: TextDirection.ltr,
      child: new Center(
27 28 29 30 31 32
        child: new Container(
          decoration: new BoxDecoration(
            border: new Border.all(color: const Color(0xFFFFFF00))
          ),
          height: 200.0,
          width: 300.0,
33
          child: new Scrollbar(
34
            child: new ListView(
35
              children: <Widget>[
36 37 38 39 40 41 42 43
                new Container(height: 40.0, child: const Text('0')),
                new Container(height: 40.0, child: const Text('1')),
                new Container(height: 40.0, child: const Text('2')),
                new Container(height: 40.0, child: const Text('3')),
                new Container(height: 40.0, child: const Text('4')),
                new Container(height: 40.0, child: const Text('5')),
                new Container(height: 40.0, child: const Text('6')),
                new Container(height: 40.0, child: const Text('7')),
44 45 46 47 48 49
              ],
            ),
          ),
        ),
      ),
    ));
50 51

    SchedulerBinding.instance.debugAssertNoTransientCallbacks('Building a list with a scrollbar triggered an animation.');
52
    await tester.tap(find.byType(ListView));
53 54 55 56 57
    SchedulerBinding.instance.debugAssertNoTransientCallbacks('Tapping a block with a scrollbar triggered an animation.');
    await tester.pump(const Duration(milliseconds: 200));
    await tester.pump(const Duration(milliseconds: 200));
    await tester.pump(const Duration(milliseconds: 200));
    await tester.pump(const Duration(milliseconds: 200));
58
    await tester.drag(find.byType(ListView), const Offset(0.0, -10.0));
59 60 61 62 63 64
    expect(SchedulerBinding.instance.transientCallbackCount, greaterThan(0));
    await tester.pump(const Duration(milliseconds: 200));
    await tester.pump(const Duration(milliseconds: 200));
    await tester.pump(const Duration(milliseconds: 200));
    await tester.pump(const Duration(milliseconds: 200));
  });
65 66

  testWidgets('ScrollbarPainter does not divide by zero', (WidgetTester tester) async {
67 68 69
    await tester.pumpWidget(new Directionality(
      textDirection: TextDirection.ltr,
      child: new Container(
70 71 72 73 74 75
        height: 200.0,
        width: 300.0,
        child: new Scrollbar(
          child: new ListView(
            children: <Widget>[
              new Container(height: 40.0, child: const Text('0')),
76 77 78 79 80
            ],
          ),
        ),
      ),
    ));
81

82 83 84 85
    final CustomPaint custom = tester.widget(find.descendant(
      of: find.byType(Scrollbar),
      matching: find.byType(CustomPaint)).first
    );
86
    final dynamic scrollPainter = custom.foregroundPainter;
87 88 89 90 91
    // Dragging makes the scrollbar first appear.
    await tester.drag(find.text('0'), const Offset(0.0, -10.0));
    await tester.pump(const Duration(milliseconds: 200));
    await tester.pump(const Duration(milliseconds: 200));

92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
    final ScrollMetrics metrics = new FixedScrollMetrics(
      minScrollExtent: 0.0,
      maxScrollExtent: 0.0,
      pixels: 0.0,
      viewportDimension: 100.0,
      axisDirection: AxisDirection.down
    );
    scrollPainter.update(metrics, AxisDirection.down);

    final List<Invocation> invocations = <Invocation>[];
    final TestCanvas canvas = new TestCanvas(invocations);
    scrollPainter.paint(canvas, const Size(10.0, 100.0));
    final Rect thumbRect = invocations.single.positionalArguments[0];
    expect(thumbRect.isFinite, isTrue);
  });
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141

  testWidgets('Adaptive scrollbar', (WidgetTester tester) async {
    Widget viewWithScroll(TargetPlatform platform) {
      return new Directionality(
        textDirection: TextDirection.ltr,
        child: new Theme(
          data: new ThemeData(
            platform: platform
          ),
          child: new Scrollbar(
            child: new SingleChildScrollView(
              child: const SizedBox(width: 4000.0, height: 4000.0),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(viewWithScroll(TargetPlatform.android));
    await tester.drag(find.byType(SingleChildScrollView), const Offset(0.0, -10.0));
    await tester.pump();
    // Scrollbar fully showing
    await tester.pump(const Duration(milliseconds: 500));
    expect(find.byType(Scrollbar), paints..rect());

    await tester.pumpWidget(viewWithScroll(TargetPlatform.iOS));
    final TestGesture gesture = await tester.startGesture(
      tester.getCenter(find.byType(SingleChildScrollView))
    );
    await gesture.moveBy(const Offset(0.0, -10.0));
    await tester.drag(find.byType(SingleChildScrollView), const Offset(0.0, -10.0));
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 200));
    expect(find.byType(Scrollbar), paints..rrect());
  });
142
}