slivers_test.dart 35.7 KB
Newer Older
1 2 3 4 5
// Copyright 2015 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/rendering.dart';
6
import 'package:flutter_test/flutter_test.dart';
7
import 'package:vector_math/vector_math_64.dart';
8 9 10 11

import 'rendering_tester.dart';

void main() {
Adam Barth's avatar
Adam Barth committed
12
  test('RenderViewport basic test - no children', () {
13
    final RenderViewport root = RenderViewport(
14
      crossAxisDirection: AxisDirection.right,
15
      offset: ViewportOffset.zero(),
Ian Hickson's avatar
Ian Hickson committed
16
    );
17
    expect(root, hasAGoodToStringDeep);
18
    expect(
19
      root.toStringDeep(minLevel: DiagnosticLevel.info),
20 21
      equalsIgnoringHashCodes(
        'RenderViewport#00000 NEEDS-LAYOUT NEEDS-PAINT DETACHED\n'
Ian Hickson's avatar
Ian Hickson committed
22 23
        '   parentData: MISSING\n'
        '   constraints: MISSING\n'
24 25
        '   size: MISSING\n'
        '   axisDirection: down\n'
26
        '   crossAxisDirection: right\n'
27 28
        '   offset: _FixedViewportOffset#00000(offset: 0.0)\n'
        '   anchor: 0.0\n'
29 30
      ),
    );
31
    layout(root);
32
    root.offset = ViewportOffset.fixed(900.0);
33
    expect(root, hasAGoodToStringDeep);
34
    expect(
35
      root.toStringDeep(minLevel: DiagnosticLevel.info),
36 37
      equalsIgnoringHashCodes(
        'RenderViewport#00000 NEEDS-LAYOUT NEEDS-PAINT\n'
38 39 40 41
        '   parentData: <none>\n'
        '   constraints: BoxConstraints(w=800.0, h=600.0)\n'
        '   size: Size(800.0, 600.0)\n'
        '   axisDirection: down\n'
42
        '   crossAxisDirection: right\n'
43 44
        '   offset: _FixedViewportOffset#00000(offset: 900.0)\n'
        '   anchor: 0.0\n',
45 46 47
      ),
    );

48 49 50
    pumpFrame();
  });

Adam Barth's avatar
Adam Barth committed
51
  test('RenderViewport basic test - down', () {
52
    RenderBox a, b, c, d, e;
53
    final RenderViewport root = RenderViewport(
54
      crossAxisDirection: AxisDirection.right,
55
      offset: ViewportOffset.zero(),
56
      children: <RenderSliver>[
57 58 59 60 61
        RenderSliverToBoxAdapter(child: a = RenderSizedBox(const Size(100.0, 400.0))),
        RenderSliverToBoxAdapter(child: b = RenderSizedBox(const Size(100.0, 400.0))),
        RenderSliverToBoxAdapter(child: c = RenderSizedBox(const Size(100.0, 400.0))),
        RenderSliverToBoxAdapter(child: d = RenderSizedBox(const Size(100.0, 400.0))),
        RenderSliverToBoxAdapter(child: e = RenderSizedBox(const Size(100.0, 400.0))),
62 63
      ],
    );
64
    expect(root, hasAGoodToStringDeep);
65 66 67 68 69
    layout(root);

    expect(root.size.width, equals(800.0));
    expect(root.size.height, equals(600.0));

70 71
    expect(root, hasAGoodToStringDeep);
    expect(
72
      root.toStringDeep(minLevel: DiagnosticLevel.info),
73 74 75 76 77
      equalsIgnoringHashCodes(
        'RenderViewport#00000 NEEDS-PAINT\n'
        ' │ parentData: <none>\n'
        ' │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
        ' │ size: Size(800.0, 600.0)\n'
78
        ' │ axisDirection: down\n'
79
        ' │ crossAxisDirection: right\n'
80 81 82 83 84 85 86 87
        ' │ offset: _FixedViewportOffset#00000(offset: 0.0)\n'
        ' │ anchor: 0.0\n'
        ' │\n'
        ' ├─center child: RenderSliverToBoxAdapter#00000 relayoutBoundary=up1 NEEDS-PAINT\n'
        ' │ │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n'
        ' │ │ constraints: SliverConstraints(AxisDirection.down,\n'
        ' │ │   GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
        ' │ │   0.0, remainingPaintExtent: 600.0, crossAxisExtent: 800.0,\n'
88
        ' │ │   crossAxisDirection: AxisDirection.right,\n'
89 90
        ' │ │   viewportMainAxisExtent: 600.0, remainingCacheExtent: 850.0\n'
        ' │ │   cacheOrigin: 0.0 )\n'
91
        ' │ │ geometry: SliverGeometry(scrollExtent: 400.0, paintExtent: 400.0,\n'
92
        ' │ │   maxPaintExtent: 400.0, cacheExtent: 400.0)\n'
93 94 95 96 97 98 99 100 101 102 103
        ' │ │\n'
        ' │ └─child: RenderSizedBox#00000 NEEDS-PAINT\n'
        ' │     parentData: paintOffset=Offset(0.0, -0.0) (can use size)\n'
        ' │     constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
        ' │     size: Size(800.0, 400.0)\n'
        ' │\n'
        ' ├─child 1: RenderSliverToBoxAdapter#00000 relayoutBoundary=up1 NEEDS-PAINT\n'
        ' │ │ parentData: paintOffset=Offset(0.0, 400.0) (can use size)\n'
        ' │ │ constraints: SliverConstraints(AxisDirection.down,\n'
        ' │ │   GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
        ' │ │   0.0, remainingPaintExtent: 200.0, crossAxisExtent: 800.0,\n'
104
        ' │ │   crossAxisDirection: AxisDirection.right,\n'
105 106
        ' │ │   viewportMainAxisExtent: 600.0, remainingCacheExtent: 450.0\n'
        ' │ │   cacheOrigin: 0.0 )\n'
107
        ' │ │ geometry: SliverGeometry(scrollExtent: 400.0, paintExtent: 200.0,\n'
108 109
        ' │ │   maxPaintExtent: 400.0, hasVisualOverflow: true, cacheExtent:\n'
        ' │ │   400.0)\n'
110 111 112 113 114 115 116
        ' │ │\n'
        ' │ └─child: RenderSizedBox#00000 NEEDS-PAINT\n'
        ' │     parentData: paintOffset=Offset(0.0, -0.0) (can use size)\n'
        ' │     constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
        ' │     size: Size(800.0, 400.0)\n'
        ' │\n'
        ' ├─child 2: RenderSliverToBoxAdapter#00000 relayoutBoundary=up1 NEEDS-PAINT\n'
117
        ' │ │ parentData: paintOffset=Offset(0.0, 800.0) (can use size)\n'
118 119 120
        ' │ │ constraints: SliverConstraints(AxisDirection.down,\n'
        ' │ │   GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
        ' │ │   0.0, remainingPaintExtent: 0.0, crossAxisExtent: 800.0,\n'
121
        ' │ │   crossAxisDirection: AxisDirection.right,\n'
122 123
        ' │ │   viewportMainAxisExtent: 600.0, remainingCacheExtent: 50.0\n'
        ' │ │   cacheOrigin: 0.0 )\n'
124
        ' │ │ geometry: SliverGeometry(scrollExtent: 400.0, hidden,\n'
125 126
        ' │ │   maxPaintExtent: 400.0, hasVisualOverflow: true, cacheExtent:\n'
        ' │ │   50.0)\n'
127 128 129 130 131 132 133
        ' │ │\n'
        ' │ └─child: RenderSizedBox#00000 NEEDS-PAINT\n'
        ' │     parentData: paintOffset=Offset(0.0, -0.0) (can use size)\n'
        ' │     constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
        ' │     size: Size(800.0, 400.0)\n'
        ' │\n'
        ' ├─child 3: RenderSliverToBoxAdapter#00000 relayoutBoundary=up1 NEEDS-PAINT\n'
134
        ' │ │ parentData: paintOffset=Offset(0.0, 1200.0) (can use size)\n'
135 136 137
        ' │ │ constraints: SliverConstraints(AxisDirection.down,\n'
        ' │ │   GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
        ' │ │   0.0, remainingPaintExtent: 0.0, crossAxisExtent: 800.0,\n'
138
        ' │ │   crossAxisDirection: AxisDirection.right,\n'
139 140
        ' │ │   viewportMainAxisExtent: 600.0, remainingCacheExtent: 0.0\n'
        ' │ │   cacheOrigin: 0.0 )\n'
141
        ' │ │ geometry: SliverGeometry(scrollExtent: 400.0, hidden,\n'
142
        ' │ │   maxPaintExtent: 400.0, hasVisualOverflow: true)\n'
143 144 145 146 147 148 149
        ' │ │\n'
        ' │ └─child: RenderSizedBox#00000 NEEDS-PAINT\n'
        ' │     parentData: paintOffset=Offset(0.0, -0.0) (can use size)\n'
        ' │     constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
        ' │     size: Size(800.0, 400.0)\n'
        ' │\n'
        ' └─child 4: RenderSliverToBoxAdapter#00000 relayoutBoundary=up1 NEEDS-PAINT\n'
150
        '   │ parentData: paintOffset=Offset(0.0, 1600.0) (can use size)\n'
151 152 153
        '   │ constraints: SliverConstraints(AxisDirection.down,\n'
        '   │   GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
        '   │   0.0, remainingPaintExtent: 0.0, crossAxisExtent: 800.0,\n'
154
        '   │   crossAxisDirection: AxisDirection.right,\n'
155 156
        '   │   viewportMainAxisExtent: 600.0, remainingCacheExtent: 0.0\n'
        '   │   cacheOrigin: 0.0 )\n'
157
        '   │ geometry: SliverGeometry(scrollExtent: 400.0, hidden,\n'
158
        '   │   maxPaintExtent: 400.0, hasVisualOverflow: true)\n'
159 160 161 162
        '   │\n'
        '   └─child: RenderSizedBox#00000 NEEDS-PAINT\n'
        '       parentData: paintOffset=Offset(0.0, -0.0) (can use size)\n'
        '       constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
163
        '       size: Size(800.0, 400.0)\n'
164 165
      ),
    );
166 167
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 400.0));
168 169 170
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 800.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1200.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1600.0));
171 172 173

    expect(a.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 400.0));
    expect(b.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 800.0));
174 175 176
    expect(c.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 1200.0));
    expect(d.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 1600.0));
    expect(e.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 2000.0));
177

178
    root.offset = ViewportOffset.fixed(200.0);
179
    pumpFrame();
180 181 182
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -200.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 200.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 600.0));
183 184
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1000.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1400.0));
185

186
    root.offset = ViewportOffset.fixed(600.0);
187
    pumpFrame();
188 189 190 191
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -600.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -200.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 200.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 600.0));
192
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1000.0));
193

194
    root.offset = ViewportOffset.fixed(900.0);
195
    pumpFrame();
196 197 198 199
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -900.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -500.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -100.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 300.0));
200
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 700.0));
201

202
    final HitTestResult result = HitTestResult();
203
    root.hitTest(result, position: const Offset(130.0, 150.0));
204
    expect(result.path.first.target, equals(c));
205 206
  });

Adam Barth's avatar
Adam Barth committed
207
  test('RenderViewport basic test - up', () {
208
    RenderBox a, b, c, d, e;
209
    final RenderViewport root = RenderViewport(
210
      axisDirection: AxisDirection.up,
211
      crossAxisDirection: AxisDirection.right,
212
      offset: ViewportOffset.zero(),
213
      children: <RenderSliver>[
214 215 216 217 218
        RenderSliverToBoxAdapter(child: a = RenderSizedBox(const Size(100.0, 400.0))),
        RenderSliverToBoxAdapter(child: b = RenderSizedBox(const Size(100.0, 400.0))),
        RenderSliverToBoxAdapter(child: c = RenderSizedBox(const Size(100.0, 400.0))),
        RenderSliverToBoxAdapter(child: d = RenderSizedBox(const Size(100.0, 400.0))),
        RenderSliverToBoxAdapter(child: e = RenderSizedBox(const Size(100.0, 400.0))),
219 220 221 222 223 224 225
      ],
    );
    layout(root);

    expect(root.size.width, equals(800.0));
    expect(root.size.height, equals(600.0));

226 227
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 200.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -200.0));
228 229 230
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -600.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -1000.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -1400.0));
231

232
    root.offset = ViewportOffset.fixed(200.0);
233
    pumpFrame();
234 235 236
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 400.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0));
237 238
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -800.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -1200.0));
239

240
    root.offset = ViewportOffset.fixed(600.0);
241
    pumpFrame();
242 243 244 245
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 800.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 400.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0));
246
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -800.0));
247

248
    root.offset = ViewportOffset.fixed(900.0);
249
    pumpFrame();
250 251 252 253
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1100.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 700.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 300.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -100.0));
254
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -500.0));
255

256
    final HitTestResult result = HitTestResult();
257
    root.hitTest(result, position: const Offset(150.0, 350.0));
258
    expect(result.path.first.target, equals(c));
259 260
  });

261
  Offset _getPaintOrigin(RenderObject render) {
262 263
    final Vector3 transformed3 = render.getTransformTo(null).perspectiveTransform(Vector3(0.0, 0.0, 0.0));
    return Offset(transformed3.x, transformed3.y);
264 265
  }

Adam Barth's avatar
Adam Barth committed
266
  test('RenderViewport basic test - right', () {
267
    RenderBox a, b, c, d, e;
268
    final RenderViewport root = RenderViewport(
269
      axisDirection: AxisDirection.right,
270
      crossAxisDirection: AxisDirection.down,
271
      offset: ViewportOffset.zero(),
272
      children: <RenderSliver>[
273 274 275 276 277
        RenderSliverToBoxAdapter(child: a = RenderSizedBox(const Size(400.0, 100.0))),
        RenderSliverToBoxAdapter(child: b = RenderSizedBox(const Size(400.0, 100.0))),
        RenderSliverToBoxAdapter(child: c = RenderSizedBox(const Size(400.0, 100.0))),
        RenderSliverToBoxAdapter(child: d = RenderSizedBox(const Size(400.0, 100.0))),
        RenderSliverToBoxAdapter(child: e = RenderSizedBox(const Size(400.0, 100.0))),
278 279 280 281 282 283 284
      ],
    );
    layout(root);

    expect(root.size.width, equals(800.0));
    expect(root.size.height, equals(600.0));

285 286 287 288 289 290
    final RenderSliver sliverA = a.parent;
    final RenderSliver sliverB = b.parent;
    final RenderSliver sliverC = c.parent;
    final RenderSliver sliverD = d.parent;
    final RenderSliver sliverE = e.parent;

291 292 293
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(400.0, 0.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(800.0, 0.0));
294 295
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(1200.0, 0.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(1600.0, 0.0));
296

297 298 299
    expect(_getPaintOrigin(sliverA), const Offset(0.0, 0.0));
    expect(_getPaintOrigin(sliverB), const Offset(400.0, 0.0));
    expect(_getPaintOrigin(sliverC), const Offset(800.0, 0.0));
300 301
    expect(_getPaintOrigin(sliverD), const Offset(1200.0, 0.0));
    expect(_getPaintOrigin(sliverE), const Offset(1600.0, 0.0));
302

303
    root.offset = ViewportOffset.fixed(200.0);
304
    pumpFrame();
305 306 307
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(-200.0, 0.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(200.0, 0.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(600.0, 0.0));
308 309
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(1000.0, 0.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(1400.0, 0.0));
310

311 312 313
    expect(_getPaintOrigin(sliverA), const Offset(000.0, 0.0));
    expect(_getPaintOrigin(sliverB), const Offset(200.0, 0.0));
    expect(_getPaintOrigin(sliverC), const Offset(600.0, 0.0));
314 315
    expect(_getPaintOrigin(sliverD), const Offset(1000.0, 0.0));
    expect(_getPaintOrigin(sliverE), const Offset(1400.0, 0.0));
316

317
    root.offset = ViewportOffset.fixed(600.0);
318
    pumpFrame();
319 320 321 322
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(-600.0, 0.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(-200.0, 0.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(200.0, 0.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(600.0, 0.0));
323
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(1000.0, 0.0));
324

325 326 327 328
    expect(_getPaintOrigin(sliverA), const Offset(000.0, 0.0));
    expect(_getPaintOrigin(sliverB), const Offset(000.0, 0.0));
    expect(_getPaintOrigin(sliverC), const Offset(200.0, 0.0));
    expect(_getPaintOrigin(sliverD), const Offset(600.0, 0.0));
329
    expect(_getPaintOrigin(sliverE), const Offset(1000.0, 0.0));
330

331
    root.offset = ViewportOffset.fixed(900.0);
332
    pumpFrame();
333 334 335 336 337
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(-900.0, 0.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(-500.0, 0.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(-100.0, 0.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(300.0, 0.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(700.0, 0.0));
338

339 340 341 342 343 344
    expect(_getPaintOrigin(sliverA), const Offset(000.0, 0.0));
    expect(_getPaintOrigin(sliverB), const Offset(000.0, 0.0));
    expect(_getPaintOrigin(sliverC), const Offset(000.0, 0.0));
    expect(_getPaintOrigin(sliverD), const Offset(300.0, 0.0));
    expect(_getPaintOrigin(sliverE), const Offset(700.0, 0.0));

345
    final HitTestResult result = HitTestResult();
346
    root.hitTest(result, position: const Offset(150.0, 450.0));
347
    expect(result.path.first.target, equals(c));
348 349
  });

Adam Barth's avatar
Adam Barth committed
350
  test('RenderViewport basic test - left', () {
351
    RenderBox a, b, c, d, e;
352
    final RenderViewport root = RenderViewport(
353
      axisDirection: AxisDirection.left,
354
      crossAxisDirection: AxisDirection.down,
355
      offset: ViewportOffset.zero(),
356
      children: <RenderSliver>[
357 358 359 360 361
        RenderSliverToBoxAdapter(child: a = RenderSizedBox(const Size(400.0, 100.0))),
        RenderSliverToBoxAdapter(child: b = RenderSizedBox(const Size(400.0, 100.0))),
        RenderSliverToBoxAdapter(child: c = RenderSizedBox(const Size(400.0, 100.0))),
        RenderSliverToBoxAdapter(child: d = RenderSizedBox(const Size(400.0, 100.0))),
        RenderSliverToBoxAdapter(child: e = RenderSizedBox(const Size(400.0, 100.0))),
362 363 364 365 366 367 368
      ],
    );
    layout(root);

    expect(root.size.width, equals(800.0));
    expect(root.size.height, equals(600.0));

369 370 371
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(400.0, 0.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(-400.0, 0.0));
372 373
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(-800.0, 0.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-1200.0, 0.0));
374

375
    root.offset = ViewportOffset.fixed(200.0);
376
    pumpFrame();
377 378 379
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(600.0, 0.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(200.0, 0.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(-200.0, 0.0));
380 381
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(-600.0, 0.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-1000.0, 0.0));
382

383
    root.offset = ViewportOffset.fixed(600.0);
384
    pumpFrame();
385 386 387 388
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(1000.0, 0.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(600.0, 0.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(200.0, 0.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(-200.0, 0.0));
389
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-600.0, 0.0));
390

391
    root.offset = ViewportOffset.fixed(900.0);
392
    pumpFrame();
393 394 395 396 397
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(1300.0, 0.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(900.0, 0.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(500.0, 0.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(100.0, 0.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-300.0, 0.0));
398

399
    final HitTestResult result = HitTestResult();
400
    root.hitTest(result, position: const Offset(550.0, 150.0));
401
    expect(result.path.first.target, equals(c));
402 403 404 405 406 407
  });

  // TODO(ianh): test anchor
  // TODO(ianh): test center
  // TODO(ianh): test semantics

408
  test('RenderShrinkWrappingViewport basic test - no children', () {
409
    final RenderShrinkWrappingViewport root = RenderShrinkWrappingViewport(
410
      crossAxisDirection: AxisDirection.right,
411
      offset: ViewportOffset.zero(),
412
    );
413
    expect(root, hasAGoodToStringDeep);
414
    layout(root);
415
    root.offset = ViewportOffset.fixed(900.0);
416 417 418 419 420
    pumpFrame();
  });

  test('RenderShrinkWrappingViewport basic test - down', () {
    RenderBox a, b, c, d, e;
421
    final RenderShrinkWrappingViewport root = RenderShrinkWrappingViewport(
422
      crossAxisDirection: AxisDirection.right,
423
      offset: ViewportOffset.zero(),
424
      children: <RenderSliver>[
425 426 427 428 429
        RenderSliverToBoxAdapter(child: a = RenderSizedBox(const Size(100.0, 400.0))),
        RenderSliverToBoxAdapter(child: b = RenderSizedBox(const Size(100.0, 400.0))),
        RenderSliverToBoxAdapter(child: c = RenderSizedBox(const Size(100.0, 400.0))),
        RenderSliverToBoxAdapter(child: d = RenderSizedBox(const Size(100.0, 400.0))),
        RenderSliverToBoxAdapter(child: e = RenderSizedBox(const Size(100.0, 400.0))),
430 431 432 433 434 435 436
      ],
    );
    layout(root);

    expect(root.size.width, equals(800.0));
    expect(root.size.height, equals(600.0));

437 438
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 400.0));
439 440 441
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 800.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1200.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1600.0));
442

443 444
    expect(a.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 400.0));
    expect(b.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 800.0));
445 446 447
    expect(c.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 1200.0));
    expect(d.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 1600.0));
    expect(e.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 2000.0));
448

449
    root.offset = ViewportOffset.fixed(200.0);
450
    pumpFrame();
451 452 453
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -200.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 200.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 600.0));
454 455
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1000.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1400.0));
456

457
    root.offset = ViewportOffset.fixed(600.0);
458
    pumpFrame();
459 460 461 462
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -600.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -200.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 200.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 600.0));
463
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1000.0));
464

465
    root.offset = ViewportOffset.fixed(900.0);
466
    pumpFrame();
467 468 469 470
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -900.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -500.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -100.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 300.0));
471
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 700.0));
472

473
    final HitTestResult result = HitTestResult();
474
    root.hitTest(result, position: const Offset(130.0, 150.0));
475 476 477 478 479
    expect(result.path.first.target, equals(c));
  });

  test('RenderShrinkWrappingViewport basic test - up', () {
    RenderBox a, b, c, d, e;
480
    final RenderShrinkWrappingViewport root = RenderShrinkWrappingViewport(
481
      axisDirection: AxisDirection.up,
482
      crossAxisDirection: AxisDirection.right,
483
      offset: ViewportOffset.zero(),
484
      children: <RenderSliver>[
485 486 487 488 489
        RenderSliverToBoxAdapter(child: a = RenderSizedBox(const Size(100.0, 400.0))),
        RenderSliverToBoxAdapter(child: b = RenderSizedBox(const Size(100.0, 400.0))),
        RenderSliverToBoxAdapter(child: c = RenderSizedBox(const Size(100.0, 400.0))),
        RenderSliverToBoxAdapter(child: d = RenderSizedBox(const Size(100.0, 400.0))),
        RenderSliverToBoxAdapter(child: e = RenderSizedBox(const Size(100.0, 400.0))),
490 491 492 493 494 495 496
      ],
    );
    layout(root);

    expect(root.size.width, equals(800.0));
    expect(root.size.height, equals(600.0));

497 498
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 200.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -200.0));
499 500 501
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -600.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -1000.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -1400.0));
502

503
    root.offset = ViewportOffset.fixed(200.0);
504
    pumpFrame();
505 506 507
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 400.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0));
508 509
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -800.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -1200.0));
510

511
    root.offset = ViewportOffset.fixed(600.0);
512
    pumpFrame();
513 514 515 516
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 800.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 400.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0));
517
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -800.0));
518

519
    root.offset = ViewportOffset.fixed(900.0);
520
    pumpFrame();
521 522 523 524
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 1100.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 700.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 300.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -100.0));
525
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -500.0));
526

527
    final HitTestResult result = HitTestResult();
528
    root.hitTest(result, position: const Offset(150.0, 350.0));
529 530 531 532 533
    expect(result.path.first.target, equals(c));
  });

  test('RenderShrinkWrappingViewport basic test - right', () {
    RenderBox a, b, c, d, e;
534
    final RenderShrinkWrappingViewport root = RenderShrinkWrappingViewport(
535
      axisDirection: AxisDirection.right,
536
      crossAxisDirection: AxisDirection.down,
537
      offset: ViewportOffset.zero(),
538
      children: <RenderSliver>[
539 540 541 542 543
        RenderSliverToBoxAdapter(child: a = RenderSizedBox(const Size(400.0, 100.0))),
        RenderSliverToBoxAdapter(child: b = RenderSizedBox(const Size(400.0, 100.0))),
        RenderSliverToBoxAdapter(child: c = RenderSizedBox(const Size(400.0, 100.0))),
        RenderSliverToBoxAdapter(child: d = RenderSizedBox(const Size(400.0, 100.0))),
        RenderSliverToBoxAdapter(child: e = RenderSizedBox(const Size(400.0, 100.0))),
544 545 546 547 548 549 550
      ],
    );
    layout(root);

    expect(root.size.width, equals(800.0));
    expect(root.size.height, equals(600.0));

551 552 553
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(400.0, 0.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(800.0, 0.0));
554 555
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(1200.0, 0.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(1600.0, 0.0));
556

557
    root.offset = ViewportOffset.fixed(200.0);
558
    pumpFrame();
559 560 561
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(-200.0, 0.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(200.0, 0.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(600.0, 0.0));
562 563
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(1000.0, 0.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(1400.0, 0.0));
564

565
    root.offset = ViewportOffset.fixed(600.0);
566
    pumpFrame();
567 568 569 570
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(-600.0, 0.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(-200.0, 0.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(200.0, 0.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(600.0, 0.0));
571
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(1000.0, 0.0));
572

573
    root.offset = ViewportOffset.fixed(900.0);
574
    pumpFrame();
575 576 577 578 579
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(-900.0, 0.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(-500.0, 0.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(-100.0, 0.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(300.0, 0.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(700.0, 0.0));
580

581
    final HitTestResult result = HitTestResult();
582
    root.hitTest(result, position: const Offset(150.0, 450.0));
583 584 585 586 587
    expect(result.path.first.target, equals(c));
  });

  test('RenderShrinkWrappingViewport basic test - left', () {
    RenderBox a, b, c, d, e;
588
    final RenderShrinkWrappingViewport root = RenderShrinkWrappingViewport(
589
      axisDirection: AxisDirection.left,
590
      crossAxisDirection: AxisDirection.down,
591
      offset: ViewportOffset.zero(),
592
      children: <RenderSliver>[
593 594 595 596 597
        RenderSliverToBoxAdapter(child: a = RenderSizedBox(const Size(400.0, 100.0))),
        RenderSliverToBoxAdapter(child: b = RenderSizedBox(const Size(400.0, 100.0))),
        RenderSliverToBoxAdapter(child: c = RenderSizedBox(const Size(400.0, 100.0))),
        RenderSliverToBoxAdapter(child: d = RenderSizedBox(const Size(400.0, 100.0))),
        RenderSliverToBoxAdapter(child: e = RenderSizedBox(const Size(400.0, 100.0))),
598 599 600 601 602 603 604
      ],
    );
    layout(root);

    expect(root.size.width, equals(800.0));
    expect(root.size.height, equals(600.0));

605 606 607
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(400.0, 0.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 0.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(-400.0, 0.0));
608 609
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(-800.0, 0.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-1200.0, 0.0));
610

611
    root.offset = ViewportOffset.fixed(200.0);
612
    pumpFrame();
613 614 615
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(600.0, 0.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(200.0, 0.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(-200.0, 0.0));
616 617
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(-600.0, 0.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-1000.0, 0.0));
618

619
    root.offset = ViewportOffset.fixed(600.0);
620
    pumpFrame();
621 622 623 624
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(1000.0, 0.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(600.0, 0.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(200.0, 0.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(-200.0, 0.0));
625
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-600.0, 0.0));
626

627
    root.offset = ViewportOffset.fixed(900.0);
628
    pumpFrame();
629 630 631 632 633
    expect(a.localToGlobal(const Offset(0.0, 0.0)), const Offset(1300.0, 0.0));
    expect(b.localToGlobal(const Offset(0.0, 0.0)), const Offset(900.0, 0.0));
    expect(c.localToGlobal(const Offset(0.0, 0.0)), const Offset(500.0, 0.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(100.0, 0.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-300.0, 0.0));
634

635
    final HitTestResult result = HitTestResult();
636
    root.hitTest(result, position: const Offset(550.0, 150.0));
637 638 639 640 641
    expect(result.path.first.target, equals(c));
  });

  test('RenderShrinkWrappingViewport shrinkwrap test - 1 child', () {
    RenderBox child;
642 643
    final RenderBox root = RenderPositionedBox(
      child: child = RenderShrinkWrappingViewport(
644
        axisDirection: AxisDirection.left,
645
        crossAxisDirection: AxisDirection.down,
646
        offset: ViewportOffset.fixed(200.0),
647
        children: <RenderSliver>[
648
          RenderSliverToBoxAdapter(child: RenderSizedBox(const Size(400.0, 100.0))),
649 650 651 652 653 654 655 656 657 658 659 660 661
        ],
      ),
    );
    layout(root);

    expect(root.size.width, equals(800.0));
    expect(root.size.height, equals(600.0));
    expect(child.size.width, equals(400.0));
    expect(child.size.height, equals(600.0));
  });

  test('RenderShrinkWrappingViewport shrinkwrap test - 2 children', () {
    RenderBox child;
662 663
    final RenderBox root = RenderPositionedBox(
      child: child = RenderShrinkWrappingViewport(
664
        axisDirection: AxisDirection.right,
665
        crossAxisDirection: AxisDirection.down,
666
        offset: ViewportOffset.fixed(200.0),
667
        children: <RenderSliver>[
668 669
          RenderSliverToBoxAdapter(child: RenderSizedBox(const Size(300.0, 100.0))),
          RenderSliverToBoxAdapter(child: RenderSizedBox(const Size(150.0, 100.0))),
670 671 672 673 674 675 676 677 678 679
        ],
      ),
    );
    layout(root);

    expect(root.size.width, equals(800.0));
    expect(root.size.height, equals(600.0));
    expect(child.size.width, equals(450.0));
    expect(child.size.height, equals(600.0));
  });
680 681 682

  test('SliverGeometry toString', () {
    expect(
683 684 685
      const SliverGeometry().toString(),
      equals('SliverGeometry(scrollExtent: 0.0, hidden, maxPaintExtent: 0.0)'),
    );
686
    expect(
687 688 689 690 691 692 693
      const SliverGeometry(
        scrollExtent: 100.0,
        paintExtent: 50.0,
        layoutExtent: 20.0,
        visible: true,
      ).toString(),
      equals(
694
        'SliverGeometry(scrollExtent: 100.0, paintExtent: 50.0, layoutExtent: 20.0, maxPaintExtent: 0.0, cacheExtent: 20.0)',
695 696 697 698 699 700 701 702 703
      ),
    );
    expect(
      const SliverGeometry(
        scrollExtent: 100.0,
        paintExtent: 0.0,
        layoutExtent: 20.0,
      ).toString(),
      equals(
704
        'SliverGeometry(scrollExtent: 100.0, hidden, layoutExtent: 20.0, maxPaintExtent: 0.0, cacheExtent: 20.0)',
705 706
      ),
    );
707
  });
708 709 710 711

  test('Sliver paintBounds and semanticBounds - vertical', () {
    const double height = 150.0;

712 713
    final RenderSliver sliver = RenderSliverToBoxAdapter(
        child: RenderSizedBox(const Size(400.0, height)),
714
    );
715
    final RenderViewport root = RenderViewport(
716
      axisDirection: AxisDirection.down,
717
      crossAxisDirection: AxisDirection.right,
718
      offset: ViewportOffset.zero(),
719 720 721 722 723 724
      children: <RenderSliver>[
        sliver,
      ],
    );
    layout(root);

725
    final Rect expectedRect = Rect.fromLTWH(0.0, 0.0, root.size.width, height);
726 727 728 729 730 731 732 733

    expect(sliver.paintBounds, expectedRect);
    expect(sliver.semanticBounds, expectedRect);
  });

  test('Sliver paintBounds and semanticBounds - horizontal', () {
    const double width = 150.0;

734 735
    final RenderSliver sliver = RenderSliverToBoxAdapter(
      child: RenderSizedBox(const Size(width, 400.0)),
736
    );
737
    final RenderViewport root = RenderViewport(
738
      axisDirection: AxisDirection.right,
739
      crossAxisDirection: AxisDirection.down,
740
      offset: ViewportOffset.zero(),
741 742 743 744 745 746
      children: <RenderSliver>[
        sliver,
      ],
    );
    layout(root);

747
    final Rect expectedRect = Rect.fromLTWH(0.0, 0.0, width, root.size.height);
748 749 750 751

    expect(sliver.paintBounds, expectedRect);
    expect(sliver.semanticBounds, expectedRect);
  });
752
}