blob: e08169cdd46513a32c34aa3fbdf76244fb9087d3 [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/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
test('DataTableThemeData copyWith, ==, hashCode basics', () {
expect(const DataTableThemeData(), const DataTableThemeData().copyWith());
expect(const DataTableThemeData().hashCode, const DataTableThemeData().copyWith().hashCode);
});
test('DataTableThemeData copyWith dataRowHeight', () {
const DataTableThemeData themeData = DataTableThemeData(
dataRowMinHeight: 10,
dataRowMaxHeight: 10,
);
expect(themeData, themeData.copyWith());
expect(themeData.copyWith(dataRowMinHeight: 20, dataRowMaxHeight: 20),
themeData.copyWith(dataRowHeight: 20));
});
test('DataTableThemeData lerp special cases', () {
const DataTableThemeData data = DataTableThemeData();
expect(identical(DataTableThemeData.lerp(data, data, 0.5), data), true);
});
test('DataTableThemeData defaults', () {
const DataTableThemeData themeData = DataTableThemeData();
expect(themeData.decoration, null);
expect(themeData.dataRowColor, null);
expect(themeData.dataRowHeight, null);
expect(themeData.dataRowMinHeight, null);
expect(themeData.dataRowMaxHeight, null);
expect(themeData.dataTextStyle, null);
expect(themeData.headingRowColor, null);
expect(themeData.headingRowHeight, null);
expect(themeData.headingTextStyle, null);
expect(themeData.horizontalMargin, null);
expect(themeData.columnSpacing, null);
expect(themeData.dividerThickness, null);
expect(themeData.checkboxHorizontalMargin, null);
expect(themeData.headingCellCursor, null);
expect(themeData.dataRowCursor, null);
const DataTableTheme theme = DataTableTheme(data: DataTableThemeData(), child: SizedBox());
expect(theme.data.decoration, null);
expect(theme.data.dataRowColor, null);
expect(theme.data.dataRowHeight, null);
expect(theme.data.dataRowMinHeight, null);
expect(theme.data.dataRowMaxHeight, null);
expect(theme.data.dataTextStyle, null);
expect(theme.data.headingRowColor, null);
expect(theme.data.headingRowHeight, null);
expect(theme.data.headingTextStyle, null);
expect(theme.data.horizontalMargin, null);
expect(theme.data.columnSpacing, null);
expect(theme.data.dividerThickness, null);
expect(theme.data.checkboxHorizontalMargin, null);
expect(theme.data.headingCellCursor, null);
expect(theme.data.dataRowCursor, null);
});
testWidgets('Default DataTableThemeData debugFillProperties', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
const DataTableThemeData().debugFillProperties(builder);
final List<String> description = builder.properties
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
.map((DiagnosticsNode node) => node.toString())
.toList();
expect(description, <String>[]);
});
testWidgets('DataTableThemeData implements debugFillProperties', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
DataTableThemeData(
decoration: const BoxDecoration(color: Color(0xfffffff0)),
dataRowColor: MaterialStateProperty.resolveWith<Color>(
(Set<MaterialState> states) => const Color(0xfffffff1),
),
dataRowMinHeight: 41.0,
dataRowMaxHeight: 42.0,
dataTextStyle: const TextStyle(fontSize: 12.0),
headingRowColor: MaterialStateProperty.resolveWith<Color>(
(Set<MaterialState> states) => const Color(0xfffffff2),
),
headingRowHeight: 52.0,
headingTextStyle: const TextStyle(fontSize: 14.0),
horizontalMargin: 3.0,
columnSpacing: 4.0,
dividerThickness: 5.0,
checkboxHorizontalMargin: 6.0,
headingCellCursor: const MaterialStatePropertyAll<MouseCursor>(SystemMouseCursors.grab),
dataRowCursor: const MaterialStatePropertyAll<MouseCursor>(SystemMouseCursors.forbidden),
).debugFillProperties(builder);
final List<String> description = builder.properties
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
.map((DiagnosticsNode node) => node.toString())
.toList();
expect(description[0], 'decoration: BoxDecoration(color: Color(0xfffffff0))');
expect(description[1], "dataRowColor: Instance of '_MaterialStatePropertyWith<Color>'");
expect(description[2], 'dataRowMinHeight: 41.0');
expect(description[3], 'dataRowMaxHeight: 42.0');
expect(description[4], 'dataTextStyle: TextStyle(inherit: true, size: 12.0)');
expect(description[5], "headingRowColor: Instance of '_MaterialStatePropertyWith<Color>'");
expect(description[6], 'headingRowHeight: 52.0');
expect(description[7], 'headingTextStyle: TextStyle(inherit: true, size: 14.0)');
expect(description[8], 'horizontalMargin: 3.0');
expect(description[9], 'columnSpacing: 4.0');
expect(description[10], 'dividerThickness: 5.0');
expect(description[11], 'checkboxHorizontalMargin: 6.0');
expect(description[12], 'headingCellCursor: MaterialStatePropertyAll(SystemMouseCursor(grab))');
expect(description[13], 'dataRowCursor: MaterialStatePropertyAll(SystemMouseCursor(forbidden))');
});
testWidgets('DataTable is themeable', (WidgetTester tester) async {
const BoxDecoration decoration = BoxDecoration(color: Color(0xfffffff0));
const MaterialStateProperty<Color> dataRowColor = MaterialStatePropertyAll<Color>(Color(0xfffffff1));
const double minMaxDataRowHeight = 41.0;
const TextStyle dataTextStyle = TextStyle(fontSize: 12.5);
const MaterialStateProperty<Color> headingRowColor = MaterialStatePropertyAll<Color>(Color(0xfffffff2));
const double headingRowHeight = 52.0;
const TextStyle headingTextStyle = TextStyle(fontSize: 14.5);
const double horizontalMargin = 3.0;
const double columnSpacing = 4.0;
const double dividerThickness = 5.0;
const MaterialStateProperty<MouseCursor> headingCellCursor = MaterialStatePropertyAll<MouseCursor>(SystemMouseCursors.grab);
const MaterialStateProperty<MouseCursor> dataRowCursor = MaterialStatePropertyAll<MouseCursor>(SystemMouseCursors.forbidden);
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(
dataTableTheme: const DataTableThemeData(
decoration: decoration,
dataRowColor: dataRowColor,
dataRowMinHeight: minMaxDataRowHeight,
dataRowMaxHeight: minMaxDataRowHeight,
dataTextStyle: dataTextStyle,
headingRowColor: headingRowColor,
headingRowHeight: headingRowHeight,
headingTextStyle: headingTextStyle,
horizontalMargin: horizontalMargin,
columnSpacing: columnSpacing,
dividerThickness: dividerThickness,
headingCellCursor: headingCellCursor,
dataRowCursor: dataRowCursor,
),
),
home: Scaffold(
body: DataTable(
sortColumnIndex: 0,
showCheckboxColumn: false,
columns: <DataColumn>[
DataColumn(
label: const Text('A'),
onSort: (int columnIndex, bool ascending) {},
),
const DataColumn(label: Text('B')),
],
rows: <DataRow>[
DataRow(
cells: const <DataCell>[
DataCell(Text('Data')),
DataCell(Text('Data 2')),
],
onSelectChanged: (bool? value) { },
),
],
),
),
),
);
final Finder tableContainerFinder = find.ancestor(of: find.byType(Table), matching: find.byType(Container));
expect(tester.widgetList<Container>(tableContainerFinder).first.decoration, decoration);
final TextStyle dataRowTextStyle = tester.renderObject<RenderParagraph>(find.text('Data')).text.style!;
expect(dataRowTextStyle.fontSize, dataTextStyle.fontSize);
expect(_tableRowBoxDecoration(tester: tester, index: 1).color, dataRowColor.resolve(<MaterialState>{}));
expect(_tableRowBoxDecoration(tester: tester, index: 1).border!.top.width, dividerThickness);
expect(tester.getSize(_findFirstContainerFor('Data')).height, minMaxDataRowHeight);
final TextStyle headingRowTextStyle = tester.renderObject<RenderParagraph>(find.text('A')).text.style!;
expect(headingRowTextStyle.fontSize, headingTextStyle.fontSize);
expect(_tableRowBoxDecoration(tester: tester, index: 0).color, headingRowColor.resolve(<MaterialState>{}));
expect(tester.getSize(_findFirstContainerFor('A')).height, headingRowHeight);
expect(tester.getTopLeft(find.text('A')).dx, horizontalMargin);
expect(tester.getTopLeft(find.text('Data 2')).dx - tester.getTopRight(find.text('Data')).dx, columnSpacing);
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, pointer: 1);
await gesture.addPointer(location: tester.getCenter(find.text('A')));
await tester.pump();
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.grab);
await gesture.moveTo(tester.getCenter(find.text('Data')));
await tester.pump();
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.forbidden);
});
testWidgets('DataTable is themeable - separate test for deprecated dataRowHeight', (WidgetTester tester) async {
const double dataRowHeight = 51.0;
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(
dataTableTheme: const DataTableThemeData(
dataRowHeight: dataRowHeight,
),
),
home: Scaffold(
body: DataTable(
sortColumnIndex: 0,
columns: <DataColumn>[
DataColumn(
label: const Text('A'),
onSort: (int columnIndex, bool ascending) {},
),
const DataColumn(label: Text('B')),
],
rows: const <DataRow>[
DataRow(cells: <DataCell>[
DataCell(Text('Data')),
DataCell(Text('Data 2')),
]),
],
),
),
),
);
expect(tester.getSize(_findFirstContainerFor('Data')).height, dataRowHeight);
});
testWidgets('DataTable properties are taken over the theme values', (WidgetTester tester) async {
const BoxDecoration themeDecoration = BoxDecoration(color: Color(0xfffffff1));
const MaterialStateProperty<Color> themeDataRowColor = MaterialStatePropertyAll<Color>(Color(0xfffffff0));
const double minMaxThemeDataRowHeight = 50.0;
const TextStyle themeDataTextStyle = TextStyle(fontSize: 11.5);
const MaterialStateProperty<Color> themeHeadingRowColor = MaterialStatePropertyAll<Color>(Color(0xfffffff1));
const double themeHeadingRowHeight = 51.0;
const TextStyle themeHeadingTextStyle = TextStyle(fontSize: 13.5);
const double themeHorizontalMargin = 2.0;
const double themeColumnSpacing = 3.0;
const double themeDividerThickness = 4.0;
const MaterialStateProperty<MouseCursor> themeHeadingCellCursor = MaterialStatePropertyAll<MouseCursor>(SystemMouseCursors.copy);
const MaterialStateProperty<MouseCursor> themeDataRowCursor = MaterialStatePropertyAll<MouseCursor>(SystemMouseCursors.copy);
const BoxDecoration decoration = BoxDecoration(color: Color(0xfffffff0));
const MaterialStateProperty<Color> dataRowColor = MaterialStatePropertyAll<Color>(Color(0xfffffff1));
const double minMaxDataRowHeight = 51.0;
const TextStyle dataTextStyle = TextStyle(fontSize: 12.5);
const MaterialStateProperty<Color> headingRowColor = MaterialStatePropertyAll<Color>(Color(0xfffffff2));
const double headingRowHeight = 52.0;
const TextStyle headingTextStyle = TextStyle(fontSize: 14.5);
const double horizontalMargin = 3.0;
const double columnSpacing = 4.0;
const double dividerThickness = 5.0;
const MaterialStateProperty<MouseCursor> headingCellCursor = MaterialStatePropertyAll<MouseCursor>(SystemMouseCursors.forbidden);
const MaterialStateProperty<MouseCursor> dataRowCursor = MaterialStatePropertyAll<MouseCursor>(SystemMouseCursors.forbidden);
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(
dataTableTheme: const DataTableThemeData(
decoration: themeDecoration,
dataRowColor: themeDataRowColor,
dataRowMinHeight: minMaxThemeDataRowHeight,
dataRowMaxHeight: minMaxThemeDataRowHeight,
dataTextStyle: themeDataTextStyle,
headingRowColor: themeHeadingRowColor,
headingRowHeight: themeHeadingRowHeight,
headingTextStyle: themeHeadingTextStyle,
horizontalMargin: themeHorizontalMargin,
columnSpacing: themeColumnSpacing,
dividerThickness: themeDividerThickness,
headingCellCursor: themeHeadingCellCursor,
dataRowCursor: themeDataRowCursor,
),
),
home: Scaffold(
body: DataTable(
showCheckboxColumn: false,
decoration: decoration,
dataRowColor: dataRowColor,
dataRowMinHeight: minMaxDataRowHeight,
dataRowMaxHeight: minMaxDataRowHeight,
dataTextStyle: dataTextStyle,
headingRowColor: headingRowColor,
headingRowHeight: headingRowHeight,
headingTextStyle: headingTextStyle,
horizontalMargin: horizontalMargin,
columnSpacing: columnSpacing,
dividerThickness: dividerThickness,
sortColumnIndex: 0,
columns: <DataColumn>[
DataColumn(
label: const Text('A'),
mouseCursor: headingCellCursor,
onSort: (int columnIndex, bool ascending) {},
),
const DataColumn(label: Text('B')),
],
rows: <DataRow>[
DataRow(
mouseCursor: dataRowCursor,
onSelectChanged: (bool? selected) {},
cells: const <DataCell>[
DataCell(Text('Data')),
DataCell(Text('Data 2')),
],
),
],
),
),
),
);
final Finder tableContainerFinder = find.ancestor(of: find.byType(Table), matching: find.byType(Container));
expect(tester.widget<Container>(tableContainerFinder).decoration, decoration);
final TextStyle dataRowTextStyle = tester.renderObject<RenderParagraph>(find.text('Data')).text.style!;
expect(dataRowTextStyle.fontSize, dataTextStyle.fontSize);
expect(_tableRowBoxDecoration(tester: tester, index: 1).color, dataRowColor.resolve(<MaterialState>{}));
expect(_tableRowBoxDecoration(tester: tester, index: 1).border!.top.width, dividerThickness);
expect(tester.getSize(_findFirstContainerFor('Data')).height, minMaxDataRowHeight);
final TextStyle headingRowTextStyle = tester.renderObject<RenderParagraph>(find.text('A')).text.style!;
expect(headingRowTextStyle.fontSize, headingTextStyle.fontSize);
expect(_tableRowBoxDecoration(tester: tester, index: 0).color, headingRowColor.resolve(<MaterialState>{}));
expect(tester.getSize(_findFirstContainerFor('A')).height, headingRowHeight);
expect(tester.getTopLeft(find.text('A')).dx, horizontalMargin);
expect(tester.getTopLeft(find.text('Data 2')).dx - tester.getTopRight(find.text('Data')).dx, columnSpacing);
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, pointer: 1);
await gesture.addPointer(location: tester.getCenter(find.text('A')));
await tester.pump();
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), headingCellCursor.resolve(<MaterialState>{}));
await gesture.moveTo(tester.getCenter(find.text('Data')));
await tester.pump();
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), dataRowCursor.resolve(<MaterialState>{}));
});
testWidgets('DataTable properties are taken over the theme values - separate test for deprecated dataRowHeight', (WidgetTester tester) async {
const double themeDataRowHeight = 50.0;
const double dataRowHeight = 51.0;
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(
dataTableTheme: const DataTableThemeData(
dataRowHeight: themeDataRowHeight,
),
),
home: Scaffold(
body: DataTable(
dataRowHeight: dataRowHeight,
sortColumnIndex: 0,
columns: <DataColumn>[
DataColumn(
label: const Text('A'),
onSort: (int columnIndex, bool ascending) {},
),
const DataColumn(label: Text('B')),
],
rows: const <DataRow>[
DataRow(cells: <DataCell>[
DataCell(Text('Data')),
DataCell(Text('Data 2')),
]),
],
),
),
),
);
expect(tester.getSize(_findFirstContainerFor('Data')).height, dataRowHeight);
});
testWidgets('Local DataTableTheme can override global DataTableTheme', (WidgetTester tester) async {
const BoxDecoration globalThemeDecoration = BoxDecoration(color: Color(0xfffffff1));
const MaterialStateProperty<Color> globalThemeDataRowColor = MaterialStatePropertyAll<Color>(Color(0xfffffff0));
const double minMaxGlobalThemeDataRowHeight = 50.0;
const TextStyle globalThemeDataTextStyle = TextStyle(fontSize: 11.5);
const MaterialStateProperty<Color> globalThemeHeadingRowColor = MaterialStatePropertyAll<Color>(Color(0xfffffff1));
const double globalThemeHeadingRowHeight = 51.0;
const TextStyle globalThemeHeadingTextStyle = TextStyle(fontSize: 13.5);
const double globalThemeHorizontalMargin = 2.0;
const double globalThemeColumnSpacing = 3.0;
const double globalThemeDividerThickness = 4.0;
const MaterialStateProperty<MouseCursor> globalHeadingCellCursor = MaterialStatePropertyAll<MouseCursor>(SystemMouseCursors.allScroll);
const MaterialStateProperty<MouseCursor> globalDataRowCursor = MaterialStatePropertyAll<MouseCursor>(SystemMouseCursors.allScroll);
const BoxDecoration localThemeDecoration = BoxDecoration(color: Color(0xfffffff0));
const MaterialStateProperty<Color> localThemeDataRowColor = MaterialStatePropertyAll<Color>(Color(0xfffffff1));
const double minMaxLocalThemeDataRowHeight = 51.0;
const TextStyle localThemeDataTextStyle = TextStyle(fontSize: 12.5);
const MaterialStateProperty<Color> localThemeHeadingRowColor = MaterialStatePropertyAll<Color>(Color(0xfffffff2));
const double localThemeHeadingRowHeight = 52.0;
const TextStyle localThemeHeadingTextStyle = TextStyle(fontSize: 14.5);
const double localThemeHorizontalMargin = 3.0;
const double localThemeColumnSpacing = 4.0;
const double localThemeDividerThickness = 5.0;
const MaterialStateProperty<MouseCursor> localHeadingCellCursor = MaterialStatePropertyAll<MouseCursor>(SystemMouseCursors.move);
const MaterialStateProperty<MouseCursor> localDataRowCursor = MaterialStatePropertyAll<MouseCursor>(SystemMouseCursors.move);
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(
dataTableTheme: const DataTableThemeData(
decoration: globalThemeDecoration,
dataRowColor: globalThemeDataRowColor,
dataRowMinHeight: minMaxGlobalThemeDataRowHeight,
dataRowMaxHeight: minMaxGlobalThemeDataRowHeight,
dataTextStyle: globalThemeDataTextStyle,
headingRowColor: globalThemeHeadingRowColor,
headingRowHeight: globalThemeHeadingRowHeight,
headingTextStyle: globalThemeHeadingTextStyle,
horizontalMargin: globalThemeHorizontalMargin,
columnSpacing: globalThemeColumnSpacing,
dividerThickness: globalThemeDividerThickness,
headingCellCursor: globalHeadingCellCursor,
dataRowCursor: globalDataRowCursor,
),
),
home: Scaffold(
body: DataTableTheme(
data: const DataTableThemeData(
decoration: localThemeDecoration,
dataRowColor: localThemeDataRowColor,
dataRowMinHeight: minMaxLocalThemeDataRowHeight,
dataRowMaxHeight: minMaxLocalThemeDataRowHeight,
dataTextStyle: localThemeDataTextStyle,
headingRowColor: localThemeHeadingRowColor,
headingRowHeight: localThemeHeadingRowHeight,
headingTextStyle: localThemeHeadingTextStyle,
horizontalMargin: localThemeHorizontalMargin,
columnSpacing: localThemeColumnSpacing,
dividerThickness: localThemeDividerThickness,
headingCellCursor: localHeadingCellCursor,
dataRowCursor: localDataRowCursor,
),
child: DataTable(
showCheckboxColumn: false,
sortColumnIndex: 0,
columns: <DataColumn>[
DataColumn(
label: const Text('A'),
onSort: (int columnIndex, bool ascending) {},
),
const DataColumn(label: Text('B')),
],
rows: <DataRow>[
DataRow(
onSelectChanged: (bool? selected) {},
cells: const <DataCell>[
DataCell(Text('Data')),
DataCell(Text('Data 2')),
],
),
],
),
),
),
),
);
final Finder tableContainerFinder = find.ancestor(of: find.byType(Table), matching: find.byType(Container));
expect(tester.widgetList<Container>(tableContainerFinder).first.decoration, localThemeDecoration);
final TextStyle dataRowTextStyle = tester.renderObject<RenderParagraph>(find.text('Data')).text.style!;
expect(dataRowTextStyle.fontSize, localThemeDataTextStyle.fontSize);
expect(_tableRowBoxDecoration(tester: tester, index: 1).color, localThemeDataRowColor.resolve(<MaterialState>{}));
expect(_tableRowBoxDecoration(tester: tester, index: 1).border!.top.width, localThemeDividerThickness);
expect(tester.getSize(_findFirstContainerFor('Data')).height, minMaxLocalThemeDataRowHeight);
final TextStyle headingRowTextStyle = tester.renderObject<RenderParagraph>(find.text('A')).text.style!;
expect(headingRowTextStyle.fontSize, localThemeHeadingTextStyle.fontSize);
expect(_tableRowBoxDecoration(tester: tester, index: 0).color, localThemeHeadingRowColor.resolve(<MaterialState>{}));
expect(tester.getSize(_findFirstContainerFor('A')).height, localThemeHeadingRowHeight);
expect(tester.getTopLeft(find.text('A')).dx, localThemeHorizontalMargin);
expect(tester.getTopLeft(find.text('Data 2')).dx - tester.getTopRight(find.text('Data')).dx, localThemeColumnSpacing);
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, pointer: 1);
await gesture.addPointer(location: tester.getCenter(find.text('A')));
await tester.pump();
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), localHeadingCellCursor.resolve(<MaterialState>{}));
await gesture.moveTo(tester.getCenter(find.text('Data')));
await tester.pump();
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), localDataRowCursor.resolve(<MaterialState>{}));
});
testWidgets('Local DataTableTheme can override global DataTableTheme - separate test for deprecated dataRowHeight', (WidgetTester tester) async {
const double globalThemeDataRowHeight = 50.0;
const double localThemeDataRowHeight = 51.0;
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(
dataTableTheme: const DataTableThemeData(
dataRowHeight: globalThemeDataRowHeight,
),
),
home: Scaffold(
body: DataTableTheme(
data: const DataTableThemeData(
dataRowHeight: localThemeDataRowHeight,
),
child: DataTable(
sortColumnIndex: 0,
columns: <DataColumn>[
DataColumn(
label: const Text('A'),
onSort: (int columnIndex, bool ascending) {},
),
const DataColumn(label: Text('B')),
],
rows: const <DataRow>[
DataRow(cells: <DataCell>[
DataCell(Text('Data')),
DataCell(Text('Data 2')),
]),
],
),
),
),
),
);
expect(tester.getSize(_findFirstContainerFor('Data')).height, localThemeDataRowHeight);
});
}
BoxDecoration _tableRowBoxDecoration({required WidgetTester tester, required int index}) {
final Table table = tester.widget(find.byType(Table));
final TableRow tableRow = table.children[index];
return tableRow.decoration! as BoxDecoration;
}
// The finder matches with the Container of the cell content, as well as the
// Container wrapping the whole table. The first one is used to test row
// heights.
Finder _findFirstContainerFor(String text) => find.widgetWithText(Container, text).first;