blob: 345c941c8e51fe2c9e955dce1879bc0052f83865 [file] [log] [blame]
// Copyright 2014 The Flutter 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/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
class TestStatefulWidget extends StatefulWidget {
const TestStatefulWidget({ super.key });
@override
TestStatefulWidgetState createState() => TestStatefulWidgetState();
}
class TestStatefulWidgetState extends State<TestStatefulWidget> {
@override
Widget build(BuildContext context) => Container();
}
class TestChildWidget extends StatefulWidget {
const TestChildWidget({ super.key });
@override
TestChildState createState() => TestChildState();
}
class TestChildState extends State<TestChildWidget> {
bool toggle = true;
void toggleMe() {
setState(() { toggle = !toggle; });
}
@override
Widget build(BuildContext context) => toggle ? const SizedBox() : const Text('CRASHHH');
}
void main() {
testWidgets('Table widget - empty', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Table(),
),
);
});
testWidgets('Table widget - control test', (WidgetTester tester) async {
Future<void> run(TextDirection textDirection) async {
await tester.pumpWidget(
Directionality(
textDirection: textDirection,
child: Table(
children: const <TableRow>[
TableRow(
children: <Widget>[
Text('AAAAAA'), Text('B'), Text('C'),
],
),
TableRow(
children: <Widget>[
Text('D'), Text('EEE'), Text('F'),
],
),
TableRow(
children: <Widget>[
Text('G'), Text('H'), Text('III'),
],
),
],
),
),
);
final RenderBox boxA = tester.renderObject(find.text('AAAAAA'));
final RenderBox boxD = tester.renderObject(find.text('D'));
final RenderBox boxG = tester.renderObject(find.text('G'));
final RenderBox boxB = tester.renderObject(find.text('B'));
expect(boxA.size, equals(boxD.size));
expect(boxA.size, equals(boxG.size));
expect(boxA.size, equals(boxB.size));
}
await run(TextDirection.ltr);
await tester.pumpWidget(Container());
await run(TextDirection.rtl);
});
testWidgets('Table widget can be detached and re-attached', (WidgetTester tester) async {
final Widget table = Table(
key: GlobalKey(),
children: const <TableRow>[
TableRow(
decoration: BoxDecoration(
color: Colors.yellow,
),
children: <Widget>[Placeholder()],
),
],
);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Center(
child: table,
),
),
);
// Move table to a different location to simulate detaching and re-attaching effect.
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Center(
child: Center(
child: table,
),
),
),
);
expect(tester.takeException(), isNull);
});
testWidgets('Table widget - column offset (LTR)', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Center(
child: Table(
columnWidths: const <int, TableColumnWidth>{
0: FixedColumnWidth(100.0),
1: FixedColumnWidth(110.0),
2: FixedColumnWidth(125.0),
},
defaultColumnWidth: const FixedColumnWidth(333.0),
children: const <TableRow>[
TableRow(
children: <Widget>[
Text('A1'), Text('B1'), Text('C1'),
],
),
TableRow(
children: <Widget>[
Text('A2'), Text('B2'), Text('C2'),
],
),
TableRow(
children: <Widget>[
Text('A3'), Text('B3'), Text('C3'),
],
),
],
),
),
),
);
final Rect table = tester.getRect(find.byType(Table));
final Rect a1 = tester.getRect(find.text('A1'));
final Rect a2 = tester.getRect(find.text('A2'));
final Rect a3 = tester.getRect(find.text('A3'));
final Rect b1 = tester.getRect(find.text('B1'));
final Rect b2 = tester.getRect(find.text('B2'));
final Rect b3 = tester.getRect(find.text('B3'));
final Rect c1 = tester.getRect(find.text('C1'));
final Rect c2 = tester.getRect(find.text('C2'));
final Rect c3 = tester.getRect(find.text('C3'));
expect(a1.width, equals(100.0));
expect(a2.width, equals(100.0));
expect(a3.width, equals(100.0));
expect(b1.width, equals(110.0));
expect(b2.width, equals(110.0));
expect(b3.width, equals(110.0));
expect(c1.width, equals(125.0));
expect(c2.width, equals(125.0));
expect(c3.width, equals(125.0));
expect(table.width, equals(335.0));
expect(a1.left, equals(table.left));
expect(a2.left, equals(a1.left));
expect(a3.left, equals(a1.left));
expect(b1.left, equals(table.left + a1.width));
expect(b2.left, equals(b1.left));
expect(b3.left, equals(b1.left));
expect(c1.left, equals(table.left + a1.width + b1.width));
expect(c2.left, equals(c1.left));
expect(c3.left, equals(c1.left));
});
testWidgets('Table widget - column offset (RTL)', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.rtl,
child: Center(
child: Table(
columnWidths: const <int, TableColumnWidth>{
0: FixedColumnWidth(100.0),
1: FixedColumnWidth(110.0),
2: FixedColumnWidth(125.0),
},
defaultColumnWidth: const FixedColumnWidth(333.0),
children: const <TableRow>[
TableRow(
children: <Widget>[
Text('A1'), Text('B1'), Text('C1'),
],
),
TableRow(
children: <Widget>[
Text('A2'), Text('B2'), Text('C2'),
],
),
TableRow(
children: <Widget>[
Text('A3'), Text('B3'), Text('C3'),
],
),
],
),
),
),
);
final Rect table = tester.getRect(find.byType(Table));
final Rect a1 = tester.getRect(find.text('A1'));
final Rect a2 = tester.getRect(find.text('A2'));
final Rect a3 = tester.getRect(find.text('A3'));
final Rect b1 = tester.getRect(find.text('B1'));
final Rect b2 = tester.getRect(find.text('B2'));
final Rect b3 = tester.getRect(find.text('B3'));
final Rect c1 = tester.getRect(find.text('C1'));
final Rect c2 = tester.getRect(find.text('C2'));
final Rect c3 = tester.getRect(find.text('C3'));
expect(a1.width, equals(100.0));
expect(a2.width, equals(100.0));
expect(a3.width, equals(100.0));
expect(b1.width, equals(110.0));
expect(b2.width, equals(110.0));
expect(b3.width, equals(110.0));
expect(c1.width, equals(125.0));
expect(c2.width, equals(125.0));
expect(c3.width, equals(125.0));
expect(table.width, equals(335.0));
expect(a1.right, equals(table.right));
expect(a2.right, equals(a1.right));
expect(a3.right, equals(a1.right));
expect(b1.right, equals(table.right - a1.width));
expect(b2.right, equals(b1.right));
expect(b3.right, equals(b1.right));
expect(c1.right, equals(table.right - a1.width - b1.width));
expect(c2.right, equals(c1.right));
expect(c3.right, equals(c1.right));
});
testWidgets('Table border - smoke test', (WidgetTester tester) async {
Future<void> run(TextDirection textDirection) async {
await tester.pumpWidget(
Directionality(
textDirection: textDirection,
child: Table(
border: TableBorder.all(),
children: const <TableRow>[
TableRow(
children: <Widget>[
Text('AAAAAA'), Text('B'), Text('C'),
],
),
TableRow(
children: <Widget>[
Text('D'), Text('EEE'), Text('F'),
],
),
TableRow(
children: <Widget>[
Text('G'), Text('H'), Text('III'),
],
),
],
),
),
);
}
await run(TextDirection.ltr);
await tester.pumpWidget(Container());
await run(TextDirection.rtl);
});
testWidgets('Table widget - changing table dimensions', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Table(
children: const <TableRow>[
TableRow(
children: <Widget>[
Text('A'), Text('B'), Text('C'),
],
),
TableRow(
children: <Widget>[
Text('D'), Text('E'), Text('F'),
],
),
TableRow(
children: <Widget>[
Text('G'), Text('H'), Text('I'),
],
),
],
),
),
);
final RenderBox boxA1 = tester.renderObject(find.text('A'));
final RenderBox boxG1 = tester.renderObject(find.text('G'));
expect(boxA1, isNotNull);
expect(boxG1, isNotNull);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Table(
children: const <TableRow>[
TableRow(
children: <Widget>[
Text('a'), Text('b'), Text('c'), Text('d'),
],
),
TableRow(
children: <Widget>[
Text('e'), Text('f'), Text('g'), Text('h'),
],
),
],
),
),
);
final RenderBox boxA2 = tester.renderObject(find.text('a'));
final RenderBox boxG2 = tester.renderObject(find.text('g'));
expect(boxA2, isNotNull);
expect(boxG2, isNotNull);
expect(boxA1, equals(boxA2));
expect(boxG1, isNot(equals(boxG2)));
});
testWidgets('Really small deficit double precision error', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/27083
const SizedBox cell = SizedBox(width: 16, height: 16);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Table(
children: const <TableRow>[
TableRow(
children: <Widget>[
cell, cell, cell, cell, cell, cell,
],
),
TableRow(
children: <Widget>[
cell, cell, cell, cell, cell, cell,
],
),
],
),
),
);
// If the above bug is present this test will never terminate.
});
testWidgets('Calculating flex columns with small width deficit', (WidgetTester tester) async {
const SizedBox cell = SizedBox(width: 1, height: 1);
// If the error is present, pumpWidget() will fail due to an unsatisfied
// assertion during the layout phase.
await tester.pumpWidget(
ConstrainedBox(
constraints: BoxConstraints.tight(const Size(600, 800)),
child: Directionality(
textDirection: TextDirection.ltr,
child: Table(
columnWidths: const <int, TableColumnWidth>{
0: FlexColumnWidth(),
1: FlexColumnWidth(0.123),
2: FlexColumnWidth(0.123),
3: FlexColumnWidth(0.123),
4: FlexColumnWidth(0.123),
5: FlexColumnWidth(0.123),
6: FlexColumnWidth(0.123),
},
children: <TableRow>[
TableRow(children: List<Widget>.filled(7, cell)),
TableRow(children: List<Widget>.filled(7, cell)),
],
),
),
),
);
expect(tester.takeException(), null);
});
testWidgets('Table widget - repump test', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Table(
children: const <TableRow>[
TableRow(
children: <Widget>[
Text('AAAAAA'), Text('B'), Text('C'),
],
),
TableRow(
children: <Widget>[
Text('D'), Text('EEE'), Text('F'),
],
),
TableRow(
children: <Widget>[
Text('G'), Text('H'), Text('III'),
],
),
],
),
),
);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Table(
children: const <TableRow>[
TableRow(
children: <Widget>[
Text('AAA'), Text('B'), Text('C'),
],
),
TableRow(
children: <Widget>[
Text('D'), Text('E'), Text('FFFFFF'),
],
),
TableRow(
children: <Widget>[
Text('G'), Text('H'), Text('III'),
],
),
],
),
),
);
final RenderBox boxA = tester.renderObject(find.text('AAA'));
final RenderBox boxD = tester.renderObject(find.text('D'));
final RenderBox boxG = tester.renderObject(find.text('G'));
final RenderBox boxB = tester.renderObject(find.text('B'));
expect(boxA.size, equals(boxD.size));
expect(boxA.size, equals(boxG.size));
expect(boxA.size, equals(boxB.size));
});
testWidgets('Table widget - intrinsic sizing test', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: const <TableRow>[
TableRow(
children: <Widget>[
Text('AAA'), Text('B'), Text('C'),
],
),
TableRow(
children: <Widget>[
Text('D'), Text('E'), Text('FFFFFF'),
],
),
TableRow(
children: <Widget>[
Text('G'), Text('H'), Text('III'),
],
),
],
),
),
);
final RenderBox boxA = tester.renderObject(find.text('AAA'));
final RenderBox boxD = tester.renderObject(find.text('D'));
final RenderBox boxG = tester.renderObject(find.text('G'));
final RenderBox boxB = tester.renderObject(find.text('B'));
expect(boxA.size, equals(boxD.size));
expect(boxA.size, equals(boxG.size));
expect(boxA.size.width, greaterThan(boxB.size.width));
expect(boxA.size.height, equals(boxB.size.height));
});
testWidgets('Table widget - intrinsic sizing test, resizing', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: const <TableRow>[
TableRow(
children: <Widget>[
Text('AAAAAA'), Text('B'), Text('C'),
],
),
TableRow(
children: <Widget>[
Text('D'), Text('EEE'), Text('F'),
],
),
TableRow(
children: <Widget>[
Text('G'), Text('H'), Text('III'),
],
),
],
),
),
);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: const <TableRow>[
TableRow(
children: <Widget>[
Text('A'), Text('B'), Text('C'),
],
),
TableRow(
children: <Widget>[
Text('D'), Text('EEE'), Text('F'),
],
),
TableRow(
children: <Widget>[
Text('G'), Text('H'), Text('III'),
],
),
],
),
),
);
final RenderBox boxA = tester.renderObject(find.text('A'));
final RenderBox boxD = tester.renderObject(find.text('D'));
final RenderBox boxG = tester.renderObject(find.text('G'));
final RenderBox boxB = tester.renderObject(find.text('B'));
expect(boxA.size, equals(boxD.size));
expect(boxA.size, equals(boxG.size));
expect(boxA.size.width, lessThan(boxB.size.width));
expect(boxA.size.height, equals(boxB.size.height));
});
testWidgets('Table widget - intrinsic sizing test, changing column widths', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Table(
children: const <TableRow>[
TableRow(
children: <Widget>[
Text('AAA'), Text('B'), Text('C'),
],
),
TableRow(
children: <Widget>[
Text('D'), Text('E'), Text('FFFFFF'),
],
),
TableRow(
children: <Widget>[
Text('G'), Text('H'), Text('III'),
],
),
],
),
),
);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: const <TableRow>[
TableRow(
children: <Widget>[
Text('AAA'), Text('B'), Text('C'),
],
),
TableRow(
children: <Widget>[
Text('D'), Text('E'), Text('FFFFFF'),
],
),
TableRow(
children: <Widget>[
Text('G'), Text('H'), Text('III'),
],
),
],
),
),
);
final RenderBox boxA = tester.renderObject(find.text('AAA'));
final RenderBox boxD = tester.renderObject(find.text('D'));
final RenderBox boxG = tester.renderObject(find.text('G'));
final RenderBox boxB = tester.renderObject(find.text('B'));
expect(boxA.size, equals(boxD.size));
expect(boxA.size, equals(boxG.size));
expect(boxA.size.width, greaterThan(boxB.size.width));
expect(boxA.size.height, equals(boxB.size.height));
});
testWidgets('Table widget - moving test', (WidgetTester tester) async {
final List<BuildContext> contexts = <BuildContext>[];
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Table(
children: <TableRow>[
TableRow(
key: const ValueKey<int>(1),
children: <Widget>[
StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
contexts.add(context);
return const Text('A');
},
),
],
),
const TableRow(
children: <Widget>[
Text('b'),
],
),
],
),
),
);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Table(
children: <TableRow>[
const TableRow(
children: <Widget>[
Text('b'),
],
),
TableRow(
key: const ValueKey<int>(1),
children: <Widget>[
StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
contexts.add(context);
return const Text('A');
},
),
],
),
],
),
),
);
expect(contexts.length, equals(2));
expect(contexts[0], equals(contexts[1]));
});
testWidgets('Table widget - keyed rows', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Table(
children: const <TableRow>[
TableRow(
key: ValueKey<int>(1),
children: <Widget>[
TestStatefulWidget(key: ValueKey<int>(11)),
TestStatefulWidget(key: ValueKey<int>(12)),
],
),
TableRow(
key: ValueKey<int>(2),
children: <Widget>[
TestStatefulWidget(key: ValueKey<int>(21)),
TestStatefulWidget(key: ValueKey<int>(22)),
],
),
],
),
),
);
final TestStatefulWidgetState state11 = tester.state(find.byKey(const ValueKey<int>(11)));
final TestStatefulWidgetState state12 = tester.state(find.byKey(const ValueKey<int>(12)));
final TestStatefulWidgetState state21 = tester.state(find.byKey(const ValueKey<int>(21)));
final TestStatefulWidgetState state22 = tester.state(find.byKey(const ValueKey<int>(22)));
expect(state11.mounted, isTrue);
expect(state12.mounted, isTrue);
expect(state21.mounted, isTrue);
expect(state22.mounted, isTrue);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Table(
children: const <TableRow>[
TableRow(
key: ValueKey<int>(2),
children: <Widget>[
TestStatefulWidget(key: ValueKey<int>(21)),
TestStatefulWidget(key: ValueKey<int>(22)),
],
),
],
),
),
);
expect(state11.mounted, isFalse);
expect(state12.mounted, isFalse);
expect(state21.mounted, isTrue);
expect(state22.mounted, isTrue);
});
testWidgets('Table widget - global key reparenting', (WidgetTester tester) async {
final GlobalKey key = GlobalKey();
final Key tableKey = UniqueKey();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Column(
children: <Widget> [
Expanded(
key: tableKey,
child: Table(
children: <TableRow>[
TableRow(
children: <Widget>[
Container(key: const ValueKey<int>(1)),
TestStatefulWidget(key: key),
Container(key: const ValueKey<int>(2)),
],
),
],
),
),
],
),
),
);
final RenderTable table = tester.renderObject(find.byType(Table));
expect(table.row(0).length, 3);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Column(
children: <Widget> [
Expanded(child: TestStatefulWidget(key: key)),
Expanded(
key: tableKey,
child: Table(
children: <TableRow>[
TableRow(
children: <Widget>[
Container(key: const ValueKey<int>(1)),
Container(key: const ValueKey<int>(2)),
],
),
],
),
),
],
),
),
);
expect(tester.renderObject(find.byType(Table)), equals(table));
expect(table.row(0).length, 2);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Column(
children: <Widget> [
Expanded(
key: tableKey,
child: Table(
children: <TableRow>[
TableRow(
children: <Widget>[
Container(key: const ValueKey<int>(1)),
TestStatefulWidget(key: key),
Container(key: const ValueKey<int>(2)),
],
),
],
),
),
],
),
),
);
expect(tester.renderObject(find.byType(Table)), equals(table));
expect(table.row(0).length, 3);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Column(
children: <Widget> [
Expanded(
key: tableKey,
child: Table(
children: <TableRow>[
TableRow(
children: <Widget>[
Container(key: const ValueKey<int>(1)),
Container(key: const ValueKey<int>(2)),
],
),
],
),
),
Expanded(child: TestStatefulWidget(key: key)),
],
),
),
);
expect(tester.renderObject(find.byType(Table)), equals(table));
expect(table.row(0).length, 2);
});
testWidgets('Table widget diagnostics', (WidgetTester tester) async {
GlobalKey key0;
final Widget table = Directionality(
textDirection: TextDirection.ltr,
child: Table(
key: key0 = GlobalKey(),
defaultColumnWidth: const IntrinsicColumnWidth(),
children: const <TableRow>[
TableRow(
children: <Widget>[
Text('A'), Text('B'), Text('C'),
],
),
TableRow(
children: <Widget>[
Text('D'), Text('EEE'), Text('F'),
],
),
TableRow(
children: <Widget>[
Text('G'), Text('H'), Text('III'),
],
),
],
),
);
await tester.pumpWidget(table);
final RenderObjectElement element = key0.currentContext! as RenderObjectElement;
expect(element, hasAGoodToStringDeep);
expect(
element.toStringDeep(minLevel: DiagnosticLevel.info),
equalsIgnoringHashCodes(
'Table-[GlobalKey#00000](dependencies: [Directionality], renderObject: RenderTable#00000)\n'
'├Text("A")\n'
'│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "A", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
'├Text("B")\n'
'│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "B", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
'├Text("C")\n'
'│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "C", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
'├Text("D")\n'
'│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "D", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
'├Text("EEE")\n'
'│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "EEE", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
'├Text("F")\n'
'│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "F", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
'├Text("G")\n'
'│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "G", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
'├Text("H")\n'
'│└RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "H", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n'
'└Text("III")\n'
' └RichText(softWrap: wrapping at box width, maxLines: unlimited, text: "III", dependencies: [Directionality], renderObject: RenderParagraph#00000 relayoutBoundary=up1)\n',
),
);
});
// Regression test for https://github.com/flutter/flutter/issues/31473.
testWidgets(
'Does not crash if a child RenderObject is replaced by another RenderObject of a different type',
(WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Table(children: const <TableRow>[TableRow(children: <Widget>[TestChildWidget()])]),
),
);
expect(find.text('CRASHHH'), findsNothing);
final TestChildState state = tester.state(find.byType(TestChildWidget));
state.toggleMe();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Table(children: const <TableRow>[TableRow(children: <Widget>[TestChildWidget()])]),
),
);
// Should not crash.
expect(find.text('CRASHHH'), findsOneWidget);
},
);
testWidgets('Table widget - Default textBaseline is null', (WidgetTester tester) async {
expect(
() => Table(defaultVerticalAlignment: TableCellVerticalAlignment.baseline),
throwsA(
isAssertionError
.having((AssertionError error) => error.message, 'exception message', contains('baseline')),
),
);
});
testWidgets(
'Table widget requires all TableRows to have non-null children',
(WidgetTester tester) async {
FlutterError? error;
try {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Table(
children: const <TableRow>[
TableRow(children: <Widget>[Text('Some Text')]),
TableRow(),
],
),
),
);
} on FlutterError catch (e) {
error = e;
} finally {
expect(error, isNotNull);
expect(error!.toStringDeep(), contains('The children property of TableRow must not be null.'));
}
},
);
testWidgets('Can replace child with a different RenderObject type', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/69395.
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Table(children: const <TableRow>[
TableRow(children: <Widget>[
TestChildWidget(),
TestChildWidget(),
TestChildWidget(),
]),
TableRow(children: <Widget>[
TestChildWidget(),
TestChildWidget(),
TestChildWidget(),
]),
]),
),
);
final RenderTable table = tester.renderObject(find.byType(Table));
expect(find.text('CRASHHH'), findsNothing);
expect(find.byType(SizedBox), findsNWidgets(3 * 2));
final Type toBeReplaced = table.column(2).last.runtimeType;
final TestChildState state = tester.state(find.byType(TestChildWidget).last);
state.toggleMe();
await tester.pump();
expect(find.byType(SizedBox), findsNWidgets(5));
expect(find.text('CRASHHH'), findsOneWidget);
// The RenderObject got replaced by a different type.
expect(table.column(2).last.runtimeType, isNot(toBeReplaced));
});
testWidgets('Do not crash if a child that has not been layed out in a previous build is removed', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/60488.
Widget buildTable(Key key) {
return Directionality(
textDirection: TextDirection.ltr,
child: Table(
children: <TableRow>[
TableRow(
children: <Widget>[
KeyedSubtree(
key: key,
child: const Text('Hello'),
),
],
),
],
),
);
}
await tester.pumpWidget(
buildTable(const ValueKey<int>(1)),
null, EnginePhase.build, // Children are not layed out!
);
await tester.pumpWidget(
buildTable(const ValueKey<int>(2)),
);
expect(tester.takeException(), isNull);
expect(find.text('Hello'), findsOneWidget);
});
// TODO(ianh): Test handling of TableCell object
}