scroll_physics_test.dart 7.06 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
// 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/widgets.dart';
import 'package:flutter_test/flutter_test.dart';

class TestScrollPhysics extends ScrollPhysics {
  const TestScrollPhysics({ this.name, ScrollPhysics parent }) : super(parent: parent);
  final String name;

  @override
  TestScrollPhysics applyTo(ScrollPhysics ancestor) {
14
    return TestScrollPhysics(name: name, parent: parent?.applyTo(ancestor) ?? ancestor);
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
  }

  TestScrollPhysics get namedParent => parent;
  String get names => parent == null ? name : '$name ${namedParent.names}';

  @override
  String toString() {
    if (parent == null)
      return '$runtimeType($name)';
    return '$runtimeType($name) -> $parent';
  }
}


void main() {
  test('ScrollPhysics applyTo()', () {
31 32 33 34 35
    const ScrollPhysics a = TestScrollPhysics(name: 'a');
    const ScrollPhysics b = TestScrollPhysics(name: 'b');
    const ScrollPhysics c = TestScrollPhysics(name: 'c');
    const ScrollPhysics d = TestScrollPhysics(name: 'd');
    const ScrollPhysics e = TestScrollPhysics(name: 'e');
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54

    expect(a.parent, null);
    expect(b.parent, null);
    expect(c.parent, null);

    final TestScrollPhysics ab = a.applyTo(b);
    expect(ab.names, 'a b');

    final TestScrollPhysics abc = ab.applyTo(c);
    expect(abc.names, 'a b c');

    final TestScrollPhysics de = d.applyTo(e);
    expect(de.names, 'd e');

    final TestScrollPhysics abcde = abc.applyTo(de);
    expect(abcde.names, 'a b c d e');
  });

  test('ScrollPhysics subclasses applyTo()', () {
55 56 57 58 59
    const ScrollPhysics bounce = BouncingScrollPhysics();
    const ScrollPhysics clamp = ClampingScrollPhysics();
    const ScrollPhysics never = NeverScrollableScrollPhysics();
    const ScrollPhysics always = AlwaysScrollableScrollPhysics();
    const ScrollPhysics page = PageScrollPhysics();
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77

    String types(ScrollPhysics s) => s.parent == null ? '${s.runtimeType}' : '${s.runtimeType} ${types(s.parent)}';

    expect(types(bounce.applyTo(clamp.applyTo(never.applyTo(always.applyTo(page))))),
      'BouncingScrollPhysics ClampingScrollPhysics NeverScrollableScrollPhysics AlwaysScrollableScrollPhysics PageScrollPhysics');

    expect(types(clamp.applyTo(never.applyTo(always.applyTo(page.applyTo(bounce))))),
      'ClampingScrollPhysics NeverScrollableScrollPhysics AlwaysScrollableScrollPhysics PageScrollPhysics BouncingScrollPhysics');

    expect(types(never.applyTo(always.applyTo(page.applyTo(bounce.applyTo(clamp))))),
      'NeverScrollableScrollPhysics AlwaysScrollableScrollPhysics PageScrollPhysics BouncingScrollPhysics ClampingScrollPhysics');

    expect(types(always.applyTo(page.applyTo(bounce.applyTo(clamp.applyTo(never))))),
      'AlwaysScrollableScrollPhysics PageScrollPhysics BouncingScrollPhysics ClampingScrollPhysics NeverScrollableScrollPhysics');

    expect(types(page.applyTo(bounce.applyTo(clamp.applyTo(never.applyTo(always))))),
      'PageScrollPhysics BouncingScrollPhysics ClampingScrollPhysics NeverScrollableScrollPhysics AlwaysScrollableScrollPhysics');
  });
78 79 80 81 82 83 84 85 86

  group('BouncingScrollPhysics test', () {
    BouncingScrollPhysics physicsUnderTest;

    setUp(() {
      physicsUnderTest = const BouncingScrollPhysics();
    });

    test('overscroll is progressively harder', () {
87
      final ScrollMetrics lessOverscrolledPosition = FixedScrollMetrics(
88 89 90 91 92 93 94
          minScrollExtent: 0.0,
          maxScrollExtent: 1000.0,
          pixels: -20.0,
          viewportDimension: 100.0,
          axisDirection: AxisDirection.down,
      );

95
      final ScrollMetrics moreOverscrolledPosition = FixedScrollMetrics(
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
        minScrollExtent: 0.0,
        maxScrollExtent: 1000.0,
        pixels: -40.0,
        viewportDimension: 100.0,
        axisDirection: AxisDirection.down,
      );

      final double lessOverscrollApplied =
          physicsUnderTest.applyPhysicsToUserOffset(lessOverscrolledPosition, 10.0);

      final double moreOverscrollApplied =
          physicsUnderTest.applyPhysicsToUserOffset(moreOverscrolledPosition, 10.0);

      expect(lessOverscrollApplied, greaterThan(1.0));
      expect(lessOverscrollApplied, lessThan(20.0));

      expect(moreOverscrollApplied, greaterThan(1.0));
      expect(moreOverscrollApplied, lessThan(20.0));

      // Scrolling from a more overscrolled position meets more resistance.
      expect(lessOverscrollApplied.abs(), greaterThan(moreOverscrollApplied.abs()));
    });

    test('easing an overscroll still has resistance', () {
120
      final ScrollMetrics overscrolledPosition = FixedScrollMetrics(
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
        minScrollExtent: 0.0,
        maxScrollExtent: 1000.0,
        pixels: -20.0,
        viewportDimension: 100.0,
        axisDirection: AxisDirection.down,
      );

      final double easingApplied =
          physicsUnderTest.applyPhysicsToUserOffset(overscrolledPosition, -10.0);

      expect(easingApplied, lessThan(-1.0));
      expect(easingApplied, greaterThan(-10.0));
    });

    test('no resistance when not overscrolled', () {
136
      final ScrollMetrics scrollPosition = FixedScrollMetrics(
137 138 139 140 141 142 143 144 145 146 147 148
        minScrollExtent: 0.0,
        maxScrollExtent: 1000.0,
        pixels: 300.0,
        viewportDimension: 100.0,
        axisDirection: AxisDirection.down,
      );

      expect(physicsUnderTest.applyPhysicsToUserOffset(scrollPosition, 10.0), 10.0);
      expect(physicsUnderTest.applyPhysicsToUserOffset(scrollPosition, -10.0), -10.0);
    });

    test('easing an overscroll meets less resistance than tensioning', () {
149
      final ScrollMetrics overscrolledPosition = FixedScrollMetrics(
150 151 152 153 154 155 156 157 158 159 160 161 162 163
        minScrollExtent: 0.0,
        maxScrollExtent: 1000.0,
        pixels: -20.0,
        viewportDimension: 100.0,
        axisDirection: AxisDirection.down,
      );

      final double easingApplied =
          physicsUnderTest.applyPhysicsToUserOffset(overscrolledPosition, -10.0);
      final double tensioningApplied =
          physicsUnderTest.applyPhysicsToUserOffset(overscrolledPosition, 10.0);

      expect(easingApplied.abs(), greaterThan(tensioningApplied.abs()));
    });
164 165

    test('overscroll a small list and a big list works the same way', () {
166
      final ScrollMetrics smallListOverscrolledPosition = FixedScrollMetrics(
167 168 169 170 171 172 173
          minScrollExtent: 0.0,
          maxScrollExtent: 10.0,
          pixels: -20.0,
          viewportDimension: 100.0,
          axisDirection: AxisDirection.down,
      );

174
      final ScrollMetrics bigListOverscrolledPosition = FixedScrollMetrics(
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
        minScrollExtent: 0.0,
        maxScrollExtent: 1000.0,
        pixels: -20.0,
        viewportDimension: 100.0,
        axisDirection: AxisDirection.down,
      );

      final double smallListOverscrollApplied =
          physicsUnderTest.applyPhysicsToUserOffset(smallListOverscrolledPosition, 10.0);

      final double bigListOverscrollApplied =
          physicsUnderTest.applyPhysicsToUserOffset(bigListOverscrolledPosition, 10.0);

      expect(smallListOverscrollApplied, equals(bigListOverscrollApplied));

      expect(smallListOverscrollApplied, greaterThan(1.0));
      expect(smallListOverscrollApplied, lessThan(20.0));
    });
193
  });
194
}