clamp_overscrolls_test.dart 4.66 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4 5
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

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

// Assuming that the test container is 800x600. The height of the
// viewport's contents is 650.0, the top and bottom text children
// are 100 pixels high and top/left edge of both widgets are visible.
// The top of the bottom widget is at 550 (the top of the top widget
// is at 0). The top of the bottom widget is 500 when it has been
// scrolled completely into view.
14
Widget buildFrame(ScrollPhysics physics, { ScrollController? scrollController }) {
15 16
  return SingleChildScrollView(
    key: UniqueKey(),
17
    physics: physics,
18
    controller: scrollController,
19
    child: SizedBox(
20
      height: 650.0,
21
      child: Column(
22
        crossAxisAlignment: CrossAxisAlignment.start,
23
        textDirection: TextDirection.ltr,
24
        children: <Widget>[
25
          const SizedBox(height: 100.0, child: Text('top', textDirection: TextDirection.ltr)),
26
          Expanded(child: Container()),
27
          const SizedBox(height: 100.0, child: Text('bottom', textDirection: TextDirection.ltr)),
28 29 30
        ],
      ),
    ),
31 32 33 34
  );
}

void main() {
35
  testWidgets('ClampingScrollPhysics', (WidgetTester tester) async {
36 37 38

    // Scroll the target text widget by offset and then return its origin
    // in global coordinates.
39
    Future<Offset> locationAfterScroll(String target, Offset offset) async {
40
      await tester.dragFrom(tester.getTopLeft(find.text(target)), offset);
41 42
      await tester.pump();
      final RenderBox textBox = tester.renderObject(find.text(target));
43
      final Offset widgetOrigin = textBox.localToGlobal(Offset.zero);
44
      await tester.pump(const Duration(seconds: 1)); // Allow overscroll to settle
45
      return Future<Offset>.value(widgetOrigin);
46 47
    }

48
    await tester.pumpWidget(buildFrame(const BouncingScrollPhysics()));
49 50
    Offset origin = await locationAfterScroll('top', const Offset(0.0, 400.0));
    expect(origin.dy, greaterThan(0.0));
51
    origin = await locationAfterScroll('bottom', const Offset(0.0, -400.0));
52
    expect(origin.dy, lessThan(500.0));
53 54


55
    await tester.pumpWidget(buildFrame(const ClampingScrollPhysics()));
56
    origin = await locationAfterScroll('top', const Offset(0.0, 400.0));
57
    expect(origin.dy, equals(0.0));
58
    origin = await locationAfterScroll('bottom', const Offset(0.0, -400.0));
59
    expect(origin.dy, equals(500.0));
60
  });
61

62
  testWidgets('ClampingScrollPhysics affects ScrollPosition', (WidgetTester tester) async {
63

64
    // BouncingScrollPhysics
65

66
    await tester.pumpWidget(buildFrame(const BouncingScrollPhysics()));
Adam Barth's avatar
Adam Barth committed
67
    ScrollableState scrollable = tester.state(find.byType(Scrollable));
68

69
    await tester.dragFrom(tester.getTopLeft(find.text('top')), const Offset(0.0, 400.0));
70
    await tester.pump();
71
    expect(scrollable.position.pixels, lessThan(0.0));
72 73
    await tester.pump(const Duration(seconds: 1)); // Allow overscroll to settle

74
    await tester.dragFrom(tester.getTopLeft(find.text('bottom')), const Offset(0.0, -400.0));
75
    await tester.pump();
76
    expect(scrollable.position.pixels, greaterThan(0.0));
77 78
    await tester.pump(const Duration(seconds: 1)); // Allow overscroll to settle

79
    // ClampingScrollPhysics
80

81
    await tester.pumpWidget(buildFrame(const ClampingScrollPhysics()));
Adam Barth's avatar
Adam Barth committed
82
    scrollable = scrollable = tester.state(find.byType(Scrollable));
83

84
    await tester.dragFrom(tester.getTopLeft(find.text('top')), const Offset(0.0, 400.0));
85
    await tester.pump();
86
    expect(scrollable.position.pixels, equals(0.0));
87 88
    await tester.pump(const Duration(seconds: 1)); // Allow overscroll to settle

89
    await tester.dragFrom(tester.getTopLeft(find.text('bottom')), const Offset(0.0, -400.0));
90
    await tester.pump();
91
    expect(scrollable.position.pixels, equals(50.0));
92
  });
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107

  testWidgets('ClampingScrollPhysics handles out of bounds ScrollPosition', (WidgetTester tester) async {
    Future<void> testOutOfBounds(ScrollPhysics physics, double initialOffset, double expectedOffset) async {
      final ScrollController scrollController = ScrollController(initialScrollOffset: initialOffset);
      await tester.pumpWidget(buildFrame(physics, scrollController: scrollController));
      final ScrollableState scrollable = tester.state(find.byType(Scrollable));

      expect(scrollable.position.pixels, equals(initialOffset));
      await tester.pump(const Duration(seconds: 1)); // Allow overscroll to settle
      expect(scrollable.position.pixels, equals(expectedOffset));
    }

    await testOutOfBounds(const ClampingScrollPhysics(), -400.0, 0.0);
    await testOutOfBounds(const ClampingScrollPhysics(), 800.0, 50.0);
  });
108
}