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

Adam Barth's avatar
Adam Barth committed
5
import 'package:flutter_test/flutter_test.dart';
6
import 'package:flutter/widgets.dart';
Hixie's avatar
Hixie committed
7

8
const Key blockKey = Key('test');
Hixie's avatar
Hixie committed
9 10

void main() {
11 12
  testWidgets('Cannot scroll a non-overflowing block', (WidgetTester tester) async {
    await tester.pumpWidget(
13
      Directionality(
14
        textDirection: TextDirection.ltr,
15
        child: ListView(
16
          key: blockKey,
17 18
          children: const <Widget>[
            SizedBox(
19
              height: 200.0, // less than 600, the height of the test area
20
              child: Text('Hello'),
21 22 23 24
            ),
          ],
        ),
      ),
25 26
    );

27 28
    final Offset middleOfContainer = tester.getCenter(find.text('Hello'));
    final Offset target = tester.getCenter(find.byKey(blockKey));
29
    final TestGesture gesture = await tester.startGesture(target);
30
    await gesture.moveBy(const Offset(0.0, -10.0));
31

32
    await tester.pump(const Duration(milliseconds: 1));
33 34 35

    expect(tester.getCenter(find.text('Hello')) == middleOfContainer, isTrue);

36
    await gesture.up();
Hixie's avatar
Hixie committed
37 38
  });

39 40
  testWidgets('Can scroll an overflowing block', (WidgetTester tester) async {
    await tester.pumpWidget(
41
      Directionality(
42
        textDirection: TextDirection.ltr,
43
        child: ListView(
44
          key: blockKey,
45 46
          children: const <Widget>[
            SizedBox(
47
              height: 2000.0, // more than 600, the height of the test area
48
              child: Text('Hello'),
49 50 51 52
            ),
          ],
        ),
      ),
53
    );
54

55 56 57
    final Offset middleOfContainer = tester.getCenter(find.text('Hello'));
    expect(middleOfContainer.dx, equals(400.0));
    expect(middleOfContainer.dy, equals(1000.0));
58

59
    final Offset target = tester.getCenter(find.byKey(blockKey));
60
    final TestGesture gesture = await tester.startGesture(target);
61
    await gesture.moveBy(const Offset(0.0, -10.0));
62

63
    await tester.pump(); // redo layout
64

65
    expect(tester.getCenter(find.text('Hello')), isNot(equals(middleOfContainer)));
66

67
    await gesture.up();
Hixie's avatar
Hixie committed
68
  });
69

70
  testWidgets('ListView reverse', (WidgetTester tester) async {
71 72 73
    int first = 0;
    int second = 0;

74
    Widget buildBlock({ bool reverse = false }) {
75
      return Directionality(
76
        textDirection: TextDirection.ltr,
77 78
        child: ListView(
          key: UniqueKey(),
79 80
          reverse: reverse,
          children: <Widget>[
81
            GestureDetector(
82
              onTap: () { first += 1; },
83
              child: Container(
84 85
                height: 350.0, // more than half the height of the test area
                color: const Color(0xFF00FF00),
86
              ),
87
            ),
88
            GestureDetector(
89
              onTap: () { second += 1; },
90
              child: Container(
91 92 93 94 95 96
                height: 350.0, // more than half the height of the test area
                color: const Color(0xFF0000FF),
              ),
            ),
          ],
        ),
97 98
      );
    }
99

100
    await tester.pumpWidget(buildBlock(reverse: true));
101

102
    const Offset target = Offset(200.0, 200.0);
103
    await tester.tapAt(target);
104 105
    expect(first, equals(0));
    expect(second, equals(1));
106

107
    await tester.pumpWidget(buildBlock(reverse: false));
108

109
    await tester.tapAt(target);
110 111
    expect(first, equals(1));
    expect(second, equals(1));
112
  });
113

114
  testWidgets('ListView controller', (WidgetTester tester) async {
115
    final ScrollController controller = ScrollController();
116

117
    Widget buildBlock() {
118
      return Directionality(
119
        textDirection: TextDirection.ltr,
120
        child: ListView(
121
          controller: controller,
122
          children: const <Widget>[Text('A'), Text('B'), Text('C')],
123
        ),
124 125 126
      );
    }
    await tester.pumpWidget(buildBlock());
127
    expect(controller.offset, equals(0.0));
128
  });
129

130
  testWidgets('SliverBlockChildListDelegate.estimateMaxScrollOffset hits end', (WidgetTester tester) async {
131 132 133 134 135 136
    final SliverChildListDelegate delegate = SliverChildListDelegate(<Widget>[
      Container(),
      Container(),
      Container(),
      Container(),
      Container(),
137 138
    ]);

139
    await tester.pumpWidget(
140
      Directionality(
141
        textDirection: TextDirection.ltr,
142
        child: CustomScrollView(
143
          slivers: <Widget>[
144
            SliverList(
145 146 147
              delegate: delegate,
            ),
          ],
148
        ),
149 150
      ),
    );
151

152
    final SliverMultiBoxAdaptorElement element = tester.element(find.byType(SliverList, skipOffstage: false));
153 154 155 156 157 158

    final double maxScrollOffset = element.estimateMaxScrollOffset(
      null,
      firstIndex: 3,
      lastIndex: 4,
      leadingScrollOffset: 25.0,
159
      trailingScrollOffset: 26.0,
160 161
    );
    expect(maxScrollOffset, equals(26.0));
162
  });
163 164 165

  testWidgets('Resizing a ListView child restores scroll offset', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/9221
166
    final AnimationController controller = AnimationController(
167 168 169 170 171 172
      vsync: const TestVSync(),
      duration: const Duration(milliseconds: 200),
    );

    // The overall height of the frame is (as ever) 600
    Widget buildFrame() {
173
      return Directionality(
174
        textDirection: TextDirection.ltr,
175
        child: Column(
176
          children: <Widget>[
177
            Flexible(
178
              // The overall height of the ListView's contents is 500
179
              child: ListView(
180
                children: const <Widget>[
181
                  SizedBox(
182
                    height: 150.0,
183
                    child: Center(
184
                      child: Text('top'),
185
                    ),
186
                  ),
187
                  SizedBox(
188
                    height: 200.0,
189
                    child: Center(
190
                      child: Text('middle'),
191
                    ),
192
                  ),
193
                  SizedBox(
194
                    height: 150.0,
195
                    child: Center(
196
                      child: Text('bottom'),
197
                    ),
198
                  ),
199 200
                ],
              ),
201
            ),
202
            // If this widget's height is > 100 the ListView can scroll.
203
            SizeTransition(
204 205 206
              sizeFactor: controller.view,
              child: const SizedBox(
                height: 300.0,
207
                child: Text('keyboard'),
208
              ),
209
            ),
210 211
          ],
        ),
212 213 214 215 216 217
      );
    }

    await tester.pumpWidget(buildFrame());
    expect(find.text('top'), findsOneWidget);

218
    final ScrollPosition position = Scrollable.of(tester.element(find.text('middle')))!.position;
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
    expect(position.viewportDimension, 600.0);
    expect(position.pixels, 0.0);

    // Animate the 'keyboard' height from 0 to 300
    controller.forward();
    await tester.pumpAndSettle();
    expect(position.viewportDimension, 300.0);

    // Scroll the ListView upwards
    position.jumpTo(200.0);
    await tester.pumpAndSettle();
    expect(position.pixels, 200.0);
    expect(find.text('top'), findsNothing);

    // Animate the 'keyboard' height back to 0. This causes the scroll
    // offset to return to 0.0
    controller.reverse();
    await tester.pumpAndSettle();
    expect(position.viewportDimension, 600.0);
    expect(position.pixels, 0.0);
    expect(find.text('top'), findsOneWidget);
  });
Hixie's avatar
Hixie committed
241
}