slivers_test.dart 35.8 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 = new RenderViewport(
14
      crossAxisDirection: AxisDirection.right,
Ian Hickson's avatar
Ian Hickson committed
15 16
      offset: new ViewportOffset.zero(),
    );
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 32
    layout(root);
    root.offset = new 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 = new RenderViewport(
54
      crossAxisDirection: AxisDirection.right,
Ian Hickson's avatar
Ian Hickson committed
55
      offset: new ViewportOffset.zero(),
56 57 58 59 60 61 62 63
      children: <RenderSliver>[
        new RenderSliverToBoxAdapter(child: a = new RenderSizedBox(const Size(100.0, 400.0))),
        new RenderSliverToBoxAdapter(child: b = new RenderSizedBox(const Size(100.0, 400.0))),
        new RenderSliverToBoxAdapter(child: c = new RenderSizedBox(const Size(100.0, 400.0))),
        new RenderSliverToBoxAdapter(child: d = new RenderSizedBox(const Size(100.0, 400.0))),
        new RenderSliverToBoxAdapter(child: e = new RenderSizedBox(const Size(100.0, 400.0))),
      ],
    );
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)\n'
        ' │ │ geometry: SliverGeometry(scrollExtent: 400.0, paintExtent: 400.0,\n'
91
        ' │ │   maxPaintExtent: 400.0)\n'
92 93 94 95 96 97 98 99 100 101 102
        ' │ │\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'
103
        ' │ │   crossAxisDirection: AxisDirection.right,\n'
104 105
        ' │ │   viewportMainAxisExtent: 600.0)\n'
        ' │ │ geometry: SliverGeometry(scrollExtent: 400.0, paintExtent: 200.0,\n'
106
        ' │ │   maxPaintExtent: 400.0, hasVisualOverflow: true)\n'
107 108 109 110 111 112 113 114 115 116 117
        ' │ │\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'
        ' │ │ parentData: paintOffset=Offset(0.0, 600.0) (can use size)\n'
        ' │ │ constraints: SliverConstraints(AxisDirection.down,\n'
        ' │ │   GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
        ' │ │   0.0, remainingPaintExtent: 0.0, crossAxisExtent: 800.0,\n'
118
        ' │ │   crossAxisDirection: AxisDirection.right,\n'
119 120
        ' │ │   viewportMainAxisExtent: 600.0)\n'
        ' │ │ geometry: SliverGeometry(scrollExtent: 400.0, hidden,\n'
121
        ' │ │   maxPaintExtent: 400.0, hasVisualOverflow: true)\n'
122 123 124 125 126 127 128 129 130 131 132
        ' │ │\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'
        ' │ │ parentData: paintOffset=Offset(0.0, 600.0) (can use size)\n'
        ' │ │ constraints: SliverConstraints(AxisDirection.down,\n'
        ' │ │   GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
        ' │ │   0.0, remainingPaintExtent: 0.0, crossAxisExtent: 800.0,\n'
133
        ' │ │   crossAxisDirection: AxisDirection.right,\n'
134 135
        ' │ │   viewportMainAxisExtent: 600.0)\n'
        ' │ │ geometry: SliverGeometry(scrollExtent: 400.0, hidden,\n'
136
        ' │ │   maxPaintExtent: 400.0, hasVisualOverflow: true)\n'
137 138 139 140 141 142 143 144 145 146 147
        ' │ │\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'
        '   │ parentData: paintOffset=Offset(0.0, 600.0) (can use size)\n'
        '   │ constraints: SliverConstraints(AxisDirection.down,\n'
        '   │   GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n'
        '   │   0.0, remainingPaintExtent: 0.0, crossAxisExtent: 800.0,\n'
148
        '   │   crossAxisDirection: AxisDirection.right,\n'
149 150
        '   │   viewportMainAxisExtent: 600.0)\n'
        '   │ geometry: SliverGeometry(scrollExtent: 400.0, hidden,\n'
151
        '   │   maxPaintExtent: 400.0, hasVisualOverflow: true)\n'
152 153 154 155
        '   │\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'
156
        '       size: Size(800.0, 400.0)\n'
157 158
      ),
    );
159 160 161 162 163 164 165 166 167 168 169
    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));
    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, 600.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 600.0));

    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));
    expect(c.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 1000.0));
    expect(d.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 1000.0));
    expect(e.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 1000.0));
170

171 172
    root.offset = new ViewportOffset.fixed(200.0);
    pumpFrame();
173 174 175 176 177
    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));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 600.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 600.0));
178 179 180

    root.offset = new ViewportOffset.fixed(600.0);
    pumpFrame();
181 182 183 184 185
    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));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 600.0));
186 187 188

    root.offset = new ViewportOffset.fixed(900.0);
    pumpFrame();
189 190 191 192 193
    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));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 600.0));
194

195
    final HitTestResult result = new HitTestResult();
196
    root.hitTest(result, position: const Offset(130.0, 150.0));
197
    expect(result.path.first.target, equals(c));
198 199
  });

Adam Barth's avatar
Adam Barth committed
200
  test('RenderViewport basic test - up', () {
201
    RenderBox a, b, c, d, e;
202
    final RenderViewport root = new RenderViewport(
203
      axisDirection: AxisDirection.up,
204
      crossAxisDirection: AxisDirection.right,
Ian Hickson's avatar
Ian Hickson committed
205
      offset: new ViewportOffset.zero(),
206 207 208 209 210 211 212 213 214 215 216 217 218
      children: <RenderSliver>[
        new RenderSliverToBoxAdapter(child: a = new RenderSizedBox(const Size(100.0, 400.0))),
        new RenderSliverToBoxAdapter(child: b = new RenderSizedBox(const Size(100.0, 400.0))),
        new RenderSliverToBoxAdapter(child: c = new RenderSizedBox(const Size(100.0, 400.0))),
        new RenderSliverToBoxAdapter(child: d = new RenderSizedBox(const Size(100.0, 400.0))),
        new RenderSliverToBoxAdapter(child: e = new RenderSizedBox(const Size(100.0, 400.0))),
      ],
    );
    layout(root);

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

219 220 221 222 223
    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, -400.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0));
224 225 226

    root.offset = new ViewportOffset.fixed(200.0);
    pumpFrame();
227 228 229 230 231
    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));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0));
232 233 234

    root.offset = new ViewportOffset.fixed(600.0);
    pumpFrame();
235 236 237 238 239
    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));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0));
240 241 242

    root.offset = new ViewportOffset.fixed(900.0);
    pumpFrame();
243 244 245 246 247
    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));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0));
248

249
    final HitTestResult result = new HitTestResult();
250
    root.hitTest(result, position: const Offset(150.0, 350.0));
251
    expect(result.path.first.target, equals(c));
252 253
  });

254 255 256 257 258
  Offset _getPaintOrigin(RenderObject render) {
    final Vector3 transformed3 = render.getTransformTo(null).perspectiveTransform(new Vector3(0.0, 0.0, 0.0));
    return new Offset(transformed3.x, transformed3.y);
  }

Adam Barth's avatar
Adam Barth committed
259
  test('RenderViewport basic test - right', () {
260
    RenderBox a, b, c, d, e;
261
    final RenderViewport root = new RenderViewport(
262
      axisDirection: AxisDirection.right,
263
      crossAxisDirection: AxisDirection.down,
Ian Hickson's avatar
Ian Hickson committed
264
      offset: new ViewportOffset.zero(),
265 266 267 268 269 270 271 272 273 274 275 276 277
      children: <RenderSliver>[
        new RenderSliverToBoxAdapter(child: a = new RenderSizedBox(const Size(400.0, 100.0))),
        new RenderSliverToBoxAdapter(child: b = new RenderSizedBox(const Size(400.0, 100.0))),
        new RenderSliverToBoxAdapter(child: c = new RenderSizedBox(const Size(400.0, 100.0))),
        new RenderSliverToBoxAdapter(child: d = new RenderSizedBox(const Size(400.0, 100.0))),
        new RenderSliverToBoxAdapter(child: e = new RenderSizedBox(const Size(400.0, 100.0))),
      ],
    );
    layout(root);

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

278 279 280 281 282 283
    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;

284 285 286 287 288
    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));
    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(800.0, 0.0));
289

290 291 292 293 294 295
    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));
    expect(_getPaintOrigin(sliverD), const Offset(800.0, 0.0));
    expect(_getPaintOrigin(sliverE), const Offset(800.0, 0.0));

296 297
    root.offset = new ViewportOffset.fixed(200.0);
    pumpFrame();
298 299 300 301 302
    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));
    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(800.0, 0.0));
303

304 305 306 307 308 309
    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));
    expect(_getPaintOrigin(sliverD), const Offset(800.0, 0.0));
    expect(_getPaintOrigin(sliverE), const Offset(800.0, 0.0));

310 311
    root.offset = new ViewportOffset.fixed(600.0);
    pumpFrame();
312 313 314 315 316
    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));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(800.0, 0.0));
317

318 319 320 321 322 323
    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));
    expect(_getPaintOrigin(sliverE), const Offset(800.0, 0.0));

324 325
    root.offset = new ViewportOffset.fixed(900.0);
    pumpFrame();
326 327 328 329 330
    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));
331

332 333 334 335 336 337
    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));

338
    final HitTestResult result = new HitTestResult();
339
    root.hitTest(result, position: const Offset(150.0, 450.0));
340
    expect(result.path.first.target, equals(c));
341 342
  });

Adam Barth's avatar
Adam Barth committed
343
  test('RenderViewport basic test - left', () {
344
    RenderBox a, b, c, d, e;
345
    final RenderViewport root = new RenderViewport(
346
      axisDirection: AxisDirection.left,
347
      crossAxisDirection: AxisDirection.down,
Ian Hickson's avatar
Ian Hickson committed
348
      offset: new ViewportOffset.zero(),
349 350 351 352 353 354 355 356 357 358 359 360 361
      children: <RenderSliver>[
        new RenderSliverToBoxAdapter(child: a = new RenderSizedBox(const Size(400.0, 100.0))),
        new RenderSliverToBoxAdapter(child: b = new RenderSizedBox(const Size(400.0, 100.0))),
        new RenderSliverToBoxAdapter(child: c = new RenderSizedBox(const Size(400.0, 100.0))),
        new RenderSliverToBoxAdapter(child: d = new RenderSizedBox(const Size(400.0, 100.0))),
        new RenderSliverToBoxAdapter(child: e = new RenderSizedBox(const Size(400.0, 100.0))),
      ],
    );
    layout(root);

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

362 363 364 365 366
    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));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(-400.0, 0.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-400.0, 0.0));
367 368 369

    root.offset = new ViewportOffset.fixed(200.0);
    pumpFrame();
370 371 372 373 374
    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(-400.0, 0.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-400.0, 0.0));
375 376 377

    root.offset = new ViewportOffset.fixed(600.0);
    pumpFrame();
378 379 380 381 382
    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));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-400.0, 0.0));
383 384 385

    root.offset = new ViewportOffset.fixed(900.0);
    pumpFrame();
386 387 388 389 390
    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));
391

392
    final HitTestResult result = new HitTestResult();
393
    root.hitTest(result, position: const Offset(550.0, 150.0));
394
    expect(result.path.first.target, equals(c));
395 396 397 398 399 400
  });

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

401
  test('RenderShrinkWrappingViewport basic test - no children', () {
402
    final RenderShrinkWrappingViewport root = new RenderShrinkWrappingViewport(
403
      crossAxisDirection: AxisDirection.right,
404 405
      offset: new ViewportOffset.zero(),
    );
406
    expect(root, hasAGoodToStringDeep);
407 408 409 410 411 412 413
    layout(root);
    root.offset = new ViewportOffset.fixed(900.0);
    pumpFrame();
  });

  test('RenderShrinkWrappingViewport basic test - down', () {
    RenderBox a, b, c, d, e;
414
    final RenderShrinkWrappingViewport root = new RenderShrinkWrappingViewport(
415
      crossAxisDirection: AxisDirection.right,
416 417 418 419 420 421 422 423 424 425 426 427 428 429
      offset: new ViewportOffset.zero(),
      children: <RenderSliver>[
        new RenderSliverToBoxAdapter(child: a = new RenderSizedBox(const Size(100.0, 400.0))),
        new RenderSliverToBoxAdapter(child: b = new RenderSizedBox(const Size(100.0, 400.0))),
        new RenderSliverToBoxAdapter(child: c = new RenderSizedBox(const Size(100.0, 400.0))),
        new RenderSliverToBoxAdapter(child: d = new RenderSizedBox(const Size(100.0, 400.0))),
        new RenderSliverToBoxAdapter(child: e = new RenderSizedBox(const Size(100.0, 400.0))),
      ],
    );
    layout(root);

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

430 431 432 433 434
    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));
    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, 600.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 600.0));
435

436 437 438 439 440
    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));
    expect(c.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 1000.0));
    expect(d.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 1000.0));
    expect(e.localToGlobal(const Offset(800.0, 400.0)), const Offset(800.0, 1000.0));
441 442 443

    root.offset = new ViewportOffset.fixed(200.0);
    pumpFrame();
444 445 446 447 448
    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));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 600.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 600.0));
449 450 451

    root.offset = new ViewportOffset.fixed(600.0);
    pumpFrame();
452 453 454 455 456
    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));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 600.0));
457 458 459

    root.offset = new ViewportOffset.fixed(900.0);
    pumpFrame();
460 461 462 463 464
    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));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, 600.0));
465

466
    final HitTestResult result = new HitTestResult();
467
    root.hitTest(result, position: const Offset(130.0, 150.0));
468 469 470 471 472
    expect(result.path.first.target, equals(c));
  });

  test('RenderShrinkWrappingViewport basic test - up', () {
    RenderBox a, b, c, d, e;
473
    final RenderShrinkWrappingViewport root = new RenderShrinkWrappingViewport(
474
      axisDirection: AxisDirection.up,
475
      crossAxisDirection: AxisDirection.right,
476 477 478 479 480 481 482 483 484 485 486 487 488 489
      offset: new ViewportOffset.zero(),
      children: <RenderSliver>[
        new RenderSliverToBoxAdapter(child: a = new RenderSizedBox(const Size(100.0, 400.0))),
        new RenderSliverToBoxAdapter(child: b = new RenderSizedBox(const Size(100.0, 400.0))),
        new RenderSliverToBoxAdapter(child: c = new RenderSizedBox(const Size(100.0, 400.0))),
        new RenderSliverToBoxAdapter(child: d = new RenderSizedBox(const Size(100.0, 400.0))),
        new RenderSliverToBoxAdapter(child: e = new RenderSizedBox(const Size(100.0, 400.0))),
      ],
    );
    layout(root);

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

490 491 492 493 494
    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, -400.0));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0));
495 496 497

    root.offset = new ViewportOffset.fixed(200.0);
    pumpFrame();
498 499 500 501 502
    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));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0));
503 504 505

    root.offset = new ViewportOffset.fixed(600.0);
    pumpFrame();
506 507 508 509 510
    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));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0));
511 512 513

    root.offset = new ViewportOffset.fixed(900.0);
    pumpFrame();
514 515 516 517 518
    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));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(0.0, -400.0));
519

520
    final HitTestResult result = new HitTestResult();
521
    root.hitTest(result, position: const Offset(150.0, 350.0));
522 523 524 525 526
    expect(result.path.first.target, equals(c));
  });

  test('RenderShrinkWrappingViewport basic test - right', () {
    RenderBox a, b, c, d, e;
527
    final RenderShrinkWrappingViewport root = new RenderShrinkWrappingViewport(
528
      axisDirection: AxisDirection.right,
529
      crossAxisDirection: AxisDirection.down,
530 531 532 533 534 535 536 537 538 539 540 541 542 543
      offset: new ViewportOffset.zero(),
      children: <RenderSliver>[
        new RenderSliverToBoxAdapter(child: a = new RenderSizedBox(const Size(400.0, 100.0))),
        new RenderSliverToBoxAdapter(child: b = new RenderSizedBox(const Size(400.0, 100.0))),
        new RenderSliverToBoxAdapter(child: c = new RenderSizedBox(const Size(400.0, 100.0))),
        new RenderSliverToBoxAdapter(child: d = new RenderSizedBox(const Size(400.0, 100.0))),
        new RenderSliverToBoxAdapter(child: e = new RenderSizedBox(const Size(400.0, 100.0))),
      ],
    );
    layout(root);

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

544 545 546 547 548
    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));
    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(800.0, 0.0));
549 550 551

    root.offset = new ViewportOffset.fixed(200.0);
    pumpFrame();
552 553 554 555 556
    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));
    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(800.0, 0.0));
557 558 559

    root.offset = new ViewportOffset.fixed(600.0);
    pumpFrame();
560 561 562 563 564
    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));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(800.0, 0.0));
565 566 567

    root.offset = new ViewportOffset.fixed(900.0);
    pumpFrame();
568 569 570 571 572
    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));
573

574
    final HitTestResult result = new HitTestResult();
575
    root.hitTest(result, position: const Offset(150.0, 450.0));
576 577 578 579 580
    expect(result.path.first.target, equals(c));
  });

  test('RenderShrinkWrappingViewport basic test - left', () {
    RenderBox a, b, c, d, e;
581
    final RenderShrinkWrappingViewport root = new RenderShrinkWrappingViewport(
582
      axisDirection: AxisDirection.left,
583
      crossAxisDirection: AxisDirection.down,
584 585 586 587 588 589 590 591 592 593 594 595 596 597
      offset: new ViewportOffset.zero(),
      children: <RenderSliver>[
        new RenderSliverToBoxAdapter(child: a = new RenderSizedBox(const Size(400.0, 100.0))),
        new RenderSliverToBoxAdapter(child: b = new RenderSizedBox(const Size(400.0, 100.0))),
        new RenderSliverToBoxAdapter(child: c = new RenderSizedBox(const Size(400.0, 100.0))),
        new RenderSliverToBoxAdapter(child: d = new RenderSizedBox(const Size(400.0, 100.0))),
        new RenderSliverToBoxAdapter(child: e = new RenderSizedBox(const Size(400.0, 100.0))),
      ],
    );
    layout(root);

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

598 599 600 601 602
    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));
    expect(d.localToGlobal(const Offset(0.0, 0.0)), const Offset(-400.0, 0.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-400.0, 0.0));
603 604 605

    root.offset = new ViewportOffset.fixed(200.0);
    pumpFrame();
606 607 608 609 610
    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(-400.0, 0.0));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-400.0, 0.0));
611 612 613

    root.offset = new ViewportOffset.fixed(600.0);
    pumpFrame();
614 615 616 617 618
    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));
    expect(e.localToGlobal(const Offset(0.0, 0.0)), const Offset(-400.0, 0.0));
619 620 621

    root.offset = new ViewportOffset.fixed(900.0);
    pumpFrame();
622 623 624 625 626
    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));
627

628
    final HitTestResult result = new HitTestResult();
629
    root.hitTest(result, position: const Offset(550.0, 150.0));
630 631 632 633 634
    expect(result.path.first.target, equals(c));
  });

  test('RenderShrinkWrappingViewport shrinkwrap test - 1 child', () {
    RenderBox child;
635
    final RenderBox root = new RenderPositionedBox(
636 637
      child: child = new RenderShrinkWrappingViewport(
        axisDirection: AxisDirection.left,
638
        crossAxisDirection: AxisDirection.down,
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654
        offset: new ViewportOffset.fixed(200.0),
        children: <RenderSliver>[
          new RenderSliverToBoxAdapter(child: new RenderSizedBox(const Size(400.0, 100.0))),
        ],
      ),
    );
    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;
655
    final RenderBox root = new RenderPositionedBox(
656 657
      child: child = new RenderShrinkWrappingViewport(
        axisDirection: AxisDirection.right,
658
        crossAxisDirection: AxisDirection.down,
659 660 661 662 663 664 665 666 667 668 669 670 671 672
        offset: new ViewportOffset.fixed(200.0),
        children: <RenderSliver>[
          new RenderSliverToBoxAdapter(child: new RenderSizedBox(const Size(300.0, 100.0))),
          new RenderSliverToBoxAdapter(child: new RenderSizedBox(const Size(150.0, 100.0))),
        ],
      ),
    );
    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));
  });
673 674 675

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

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

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

    final Rect expectedRect = new Rect.fromLTWH(0.0, 0.0, root.size.width, height);

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

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

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

    final Rect expectedRect = new Rect.fromLTWH(0.0, 0.0, width, root.size.height);

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