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
import 'package:flutter/material.dart';
Ian Hickson's avatar
Ian Hickson committed
6 7
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/rendering.dart';
8
import 'package:flutter/widgets.dart';
Ian Hickson's avatar
Ian Hickson committed
9

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

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

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

52
    await test(tester, 200.0, padding, AxisDirection.down, TextDirection.ltr);
Ian Hickson's avatar
Ian Hickson committed
53
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
54 55 56
      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
57 58
    ]);

59
    await test(tester, 390.0, padding, AxisDirection.down, TextDirection.ltr);
Ian Hickson's avatar
Ian Hickson committed
60
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
61 62 63
      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
64 65
    ]);

66
    await test(tester, 490.0, padding, AxisDirection.down, TextDirection.ltr);
Ian Hickson's avatar
Ian Hickson committed
67
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
68 69 70
      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
71 72
    ]);

73
    await test(tester, 10000.0, padding, AxisDirection.down, TextDirection.ltr);
Ian Hickson's avatar
Ian Hickson committed
74
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
75 76 77
      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
78 79 80
    ]);
  });

81
  testWidgets('Viewport+SliverPadding basic test (LTR)', (WidgetTester tester) async {
82
    const EdgeInsetsDirectional padding = EdgeInsetsDirectional.fromSTEB(25.0, 20.0, 15.0, 35.0);
83
    await test(tester, 0.0, padding, AxisDirection.down, TextDirection.ltr);
84 85
    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
86 87 88
      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),
89 90
    ]);

91
    await test(tester, 200.0, padding, AxisDirection.down, TextDirection.ltr);
92
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
93 94 95
      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),
96 97
    ]);

98
    await test(tester, 390.0, padding, AxisDirection.down, TextDirection.ltr);
99
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
100 101 102
      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),
103 104
    ]);

105
    await test(tester, 490.0, padding, AxisDirection.down, TextDirection.ltr);
106
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
107 108 109
      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),
110 111
    ]);

112
    await test(tester, 10000.0, padding, AxisDirection.down, TextDirection.ltr);
113
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
114 115 116
      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),
117 118 119 120
    ]);
  });

  testWidgets('Viewport+SliverPadding basic test (RTL)', (WidgetTester tester) async {
121
    const EdgeInsetsDirectional padding = EdgeInsetsDirectional.fromSTEB(25.0, 20.0, 15.0, 35.0);
122
    await test(tester, 0.0, padding, AxisDirection.down, TextDirection.rtl);
123 124
    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
125 126 127
      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),
128 129
    ]);

130
    await test(tester, 200.0, padding, AxisDirection.down, TextDirection.rtl);
131
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
132 133 134
      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),
135 136
    ]);

137
    await test(tester, 390.0, padding, AxisDirection.down, TextDirection.rtl);
138
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
139 140 141
      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),
142 143
    ]);

144
    await test(tester, 490.0, padding, AxisDirection.down, TextDirection.rtl);
145
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
146 147 148
      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),
149 150
    ]);

151
    await test(tester, 10000.0, padding, AxisDirection.down, TextDirection.rtl);
152
    verify(tester, <Rect>[
Dan Field's avatar
Dan Field committed
153 154 155
      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),
156 157 158
    ]);
  });

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

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

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

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

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

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

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

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

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

    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
401
      const Rect.fromLTRB(0.0, 100.0, 800.0, 300.0),
402 403 404 405 406 407
    );

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

    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
424
      const Rect.fromLTRB(0.0, -200.0, 800.0, 200.0),
425 426
    );
  });
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

  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
460
}