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

5 6
// @dart = 2.8

7
import 'package:flutter/material.dart';
Ian Hickson's avatar
Ian Hickson committed
8 9
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/rendering.dart';
10
import 'package:flutter/widgets.dart';
Ian Hickson's avatar
Ian Hickson committed
11

12
Future<void> test(WidgetTester tester, double offset, EdgeInsetsGeometry padding, AxisDirection axisDirection, TextDirection textDirection) {
13
  return tester.pumpWidget(
14
    Directionality(
15
      textDirection: textDirection,
16 17
      child: Viewport(
        offset: ViewportOffset.fixed(offset),
18 19
        axisDirection: axisDirection,
        slivers: <Widget>[
20
          const SliverToBoxAdapter(child: SizedBox(width: 400.0, height: 400.0, child: Text('before'))),
21
          SliverPadding(
22
            padding: padding,
23
            sliver: const SliverToBoxAdapter(child: SizedBox(width: 400.0, height: 400.0, child: Text('padded'))),
24
          ),
25
          const SliverToBoxAdapter(child: SizedBox(width: 400.0, height: 400.0, child: Text('after'))),
26
        ],
Ian Hickson's avatar
Ian Hickson committed
27
      ),
28
    ),
29
  );
Ian Hickson's avatar
Ian Hickson committed
30 31 32
}

void verify(WidgetTester tester, List<Rect> answerKey) {
33
  final List<Rect> testAnswers = tester.renderObjectList<RenderBox>(find.byType(SizedBox, skipOffstage: false)).map<Rect>(
Ian Hickson's avatar
Ian Hickson committed
34
    (RenderBox target) {
35 36
      final Offset topLeft = target.localToGlobal(Offset.zero);
      final Offset bottomRight = target.localToGlobal(target.size.bottomRight(Offset.zero));
37
      return Rect.fromPoints(topLeft, bottomRight);
Ian Hickson's avatar
Ian Hickson committed
38 39 40 41 42 43
    }
  ).toList();
  expect(testAnswers, equals(answerKey));
}

void main() {
44
  testWidgets('Viewport+SliverPadding basic test (VISUAL)', (WidgetTester tester) async {
45
    const EdgeInsets padding = EdgeInsets.fromLTRB(25.0, 20.0, 15.0, 35.0);
46
    await test(tester, 0.0, padding, AxisDirection.down, TextDirection.ltr);
Adam Barth's avatar
Adam Barth committed
47
    expect(tester.renderObject<RenderBox>(find.byType(Viewport)).size, equals(const Size(800.0, 600.0)));
Ian Hickson's avatar
Ian Hickson committed
48
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
49 50 51
      const Rect.fromLTWH(0.0, 0.0, 800.0, 400.0),
      const Rect.fromLTWH(25.0, 420.0, 760.0, 400.0),
      const Rect.fromLTWH(0.0, 855.0, 800.0, 400.0),
Ian Hickson's avatar
Ian Hickson committed
52 53
    ]);

54
    await test(tester, 200.0, padding, AxisDirection.down, TextDirection.ltr);
Ian Hickson's avatar
Ian Hickson committed
55
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
56 57 58
      const Rect.fromLTWH(0.0, -200.0, 800.0, 400.0),
      const Rect.fromLTWH(25.0, 220.0, 760.0, 400.0),
      const Rect.fromLTWH(0.0, 655.0, 800.0, 400.0),
Ian Hickson's avatar
Ian Hickson committed
59 60
    ]);

61
    await test(tester, 390.0, padding, AxisDirection.down, TextDirection.ltr);
Ian Hickson's avatar
Ian Hickson committed
62
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
63 64 65
      const Rect.fromLTWH(0.0, -390.0, 800.0, 400.0),
      const Rect.fromLTWH(25.0, 30.0, 760.0, 400.0),
      const Rect.fromLTWH(0.0, 465.0, 800.0, 400.0),
Ian Hickson's avatar
Ian Hickson committed
66 67
    ]);

68
    await test(tester, 490.0, padding, AxisDirection.down, TextDirection.ltr);
Ian Hickson's avatar
Ian Hickson committed
69
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
70 71 72
      const Rect.fromLTWH(0.0, -490.0, 800.0, 400.0),
      const Rect.fromLTWH(25.0, -70.0, 760.0, 400.0),
      const Rect.fromLTWH(0.0, 365.0, 800.0, 400.0),
Ian Hickson's avatar
Ian Hickson committed
73 74
    ]);

75
    await test(tester, 10000.0, padding, AxisDirection.down, TextDirection.ltr);
Ian Hickson's avatar
Ian Hickson committed
76
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
77 78 79
      const Rect.fromLTWH(0.0, -10000.0, 800.0, 400.0),
      const Rect.fromLTWH(25.0, -9580.0, 760.0, 400.0),
      const Rect.fromLTWH(0.0, -9145.0, 800.0, 400.0),
Ian Hickson's avatar
Ian Hickson committed
80 81 82
    ]);
  });

83
  testWidgets('Viewport+SliverPadding basic test (LTR)', (WidgetTester tester) async {
84
    const EdgeInsetsDirectional padding = EdgeInsetsDirectional.fromSTEB(25.0, 20.0, 15.0, 35.0);
85
    await test(tester, 0.0, padding, AxisDirection.down, TextDirection.ltr);
86 87
    expect(tester.renderObject<RenderBox>(find.byType(Viewport)).size, equals(const Size(800.0, 600.0)));
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
88 89 90
      const Rect.fromLTWH(0.0, 0.0, 800.0, 400.0),
      const Rect.fromLTWH(25.0, 420.0, 760.0, 400.0),
      const Rect.fromLTWH(0.0, 855.0, 800.0, 400.0),
91 92
    ]);

93
    await test(tester, 200.0, padding, AxisDirection.down, TextDirection.ltr);
94
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
95 96 97
      const Rect.fromLTWH(0.0, -200.0, 800.0, 400.0),
      const Rect.fromLTWH(25.0, 220.0, 760.0, 400.0),
      const Rect.fromLTWH(0.0, 655.0, 800.0, 400.0),
98 99
    ]);

100
    await test(tester, 390.0, padding, AxisDirection.down, TextDirection.ltr);
101
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
102 103 104
      const Rect.fromLTWH(0.0, -390.0, 800.0, 400.0),
      const Rect.fromLTWH(25.0, 30.0, 760.0, 400.0),
      const Rect.fromLTWH(0.0, 465.0, 800.0, 400.0),
105 106
    ]);

107
    await test(tester, 490.0, padding, AxisDirection.down, TextDirection.ltr);
108
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
109 110 111
      const Rect.fromLTWH(0.0, -490.0, 800.0, 400.0),
      const Rect.fromLTWH(25.0, -70.0, 760.0, 400.0),
      const Rect.fromLTWH(0.0, 365.0, 800.0, 400.0),
112 113
    ]);

114
    await test(tester, 10000.0, padding, AxisDirection.down, TextDirection.ltr);
115
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
116 117 118
      const Rect.fromLTWH(0.0, -10000.0, 800.0, 400.0),
      const Rect.fromLTWH(25.0, -9580.0, 760.0, 400.0),
      const Rect.fromLTWH(0.0, -9145.0, 800.0, 400.0),
119 120 121 122
    ]);
  });

  testWidgets('Viewport+SliverPadding basic test (RTL)', (WidgetTester tester) async {
123
    const EdgeInsetsDirectional padding = EdgeInsetsDirectional.fromSTEB(25.0, 20.0, 15.0, 35.0);
124
    await test(tester, 0.0, padding, AxisDirection.down, TextDirection.rtl);
125 126
    expect(tester.renderObject<RenderBox>(find.byType(Viewport)).size, equals(const Size(800.0, 600.0)));
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
127 128 129
      const Rect.fromLTWH(0.0, 0.0, 800.0, 400.0),
      const Rect.fromLTWH(15.0, 420.0, 760.0, 400.0),
      const Rect.fromLTWH(0.0, 855.0, 800.0, 400.0),
130 131
    ]);

132
    await test(tester, 200.0, padding, AxisDirection.down, TextDirection.rtl);
133
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
134 135 136
      const Rect.fromLTWH(0.0, -200.0, 800.0, 400.0),
      const Rect.fromLTWH(15.0, 220.0, 760.0, 400.0),
      const Rect.fromLTWH(0.0, 655.0, 800.0, 400.0),
137 138
    ]);

139
    await test(tester, 390.0, padding, AxisDirection.down, TextDirection.rtl);
140
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
141 142 143
      const Rect.fromLTWH(0.0, -390.0, 800.0, 400.0),
      const Rect.fromLTWH(15.0, 30.0, 760.0, 400.0),
      const Rect.fromLTWH(0.0, 465.0, 800.0, 400.0),
144 145
    ]);

146
    await test(tester, 490.0, padding, AxisDirection.down, TextDirection.rtl);
147
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
148 149 150
      const Rect.fromLTWH(0.0, -490.0, 800.0, 400.0),
      const Rect.fromLTWH(15.0, -70.0, 760.0, 400.0),
      const Rect.fromLTWH(0.0, 365.0, 800.0, 400.0),
151 152
    ]);

153
    await test(tester, 10000.0, padding, AxisDirection.down, TextDirection.rtl);
154
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
155 156 157
      const Rect.fromLTWH(0.0, -10000.0, 800.0, 400.0),
      const Rect.fromLTWH(15.0, -9580.0, 760.0, 400.0),
      const Rect.fromLTWH(0.0, -9145.0, 800.0, 400.0),
158 159 160
    ]);
  });

Adam Barth's avatar
Adam Barth committed
161
  testWidgets('Viewport+SliverPadding hit testing', (WidgetTester tester) async {
162
    const EdgeInsets padding = EdgeInsets.all(30.0);
163
    await test(tester, 350.0, padding, AxisDirection.down, TextDirection.ltr);
Adam Barth's avatar
Adam Barth committed
164
    expect(tester.renderObject<RenderBox>(find.byType(Viewport)).size, equals(const Size(800.0, 600.0)));
Ian Hickson's avatar
Ian Hickson committed
165
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
166 167 168
      const Rect.fromLTWH(0.0, -350.0, 800.0, 400.0),
      const Rect.fromLTWH(30.0, 80.0, 740.0, 400.0),
      const Rect.fromLTWH(0.0, 510.0, 800.0, 400.0),
Ian Hickson's avatar
Ian Hickson committed
169 170
    ]);
    HitTestResult result;
171
    result = tester.hitTestOnBinding(const Offset(10.0, 10.0));
Ian Hickson's avatar
Ian Hickson committed
172
    expect(result.path.first.target, tester.firstRenderObject<RenderObject>(find.byType(Text)));
173
    result = tester.hitTestOnBinding(const Offset(10.0, 60.0));
Dan Field's avatar
Dan Field committed
174
    expect(result.path.first.target, isA<RenderView>());
175
    result = tester.hitTestOnBinding(const Offset(100.0, 100.0));
Ian Hickson's avatar
Ian Hickson committed
176
    expect(result.path.first.target, tester.renderObjectList<RenderObject>(find.byType(Text)).skip(1).first);
177
    result = tester.hitTestOnBinding(const Offset(100.0, 490.0));
Dan Field's avatar
Dan Field committed
178
    expect(result.path.first.target, isA<RenderView>());
179
    result = tester.hitTestOnBinding(const Offset(10.0, 520.0));
Ian Hickson's avatar
Ian Hickson committed
180 181 182
    expect(result.path.first.target, tester.renderObjectList<RenderObject>(find.byType(Text)).last);
  });

Adam Barth's avatar
Adam Barth committed
183
  testWidgets('Viewport+SliverPadding hit testing up', (WidgetTester tester) async {
184
    const EdgeInsets padding = EdgeInsets.all(30.0);
185
    await test(tester, 350.0, padding, AxisDirection.up, TextDirection.ltr);
Adam Barth's avatar
Adam Barth committed
186
    expect(tester.renderObject<RenderBox>(find.byType(Viewport)).size, equals(const Size(800.0, 600.0)));
Ian Hickson's avatar
Ian Hickson committed
187
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
188 189 190
      const Rect.fromLTWH(0.0, 600.0+350.0-400.0, 800.0, 400.0),
      const Rect.fromLTWH(30.0, 600.0-80.0-400.0, 740.0, 400.0),
      const Rect.fromLTWH(0.0, 600.0-510.0-400.0, 800.0, 400.0),
Ian Hickson's avatar
Ian Hickson committed
191 192
    ]);
    HitTestResult result;
193
    result = tester.hitTestOnBinding(const Offset(10.0, 600.0-10.0));
Ian Hickson's avatar
Ian Hickson committed
194
    expect(result.path.first.target, tester.firstRenderObject<RenderObject>(find.byType(Text)));
195
    result = tester.hitTestOnBinding(const Offset(10.0, 600.0-60.0));
Dan Field's avatar
Dan Field committed
196
    expect(result.path.first.target, isA<RenderView>());
197
    result = tester.hitTestOnBinding(const Offset(100.0, 600.0-100.0));
Ian Hickson's avatar
Ian Hickson committed
198
    expect(result.path.first.target, tester.renderObjectList<RenderObject>(find.byType(Text)).skip(1).first);
199
    result = tester.hitTestOnBinding(const Offset(100.0, 600.0-490.0));
Dan Field's avatar
Dan Field committed
200
    expect(result.path.first.target, isA<RenderView>());
201
    result = tester.hitTestOnBinding(const Offset(10.0, 600.0-520.0));
Ian Hickson's avatar
Ian Hickson committed
202 203 204
    expect(result.path.first.target, tester.renderObjectList<RenderObject>(find.byType(Text)).last);
  });

Adam Barth's avatar
Adam Barth committed
205
  testWidgets('Viewport+SliverPadding hit testing left', (WidgetTester tester) async {
206
    const EdgeInsets padding = EdgeInsets.all(30.0);
207
    await test(tester, 350.0, padding, AxisDirection.left, TextDirection.ltr);
Adam Barth's avatar
Adam Barth committed
208
    expect(tester.renderObject<RenderBox>(find.byType(Viewport)).size, equals(const Size(800.0, 600.0)));
Ian Hickson's avatar
Ian Hickson committed
209
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
210 211 212
      const Rect.fromLTWH(800.0+350.0-400.0, 0.0, 400.0, 600.0),
      const Rect.fromLTWH(800.0-80.0-400.0, 30.0, 400.0, 540.0),
      const Rect.fromLTWH(800.0-510.0-400.0, 0.0, 400.0, 600.0),
Ian Hickson's avatar
Ian Hickson committed
213 214
    ]);
    HitTestResult result;
215
    result = tester.hitTestOnBinding(const Offset(800.0-10.0, 10.0));
Ian Hickson's avatar
Ian Hickson committed
216
    expect(result.path.first.target, tester.firstRenderObject<RenderObject>(find.byType(Text)));
217
    result = tester.hitTestOnBinding(const Offset(800.0-60.0, 10.0));
Dan Field's avatar
Dan Field committed
218
    expect(result.path.first.target, isA<RenderView>());
219
    result = tester.hitTestOnBinding(const Offset(800.0-100.0, 100.0));
Ian Hickson's avatar
Ian Hickson committed
220
    expect(result.path.first.target, tester.renderObjectList<RenderObject>(find.byType(Text)).skip(1).first);
221
    result = tester.hitTestOnBinding(const Offset(800.0-490.0, 100.0));
Dan Field's avatar
Dan Field committed
222
    expect(result.path.first.target, isA<RenderView>());
223
    result = tester.hitTestOnBinding(const Offset(800.0-520.0, 10.0));
Ian Hickson's avatar
Ian Hickson committed
224 225 226
    expect(result.path.first.target, tester.renderObjectList<RenderObject>(find.byType(Text)).last);
  });

Adam Barth's avatar
Adam Barth committed
227
  testWidgets('Viewport+SliverPadding hit testing right', (WidgetTester tester) async {
228
    const EdgeInsets padding = EdgeInsets.all(30.0);
229
    await test(tester, 350.0, padding, AxisDirection.right, TextDirection.ltr);
Adam Barth's avatar
Adam Barth committed
230
    expect(tester.renderObject<RenderBox>(find.byType(Viewport)).size, equals(const Size(800.0, 600.0)));
Ian Hickson's avatar
Ian Hickson committed
231
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
232 233 234
      const Rect.fromLTWH(-350.0, 0.0, 400.0, 600.0),
      const Rect.fromLTWH(80.0, 30.0, 400.0, 540.0),
      const Rect.fromLTWH(510.0, 0.0, 400.0, 600.0),
Ian Hickson's avatar
Ian Hickson committed
235 236
    ]);
    HitTestResult result;
237
    result = tester.hitTestOnBinding(const Offset(10.0, 10.0));
Ian Hickson's avatar
Ian Hickson committed
238
    expect(result.path.first.target, tester.firstRenderObject<RenderObject>(find.byType(Text)));
239
    result = tester.hitTestOnBinding(const Offset(60.0, 10.0));
Dan Field's avatar
Dan Field committed
240
    expect(result.path.first.target, isA<RenderView>());
241
    result = tester.hitTestOnBinding(const Offset(100.0, 100.0));
Ian Hickson's avatar
Ian Hickson committed
242
    expect(result.path.first.target, tester.renderObjectList<RenderObject>(find.byType(Text)).skip(1).first);
243
    result = tester.hitTestOnBinding(const Offset(490.0, 100.0));
Dan Field's avatar
Dan Field committed
244
    expect(result.path.first.target, isA<RenderView>());
245
    result = tester.hitTestOnBinding(const Offset(520.0, 10.0));
Ian Hickson's avatar
Ian Hickson committed
246 247 248
    expect(result.path.first.target, tester.renderObjectList<RenderObject>(find.byType(Text)).last);
  });

Adam Barth's avatar
Adam Barth committed
249
  testWidgets('Viewport+SliverPadding no child', (WidgetTester tester) async {
250
    await tester.pumpWidget(
251
      Directionality(
252
        textDirection: TextDirection.ltr,
253 254
        child: Viewport(
          offset: ViewportOffset.fixed(0.0),
255
          slivers: const <Widget>[
256 257
            SliverPadding(padding: EdgeInsets.all(100.0)),
            SliverToBoxAdapter(child: SizedBox(width: 400.0, height: 400.0, child: Text('x'))),
258 259 260 261
          ],
        ),
      ),
    );
262
    expect(tester.renderObject<RenderBox>(find.text('x')).localToGlobal(Offset.zero), const Offset(0.0, 200.0));
Ian Hickson's avatar
Ian Hickson committed
263 264
  });

Adam Barth's avatar
Adam Barth committed
265
  testWidgets('Viewport+SliverPadding changing padding', (WidgetTester tester) async {
266
    await tester.pumpWidget(
267
      Directionality(
268
        textDirection: TextDirection.ltr,
269
        child: Viewport(
270
          axisDirection: AxisDirection.left,
271
          offset: ViewportOffset.fixed(0.0),
272
          slivers: const <Widget>[
273 274
            SliverPadding(padding: EdgeInsets.fromLTRB(90.0, 1.0, 110.0, 2.0)),
            SliverToBoxAdapter(child: SizedBox(width: 201.0, child: Text('x'))),
275 276 277 278
          ],
        ),
      ),
    );
279
    expect(tester.renderObject<RenderBox>(find.text('x')).localToGlobal(Offset.zero), const Offset(399.0, 0.0));
280
    await tester.pumpWidget(
281
      Directionality(
282
        textDirection: TextDirection.ltr,
283
        child: Viewport(
284
          axisDirection: AxisDirection.left,
285
          offset: ViewportOffset.fixed(0.0),
286
          slivers: const <Widget>[
287 288
            SliverPadding(padding: EdgeInsets.fromLTRB(110.0, 1.0, 80.0, 2.0)),
            SliverToBoxAdapter(child: SizedBox(width: 201.0, child: Text('x'))),
289 290 291 292
          ],
        ),
      ),
    );
293
    expect(tester.renderObject<RenderBox>(find.text('x')).localToGlobal(Offset.zero), const Offset(409.0, 0.0));
Ian Hickson's avatar
Ian Hickson committed
294 295
  });

Adam Barth's avatar
Adam Barth committed
296
  testWidgets('Viewport+SliverPadding changing direction', (WidgetTester tester) async {
297
    await tester.pumpWidget(
298
      Directionality(
299
        textDirection: TextDirection.ltr,
300
        child: Viewport(
301
          axisDirection: AxisDirection.up,
302
          offset: ViewportOffset.fixed(0.0),
303
          slivers: const <Widget>[
304
            SliverPadding(padding: EdgeInsets.fromLTRB(1.0, 2.0, 4.0, 8.0)),
305 306 307 308
          ],
        ),
      ),
    );
309
    expect(tester.renderObject<RenderSliverPadding>(find.byType(SliverPadding)).afterPadding, 2.0);
310
    await tester.pumpWidget(
311
      Directionality(
312
        textDirection: TextDirection.ltr,
313
        child: Viewport(
314
          axisDirection: AxisDirection.down,
315
          offset: ViewportOffset.fixed(0.0),
316
          slivers: const <Widget>[
317
            SliverPadding(padding: EdgeInsets.fromLTRB(1.0, 2.0, 4.0, 8.0)),
318 319 320 321
          ],
        ),
      ),
    );
322
    expect(tester.renderObject<RenderSliverPadding>(find.byType(SliverPadding)).afterPadding, 8.0);
323
    await tester.pumpWidget(
324
      Directionality(
325
        textDirection: TextDirection.ltr,
326
        child: Viewport(
327
          axisDirection: AxisDirection.right,
328
          offset: ViewportOffset.fixed(0.0),
329
          slivers: const <Widget>[
330
            SliverPadding(padding: EdgeInsets.fromLTRB(1.0, 2.0, 4.0, 8.0)),
331 332 333 334
          ],
        ),
      ),
    );
335
    expect(tester.renderObject<RenderSliverPadding>(find.byType(SliverPadding)).afterPadding, 4.0);
336
    await tester.pumpWidget(
337
      Directionality(
338
        textDirection: TextDirection.ltr,
339
        child: Viewport(
340
          axisDirection: AxisDirection.left,
341
          offset: ViewportOffset.fixed(0.0),
342
          slivers: const <Widget>[
343
            SliverPadding(padding: EdgeInsets.fromLTRB(1.0, 2.0, 4.0, 8.0)),
344 345 346 347
          ],
        ),
      ),
    );
348
    expect(tester.renderObject<RenderSliverPadding>(find.byType(SliverPadding)).afterPadding, 1.0);
349
    await tester.pumpWidget(
350
      Directionality(
351
        textDirection: TextDirection.ltr,
352
        child: Viewport(
353
          axisDirection: AxisDirection.left,
354
          offset: ViewportOffset.fixed(99999.9),
355
          slivers: const <Widget>[
356
            SliverPadding(padding: EdgeInsets.fromLTRB(1.0, 2.0, 4.0, 8.0)),
357 358 359 360
          ],
        ),
      ),
    );
361
    expect(tester.renderObject<RenderSliverPadding>(find.byType(SliverPadding)).afterPadding, 1.0);
Ian Hickson's avatar
Ian Hickson committed
362
  });
363 364 365

  testWidgets('SliverPadding propagates geometry offset corrections', (WidgetTester tester) async {
    Widget listBuilder(IndexedWidgetBuilder sliverChildBuilder) {
366
      return Directionality(
367
        textDirection: TextDirection.ltr,
368
        child: CustomScrollView(
369
          cacheExtent: 0.0,
370
          slivers: <Widget>[
371
            SliverPadding(
372
              padding: EdgeInsets.zero,
373 374
              sliver: SliverList(
                delegate: SliverChildBuilderDelegate(
375 376 377 378 379 380 381 382 383 384 385 386 387
                  sliverChildBuilder,
                  childCount: 10,
                ),
              ),
            ),
          ],
        ),
      );
    }

    await tester.pumpWidget(
      listBuilder(
        (BuildContext context, int index) {
388
          return Container(
389
            height: 200.0,
390 391
            child: Center(
              child: Text(index.toString()),
392 393 394 395 396 397 398 399 400 401 402
            ),
          );
        },
      ),
    );

    await tester.drag(find.text('2'), const Offset(0.0, -300.0));
    await tester.pump();

    expect(
      tester.getRect(find.widgetWithText(Container, '2')),
Dan Field's avatar
Dan Field committed
403
      const Rect.fromLTRB(0.0, 100.0, 800.0, 300.0),
404 405 406 407 408 409
    );

    // Now item 0 is 400.0px and going back will underflow.
    await tester.pumpWidget(
      listBuilder(
        (BuildContext context, int index) {
410
          return Container(
411
            height: index == 0 ? 400.0 : 200.0,
412 413
            child: Center(
              child: Text(index.toString()),
414 415 416 417 418 419 420 421 422 423 424 425
            ),
          );
        },
      ),
    );

    await tester.drag(find.text('2'), const Offset(0.0, 300.0));
    // On this one frame, the scroll correction must properly propagate.
    await tester.pump();

    expect(
      tester.getRect(find.widgetWithText(Container, '0')),
Dan Field's avatar
Dan Field committed
426
      const Rect.fromLTRB(0.0, -200.0, 800.0, 200.0),
427 428
    );
  });
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461

  testWidgets('SliverPadding includes preceding padding in the precedingScrollExtent provided to child', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/49195
    final UniqueKey key = UniqueKey();
    await tester.pumpWidget(Directionality(
      textDirection: TextDirection.ltr,
      child: CustomScrollView(
        slivers: <Widget>[
          SliverPadding(
            padding: const EdgeInsets.only(top: 30),
            sliver: SliverFillRemaining(
              hasScrollBody: false,
              child: Container(
                key: key,
                color: Colors.red,
              ),
            )
          ),
        ]
      ),
    ));
    await tester.pump();

    // The value of 570 is expected since SliverFillRemaining will fill all of
    // the space available to it. In this test, the extent of the viewport is
    // 600 pixels. If the SliverPadding widget provides the right constraints
    // to SliverFillRemaining, with 30 pixels preceding it, it should only have
    // a height of 570.
    expect(
      tester.renderObject<RenderBox>(find.byKey(key)).size.height,
      equals(570),
    );
  });
Ian Hickson's avatar
Ian Hickson committed
462
}