Switch existings tests to use equalsIgnoringHashCodes and add more tests. (#10954)

* Switch existings tests to use equalsIgnoringHashCodes and add more tests.
This commit is contained in:
Jacob Richman 2017-06-27 10:44:35 -07:00 committed by GitHub
parent 70d3a62125
commit 76a50fe0ca
16 changed files with 811 additions and 61 deletions

View file

@ -2755,7 +2755,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
void debugFillDescription(List<String> description) {
if (debugCreator != null)
description.add('creator: $debugCreator');
description.add('parentData: $parentData${ _debugCanParentUseSize ? " (can use size)" : ""}');
description.add('parentData: $parentData${ _debugCanParentUseSize == true ? " (can use size)" : ""}');
description.add('constraints: $constraints');
if (_layer != null) // don't access it via the "layer" getter since that's only valid when we don't need paint
description.add('layer: $_layer');

View file

@ -3,7 +3,7 @@
// found in the LICENSE file.
import 'package:flutter/foundation.dart';
import 'package:test/test.dart';
import 'package:flutter_test/flutter_test.dart';
class TestTree extends Object with TreeDiagnosticsMixin {
TestTree({
@ -40,20 +40,26 @@ void main() {
],
);
final String dump =
tree.toStringDeep().replaceAll(new RegExp(r'#[0-9a-z]{5}'), '#000');
expect(dump, equals('''TestTree#000
child node A: TestTree#000
// The final line in the tree is a problem as it contains nothing but
// a vertical line character.
expect(tree, isNot(hasAGoodToStringDeep));
expect(
tree.toStringDeep(),
equalsIgnoringHashCodes(
'''TestTree#00000
child node A: TestTree#00000
child node B: TestTree#000
child node B1: TestTree#000
child node B: TestTree#00000
child node B1: TestTree#00000
child node B2: TestTree#000
child node B2: TestTree#00000
child node B3: TestTree#000
child node B3: TestTree#00000
child node C: TestTree#000
child node C: TestTree#00000
'''));
''',
),
);
});
}

View file

@ -4,7 +4,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:test/test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'rendering_tester.dart';
@ -69,6 +69,17 @@ void main() {
final RenderBox coloredBox = new RenderDecoratedBox(
decoration: const BoxDecoration(),
);
expect(coloredBox, hasAGoodToStringDeep);
expect(coloredBox.toStringDeep(), equalsIgnoringHashCodes(
'RenderDecoratedBox#00000 NEEDS-LAYOUT NEEDS-PAINT DETACHED\n'
' parentData: null\n'
' constraints: null\n'
' size: MISSING\n'
' decoration:\n'
' <no decorations specified>\n'
' configuration: ImageConfiguration()\n'));
final RenderBox paddingBox = new RenderPadding(
padding: const EdgeInsets.all(10.0),
child: coloredBox,
@ -80,6 +91,20 @@ void main() {
layout(root);
expect(coloredBox.size.width, equals(780.0));
expect(coloredBox.size.height, equals(580.0));
expect(coloredBox, hasAGoodToStringDeep);
expect(
coloredBox.toStringDeep(),
equalsIgnoringHashCodes(
'RenderDecoratedBox#00000 NEEDS-PAINT\n'
' parentData: offset=Offset(10.0, 10.0) (can use size)\n'
' constraints: BoxConstraints(w=780.0, h=580.0)\n'
' size: Size(780.0, 580.0)\n'
' decoration:\n'
' <no decorations specified>\n'
' configuration: ImageConfiguration()\n',
),
);
});
test("reparenting should clear position", () {

View file

@ -4,7 +4,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:test/test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'rendering_tester.dart';
@ -27,6 +27,35 @@ void main() {
layout(parent);
expect(child.size.width, 100.0);
expect(child.size.height, 200.0);
expect(parent, hasAGoodToStringDeep);
expect(
parent.toStringDeep(),
equalsIgnoringHashCodes(
'RenderConstrainedOverflowBox#00000 NEEDS-PAINT\n'
' │ parentData: <none>\n'
' │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
' │ size: Size(800.0, 600.0)\n'
' │ alignment: FractionalOffset(0.5, 0.5)\n'
' │ minWidth: 0.0\n'
' │ maxWidth: Infinity\n'
' │ minHeight: 0.0\n'
' │ maxHeight: Infinity\n'
'\n'
' └─child: RenderLimitedBox#00000 relayoutBoundary=up1 NEEDS-PAINT\n'
' │ parentData: offset=Offset(350.0, 200.0) (can use size)\n'
' │ constraints: BoxConstraints(unconstrained)\n'
' │ size: Size(100.0, 200.0)\n'
' │ maxWidth: 100.0\n'
' │ maxHeight: 200.0\n'
'\n'
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up2 NEEDS-PAINT\n'
' parentData: <none> (can use size)\n'
' constraints: BoxConstraints(0.0<=w<=100.0, 0.0<=h<=200.0)\n'
' size: Size(100.0, 200.0)\n'
' additionalConstraints: BoxConstraints(w=300.0, h=400.0)\n',
),
);
});
test('LimitedBox: parent maxWidth is unconstrained', () {
@ -84,5 +113,65 @@ void main() {
);
layout(parent);
expect(box.size, const Size(10.0, 0.0));
expect(parent, hasAGoodToStringDeep);
expect(
parent.toStringDeep(),
equalsIgnoringHashCodes(
'RenderConstrainedOverflowBox#00000 NEEDS-PAINT\n'
' │ parentData: <none>\n'
' │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
' │ size: Size(800.0, 600.0)\n'
' │ alignment: FractionalOffset(0.5, 0.5)\n'
' │ minWidth: 10.0\n'
' │ maxWidth: 500.0\n'
' │ minHeight: 0.0\n'
' │ maxHeight: Infinity\n'
'\n'
' └─child: RenderLimitedBox#00000 relayoutBoundary=up1 NEEDS-PAINT\n'
' parentData: offset=Offset(395.0, 300.0) (can use size)\n'
' constraints: BoxConstraints(10.0<=w<=500.0, 0.0<=h<=Infinity)\n'
' size: Size(10.0, 0.0)\n'
' maxWidth: 100.0\n'
' maxHeight: 200.0\n',
),
);
});
test('LimitedBox: no child use parent', () {
RenderBox box;
final RenderBox parent = new RenderConstrainedOverflowBox(
minWidth: 10.0,
child: box = new RenderLimitedBox(
maxWidth: 100.0,
maxHeight: 200.0,
)
);
layout(parent);
expect(box.size, const Size(10.0, 600.0));
expect(parent, hasAGoodToStringDeep);
expect(
parent.toStringDeep(),
equalsIgnoringHashCodes(
'RenderConstrainedOverflowBox#00000 NEEDS-PAINT\n'
' │ parentData: <none>\n'
' │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
' │ size: Size(800.0, 600.0)\n'
' │ alignment: FractionalOffset(0.5, 0.5)\n'
' │ minWidth: 10.0\n'
' │ maxWidth: use parent maxWidth constraint\n'
' │ minHeight: use parent minHeight constraint\n'
' │ maxHeight: use parent maxHeight constraint\n'
'\n'
' └─child: RenderLimitedBox#00000 relayoutBoundary=up1 NEEDS-PAINT\n'
' parentData: offset=Offset(395.0, 0.0) (can use size)\n'
' constraints: BoxConstraints(10.0<=w<=800.0, h=600.0)\n'
' size: Size(10.0, 600.0)\n'
' maxWidth: 100.0\n'
' maxHeight: 200.0\n',
),
);
});
}

View file

@ -6,7 +6,7 @@ import 'dart:ui' as ui show TextBox;
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:test/test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'rendering_tester.dart';
@ -149,7 +149,6 @@ void main() {
expect(paragraph.debugHasOverflowShader, isFalse);
});
test('maxLines', () {
final RenderParagraph paragraph = new RenderParagraph(
const TextSpan(
@ -177,5 +176,30 @@ void main() {
layoutAt(3);
expect(paragraph.size.height, 30.0);
});
}
test('toStringDeep', () {
final RenderParagraph paragraph = new RenderParagraph(
const TextSpan(text: _kText),
);
// TODO(jacobr): the toStringDeep method for RenderParagraph needs to be
// fixed to not emit a spurious line of trailing whitespace and fixed so
// that the \n within the TextSpan content does not interfere with the box
// border.
expect(paragraph, isNot(hasAGoodToStringDeep));
expect(
paragraph.toStringDeep(),
equalsIgnoringHashCodes(
'RenderParagraph#00000 NEEDS-LAYOUT NEEDS-PAINT DETACHED\n'
' │ parentData: null\n'
' │ constraints: null\n'
' │ size: MISSING\n'
' ╘═╦══ text ═══\n'
' ║ TextSpan:\n'
' ║ "I polished up that handle so carefullee\n'
'That now I am the Ruler of the Queen\'s Navee!"\n'
' ╚═══════════\n'
'\n',
),
);
});
}

View file

@ -3,7 +3,7 @@
// found in the LICENSE file.
import 'package:flutter/rendering.dart';
import 'package:test/test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'rendering_tester.dart';
@ -54,6 +54,71 @@ void main() {
pumpFrame();
expect(table.size, equals(const Size(130.0, 230.0)));
expect(table, hasAGoodToStringDeep);
expect(
table.toStringDeep(),
equalsIgnoringHashCodes(
'RenderTable#00000 relayoutBoundary=up1 NEEDS-PAINT\n'
' │ parentData: offset=Offset(335.0, 185.0) (can use size)\n'
' │ constraints: BoxConstraints(0.0<=w<=800.0, 0.0<=h<=600.0)\n'
' │ size: Size(130.0, 230.0)\n'
' │ default column width: IntrinsicColumnWidth\n'
' │ table size: 5×5\n'
' │ column offsets: [0.0, 10.0, 30.0, 130.0, 130.0]\n'
' │ row offsets: [0.0, 30.0, 30.0, 30.0, 30.0, 230.0]\n'
'\n'
' ├─child (0, 0): RenderConstrainedBox#00000 relayoutBoundary=up2 NEEDS-PAINT\n'
' │ parentData: offset=Offset(0.0, 0.0); default vertical alignment\n'
' │ (can use size)\n'
' │ constraints: BoxConstraints(w=10.0, 0.0<=h<=Infinity)\n'
' │ size: Size(10.0, 30.0)\n'
' │ additionalConstraints: BoxConstraints(w=10.0, h=30.0)\n'
'\n'
' ├─child (1, 0): RenderConstrainedBox#00000 relayoutBoundary=up2 NEEDS-PAINT\n'
' │ parentData: offset=Offset(10.0, 0.0); default vertical alignment\n'
' │ (can use size)\n'
' │ constraints: BoxConstraints(w=20.0, 0.0<=h<=Infinity)\n'
' │ size: Size(20.0, 20.0)\n'
' │ additionalConstraints: BoxConstraints(w=20.0, h=20.0)\n'
'\n'
' ├─child (2, 0): RenderConstrainedBox#00000 relayoutBoundary=up2 NEEDS-PAINT\n'
' │ parentData: offset=Offset(30.0, 0.0); default vertical alignment\n'
' │ (can use size)\n'
' │ constraints: BoxConstraints(w=100.0, 0.0<=h<=Infinity)\n'
' │ size: Size(100.0, 10.0)\n'
' │ additionalConstraints: BoxConstraints(w=30.0, h=10.0)\n'
'\n'
' ├─child (3, 0) is null\n'
' ├─child (4, 0) is null\n'
' ├─child (0, 1) is null\n'
' ├─child (1, 1) is null\n'
' ├─child (2, 1) is null\n'
' ├─child (3, 1) is null\n'
' ├─child (4, 1) is null\n'
' ├─child (0, 2) is null\n'
' ├─child (1, 2) is null\n'
' ├─child (2, 2) is null\n'
' ├─child (3, 2) is null\n'
' ├─child (4, 2) is null\n'
' ├─child (0, 3) is null\n'
' ├─child (1, 3) is null\n'
' ├─child (2, 3) is null\n'
' ├─child (3, 3) is null\n'
' ├─child (4, 3) is null\n'
' ├─child (0, 4) is null\n'
' ├─child (1, 4) is null\n'
' ├─child (2, 4): RenderConstrainedBox#00000 relayoutBoundary=up2 NEEDS-PAINT\n'
' │ parentData: offset=Offset(30.0, 30.0); default vertical alignment\n'
' │ (can use size)\n'
' │ constraints: BoxConstraints(w=100.0, 0.0<=h<=Infinity)\n'
' │ size: Size(100.0, 200.0)\n'
' │ additionalConstraints: BoxConstraints(w=100.0, h=200.0)\n'
'\n'
' ├─child (3, 4) is null\n'
' └─child (4, 4) is null\n',
),
);
});
test('Table test: removing cells', () {

View file

@ -65,6 +65,41 @@ void main() {
actualDecoration = box.decoration;
expect(actualDecoration.color, equals(decorationB.color));
expect(box, hasAGoodToStringDeep);
expect(
box.toStringDeep(),
equalsIgnoringHashCodes(
'RenderDecoratedBox#00000\n'
' │ creator: DecoratedBox ← Container ←\n'
' │ AnimatedContainer-[GlobalKey#00000] ← [root]\n'
' │ parentData: <none>\n'
' │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
' │ size: Size(800.0, 600.0)\n'
' │ decoration:\n'
' │ color: Color(0xff0000ff)\n'
' │ configuration: ImageConfiguration(bundle:\n'
' │ PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
' │ android)\n'
'\n'
' └─child: RenderLimitedBox#00000\n'
' │ creator: LimitedBox ← DecoratedBox ← Container ←\n'
' │ AnimatedContainer-[GlobalKey#00000] ← [root]\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
' │ size: Size(800.0, 600.0)\n'
' │ maxWidth: 0.0\n'
' │ maxHeight: 0.0\n'
'\n'
' └─child: RenderConstrainedBox#00000\n'
' creator: ConstrainedBox ← LimitedBox ← DecoratedBox ← Container ←\n'
' AnimatedContainer-[GlobalKey#00000] ← [root]\n'
' parentData: <none> (can use size)\n'
' constraints: BoxConstraints(w=800.0, h=600.0)\n'
' size: Size(800.0, 600.0)\n'
' additionalConstraints: BoxConstraints(biggest)\n',
),
);
});
testWidgets('AnimatedContainer overanimate test', (WidgetTester tester) async {

View file

@ -76,6 +76,31 @@ void main() {
box = key.currentContext.findRenderObject();
expect(box.localToGlobal(box.size.center(Offset.zero)), equals(const Offset(37.0 + 59.0 / 2.0, 31.0 + 71.0 / 2.0)));
expect(box, hasAGoodToStringDeep);
expect(
box.toStringDeep(),
equalsIgnoringHashCodes(
'RenderLimitedBox#00000\n'
' │ creator: LimitedBox ← Container-[GlobalKey#00000] ← Positioned ←\n'
' │ AnimatedPositioned ← Stack ← [root]\n'
' │ parentData: top=31.0; left=37.0; width=59.0; height=71.0;\n'
' │ offset=Offset(37.0, 31.0) (can use size)\n'
' │ constraints: BoxConstraints(w=59.0, h=71.0)\n'
' │ size: Size(59.0, 71.0)\n'
' │ maxWidth: 0.0\n'
' │ maxHeight: 0.0\n'
'\n'
' └─child: RenderConstrainedBox#00000\n'
' creator: ConstrainedBox ← LimitedBox ←\n'
' Container-[GlobalKey#00000] ← Positioned ← AnimatedPositioned ←\n'
' Stack ← [root]\n'
' parentData: <none> (can use size)\n'
' constraints: BoxConstraints(w=59.0, h=71.0)\n'
' size: Size(59.0, 71.0)\n'
' additionalConstraints: BoxConstraints(biggest)\n',
),
);
});
testWidgets('AnimatedPositioned - interrupted animation', (WidgetTester tester) async {

View file

@ -49,6 +49,89 @@ void main() {
..rect(rect: new Rect.fromLTWH(26.0, 43.0, 25.0, 33.0), color: const Color(0xFFFFFF00))
..rect(rect: new Rect.fromLTWH(5.0, 5.0, 53.0, 78.0), color: const Color(0x7F0000FF))
);
expect(box, hasAGoodToStringDeep);
expect(
box.toStringDeep(),
equalsIgnoringHashCodes(
'RenderPadding#00000 relayoutBoundary=up1\n'
' │ creator: Padding ← Container ← Align ← [root]\n'
' │ parentData: offset=Offset(0.0, 0.0) (can use size)\n'
' │ constraints: BoxConstraints(0.0<=w<=800.0, 0.0<=h<=600.0)\n'
' │ size: Size(63.0, 88.0)\n'
' │ padding: EdgeInsets(5.0, 5.0, 5.0, 5.0)\n'
'\n'
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
' │ creator: ConstrainedBox ← Padding ← Container ← Align ← [root]\n'
' │ parentData: offset=Offset(5.0, 5.0) (can use size)\n'
' │ constraints: BoxConstraints(0.0<=w<=790.0, 0.0<=h<=590.0)\n'
' │ size: Size(53.0, 78.0)\n'
' │ additionalConstraints: BoxConstraints(w=53.0, h=78.0)\n'
'\n'
' └─child: RenderDecoratedBox#00000\n'
' │ creator: DecoratedBox ← ConstrainedBox ← Padding ← Container ←\n'
' │ Align ← [root]\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
' │ size: Size(53.0, 78.0)\n'
' │ decoration:\n'
' │ color: Color(0x7f0000ff)\n'
' │ configuration: ImageConfiguration(bundle:\n'
' │ PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
' │ android)\n'
'\n'
' └─child: RenderDecoratedBox#00000\n'
' │ creator: DecoratedBox ← DecoratedBox ← ConstrainedBox ← Padding ←\n'
' │ Container ← Align ← [root]\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
' │ size: Size(53.0, 78.0)\n'
' │ decoration:\n'
' │ color: Color(0xff00ff00)\n'
' │ configuration: ImageConfiguration(bundle:\n'
' │ PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
' │ android)\n'
'\n'
' └─child: RenderPadding#00000\n'
' │ creator: Padding ← DecoratedBox ← DecoratedBox ← ConstrainedBox ←\n'
' │ Padding ← Container ← Align ← [root]\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=53.0, h=78.0)\n'
' │ size: Size(53.0, 78.0)\n'
' │ padding: EdgeInsets(7.0, 7.0, 7.0, 7.0)\n'
'\n'
' └─child: RenderPositionedBox#00000\n'
' │ creator: Align ← Padding ← DecoratedBox ← DecoratedBox ←\n'
' │ ConstrainedBox ← Padding ← Container ← Align ← [root]\n'
' │ parentData: offset=Offset(7.0, 7.0) (can use size)\n'
' │ constraints: BoxConstraints(w=39.0, h=64.0)\n'
' │ size: Size(39.0, 64.0)\n'
' │ alignment: FractionalOffset(1.0, 1.0)\n'
' │ widthFactor: expand\n'
' │ heightFactor: expand\n'
'\n'
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up1\n'
' │ creator: SizedBox ← Align ← Padding ← DecoratedBox ← DecoratedBox\n'
' │ ← ConstrainedBox ← Padding ← Container ← Align ← [root]\n'
' │ parentData: offset=Offset(14.0, 31.0) (can use size)\n'
' │ constraints: BoxConstraints(0.0<=w<=39.0, 0.0<=h<=64.0)\n'
' │ size: Size(25.0, 33.0)\n'
' │ additionalConstraints: BoxConstraints(w=25.0, h=33.0)\n'
'\n'
' └─child: RenderDecoratedBox#00000\n'
' creator: DecoratedBox ← SizedBox ← Align ← Padding ← DecoratedBox\n'
' ← DecoratedBox ← ConstrainedBox ← Padding ← Container ← Align ←\n'
' [root]\n'
' parentData: <none> (can use size)\n'
' constraints: BoxConstraints(w=25.0, h=33.0)\n'
' size: Size(25.0, 33.0)\n'
' decoration:\n'
' color: Color(0xffffff00)\n'
' configuration: ImageConfiguration(bundle:\n'
' PlatformAssetBundle#00000(), devicePixelRatio: 1.0, platform:\n'
' android)\n',
),
);
});
testWidgets('Can be placed in an infinite box', (WidgetTester tester) async {

View file

@ -482,25 +482,29 @@ void main() {
));
final MultiChildRenderObjectElement element = key0.currentContext;
final String dump =
element.toStringDeep().replaceAll(new RegExp(r'#[0-9a-f]{5}'), '#000');
expect(dump, equals('''Column([GlobalKey#000]; renderObject: RenderFlex#000)
expect(element, hasAGoodToStringDeep);
expect(
element.toStringDeep(),
equalsIgnoringHashCodes(
'''Column([GlobalKey#00000]; renderObject: RenderFlex#00000)
Container()
LimitedBox(maxWidth: 0.0; maxHeight: 0.0; renderObject: RenderLimitedBox#000 relayoutBoundary=up1)
ConstrainedBox(BoxConstraints(biggest); renderObject: RenderConstrainedBox#000 relayoutBoundary=up2)
Container([GlobalKey#000])
LimitedBox(maxWidth: 0.0; maxHeight: 0.0; renderObject: RenderLimitedBox#000 relayoutBoundary=up1)
ConstrainedBox(BoxConstraints(biggest); renderObject: RenderConstrainedBox#000 relayoutBoundary=up2)
LimitedBox(maxWidth: 0.0; maxHeight: 0.0; renderObject: RenderLimitedBox#00000 relayoutBoundary=up1)
ConstrainedBox(BoxConstraints(biggest); renderObject: RenderConstrainedBox#00000 relayoutBoundary=up2)
Container([GlobalKey#00000])
LimitedBox(maxWidth: 0.0; maxHeight: 0.0; renderObject: RenderLimitedBox#00000 relayoutBoundary=up1)
ConstrainedBox(BoxConstraints(biggest); renderObject: RenderConstrainedBox#00000 relayoutBoundary=up2)
Container()
Container()
LimitedBox(maxWidth: 0.0; maxHeight: 0.0; renderObject: RenderLimitedBox#000 relayoutBoundary=up1)
ConstrainedBox(BoxConstraints(biggest); renderObject: RenderConstrainedBox#000 relayoutBoundary=up2)
Container([GlobalKey#000])
LimitedBox(maxWidth: 0.0; maxHeight: 0.0; renderObject: RenderLimitedBox#000 relayoutBoundary=up1)
ConstrainedBox(BoxConstraints(biggest); renderObject: RenderConstrainedBox#000 relayoutBoundary=up2)
LimitedBox(maxWidth: 0.0; maxHeight: 0.0; renderObject: RenderLimitedBox#00000 relayoutBoundary=up1)
ConstrainedBox(BoxConstraints(biggest); renderObject: RenderConstrainedBox#00000 relayoutBoundary=up2)
Container([GlobalKey#00000])
LimitedBox(maxWidth: 0.0; maxHeight: 0.0; renderObject: RenderLimitedBox#00000 relayoutBoundary=up1)
ConstrainedBox(BoxConstraints(biggest); renderObject: RenderConstrainedBox#00000 relayoutBoundary=up2)
Container()
LimitedBox(maxWidth: 0.0; maxHeight: 0.0; renderObject: RenderLimitedBox#000 relayoutBoundary=up1)
ConstrainedBox(BoxConstraints(biggest); renderObject: RenderConstrainedBox#000 relayoutBoundary=up2)
'''));
LimitedBox(maxWidth: 0.0; maxHeight: 0.0; renderObject: RenderLimitedBox#00000 relayoutBoundary=up1)
ConstrainedBox(BoxConstraints(biggest); renderObject: RenderConstrainedBox#00000 relayoutBoundary=up2)
''',
),
);
});
}

View file

@ -294,12 +294,12 @@ void main() {
final TestImageProvider imageProvider = new TestImageProvider();
await tester.pumpWidget(new Image(image: imageProvider));
final State<Image> image = tester.state/*State<Image>*/(find.byType(Image));
expect(image.toString(), matches(new RegExp(r'_ImageState#[0-9a-f]{5}\(stream: ImageStream\(OneFrameImageStreamCompleter; unresolved; 1 listener\); pixels: null\)')));
expect(image.toString(), equalsIgnoringHashCodes('_ImageState#00000(stream: ImageStream(OneFrameImageStreamCompleter; unresolved; 1 listener); pixels: null)'));
imageProvider.complete();
await tester.pump();
expect(image.toString(), matches(new RegExp(r'_ImageState#[0-9a-f]{5}\(stream: ImageStream\(OneFrameImageStreamCompleter; \[100×100\] @ 1\.0x; 1 listener\); pixels: \[100×100\] @ 1\.0x\)')));
expect(image.toString(), equalsIgnoringHashCodes('_ImageState#00000(stream: ImageStream(OneFrameImageStreamCompleter; [100×100] @ 1.0x; 1 listener); pixels: [100×100] @ 1.0x)'));
await tester.pumpWidget(new Container());
expect(image.toString(), matches(new RegExp(r'_ImageState#[0-9a-f]{5}\(_StateLifecycle.defunct; not mounted; stream: ImageStream\(OneFrameImageStreamCompleter; \[100×100\] @ 1\.0x; 0 listeners\); pixels: \[100×100\] @ 1\.0x\)')));
expect(image.toString(), equalsIgnoringHashCodes('_ImageState#00000(_StateLifecycle.defunct; not mounted; stream: ImageStream(OneFrameImageStreamCompleter; [100×100] @ 1.0x; 0 listeners); pixels: [100×100] @ 1.0x)'));
});
testWidgets('Image.memory control test', (WidgetTester tester) async {

View file

@ -274,6 +274,185 @@ void main() {
expect(list.childScrollOffset(list.firstChild), equals(0.0));
expect(list.geometry.scrollExtent, equals(300.0));
expect(list, hasAGoodToStringDeep);
expect(
list.toStringDeep(),
equalsIgnoringHashCodes(
'RenderSliverList#00000 relayoutBoundary=up1\n'
' │ creator: SliverList ← Viewport ← _ScrollableScope ←\n'
' │ IgnorePointer-[GlobalKey#00000] ← Listener ← _GestureSemantics\n'
' │ ←\n'
' │ RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' │ ← RepaintBoundary ← CustomPaint ← RepaintBoundary ←\n'
' │ NotificationListener<ScrollNotification> ←\n'
' │ GlowingOverscrollIndicator ← ⋯\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'
' │ viewportMainAxisExtent: 600.0)\n'
' │ geometry: SliverGeometry(scrollExtent: 300.0, paintExtent: 300.0,\n'
' │ maxPaintExtent: 300.0, )\n'
' │ currently live children: 0 to 2\n'
'\n'
' ├─child 1: RenderRepaintBoundary#00000 relayoutBoundary=up2\n'
' │ │ creator: RepaintBoundary-[<0>] ← SliverList ← Viewport ←\n'
' │ │ _ScrollableScope ← IgnorePointer-[GlobalKey#00000] ← Listener ←\n'
' │ │ _GestureSemantics ←\n'
' │ │ RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' │ │ ← RepaintBoundary ← CustomPaint ← RepaintBoundary ←\n'
' │ │ NotificationListener<ScrollNotification> ← ⋯\n'
' │ │ parentData: index=0; layoutOffset=0.0 (can use size)\n'
' │ │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
' │ │ layer: OffsetLayer#00000\n'
' │ │ size: Size(800.0, 100.0)\n'
' │ │ metrics: 0.0% useful (1 bad vs 0 good)\n'
' │ │ diagnosis: insufficient data to draw conclusion (less than five\n'
' │ │ repaints)\n'
' │ │\n'
' │ └─child: RenderConstrainedBox#00000 relayoutBoundary=up3\n'
' │ │ creator: ConstrainedBox ← Container ← RepaintBoundary-[<0>] ←\n'
' │ │ SliverList ← Viewport ← _ScrollableScope ←\n'
' │ │ IgnorePointer-[GlobalKey#00000] ← Listener ← _GestureSemantics\n'
' │ │ ←\n'
' │ │ RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' │ │ ← RepaintBoundary ← CustomPaint ← ⋯\n'
' │ │ parentData: <none> (can use size)\n'
' │ │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
' │ │ size: Size(800.0, 100.0)\n'
' │ │ additionalConstraints: BoxConstraints(0.0<=w<=Infinity, h=100.0)\n'
' │ │\n'
' │ └─child: RenderLimitedBox#00000\n'
' │ │ creator: LimitedBox ← ConstrainedBox ← Container ←\n'
' │ │ RepaintBoundary-[<0>] ← SliverList ← Viewport ←\n'
' │ │ _ScrollableScope ← IgnorePointer-[GlobalKey#00000] ← Listener ←\n'
' │ │ _GestureSemantics ←\n'
' │ │ RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' │ │ ← RepaintBoundary ← ⋯\n'
' │ │ parentData: <none> (can use size)\n'
' │ │ constraints: BoxConstraints(w=800.0, h=100.0)\n'
' │ │ size: Size(800.0, 100.0)\n'
' │ │ maxWidth: 0.0\n'
' │ │ maxHeight: 0.0\n'
' │ │\n'
' │ └─child: RenderConstrainedBox#00000\n'
' │ creator: ConstrainedBox ← LimitedBox ← ConstrainedBox ← Container\n'
' │ ← RepaintBoundary-[<0>] ← SliverList ← Viewport ←\n'
' │ _ScrollableScope ← IgnorePointer-[GlobalKey#00000] ← Listener ←\n'
' │ _GestureSemantics ←\n'
' │ RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' │ ← ⋯\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=800.0, h=100.0)\n'
' │ size: Size(800.0, 100.0)\n'
' │ additionalConstraints: BoxConstraints(biggest)\n'
'\n'
' ├─child 2: RenderRepaintBoundary#00000 relayoutBoundary=up2\n'
' │ │ creator: RepaintBoundary-[<1>] ← SliverList ← Viewport ←\n'
' │ │ _ScrollableScope ← IgnorePointer-[GlobalKey#00000] ← Listener ←\n'
' │ │ _GestureSemantics ←\n'
' │ │ RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' │ │ ← RepaintBoundary ← CustomPaint ← RepaintBoundary ←\n'
' │ │ NotificationListener<ScrollNotification> ← ⋯\n'
' │ │ parentData: index=1; layoutOffset=100.0 (can use size)\n'
' │ │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
' │ │ layer: OffsetLayer#00000\n'
' │ │ size: Size(800.0, 100.0)\n'
' │ │ metrics: 0.0% useful (1 bad vs 0 good)\n'
' │ │ diagnosis: insufficient data to draw conclusion (less than five\n'
' │ │ repaints)\n'
' │ │\n'
' │ └─child: RenderConstrainedBox#00000 relayoutBoundary=up3\n'
' │ │ creator: ConstrainedBox ← Container ← RepaintBoundary-[<1>] ←\n'
' │ │ SliverList ← Viewport ← _ScrollableScope ←\n'
' │ │ IgnorePointer-[GlobalKey#00000] ← Listener ← _GestureSemantics\n'
' │ │ ←\n'
' │ │ RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' │ │ ← RepaintBoundary ← CustomPaint ← ⋯\n'
' │ │ parentData: <none> (can use size)\n'
' │ │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
' │ │ size: Size(800.0, 100.0)\n'
' │ │ additionalConstraints: BoxConstraints(0.0<=w<=Infinity, h=100.0)\n'
' │ │\n'
' │ └─child: RenderLimitedBox#00000\n'
' │ │ creator: LimitedBox ← ConstrainedBox ← Container ←\n'
' │ │ RepaintBoundary-[<1>] ← SliverList ← Viewport ←\n'
' │ │ _ScrollableScope ← IgnorePointer-[GlobalKey#00000] ← Listener ←\n'
' │ │ _GestureSemantics ←\n'
' │ │ RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' │ │ ← RepaintBoundary ← ⋯\n'
' │ │ parentData: <none> (can use size)\n'
' │ │ constraints: BoxConstraints(w=800.0, h=100.0)\n'
' │ │ size: Size(800.0, 100.0)\n'
' │ │ maxWidth: 0.0\n'
' │ │ maxHeight: 0.0\n'
' │ │\n'
' │ └─child: RenderConstrainedBox#00000\n'
' │ creator: ConstrainedBox ← LimitedBox ← ConstrainedBox ← Container\n'
' │ ← RepaintBoundary-[<1>] ← SliverList ← Viewport ←\n'
' │ _ScrollableScope ← IgnorePointer-[GlobalKey#00000] ← Listener ←\n'
' │ _GestureSemantics ←\n'
' │ RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' │ ← ⋯\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=800.0, h=100.0)\n'
' │ size: Size(800.0, 100.0)\n'
' │ additionalConstraints: BoxConstraints(biggest)\n'
'\n'
' └─child 3: RenderRepaintBoundary#00000 relayoutBoundary=up2\n'
' │ creator: RepaintBoundary-[<2>] ← SliverList ← Viewport ←\n'
' │ _ScrollableScope ← IgnorePointer-[GlobalKey#00000] ← Listener ←\n'
' │ _GestureSemantics ←\n'
' │ RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' │ ← RepaintBoundary ← CustomPaint ← RepaintBoundary ←\n'
' │ NotificationListener<ScrollNotification> ← ⋯\n'
' │ parentData: index=2; layoutOffset=200.0 (can use size)\n'
' │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
' │ layer: OffsetLayer#00000\n'
' │ size: Size(800.0, 100.0)\n'
' │ metrics: 0.0% useful (1 bad vs 0 good)\n'
' │ diagnosis: insufficient data to draw conclusion (less than five\n'
' │ repaints)\n'
'\n'
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up3\n'
' │ creator: ConstrainedBox ← Container ← RepaintBoundary-[<2>] ←\n'
' │ SliverList ← Viewport ← _ScrollableScope ←\n'
' │ IgnorePointer-[GlobalKey#00000] ← Listener ← _GestureSemantics\n'
' │ ←\n'
' │ RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' │ ← RepaintBoundary ← CustomPaint ← ⋯\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=800.0, 0.0<=h<=Infinity)\n'
' │ size: Size(800.0, 100.0)\n'
' │ additionalConstraints: BoxConstraints(0.0<=w<=Infinity, h=100.0)\n'
'\n'
' └─child: RenderLimitedBox#00000\n'
' │ creator: LimitedBox ← ConstrainedBox ← Container ←\n'
' │ RepaintBoundary-[<2>] ← SliverList ← Viewport ←\n'
' │ _ScrollableScope ← IgnorePointer-[GlobalKey#00000] ← Listener ←\n'
' │ _GestureSemantics ←\n'
' │ RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' │ ← RepaintBoundary ← ⋯\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=800.0, h=100.0)\n'
' │ size: Size(800.0, 100.0)\n'
' │ maxWidth: 0.0\n'
' │ maxHeight: 0.0\n'
'\n'
' └─child: RenderConstrainedBox#00000\n'
' creator: ConstrainedBox ← LimitedBox ← ConstrainedBox ← Container\n'
' ← RepaintBoundary-[<2>] ← SliverList ← Viewport ←\n'
' _ScrollableScope ← IgnorePointer-[GlobalKey#00000] ← Listener ←\n'
' _GestureSemantics ←\n'
' RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' ← ⋯\n'
' parentData: <none> (can use size)\n'
' constraints: BoxConstraints(w=800.0, h=100.0)\n'
' size: Size(800.0, 100.0)\n'
' additionalConstraints: BoxConstraints(biggest)\n',
),
);
final ScrollPosition position = tester.state<ScrollableState>(find.byType(Scrollable)).position;
expect(position.viewportDimension, equals(600.0));

View file

@ -8,7 +8,7 @@ import 'package:flutter/widgets.dart';
void main() {
testWidgets('OverflowEntries context contains Overlay',
(WidgetTester tester) async {
final Key overlayKey = new UniqueKey();
final GlobalKey overlayKey = new GlobalKey();
bool didBuild = false;
await tester.pumpWidget(new Overlay(
key: overlayKey,
@ -25,5 +25,53 @@ void main() {
],
));
expect(didBuild, isTrue);
final RenderObject theater = overlayKey.currentContext.findRenderObject();
// TODO(jacobr): toStringDeep output is missing a trailing line break.
expect(theater, isNot(hasAGoodToStringDeep));
expect(
theater.toStringDeep(),
equalsIgnoringHashCodes(
'_RenderTheatre#00000\n'
' │ creator: _Theatre ← Overlay-[GlobalKey#00000] ← [root]\n'
' │ parentData: <none>\n'
' │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
' │ size: Size(800.0, 600.0)\n'
'\n'
' ├─onstage: RenderStack#00000\n'
' ╎ │ creator: Stack ← _Theatre ← Overlay-[GlobalKey#00000] ← [root]\n'
' ╎ │ parentData: not positioned; offset=Offset(0.0, 0.0) (can use\n'
' ╎ │ size)\n'
' ╎ │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
' ╎ │ size: Size(800.0, 600.0)\n'
' ╎ │ alignment: FractionalOffset(0.0, 0.0)\n'
' ╎ │ fit: StackFit.expand\n'
' ╎ │ overflow: Overflow.clip\n'
' ╎ │\n'
' ╎ └─child 1: RenderLimitedBox#00000\n'
' ╎ │ creator: LimitedBox ← Container ←\n'
' ╎ │ _OverlayEntry-[LabeledGlobalKey<_OverlayEntryState>#00000] ←\n'
' ╎ │ Stack ← _Theatre ← Overlay-[GlobalKey#00000] ← [root]\n'
' ╎ │ parentData: not positioned; offset=Offset(0.0, 0.0) (can use\n'
' ╎ │ size)\n'
' ╎ │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
' ╎ │ size: Size(800.0, 600.0)\n'
' ╎ │ maxWidth: 0.0\n'
' ╎ │ maxHeight: 0.0\n'
' ╎ │\n'
' ╎ └─child: RenderConstrainedBox#00000\n'
' ╎ creator: ConstrainedBox ← LimitedBox ← Container ←\n'
' ╎ _OverlayEntry-[LabeledGlobalKey<_OverlayEntryState>#00000] ←\n'
' ╎ Stack ← _Theatre ← Overlay-[GlobalKey#00000] ← [root]\n'
' ╎ parentData: <none> (can use size)\n'
' ╎ constraints: BoxConstraints(w=800.0, h=600.0)\n'
' ╎ size: Size(800.0, 600.0)\n'
' ╎ additionalConstraints: BoxConstraints(biggest)\n'
'\n'
' └╌no offstage children',
),
);
// TODO(jacobr): add a test with offstage children.
});
}

View file

@ -55,5 +55,63 @@ void main() {
expect(find.text('1'), findsNothing);
expect(find.text('2'), findsNothing);
expect(find.text('3'), findsNothing);
final RenderObject viewport = tester.renderObject<RenderObject>(find.byType(SliverFillViewport).first);
// Unfortunately this toStringDeep method currently has an extra line break
// at the end.
expect(viewport, isNot(hasAGoodToStringDeep));
expect(
viewport.toStringDeep(),
equalsIgnoringHashCodes(
'RenderSliverFillViewport#00000 relayoutBoundary=up1\n'
' │ creator: SliverFillViewport ← Viewport ← _ScrollableScope ←\n'
' │ IgnorePointer-[GlobalKey#00000] ← Listener ← _GestureSemantics\n'
' │ ←\n'
' │ RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' │ ← RepaintBoundary ← CustomPaint ← RepaintBoundary ←\n'
' │ NotificationListener<ScrollNotification> ←\n'
' │ GlowingOverscrollIndicator ← ⋯\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'
' │ viewportMainAxisExtent: 600.0)\n'
' │ geometry: SliverGeometry(scrollExtent: 12000.0, paintExtent:\n'
' │ 600.0, maxPaintExtent: 12000.0, hasVisualOverflow: true, )\n'
' │ currently live children: 0 to 0\n'
'\n'
' └─child 1: RenderRepaintBoundary#00000\n'
' │ creator: RepaintBoundary-[<0>] ← SliverFillViewport ← Viewport ←\n'
' │ _ScrollableScope ← IgnorePointer-[GlobalKey#00000] ← Listener ←\n'
' │ _GestureSemantics ←\n'
' │ RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' │ ← RepaintBoundary ← CustomPaint ← RepaintBoundary ←\n'
' │ NotificationListener<ScrollNotification> ← ⋯\n'
' │ parentData: index=0; layoutOffset=0.0\n'
' │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
' │ layer: OffsetLayer#00000\n'
' │ size: Size(800.0, 600.0)\n'
' │ metrics: 50.0% useful (1 bad vs 1 good)\n'
' │ diagnosis: insufficient data to draw conclusion (less than five\n'
' │ repaints)\n'
'\n'
' └─child: RenderParagraph#00000\n'
' │ creator: RichText ← Text ← Container ← RepaintBoundary-[<0>] ←\n'
' │ SliverFillViewport ← Viewport ← _ScrollableScope ←\n'
' │ IgnorePointer-[GlobalKey#00000] ← Listener ← _GestureSemantics\n'
' │ ←\n'
' │ RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' │ ← RepaintBoundary ← ⋯\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
' │ size: Size(800.0, 600.0)\n'
' ╘═╦══ text ═══\n'
' ║ TextSpan:\n'
' ║ inherit: true\n'
' ║ "0"\n'
' ╚═══════════\n'
'\n',
),
);
});
}

View file

@ -56,6 +56,90 @@ void main() {
verifyPaintPosition(key5, const Offset(0.0, 50.0), true);
});
testWidgets('Sliver appbars - toStringDeep of maxExtent that throws', (WidgetTester tester) async {
final TestDelegateThatCanThrow delegateThatCanThrow = new TestDelegateThatCanThrow();
GlobalKey key;
await tester.pumpWidget(
new CustomScrollView(
slivers: <Widget>[
new SliverPersistentHeader(key: key = new GlobalKey(), delegate: delegateThatCanThrow, pinned: true),
],
),
);
await tester.pumpAndSettle(const Duration(milliseconds: 10));
final RenderObject renderObject = key.currentContext.findRenderObject();
// The delegate must only start throwing immediately before calling
// toStringDeep to avoid triggering spurious exceptions.
// If the _RenderSliverPinnedPersistentHeaderForWidgets class was not
// private it would make more sense to create an instance of it directly.
delegateThatCanThrow.shouldThrow = true;
expect(renderObject, hasAGoodToStringDeep);
expect(
renderObject.toStringDeep(),
equalsIgnoringHashCodes(
'_RenderSliverPinnedPersistentHeaderForWidgets#00000 relayoutBoundary=up1\n'
' │ creator: _SliverPinnedPersistentHeader ←\n'
' │ SliverPersistentHeader-[GlobalKey#00000] ← Viewport ←\n'
' │ _ScrollableScope ← IgnorePointer-[GlobalKey#00000] ← Listener ←\n'
' │ _GestureSemantics ←\n'
' │ RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' │ ← RepaintBoundary ← CustomPaint ← RepaintBoundary ←\n'
' │ NotificationListener<ScrollNotification> ← ⋯\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'
' │ viewportMainAxisExtent: 600.0)\n'
' │ geometry: SliverGeometry(scrollExtent: 200.0, paintExtent: 200.0,\n'
' │ maxPaintExtent: 200.0, hasVisualOverflow: true, )\n'
' │ maxExtent: EXCEPTION (FlutterError)\n'
' │ child position: 0.0\n'
'\n'
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up2\n'
' │ creator: ConstrainedBox ← Container ←\n'
' │ _SliverPinnedPersistentHeader ←\n'
' │ SliverPersistentHeader-[GlobalKey#00000] ← Viewport ←\n'
' │ _ScrollableScope ← IgnorePointer-[GlobalKey#00000] ← Listener ←\n'
' │ _GestureSemantics ←\n'
' │ RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' │ ← RepaintBoundary ← CustomPaint ← ⋯\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=800.0, 0.0<=h<=200.0)\n'
' │ size: Size(800.0, 200.0)\n'
' │ additionalConstraints: BoxConstraints(0.0<=w<=Infinity,\n'
' │ 100.0<=h<=200.0)\n'
'\n'
' └─child: RenderLimitedBox#00000 relayoutBoundary=up3\n'
' │ creator: LimitedBox ← ConstrainedBox ← Container ←\n'
' │ _SliverPinnedPersistentHeader ←\n'
' │ SliverPersistentHeader-[GlobalKey#00000] ← Viewport ←\n'
' │ _ScrollableScope ← IgnorePointer-[GlobalKey#00000] ← Listener ←\n'
' │ _GestureSemantics ←\n'
' │ RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' │ ← RepaintBoundary ← ⋯\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=800.0, 100.0<=h<=200.0)\n'
' │ size: Size(800.0, 200.0)\n'
' │ maxWidth: 0.0\n'
' │ maxHeight: 0.0\n'
'\n'
' └─child: RenderConstrainedBox#00000 relayoutBoundary=up4\n'
' creator: ConstrainedBox ← LimitedBox ← ConstrainedBox ← Container\n'
' ← _SliverPinnedPersistentHeader ←\n'
' SliverPersistentHeader-[GlobalKey#00000] ← Viewport ←\n'
' _ScrollableScope ← IgnorePointer-[GlobalKey#00000] ← Listener ←\n'
' _GestureSemantics ←\n'
' RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#00000]\n'
' ← ⋯\n'
' parentData: <none> (can use size)\n'
' constraints: BoxConstraints(w=800.0, 100.0<=h<=200.0)\n'
' size: Size(800.0, 200.0)\n'
' additionalConstraints: BoxConstraints(biggest)\n',
),
);
});
testWidgets('Sliver appbars - pinned with slow scroll', (WidgetTester tester) async {
const double bigHeight = 550.0;
GlobalKey key1, key2, key3, key4, key5;
@ -70,6 +154,7 @@ void main() {
],
),
);
final ScrollPosition position = tester.state<ScrollableState>(find.byType(Scrollable)).position;
verifyPaintPosition(key1, const Offset(0.0, 0.0), true);
verifyPaintPosition(key2, const Offset(0.0, 550.0), true);
@ -236,6 +321,28 @@ class TestDelegate extends SliverPersistentHeaderDelegate {
bool shouldRebuild(TestDelegate oldDelegate) => false;
}
class TestDelegateThatCanThrow extends SliverPersistentHeaderDelegate {
bool shouldThrow = false;
@override
double get maxExtent {
return shouldThrow ? throw new FlutterError('Unavailable maxExtent') : 200.0;
}
@override
double get minExtent {
return shouldThrow ? throw new FlutterError('Unavailable minExtent') : 100.0;
}
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
return new Container(constraints: new BoxConstraints(minHeight: minExtent, maxHeight: maxExtent));
}
@override
bool shouldRebuild(TestDelegate oldDelegate) => false;
}
class RenderBigSliver extends RenderSliver {
RenderBigSliver(double height) : _height = height;

View file

@ -522,29 +522,31 @@ void main() {
);
await tester.pumpWidget(table);
final RenderObjectElement element = key0.currentContext;
final String dump =
element.toStringDeep().replaceAll(new RegExp(r'#[0-9a-f]{5}'), '#000');
expect(dump, equals('''Table([GlobalKey#000]; renderObject: RenderTable#000)
Text("A")
RichText(renderObject: RenderParagraph#000 relayoutBoundary=up1)
Text("B")
RichText(renderObject: RenderParagraph#000 relayoutBoundary=up1)
Text("C")
RichText(renderObject: RenderParagraph#000 relayoutBoundary=up1)
Text("D")
RichText(renderObject: RenderParagraph#000 relayoutBoundary=up1)
Text("EEE")
RichText(renderObject: RenderParagraph#000 relayoutBoundary=up1)
Text("F")
RichText(renderObject: RenderParagraph#000 relayoutBoundary=up1)
Text("G")
RichText(renderObject: RenderParagraph#000 relayoutBoundary=up1)
Text("H")
RichText(renderObject: RenderParagraph#000 relayoutBoundary=up1)
Text("III")
RichText(renderObject: RenderParagraph#000 relayoutBoundary=up1)
'''));
expect(element, hasAGoodToStringDeep);
expect(
element.toStringDeep(),
equalsIgnoringHashCodes(
'Table([GlobalKey#00000]; renderObject: RenderTable#00000)\n'
'├Text("A")\n'
'│└RichText(renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
'├Text("B")\n'
'│└RichText(renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
'├Text("C")\n'
'│└RichText(renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
'├Text("D")\n'
'│└RichText(renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
'├Text("EEE")\n'
'│└RichText(renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
'├Text("F")\n'
'│└RichText(renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
'├Text("G")\n'
'│└RichText(renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
'├Text("H")\n'
'│└RichText(renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
'└Text("III")\n'
' └RichText(renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n',
),
);
});
// TODO(ianh): Test handling of TableCell object