slivers_block_test.dart 11.9 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 5 6
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

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

10
Future<void> test(WidgetTester tester, double offset) {
11 12
  final ViewportOffset viewportOffset = ViewportOffset.fixed(offset);
  addTearDown(viewportOffset.dispose);
13 14 15 16
  return tester.pumpWidget(
    Directionality(
      textDirection: TextDirection.ltr,
      child: Viewport(
17
        offset: viewportOffset,
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
        slivers: <Widget>[
          SliverList(
            delegate: SliverChildListDelegate(const <Widget>[
              SizedBox(height: 400.0, child: Text('a')),
              SizedBox(height: 400.0, child: Text('b')),
              SizedBox(height: 400.0, child: Text('c')),
              SizedBox(height: 400.0, child: Text('d')),
              SizedBox(height: 400.0, child: Text('e')),
            ]),
          ),
        ],
      ),
    ),
  );
}

Future<void> testWithConstChildDelegate(WidgetTester tester, double offset) {
35 36
  final ViewportOffset viewportOffset = ViewportOffset.fixed(offset);
  addTearDown(viewportOffset.dispose);
37
  return tester.pumpWidget(
38
    Directionality(
39
      textDirection: TextDirection.ltr,
40
      child: Viewport(
41
        offset: viewportOffset,
42
        slivers: const <Widget>[
43
          SliverList(
44
            delegate: SliverChildListDelegate.fixed(<Widget>[
45 46 47 48 49
              SizedBox(height: 400.0, child: Text('a')),
              SizedBox(height: 400.0, child: Text('b')),
              SizedBox(height: 400.0, child: Text('c')),
              SizedBox(height: 400.0, child: Text('d')),
              SizedBox(height: 400.0, child: Text('e')),
50 51 52
            ]),
          ),
        ],
Ian Hickson's avatar
Ian Hickson committed
53
      ),
54 55
    ),
  );
Ian Hickson's avatar
Ian Hickson committed
56 57
}

58 59
void verify(WidgetTester tester, List<Offset> answerKey, String text) {
  final List<Offset> testAnswers = tester.renderObjectList<RenderBox>(find.byType(SizedBox)).map<Offset>(
60
    (RenderBox target) => target.localToGlobal(Offset.zero),
Ian Hickson's avatar
Ian Hickson committed
61 62 63
  ).toList();
  expect(testAnswers, equals(answerKey));
  final String foundText =
Ian Hickson's avatar
Ian Hickson committed
64
    tester.widgetList<Text>(find.byType(Text))
65
    .map<String>((Text widget) => widget.data!)
Ian Hickson's avatar
Ian Hickson committed
66 67 68 69 70
    .reduce((String value, String element) => value + element);
  expect(foundText, equals(text));
}

void main() {
71
  testWidgetsWithLeakTracking('Viewport+SliverBlock basic test', (WidgetTester tester) async {
Ian Hickson's avatar
Ian Hickson committed
72
    await test(tester, 0.0);
Adam Barth's avatar
Adam Barth committed
73
    expect(tester.renderObject<RenderBox>(find.byType(Viewport)).size, equals(const Size(800.0, 600.0)));
74
    verify(tester, <Offset>[
75
      Offset.zero,
76
      const Offset(0.0, 400.0),
Ian Hickson's avatar
Ian Hickson committed
77 78 79
    ], 'ab');

    await test(tester, 200.0);
80 81 82
    verify(tester, <Offset>[
      const Offset(0.0, -200.0),
      const Offset(0.0, 200.0),
Ian Hickson's avatar
Ian Hickson committed
83 84 85
    ], 'ab');

    await test(tester, 600.0);
86 87 88
    verify(tester, <Offset>[
      const Offset(0.0, -200.0),
      const Offset(0.0, 200.0),
Ian Hickson's avatar
Ian Hickson committed
89 90 91
    ], 'bc');

    await test(tester, 900.0);
92 93 94
    verify(tester, <Offset>[
      const Offset(0.0, -100.0),
      const Offset(0.0, 300.0),
Ian Hickson's avatar
Ian Hickson committed
95 96 97
    ], 'cd');

    await test(tester, 200.0);
98 99 100
    verify(tester, <Offset>[
      const Offset(0.0, -200.0),
      const Offset(0.0, 200.0),
Ian Hickson's avatar
Ian Hickson committed
101 102 103
    ], 'ab');
  });

104
  testWidgetsWithLeakTracking('Viewport+SliverBlock basic test with constant SliverChildListDelegate', (WidgetTester tester) async {
105 106 107
    await testWithConstChildDelegate(tester, 0.0);
    expect(tester.renderObject<RenderBox>(find.byType(Viewport)).size, equals(const Size(800.0, 600.0)));
    verify(tester, <Offset>[
108
      Offset.zero,
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
      const Offset(0.0, 400.0),
    ], 'ab');

    await testWithConstChildDelegate(tester, 200.0);
    verify(tester, <Offset>[
      const Offset(0.0, -200.0),
      const Offset(0.0, 200.0),
    ], 'ab');

    await testWithConstChildDelegate(tester, 600.0);
    verify(tester, <Offset>[
      const Offset(0.0, -200.0),
      const Offset(0.0, 200.0),
    ], 'bc');

    await testWithConstChildDelegate(tester, 900.0);
    verify(tester, <Offset>[
      const Offset(0.0, -100.0),
      const Offset(0.0, 300.0),
    ], 'cd');

    await testWithConstChildDelegate(tester, 200.0);
    verify(tester, <Offset>[
      const Offset(0.0, -200.0),
      const Offset(0.0, 200.0),
    ], 'ab');
  });

137
  testWidgetsWithLeakTracking('Viewport with GlobalKey reparenting', (WidgetTester tester) async {
138 139
    final Key key1 = GlobalKey();
    final ViewportOffset offset = ViewportOffset.zero();
140
    addTearDown(offset.dispose);
141
    await tester.pumpWidget(
142
      Directionality(
143
        textDirection: TextDirection.ltr,
144
        child: Viewport(
145 146
          offset: offset,
          slivers: <Widget>[
147 148
            SliverList(
              delegate: SliverChildListDelegate(<Widget>[
149 150
                const SizedBox(height: 251.0, child: Text('a')),
                const SizedBox(height: 252.0, child: Text('b')),
151
                SizedBox(key: key1, height: 253.0, child: const Text('c')),
152 153 154
              ]),
            ),
          ],
Ian Hickson's avatar
Ian Hickson committed
155
        ),
156 157
      ),
    );
158
    verify(tester, <Offset>[
159
      Offset.zero,
160 161
      const Offset(0.0, 251.0),
      const Offset(0.0, 503.0),
Ian Hickson's avatar
Ian Hickson committed
162
    ], 'abc');
163
    await tester.pumpWidget(
164
      Directionality(
165
        textDirection: TextDirection.ltr,
166
        child: Viewport(
167 168
          offset: offset,
          slivers: <Widget>[
169 170 171
            SliverList(
              delegate: SliverChildListDelegate(<Widget>[
                SizedBox(key: key1, height: 253.0, child: const Text('c')),
172 173
                const SizedBox(height: 251.0, child: Text('a')),
                const SizedBox(height: 252.0, child: Text('b')),
174 175 176
              ]),
            ),
          ],
Ian Hickson's avatar
Ian Hickson committed
177
        ),
178 179
      ),
    );
180
    verify(tester, <Offset>[
181
      Offset.zero,
182 183
      const Offset(0.0, 253.0),
      const Offset(0.0, 504.0),
Ian Hickson's avatar
Ian Hickson committed
184
    ], 'cab');
185
    await tester.pumpWidget(
186
      Directionality(
187
        textDirection: TextDirection.ltr,
188
        child: Viewport(
189 190
          offset: offset,
          slivers: <Widget>[
191 192
            SliverList(
              delegate: SliverChildListDelegate(<Widget>[
193
                const SizedBox(height: 251.0, child: Text('a')),
194
                SizedBox(key: key1, height: 253.0, child: const Text('c')),
195
                const SizedBox(height: 252.0, child: Text('b')),
196 197 198
              ]),
            ),
          ],
Ian Hickson's avatar
Ian Hickson committed
199
        ),
200 201
      ),
    );
202
    verify(tester, <Offset>[
203
      Offset.zero,
204 205
      const Offset(0.0, 251.0),
      const Offset(0.0, 504.0),
Ian Hickson's avatar
Ian Hickson committed
206
    ], 'acb');
207
    await tester.pumpWidget(
208
      Directionality(
209
        textDirection: TextDirection.ltr,
210
        child: Viewport(
211
          offset: offset,
212
          slivers: <Widget>[
213
            SliverList(
214
              delegate: SliverChildListDelegate(const <Widget>[
215 216
                SizedBox(height: 251.0, child: Text('a')),
                SizedBox(height: 252.0, child: Text('b')),
217 218 219
              ]),
            ),
          ],
Ian Hickson's avatar
Ian Hickson committed
220
        ),
221 222
      ),
    );
223
    verify(tester, <Offset>[
224
      Offset.zero,
225
      const Offset(0.0, 251.0),
Ian Hickson's avatar
Ian Hickson committed
226
    ], 'ab');
227
    await tester.pumpWidget(
228
      Directionality(
229
        textDirection: TextDirection.ltr,
230
        child: Viewport(
231 232
          offset: offset,
          slivers: <Widget>[
233 234
            SliverList(
              delegate: SliverChildListDelegate(<Widget>[
235
                const SizedBox(height: 251.0, child: Text('a')),
236
                SizedBox(key: key1, height: 253.0, child: const Text('c')),
237
                const SizedBox(height: 252.0, child: Text('b')),
238 239 240
              ]),
            ),
          ],
Ian Hickson's avatar
Ian Hickson committed
241
        ),
242 243
      ),
    );
244
    verify(tester, <Offset>[
245
      Offset.zero,
246 247
      const Offset(0.0, 251.0),
      const Offset(0.0, 504.0),
Ian Hickson's avatar
Ian Hickson committed
248 249
    ], 'acb');
  });
250

251 252 253 254
  testWidgetsWithLeakTracking('Viewport overflow clipping of SliverToBoxAdapter', (WidgetTester tester) async {
    final ViewportOffset offset1 = ViewportOffset.zero();
    addTearDown(offset1.dispose);

255
    await tester.pumpWidget(
256
      Directionality(
257
        textDirection: TextDirection.ltr,
258
        child: Viewport(
259
          offset: offset1,
260
          slivers: const <Widget>[
261 262
            SliverToBoxAdapter(
              child: SizedBox(height: 400.0, child: Text('a')),
263 264
            ),
          ],
265
        ),
266 267
      ),
    );
268

Adam Barth's avatar
Adam Barth committed
269
    expect(find.byType(Viewport), isNot(paints..clipRect()));
270

271 272 273
    final ViewportOffset offset2 = ViewportOffset.fixed(100.0);
    addTearDown(offset2.dispose);

274
    await tester.pumpWidget(
275
      Directionality(
276
        textDirection: TextDirection.ltr,
277
        child: Viewport(
278
          offset: offset2,
279
          slivers: const <Widget>[
280 281
            SliverToBoxAdapter(
              child: SizedBox(height: 400.0, child: Text('a')),
282 283
            ),
          ],
284
        ),
285 286
      ),
    );
287

Adam Barth's avatar
Adam Barth committed
288
    expect(find.byType(Viewport), paints..clipRect());
289

290 291 292
    final ViewportOffset offset3 = ViewportOffset.fixed(100.0);
    addTearDown(offset3.dispose);

293
    await tester.pumpWidget(
294
      Directionality(
295
        textDirection: TextDirection.ltr,
296
        child: Viewport(
297
          offset: offset3,
298
          slivers: const <Widget>[
299 300
            SliverToBoxAdapter(
              child: SizedBox(height: 4000.0, child: Text('a')),
301 302
            ),
          ],
303
        ),
304 305
      ),
    );
306

Adam Barth's avatar
Adam Barth committed
307
    expect(find.byType(Viewport), paints..clipRect());
308

309 310 311
    final ViewportOffset offset4 = ViewportOffset.zero();
    addTearDown(offset4.dispose);

312
    await tester.pumpWidget(
313
      Directionality(
314
        textDirection: TextDirection.ltr,
315
        child: Viewport(
316
          offset: offset4,
317
          slivers: const <Widget>[
318 319
            SliverToBoxAdapter(
              child: SizedBox(height: 4000.0, child: Text('a')),
320 321
            ),
          ],
322
        ),
323 324
      ),
    );
325

Adam Barth's avatar
Adam Barth committed
326
    expect(find.byType(Viewport), paints..clipRect());
327 328
  });

329 330 331 332
  testWidgetsWithLeakTracking('Viewport overflow clipping of SliverBlock', (WidgetTester tester) async {
    final ViewportOffset offset1 = ViewportOffset.zero();
    addTearDown(offset1.dispose);

333
    await tester.pumpWidget(
334
      Directionality(
335
        textDirection: TextDirection.ltr,
336
        child: Viewport(
337
          offset: offset1,
338
          slivers: <Widget>[
339
            SliverList(
340
              delegate: SliverChildListDelegate(const <Widget>[
341
                SizedBox(height: 400.0, child: Text('a')),
342 343 344
              ]),
            ),
          ],
345
        ),
346 347
      ),
    );
348

Adam Barth's avatar
Adam Barth committed
349
    expect(find.byType(Viewport), isNot(paints..clipRect()));
350

351 352 353
    final ViewportOffset offset2 = ViewportOffset.fixed(100.0);
    addTearDown(offset2.dispose);

354
    await tester.pumpWidget(
355
      Directionality(
356
        textDirection: TextDirection.ltr,
357
        child: Viewport(
358
          offset: offset2,
359
          slivers: <Widget>[
360
            SliverList(
361
              delegate: SliverChildListDelegate(const <Widget>[
362
                SizedBox(height: 400.0, child: Text('a')),
363 364 365
              ]),
            ),
          ],
366
        ),
367 368
      ),
    );
369

Adam Barth's avatar
Adam Barth committed
370
    expect(find.byType(Viewport), paints..clipRect());
371

372 373 374
    final ViewportOffset offset3 = ViewportOffset.fixed(100.0);
    addTearDown(offset3.dispose);

375
    await tester.pumpWidget(
376
      Directionality(
377
        textDirection: TextDirection.ltr,
378
        child: Viewport(
379
          offset: offset3,
380
          slivers: <Widget>[
381
            SliverList(
382
              delegate: SliverChildListDelegate(const <Widget>[
383
                SizedBox(height: 4000.0, child: Text('a')),
384 385 386
              ]),
            ),
          ],
387
        ),
388 389
      ),
    );
390

Adam Barth's avatar
Adam Barth committed
391
    expect(find.byType(Viewport), paints..clipRect());
392

393 394 395
    final ViewportOffset offset4 = ViewportOffset.zero();
    addTearDown(offset4.dispose);

396
    await tester.pumpWidget(
397
      Directionality(
398
        textDirection: TextDirection.ltr,
399
        child: Viewport(
400
          offset: offset4,
401
          slivers: <Widget>[
402
            SliverList(
403
              delegate: SliverChildListDelegate(const <Widget>[
404
                SizedBox(height: 4000.0, child: Text('a')),
405 406 407
              ]),
            ),
          ],
408
        ),
409 410
      ),
    );
411

Adam Barth's avatar
Adam Barth committed
412
    expect(find.byType(Viewport), paints..clipRect());
413
  });
Ian Hickson's avatar
Ian Hickson committed
414
}