// 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.

@TestOn('!chrome')
import 'dart:math' as math;

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:vector_math/vector_math_64.dart' show Matrix3;

import '../rendering/mock_canvas.dart';
import 'data_table_test_utils.dart';

void main() {
  testWidgets('DataTable control test', (WidgetTester tester) async {
    final List<String> log = <String>[];

    Widget buildTable({ int? sortColumnIndex, bool sortAscending = true }) {
      return DataTable(
        sortColumnIndex: sortColumnIndex,
        sortAscending: sortAscending,
        onSelectAll: (bool? value) {
          log.add('select-all: $value');
        },
        columns: <DataColumn>[
          const DataColumn(
            label: Text('Name'),
            tooltip: 'Name',
          ),
          DataColumn(
            label: const Text('Calories'),
            tooltip: 'Calories',
            numeric: true,
            onSort: (int columnIndex, bool ascending) {
              log.add('column-sort: $columnIndex $ascending');
            },
          ),
        ],
        rows: kDesserts.map<DataRow>((Dessert dessert) {
          return DataRow(
            key: ValueKey<String>(dessert.name),
            onSelectChanged: (bool? selected) {
              log.add('row-selected: ${dessert.name}');
            },
            onLongPress: () {
              log.add('onLongPress: ${dessert.name}');
            },
            cells: <DataCell>[
              DataCell(
                Text(dessert.name),
              ),
              DataCell(
                Text('${dessert.calories}'),
                showEditIcon: true,
                onTap: () {
                  log.add('cell-tap: ${dessert.calories}');
                },
                onDoubleTap: () {
                  log.add('cell-doubleTap: ${dessert.calories}');
                },
                onLongPress: () {
                  log.add('cell-longPress: ${dessert.calories}');
                },
                onTapCancel: () {
                  log.add('cell-tapCancel: ${dessert.calories}');
                },
                onTapDown: (TapDownDetails details) {
                  log.add('cell-tapDown: ${dessert.calories}');
                },
              ),
            ],
          );
        }).toList(),
      );
    }

    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildTable()),
    ));

    await tester.tap(find.byType(Checkbox).first);

    expect(log, <String>['select-all: true']);
    log.clear();

    await tester.tap(find.text('Cupcake'));

    expect(log, <String>['row-selected: Cupcake']);
    log.clear();

    await tester.longPress(find.text('Cupcake'));

    expect(log, <String>['onLongPress: Cupcake']);
    log.clear();

    await tester.tap(find.text('Calories'));

    expect(log, <String>['column-sort: 1 true']);
    log.clear();

    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildTable(sortColumnIndex: 1)),
    ));
    await tester.pumpAndSettle(const Duration(milliseconds: 200));
    await tester.tap(find.text('Calories'));

    expect(log, <String>['column-sort: 1 false']);
    log.clear();

    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildTable(sortColumnIndex: 1, sortAscending: false)),
    ));
    await tester.pumpAndSettle(const Duration(milliseconds: 200));

    await tester.tap(find.text('375'));
    await tester.pump(const Duration(milliseconds: 100));
    await tester.tap(find.text('375'));

    expect(log, <String>['cell-doubleTap: 375']);
    log.clear();

    await tester.longPress(find.text('375'));
    // The tap down is triggered on gesture down.
    // Then, the cancel is triggered when the gesture arena
    // recognizes that the long press overrides the tap event
    // so it triggers a tap cancel, followed by the long press.
    expect(log,<String>['cell-tapDown: 375' ,'cell-tapCancel: 375', 'cell-longPress: 375']);
    log.clear();

    TestGesture gesture = await tester.startGesture(
      tester.getRect(find.text('375')).center,
    );
    await tester.pump(const Duration(milliseconds: 100));
    // onTapDown callback is registered.
    expect(log, equals(<String>['cell-tapDown: 375']));
    await gesture.up();

    await tester.pump(const Duration(seconds: 1));
    // onTap callback is registered after the gesture is removed.
    expect(log, equals(<String>['cell-tapDown: 375', 'cell-tap: 375']));
    log.clear();

    // dragging off the bounds of the cell calls the cancel callback
    gesture = await tester.startGesture(tester.getRect(find.text('375')).center);
    await tester.pump(const Duration(milliseconds: 100));
    await gesture.moveBy(const Offset(0.0, 200.0));
    await gesture.cancel();
    expect(log, equals(<String>['cell-tapDown: 375', 'cell-tapCancel: 375']));

    log.clear();

    await tester.tap(find.byType(Checkbox).last);

    expect(log, <String>['row-selected: KitKat']);
    log.clear();
  });

  testWidgets('DataTable control test - tristate', (WidgetTester tester) async {
    final List<String> log = <String>[];
    const int numItems = 3;
    Widget buildTable(List<bool> selected, {int? disabledIndex}) {
      return DataTable(
        onSelectAll: (bool? value) {
          log.add('select-all: $value');
        },
        columns: const <DataColumn>[
          DataColumn(
            label: Text('Name'),
            tooltip: 'Name',
          ),
        ],
        rows: List<DataRow>.generate(
          numItems,
          (int index) => DataRow(
            cells: <DataCell>[DataCell(Text('Row $index'))],
            selected: selected[index],
            onSelectChanged: index == disabledIndex ? null : (bool? value) {
              log.add('row-selected: $index');
            },
          ),
        ),
      );
    }

    // Tapping the parent checkbox when no rows are selected, selects all.
    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildTable(<bool>[false, false, false])),
    ));
    await tester.tap(find.byType(Checkbox).first);

    expect(log, <String>['select-all: true']);
    log.clear();

    // Tapping the parent checkbox when some rows are selected, selects all.
    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildTable(<bool>[true, false, true])),
    ));
    await tester.tap(find.byType(Checkbox).first);

    expect(log, <String>['select-all: true']);
    log.clear();

    // Tapping the parent checkbox when all rows are selected, deselects all.
    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildTable(<bool>[true, true, true])),
    ));
    await tester.tap(find.byType(Checkbox).first);

    expect(log, <String>['select-all: false']);
    log.clear();

    // Tapping the parent checkbox when all rows are selected and one is
    // disabled, deselects all.
    await tester.pumpWidget(MaterialApp(
      home: Material(
        child: buildTable(
          <bool>[true, true, false],
          disabledIndex: 2,
        ),
      ),
    ));
    await tester.tap(find.byType(Checkbox).first);

    expect(log, <String>['select-all: false']);
    log.clear();
  });

  testWidgets('DataTable control test - no checkboxes', (WidgetTester tester) async {
    final List<String> log = <String>[];

    Widget buildTable({ bool checkboxes = false }) {
      return DataTable(
        showCheckboxColumn: checkboxes,
        onSelectAll: (bool? value) {
          log.add('select-all: $value');
        },
        columns: const <DataColumn>[
          DataColumn(
            label: Text('Name'),
            tooltip: 'Name',
          ),
          DataColumn(
            label: Text('Calories'),
            tooltip: 'Calories',
            numeric: true,
          ),
        ],
        rows: kDesserts.map<DataRow>((Dessert dessert) {
          return DataRow(
            key: ValueKey<String>(dessert.name),
            onSelectChanged: (bool? selected) {
              log.add('row-selected: ${dessert.name}');
            },
            cells: <DataCell>[
              DataCell(
                Text(dessert.name),
              ),
              DataCell(
                Text('${dessert.calories}'),
                showEditIcon: true,
                onTap: () {
                  log.add('cell-tap: ${dessert.calories}');
                },
              ),
            ],
          );
        }).toList(),
      );
    }

    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildTable()),
    ));

    expect(find.byType(Checkbox), findsNothing);
    await tester.tap(find.text('Cupcake'));

    expect(log, <String>['row-selected: Cupcake']);
    log.clear();

    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildTable(checkboxes: true)),
    ));

    await tester.pumpAndSettle(const Duration(milliseconds: 200));
    final Finder checkboxes = find.byType(Checkbox);
    expect(checkboxes, findsNWidgets(11));
    await tester.tap(checkboxes.first);

    expect(log, <String>['select-all: true']);
    log.clear();
  });

  testWidgets('DataTable overflow test - header', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: DataTable(
            headingTextStyle: const TextStyle(
              fontSize: 14.0,
              letterSpacing: 0.0, // Will overflow if letter spacing is larger than 0.0.
            ),
            columns: <DataColumn>[
              DataColumn(
                label: Text('X' * 2000),
              ),
            ],
            rows: const <DataRow>[
              DataRow(
                cells: <DataCell>[
                  DataCell(
                    Text('X'),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );

    expect(tester.renderObject<RenderBox>(find.byType(Text).first).size.width, greaterThan(800.0));
    expect(tester.renderObject<RenderBox>(find.byType(Row).first).size.width, greaterThan(800.0));
    expect(tester.takeException(), isNull); // column overflows table, but text doesn't overflow cell
  });

  testWidgets('DataTable overflow test - header with spaces', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: DataTable(
            columns: <DataColumn>[
              DataColumn(
                label: Text('X ' * 2000), // has soft wrap points, but they should be ignored
              ),
            ],
            rows: const <DataRow>[
              DataRow(
                cells: <DataCell>[
                  DataCell(
                    Text('X'),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
    expect(tester.renderObject<RenderBox>(find.byType(Text).first).size.width, greaterThan(800.0));
    expect(tester.renderObject<RenderBox>(find.byType(Row).first).size.width, greaterThan(800.0));
    expect(tester.takeException(), isNull); // column overflows table, but text doesn't overflow cell
  }, skip: true); // https://github.com/flutter/flutter/issues/13512

  testWidgets('DataTable overflow test', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: DataTable(
            columns: const <DataColumn>[
              DataColumn(
                label: Text('X'),
              ),
            ],
            rows: <DataRow>[
              DataRow(
                cells: <DataCell>[
                  DataCell(
                    Text('X' * 2000),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
    expect(tester.renderObject<RenderBox>(find.byType(Text).first).size.width, lessThan(800.0));
    expect(tester.renderObject<RenderBox>(find.byType(Row).first).size.width, greaterThan(800.0));
    expect(tester.takeException(), isNull); // cell overflows table, but text doesn't overflow cell
  });

  testWidgets('DataTable overflow test', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: DataTable(
            columns: const <DataColumn>[
              DataColumn(
                label: Text('X'),
              ),
            ],
            rows: <DataRow>[
              DataRow(
                cells: <DataCell>[
                  DataCell(
                    Text('X ' * 2000), // wraps
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
    expect(tester.renderObject<RenderBox>(find.byType(Text).first).size.width, lessThan(800.0));
    expect(tester.renderObject<RenderBox>(find.byType(Row).first).size.width, lessThan(800.0));
    expect(tester.takeException(), isNull);
  });

  testWidgets('DataTable column onSort test', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: DataTable(
            columns: const <DataColumn>[
              DataColumn(
                label: Text('Dessert'),
              ),
            ],
            rows: const <DataRow>[
              DataRow(
                cells: <DataCell>[
                  DataCell(
                    Text('Lollipop'), // wraps
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
    await tester.tap(find.text('Dessert'));
    await tester.pump();
    expect(tester.takeException(), isNull);
  });

  testWidgets('DataTable sort indicator orientation', (WidgetTester tester) async {
    Widget buildTable({ bool sortAscending = true }) {
      return DataTable(
        sortColumnIndex: 0,
        sortAscending: sortAscending,
        columns: <DataColumn>[
          DataColumn(
            label: const Text('Name'),
            tooltip: 'Name',
            onSort: (int columnIndex, bool ascending) {},
          ),
        ],
        rows: kDesserts.map<DataRow>((Dessert dessert) {
          return DataRow(
            cells: <DataCell>[
              DataCell(
                Text(dessert.name),
              ),
            ],
          );
        }).toList(),
      );
    }

    // Check for ascending list
    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildTable()),
    ));
    // The `tester.widget` ensures that there is exactly one upward arrow.
    final Finder iconFinder = find.descendant(
      of: find.byType(DataTable),
      matching: find.widgetWithIcon(Transform, Icons.arrow_upward),
    );
    Transform transformOfArrow = tester.widget<Transform>(iconFinder);
    expect(
      transformOfArrow.transform.getRotation(),
      equals(Matrix3.identity()),
    );

    // Check for descending list.
    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildTable(sortAscending: false)),
    ));
    await tester.pumpAndSettle();
    // The `tester.widget` ensures that there is exactly one upward arrow.
    transformOfArrow = tester.widget<Transform>(iconFinder);
    expect(
      transformOfArrow.transform.getRotation(),
      equals(Matrix3.rotationZ(math.pi)),
    );
  });

  testWidgets('DataTable sort indicator orientation does not change on state update', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/43724
    Widget buildTable({String title = 'Name1'}) {
      return DataTable(
        sortColumnIndex: 0,
        columns: <DataColumn>[
          DataColumn(
            label: Text(title),
            tooltip: 'Name',
            onSort: (int columnIndex, bool ascending) {},
          ),
        ],
        rows: kDesserts.map<DataRow>((Dessert dessert) {
          return DataRow(
            cells: <DataCell>[
              DataCell(
                Text(dessert.name),
              ),
            ],
          );
        }).toList(),
      );
    }

    // Check for ascending list
    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildTable()),
    ));
    // The `tester.widget` ensures that there is exactly one upward arrow.
    final Finder iconFinder = find.descendant(
      of: find.byType(DataTable),
      matching: find.widgetWithIcon(Transform, Icons.arrow_upward),
    );
    Transform transformOfArrow = tester.widget<Transform>(iconFinder);
    expect(
      transformOfArrow.transform.getRotation(),
      equals(Matrix3.identity()),
    );

    // Cause a rebuild by updating the widget
    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildTable(title: 'Name2')),
    ));
    await tester.pumpAndSettle();
    // The `tester.widget` ensures that there is exactly one upward arrow.
    transformOfArrow = tester.widget<Transform>(iconFinder);
    expect(
      transformOfArrow.transform.getRotation(),
      equals(Matrix3.identity()), // Should not have changed
    );
  });

  testWidgets('DataTable sort indicator orientation does not change on state update - reverse', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/43724
    Widget buildTable({String title = 'Name1'}) {
      return DataTable(
        sortColumnIndex: 0,
        sortAscending: false,
        columns: <DataColumn>[
          DataColumn(
            label: Text(title),
            tooltip: 'Name',
            onSort: (int columnIndex, bool ascending) {},
          ),
        ],
        rows: kDesserts.map<DataRow>((Dessert dessert) {
          return DataRow(
            cells: <DataCell>[
              DataCell(
                Text(dessert.name),
              ),
            ],
          );
        }).toList(),
      );
    }

    // Check for ascending list
    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildTable()),
    ));
    // The `tester.widget` ensures that there is exactly one upward arrow.
    final Finder iconFinder = find.descendant(
      of: find.byType(DataTable),
      matching: find.widgetWithIcon(Transform, Icons.arrow_upward),
    );
    Transform transformOfArrow = tester.widget<Transform>(iconFinder);
    expect(
      transformOfArrow.transform.getRotation(),
      equals(Matrix3.rotationZ(math.pi)),
    );

    // Cause a rebuild by updating the widget
    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildTable(title: 'Name2')),
    ));
    await tester.pumpAndSettle();
    // The `tester.widget` ensures that there is exactly one upward arrow.
    transformOfArrow = tester.widget<Transform>(iconFinder);
    expect(
      transformOfArrow.transform.getRotation(),
      equals(Matrix3.rotationZ(math.pi)), // Should not have changed
    );
  });

  testWidgets('DataTable row onSelectChanged test', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: DataTable(
            columns: const <DataColumn>[
              DataColumn(
                label: Text('Dessert'),
              ),
            ],
            rows: const <DataRow>[
              DataRow(
                cells: <DataCell>[
                  DataCell(
                    Text('Lollipop'), // wraps
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
    await tester.tap(find.text('Lollipop'));
    await tester.pump();
    expect(tester.takeException(), isNull);
  });

  testWidgets('DataTable custom row height', (WidgetTester tester) async {
    Widget buildCustomTable({
      int? sortColumnIndex,
      bool sortAscending = true,
      double dataRowHeight = 48.0,
      double headingRowHeight = 56.0,
    }) {
      return DataTable(
        sortColumnIndex: sortColumnIndex,
        sortAscending: sortAscending,
        onSelectAll: (bool? value) {},
        dataRowHeight: dataRowHeight,
        headingRowHeight: headingRowHeight,
        columns: <DataColumn>[
          const DataColumn(
            label: Text('Name'),
            tooltip: 'Name',
          ),
          DataColumn(
            label: const Text('Calories'),
            tooltip: 'Calories',
            numeric: true,
            onSort: (int columnIndex, bool ascending) {},
          ),
        ],
        rows: kDesserts.map<DataRow>((Dessert dessert) {
          return DataRow(
            key: ValueKey<String>(dessert.name),
            onSelectChanged: (bool? selected) {},
            cells: <DataCell>[
              DataCell(
                Text(dessert.name),
              ),
              DataCell(
                Text('${dessert.calories}'),
                showEditIcon: true,
                onTap: () {},
              ),
            ],
          );
        }).toList(),
      );
    }

    // DEFAULT VALUES
    await tester.pumpWidget(MaterialApp(
      home: Material(
        child: DataTable(
          onSelectAll: (bool? value) {},
          columns: <DataColumn>[
            const DataColumn(
              label: Text('Name'),
              tooltip: 'Name',
            ),
            DataColumn(
              label: const Text('Calories'),
              tooltip: 'Calories',
              numeric: true,
              onSort: (int columnIndex, bool ascending) {},
            ),
          ],
          rows: kDesserts.map<DataRow>((Dessert dessert) {
            return DataRow(
              key: ValueKey<String>(dessert.name),
              onSelectChanged: (bool? selected) {},
              cells: <DataCell>[
                DataCell(
                  Text(dessert.name),
                ),
                DataCell(
                  Text('${dessert.calories}'),
                  showEditIcon: true,
                  onTap: () {},
                ),
              ],
            );
          }).toList(),
        ),
      ),
    ));

    // 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;

    expect(tester.getSize(findFirstContainerFor('Name')).height, 56.0);
    expect(tester.getSize(findFirstContainerFor('Frozen yogurt')).height, 48.0);

    // CUSTOM VALUES
    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildCustomTable(headingRowHeight: 48.0)),
    ));
    expect(tester.getSize(findFirstContainerFor('Name')).height, 48.0);

    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildCustomTable(headingRowHeight: 64.0)),
    ));
    expect(tester.getSize(findFirstContainerFor('Name')).height, 64.0);

    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildCustomTable(dataRowHeight: 30.0)),
    ));
    expect(tester.getSize(findFirstContainerFor('Frozen yogurt')).height, 30.0);

    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildCustomTable(dataRowHeight: 56.0)),
    ));
    expect(tester.getSize(findFirstContainerFor('Frozen yogurt')).height, 56.0);
  });

  testWidgets('DataTable custom horizontal padding - checkbox', (WidgetTester tester) async {
    const double defaultHorizontalMargin = 24.0;
    const double defaultColumnSpacing = 56.0;
    const double customHorizontalMargin = 10.0;
    const double customColumnSpacing = 15.0;
    Finder cellContent;
    Finder checkbox;
    Finder padding;

    Widget buildDefaultTable({
      int? sortColumnIndex,
      bool sortAscending = true,
    }) {
      return DataTable(
        sortColumnIndex: sortColumnIndex,
        sortAscending: sortAscending,
        onSelectAll: (bool? value) {},
        columns: <DataColumn>[
          const DataColumn(
            label: Text('Name'),
            tooltip: 'Name',
          ),
          DataColumn(
            label: const Text('Calories'),
            tooltip: 'Calories',
            numeric: true,
            onSort: (int columnIndex, bool ascending) {},
          ),
          DataColumn(
            label: const Text('Fat'),
            tooltip: 'Fat',
            numeric: true,
            onSort: (int columnIndex, bool ascending) {},
          ),
        ],
        rows: kDesserts.map<DataRow>((Dessert dessert) {
          return DataRow(
            key: ValueKey<String>(dessert.name),
            onSelectChanged: (bool? selected) {},
            cells: <DataCell>[
              DataCell(
                Text(dessert.name),
              ),
              DataCell(
                Text('${dessert.calories}'),
                showEditIcon: true,
                onTap: () {},
              ),
              DataCell(
                Text('${dessert.fat}'),
                showEditIcon: true,
                onTap: () {},
              ),
            ],
          );
        }).toList(),
      );
    }

    // DEFAULT VALUES
    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildDefaultTable()),
    ));

    // default checkbox padding
    checkbox = find.byType(Checkbox).first;
    padding = find.ancestor(of: checkbox, matching: find.byType(Padding));
    expect(
      tester.getRect(checkbox).left - tester.getRect(padding).left,
      defaultHorizontalMargin,
    );
    expect(
      tester.getRect(padding).right - tester.getRect(checkbox).right,
      defaultHorizontalMargin / 2,
    );

    // default first column padding
    padding = find.widgetWithText(Padding, 'Frozen yogurt');
    cellContent = find.widgetWithText(Align, 'Frozen yogurt'); // DataTable wraps its DataCells in an Align widget
    expect(
      tester.getRect(cellContent).left - tester.getRect(padding).left,
      defaultHorizontalMargin / 2,
    );
    expect(
      tester.getRect(padding).right - tester.getRect(cellContent).right,
      defaultColumnSpacing / 2,
    );

    // default middle column padding
    padding = find.widgetWithText(Padding, '159');
    cellContent = find.widgetWithText(Align, '159');
    expect(
      tester.getRect(cellContent).left - tester.getRect(padding).left,
      defaultColumnSpacing / 2,
    );
    expect(
      tester.getRect(padding).right - tester.getRect(cellContent).right,
      defaultColumnSpacing / 2,
    );

    // default last column padding
    padding = find.widgetWithText(Padding, '6.0');
    cellContent = find.widgetWithText(Align, '6.0');
    expect(
      tester.getRect(cellContent).left - tester.getRect(padding).left,
      defaultColumnSpacing / 2,
    );
    expect(
      tester.getRect(padding).right - tester.getRect(cellContent).right,
      defaultHorizontalMargin,
    );

    Widget buildCustomTable({
      int? sortColumnIndex,
      bool sortAscending = true,
      double? horizontalMargin,
      double? columnSpacing,
    }) {
      return DataTable(
        sortColumnIndex: sortColumnIndex,
        sortAscending: sortAscending,
        onSelectAll: (bool? value) {},
        horizontalMargin: horizontalMargin,
        columnSpacing: columnSpacing,
        columns: <DataColumn>[
          const DataColumn(
            label: Text('Name'),
            tooltip: 'Name',
          ),
          DataColumn(
            label: const Text('Calories'),
            tooltip: 'Calories',
            numeric: true,
            onSort: (int columnIndex, bool ascending) {},
          ),
          DataColumn(
            label: const Text('Fat'),
            tooltip: 'Fat',
            numeric: true,
            onSort: (int columnIndex, bool ascending) {},
          ),
        ],
        rows: kDesserts.map<DataRow>((Dessert dessert) {
          return DataRow(
            key: ValueKey<String>(dessert.name),
            onSelectChanged: (bool? selected) {},
            cells: <DataCell>[
              DataCell(
                Text(dessert.name),
              ),
              DataCell(
                Text('${dessert.calories}'),
                showEditIcon: true,
                onTap: () {},
              ),
              DataCell(
                Text('${dessert.fat}'),
                showEditIcon: true,
                onTap: () {},
              ),
            ],
          );
        }).toList(),
      );
    }

    // CUSTOM VALUES
    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildCustomTable(
        horizontalMargin: customHorizontalMargin,
        columnSpacing: customColumnSpacing,
      )),
    ));

    // custom checkbox padding
    checkbox = find.byType(Checkbox).first;
    padding = find.ancestor(of: checkbox, matching: find.byType(Padding));
    expect(
      tester.getRect(checkbox).left - tester.getRect(padding).left,
      customHorizontalMargin,
    );
    expect(
      tester.getRect(padding).right - tester.getRect(checkbox).right,
      customHorizontalMargin / 2,
    );

    // custom first column padding
    padding = find.widgetWithText(Padding, 'Frozen yogurt').first;
    cellContent = find.widgetWithText(Align, 'Frozen yogurt'); // DataTable wraps its DataCells in an Align widget
    expect(
      tester.getRect(cellContent).left - tester.getRect(padding).left,
      customHorizontalMargin / 2,
    );
    expect(
      tester.getRect(padding).right - tester.getRect(cellContent).right,
      customColumnSpacing / 2,
    );

    // custom middle column padding
    padding = find.widgetWithText(Padding, '159');
    cellContent = find.widgetWithText(Align, '159');
    expect(
      tester.getRect(cellContent).left - tester.getRect(padding).left,
      customColumnSpacing / 2,
    );
    expect(
      tester.getRect(padding).right - tester.getRect(cellContent).right,
      customColumnSpacing / 2,
    );

    // custom last column padding
    padding = find.widgetWithText(Padding, '6.0');
    cellContent = find.widgetWithText(Align, '6.0');
    expect(
      tester.getRect(cellContent).left - tester.getRect(padding).left,
      customColumnSpacing / 2,
    );
    expect(
      tester.getRect(padding).right - tester.getRect(cellContent).right,
      customHorizontalMargin,
    );
  });

  testWidgets('DataTable custom horizontal padding - no checkbox', (WidgetTester tester) async {
    const double defaultHorizontalMargin = 24.0;
    const double defaultColumnSpacing = 56.0;
    const double customHorizontalMargin = 10.0;
    const double customColumnSpacing = 15.0;
    Finder cellContent;
    Finder padding;

    Widget buildDefaultTable({
      int? sortColumnIndex,
      bool sortAscending = true,
    }) {
      return DataTable(
        sortColumnIndex: sortColumnIndex,
        sortAscending: sortAscending,
        columns: <DataColumn>[
          const DataColumn(
            label: Text('Name'),
            tooltip: 'Name',
          ),
          DataColumn(
            label: const Text('Calories'),
            tooltip: 'Calories',
            numeric: true,
            onSort: (int columnIndex, bool ascending) {},
          ),
          DataColumn(
            label: const Text('Fat'),
            tooltip: 'Fat',
            numeric: true,
            onSort: (int columnIndex, bool ascending) {},
          ),
        ],
        rows: kDesserts.map<DataRow>((Dessert dessert) {
          return DataRow(
            key: ValueKey<String>(dessert.name),
            cells: <DataCell>[
              DataCell(
                Text(dessert.name),
              ),
              DataCell(
                Text('${dessert.calories}'),
                showEditIcon: true,
                onTap: () {},
              ),
              DataCell(
                Text('${dessert.fat}'),
                showEditIcon: true,
                onTap: () {},
              ),
            ],
          );
        }).toList(),
      );
    }

    // DEFAULT VALUES
    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildDefaultTable()),
    ));

    // default first column padding
    padding = find.widgetWithText(Padding, 'Frozen yogurt');
    cellContent = find.widgetWithText(Align, 'Frozen yogurt'); // DataTable wraps its DataCells in an Align widget
    expect(
      tester.getRect(cellContent).left - tester.getRect(padding).left,
      defaultHorizontalMargin,
    );
    expect(
      tester.getRect(padding).right - tester.getRect(cellContent).right,
      defaultColumnSpacing / 2,
    );

    // default middle column padding
    padding = find.widgetWithText(Padding, '159');
    cellContent = find.widgetWithText(Align, '159');
    expect(
      tester.getRect(cellContent).left - tester.getRect(padding).left,
      defaultColumnSpacing / 2,
    );
    expect(
      tester.getRect(padding).right - tester.getRect(cellContent).right,
      defaultColumnSpacing / 2,
    );

    // default last column padding
    padding = find.widgetWithText(Padding, '6.0');
    cellContent = find.widgetWithText(Align, '6.0');
    expect(
      tester.getRect(cellContent).left - tester.getRect(padding).left,
      defaultColumnSpacing / 2,
    );
    expect(
      tester.getRect(padding).right - tester.getRect(cellContent).right,
      defaultHorizontalMargin,
    );

    Widget buildCustomTable({
      int? sortColumnIndex,
      bool sortAscending = true,
      double? horizontalMargin,
      double? columnSpacing,
    }) {
      return DataTable(
        sortColumnIndex: sortColumnIndex,
        sortAscending: sortAscending,
        horizontalMargin: horizontalMargin,
        columnSpacing: columnSpacing,
        columns: <DataColumn>[
          const DataColumn(
            label: Text('Name'),
            tooltip: 'Name',
          ),
          DataColumn(
            label: const Text('Calories'),
            tooltip: 'Calories',
            numeric: true,
            onSort: (int columnIndex, bool ascending) {},
          ),
          DataColumn(
            label: const Text('Fat'),
            tooltip: 'Fat',
            numeric: true,
            onSort: (int columnIndex, bool ascending) {},
          ),
        ],
        rows: kDesserts.map<DataRow>((Dessert dessert) {
          return DataRow(
            key: ValueKey<String>(dessert.name),
            cells: <DataCell>[
              DataCell(
                Text(dessert.name),
              ),
              DataCell(
                Text('${dessert.calories}'),
                showEditIcon: true,
                onTap: () {},
              ),
              DataCell(
                Text('${dessert.fat}'),
                showEditIcon: true,
                onTap: () {},
              ),
            ],
          );
        }).toList(),
      );
    }

    // CUSTOM VALUES
    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildCustomTable(
        horizontalMargin: customHorizontalMargin,
        columnSpacing: customColumnSpacing,
      )),
    ));

    // custom first column padding
    padding = find.widgetWithText(Padding, 'Frozen yogurt');
    cellContent = find.widgetWithText(Align, 'Frozen yogurt'); // DataTable wraps its DataCells in an Align widget
    expect(
      tester.getRect(cellContent).left - tester.getRect(padding).left,
      customHorizontalMargin,
    );
    expect(
      tester.getRect(padding).right - tester.getRect(cellContent).right,
      customColumnSpacing / 2,
    );

    // custom middle column padding
    padding = find.widgetWithText(Padding, '159');
    cellContent = find.widgetWithText(Align, '159');
    expect(
      tester.getRect(cellContent).left - tester.getRect(padding).left,
      customColumnSpacing / 2,
    );
    expect(
      tester.getRect(padding).right - tester.getRect(cellContent).right,
      customColumnSpacing / 2,
    );

    // custom last column padding
    padding = find.widgetWithText(Padding, '6.0');
    cellContent = find.widgetWithText(Align, '6.0');
    expect(
      tester.getRect(cellContent).left - tester.getRect(padding).left,
      customColumnSpacing / 2,
    );
    expect(
      tester.getRect(padding).right - tester.getRect(cellContent).right,
      customHorizontalMargin,
    );
  });

  testWidgets('DataTable set border width test', (WidgetTester tester) async {
    const List<DataColumn> columns = <DataColumn>[
      DataColumn(label: Text('column1')),
      DataColumn(label: Text('column2')),
    ];

    const List<DataCell> cells = <DataCell>[
      DataCell(Text('cell1')),
      DataCell(Text('cell2')),
    ];

    const List<DataRow> rows = <DataRow>[
      DataRow(cells: cells),
      DataRow(cells: cells),
    ];

    // no thickness provided - border should be default: i.e "1.0" as it
    // set in DataTable constructor
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: DataTable(
            columns: columns,
            rows: rows,
          ),
        ),
      ),
    );

    Table table = tester.widget(find.byType(Table));
    TableRow tableRow = table.children.last;
    BoxDecoration boxDecoration = tableRow.decoration! as BoxDecoration;
    expect(boxDecoration.border!.top.width, 1.0);

    const double thickness =  4.2;
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: DataTable(
            dividerThickness: thickness,
            columns: columns,
            rows: rows,
          ),
        ),
      ),
    );
    table = tester.widget(find.byType(Table));
    tableRow = table.children.last;
    boxDecoration = tableRow.decoration! as BoxDecoration;
    expect(boxDecoration.border!.top.width, thickness);
  });

  testWidgets('DataTable set show bottom border', (WidgetTester tester) async {
    const List<DataColumn> columns = <DataColumn>[
      DataColumn(label: Text('column1')),
      DataColumn(label: Text('column2')),
    ];

    const List<DataCell> cells = <DataCell>[
      DataCell(Text('cell1')),
      DataCell(Text('cell2')),
    ];

    const List<DataRow> rows = <DataRow>[
      DataRow(cells: cells),
      DataRow(cells: cells),
    ];

    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: DataTable(
            showBottomBorder: true,
            columns: columns,
            rows: rows,
          ),
        ),
      ),
    );

    Table table = tester.widget(find.byType(Table));
    TableRow tableRow = table.children.last;
    BoxDecoration boxDecoration = tableRow.decoration! as BoxDecoration;
    expect(boxDecoration.border!.bottom.width, 1.0);

    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: DataTable(
            columns: columns,
            rows: rows,
          ),
        ),
      ),
    );
    table = tester.widget(find.byType(Table));
    tableRow = table.children.last;
    boxDecoration = tableRow.decoration! as BoxDecoration;
    expect(boxDecoration.border!.bottom.width, 0.0);
  });

  testWidgets('DataTable column heading cell - with and without sorting', (WidgetTester tester) async {
    Widget buildTable({ int? sortColumnIndex, bool sortEnabled = true }) {
      return DataTable(
        sortColumnIndex: sortColumnIndex,
        columns: <DataColumn>[
          DataColumn(
            label: const Expanded(child: Center(child: Text('Name'))),
            tooltip: 'Name',
            onSort: sortEnabled ? (_, __) {} : null,
          ),
        ],
        rows: const <DataRow>[
          DataRow(
            cells: <DataCell>[
              DataCell(Text('A long desert name')),
            ],
          ),
        ],
      );
    }

    // Start with without sorting
    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildTable(
        sortEnabled: false,
      )),
    ));

    {
      final Finder nameText = find.text('Name');
      expect(nameText, findsOneWidget);
      final Finder nameCell = find.ancestor(of: find.text('Name'), matching: find.byType(Container)).first;
      expect(tester.getCenter(nameText), equals(tester.getCenter(nameCell)));
      expect(find.descendant(of: nameCell, matching: find.byType(Icon)), findsNothing);
    }

    // Turn on sorting
    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildTable()),
    ));

    {
      final Finder nameText = find.text('Name');
      expect(nameText, findsOneWidget);
      final Finder nameCell = find.ancestor(of: find.text('Name'), matching: find.byType(Container)).first;
      expect(find.descendant(of: nameCell, matching: find.byType(Icon)), findsOneWidget);
    }

    // Turn off sorting again
    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildTable(
        sortEnabled: false,
      )),
    ));

    {
      final Finder nameText = find.text('Name');
      expect(nameText, findsOneWidget);
      final Finder nameCell = find.ancestor(of: find.text('Name'), matching: find.byType(Container)).first;
      expect(tester.getCenter(nameText), equals(tester.getCenter(nameCell)));
      expect(find.descendant(of: nameCell, matching: find.byType(Icon)), findsNothing);
    }
  });

  testWidgets('DataTable correctly renders with a mouse', (WidgetTester tester) async {
    // Regression test for a bug described in
    // https://github.com/flutter/flutter/pull/43735#issuecomment-589459947
    // Filed at https://github.com/flutter/flutter/issues/51152
    Widget buildTable({ int? sortColumnIndex }) {
      return DataTable(
        sortColumnIndex: sortColumnIndex,
        columns: <DataColumn>[
          const DataColumn(
            label: Expanded(child: Center(child: Text('column1'))),
            tooltip: 'Column1',
          ),
          DataColumn(
            label: const Expanded(child: Center(child: Text('column2'))),
            tooltip: 'Column2',
            onSort: (_, __) {},
          ),
        ],
        rows: const <DataRow>[
          DataRow(
            cells: <DataCell>[
              DataCell(Text('Content1')),
              DataCell(Text('Content2')),
            ],
          ),
        ],
      );
    }

    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildTable()),
    ));

    expect(tester.renderObject(find.text('column1')).attached, true);
    expect(tester.renderObject(find.text('column2')).attached, true);

    final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
    await gesture.addPointer(location: Offset.zero);

    await tester.pumpAndSettle();
    expect(tester.renderObject(find.text('column1')).attached, true);
    expect(tester.renderObject(find.text('column2')).attached, true);

    // Wait for the tooltip timer to expire to prevent it scheduling a new frame
    // after the view is destroyed, which causes exceptions.
    await tester.pumpAndSettle(const Duration(seconds: 1));
  });

  testWidgets('DataRow renders default selected row colors', (WidgetTester tester) async {
    final ThemeData themeData = ThemeData.light();
    Widget buildTable({bool selected = false}) {
      return MaterialApp(
        theme: themeData,
        home: Material(
          child: DataTable(
            columns: const <DataColumn>[
              DataColumn(
                label: Text('Column1'),
              ),
            ],
            rows: <DataRow>[
              DataRow(
                onSelectChanged: (bool? checked) {},
                selected: selected,
                cells: const <DataCell>[
                  DataCell(Text('Content1')),
                ],
              ),
            ],
          ),
        ),
      );
    }

    BoxDecoration lastTableRowBoxDecoration() {
      final Table table = tester.widget(find.byType(Table));
      final TableRow tableRow = table.children.last;
      return tableRow.decoration! as BoxDecoration;
    }

    await tester.pumpWidget(buildTable());
    expect(lastTableRowBoxDecoration().color, null);

    await tester.pumpWidget(buildTable(selected: true));
    expect(
      lastTableRowBoxDecoration().color,
      themeData.colorScheme.primary.withOpacity(0.08),
    );
  });

  testWidgets('DataRow renders checkbox with colors from CheckboxTheme', (WidgetTester tester) async {
    const Color fillColor = Color(0xFF00FF00);
    const Color checkColor = Color(0xFF0000FF);

    final ThemeData themeData = ThemeData(
      checkboxTheme: const CheckboxThemeData(
        fillColor: MaterialStatePropertyAll<Color?>(fillColor),
        checkColor: MaterialStatePropertyAll<Color?>(checkColor),
      ),
    );
    Widget buildTable() {
      return MaterialApp(
        theme: themeData,
        home: Material(
          child: DataTable(
            columns: const <DataColumn>[
              DataColumn(
                label: Text('Column1'),
              ),
            ],
            rows: <DataRow>[
              DataRow(
                selected: true,
                onSelectChanged: (bool? checked) {},
                cells: const <DataCell>[
                  DataCell(Text('Content1')),
                ],
              ),
            ],
          ),
        ),
      );
    }

    await tester.pumpWidget(buildTable());

    expect(
      Material.of(tester.element(find.byType(Checkbox).last)),
      paints
        ..path()
        ..path(color: fillColor)
        ..path(color: checkColor),
    );
  });

  testWidgets('DataRow renders custom colors when selected', (WidgetTester tester) async {
    const Color selectedColor = Colors.green;
    const Color defaultColor = Colors.red;

    Widget buildTable({bool selected = false}) {
      return Material(
        child: DataTable(
          columns: const <DataColumn>[
            DataColumn(
              label: Text('Column1'),
            ),
          ],
          rows: <DataRow>[
            DataRow(
              selected: selected,
              color: MaterialStateProperty.resolveWith<Color>(
                    (Set<MaterialState> states) {
                  if (states.contains(MaterialState.selected)) {
                    return selectedColor;
                  }
                  return defaultColor;
                },
              ),
              cells: const <DataCell>[
                DataCell(Text('Content1')),
              ],
            ),
          ],
        ),
      );
    }

    BoxDecoration lastTableRowBoxDecoration() {
      final Table table = tester.widget(find.byType(Table));
      final TableRow tableRow = table.children.last;
      return tableRow.decoration! as BoxDecoration;
    }

    await tester.pumpWidget(MaterialApp(
      home: buildTable(),
    ));
    expect(lastTableRowBoxDecoration().color, defaultColor);

    await tester.pumpWidget(MaterialApp(
      home: buildTable(selected: true),
    ));
    expect(lastTableRowBoxDecoration().color, selectedColor);
  });

  testWidgets('DataRow renders custom colors when disabled', (WidgetTester tester) async {
    const Color disabledColor = Colors.grey;
    const Color defaultColor = Colors.red;

    Widget buildTable({bool disabled = false}) {
      return Material(
        child: DataTable(
          columns: const <DataColumn>[
            DataColumn(
              label: Text('Column1'),
            ),
          ],
          rows: <DataRow>[
            DataRow(
              cells: const <DataCell>[
                DataCell(Text('Content1')),
              ],
              onSelectChanged: (bool? value) {},
            ),
            DataRow(
              color: MaterialStateProperty.resolveWith<Color>(
                    (Set<MaterialState> states) {
                  if (states.contains(MaterialState.disabled)) {
                    return disabledColor;
                  }
                  return defaultColor;
                },
              ),
              cells: const <DataCell>[
                DataCell(Text('Content2')),
              ],
              onSelectChanged: disabled ? null : (bool? value) {},
            ),
          ],
        ),
      );
    }

    BoxDecoration lastTableRowBoxDecoration() {
      final Table table = tester.widget(find.byType(Table));
      final TableRow tableRow = table.children.last;
      return tableRow.decoration! as BoxDecoration;
    }

    await tester.pumpWidget(MaterialApp(
      home: buildTable(),
    ));
    expect(lastTableRowBoxDecoration().color, defaultColor);

    await tester.pumpWidget(MaterialApp(
      home: buildTable(disabled: true),
    ));
    expect(lastTableRowBoxDecoration().color, disabledColor);
  });

  testWidgets('DataRow renders custom colors when pressed', (WidgetTester tester) async {
    const Color pressedColor = Color(0xff4caf50);
    Widget buildTable() {
      return DataTable(
        columns: const <DataColumn>[
          DataColumn(
            label: Text('Column1'),
          ),
        ],
        rows: <DataRow>[
          DataRow(
            color: MaterialStateProperty.resolveWith<Color>(
              (Set<MaterialState> states) {
                if (states.contains(MaterialState.pressed)) {
                  return pressedColor;
                }
                return Colors.transparent;
              },
            ),
            onSelectChanged: (bool? value) {},
            cells: const <DataCell>[
              DataCell(Text('Content1')),
            ],
          ),
        ],
      );
    }

    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildTable()),
    ));

    final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('Content1')));
    await tester.pump(const Duration(milliseconds: 200)); // splash is well underway
    final RenderBox box = Material.of(tester.element(find.byType(InkWell)))! as RenderBox;
    expect(box, paints..circle(x: 68.0, y: 24.0, color: pressedColor));
    await gesture.up();
  });

  testWidgets('DataTable can render inside an AlertDialog', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: AlertDialog(
            content: DataTable(
              columns: const <DataColumn>[
                DataColumn(label: Text('Col1')),
              ],
              rows: const <DataRow>[
                DataRow(cells: <DataCell>[DataCell(Text('1'))]),
              ],
            ),
            scrollable: true,
          ),
        ),
      ),
    );

    expect(tester.takeException(), isNull);
  });

  testWidgets('DataTable renders with border and background decoration', (WidgetTester tester) async {
    const double width = 800;
    const double height = 600;
    const double borderHorizontal = 5.0;
    const double borderVertical = 10.0;
    const Color borderColor = Color(0xff2196f3);
    const Color backgroundColor = Color(0xfff5f5f5);

    await tester.pumpWidget(
      MaterialApp(
        home: DataTable(
          decoration: const BoxDecoration(
            color: backgroundColor,
            border: Border.symmetric(
              vertical: BorderSide(width: borderVertical, color: borderColor),
              horizontal: BorderSide(width: borderHorizontal, color: borderColor),
            ),
          ),
          columns: const <DataColumn>[
            DataColumn(label: Text('Col1')),
          ],
          rows: const <DataRow>[
            DataRow(cells: <DataCell>[DataCell(Text('1'))]),
          ],
        ),
      ),
    );

    expect(
      find.ancestor(of: find.byType(Table), matching: find.byType(Container)),
      paints..rect(
        rect: const Rect.fromLTRB(0.0, 0.0, width, height),
        color: backgroundColor,
      ),
    );
    expect(
      find.ancestor(of: find.byType(Table), matching: find.byType(Container)),
      paints
        ..path(color: borderColor)
        ..path(color: borderColor)
        ..path(color: borderColor)
        ..path(color: borderColor),
    );
    expect(
      tester.getTopLeft(find.byType(Table)),
      const Offset(borderVertical, borderHorizontal),
    );
    expect(
      tester.getBottomRight(find.byType(Table)),
      const Offset(width - borderVertical, height - borderHorizontal),
    );
  });

  testWidgets('checkboxHorizontalMargin properly applied', (WidgetTester tester) async {
    const double customCheckboxHorizontalMargin = 15.0;
    const double customHorizontalMargin = 10.0;
    Finder cellContent;
    Finder checkbox;
    Finder padding;

    Widget buildCustomTable({
      int? sortColumnIndex,
      bool sortAscending = true,
      double? horizontalMargin,
      double? checkboxHorizontalMargin,
    }) {
      return DataTable(
        sortColumnIndex: sortColumnIndex,
        sortAscending: sortAscending,
        onSelectAll: (bool? value) {},
        horizontalMargin: horizontalMargin,
        checkboxHorizontalMargin: checkboxHorizontalMargin,
        columns: <DataColumn>[
          const DataColumn(
            label: Text('Name'),
            tooltip: 'Name',
          ),
          DataColumn(
            label: const Text('Calories'),
            tooltip: 'Calories',
            numeric: true,
            onSort: (int columnIndex, bool ascending) {},
          ),
          DataColumn(
            label: const Text('Fat'),
            tooltip: 'Fat',
            numeric: true,
            onSort: (int columnIndex, bool ascending) {},
          ),
        ],
        rows: kDesserts.map<DataRow>((Dessert dessert) {
          return DataRow(
            key: ValueKey<String>(dessert.name),
            onSelectChanged: (bool? selected) {},
            cells: <DataCell>[
              DataCell(
                Text(dessert.name),
              ),
              DataCell(
                Text('${dessert.calories}'),
                showEditIcon: true,
                onTap: () {},
              ),
              DataCell(
                Text('${dessert.fat}'),
                showEditIcon: true,
                onTap: () {},
              ),
            ],
          );
        }).toList(),
      );
    }

    await tester.pumpWidget(MaterialApp(
      home: Material(child: buildCustomTable(
        checkboxHorizontalMargin: customCheckboxHorizontalMargin,
        horizontalMargin: customHorizontalMargin,
      )),
    ));

    // Custom checkbox padding.
    checkbox = find.byType(Checkbox).first;
    padding = find.ancestor(of: checkbox, matching: find.byType(Padding));
    expect(
      tester.getRect(checkbox).left - tester.getRect(padding).left,
      customCheckboxHorizontalMargin,
    );
    expect(
      tester.getRect(padding).right - tester.getRect(checkbox).right,
      customCheckboxHorizontalMargin,
    );

    // First column padding.
    padding = find.widgetWithText(Padding, 'Frozen yogurt').first;
    cellContent = find.widgetWithText(Align, 'Frozen yogurt'); // DataTable wraps its DataCells in an Align widget.
    expect(
      tester.getRect(cellContent).left - tester.getRect(padding).left,
      customHorizontalMargin,
    );
  });

  testWidgets('DataRow is disabled when onSelectChanged is not set', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: DataTable(
            columns: const <DataColumn>[
              DataColumn(label: Text('Col1')),
              DataColumn(label: Text('Col2')),
            ],
            rows: <DataRow>[
              DataRow(cells: const <DataCell>[
                DataCell(Text('Hello')),
                DataCell(Text('world')),
              ],
              onSelectChanged: (bool? value) {},
              ),
              const DataRow(cells: <DataCell>[
                DataCell(Text('Bug')),
                DataCell(Text('report')),
              ]),
              const DataRow(cells: <DataCell>[
                DataCell(Text('GitHub')),
                DataCell(Text('issue')),
              ]),
            ],
          ),
        ),
      ),
    );

    expect(find.widgetWithText(TableRowInkWell, 'Hello'), findsOneWidget);
    expect(find.widgetWithText(TableRowInkWell, 'Bug'), findsNothing);
    expect(find.widgetWithText(TableRowInkWell, 'GitHub'), findsNothing);
  });

  testWidgets('DataTable set interior border test', (WidgetTester tester) async {
    const List<DataColumn> columns = <DataColumn>[
      DataColumn(label: Text('column1')),
      DataColumn(label: Text('column2')),
    ];

    const List<DataCell> cells = <DataCell>[
      DataCell(Text('cell1')),
      DataCell(Text('cell2')),
    ];

    const List<DataRow> rows = <DataRow>[
      DataRow(cells: cells),
      DataRow(cells: cells),
    ];

    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: DataTable(
            border: TableBorder.all(width: 2, color: Colors.red),
            columns: columns,
            rows: rows,
          ),
        ),
      ),
    );

    final Finder finder = find.byType(DataTable);
    expect(tester.getSize(finder), equals(const Size(800, 600)));

    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: DataTable(
            border: TableBorder.all(color: Colors.red),
            columns: columns,
            rows: rows,
          ),
        ),
      ),
    );

    Table table = tester.widget(find.byType(Table));
    TableBorder? tableBorder = table.border;
    expect(tableBorder!.top.color, Colors.red);
    expect(tableBorder.bottom.width, 1);

    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: DataTable(
            columns: columns,
            rows: rows,
          ),
        ),
      ),
    );

    table = tester.widget(find.byType(Table));
    tableBorder = table.border;
    expect(tableBorder?.bottom.width, null);
    expect(tableBorder?.top.color, null);
  });

  // Regression test for https://github.com/flutter/flutter/issues/100952
  testWidgets('Do not crashes when paint borders in a narrow space', (WidgetTester tester) async {
    const List<DataColumn> columns = <DataColumn>[
      DataColumn(label: Text('column1')),
      DataColumn(label: Text('column2')),
    ];

    const List<DataCell> cells = <DataCell>[
      DataCell(Text('cell1')),
      DataCell(Text('cell2')),
    ];

    const List<DataRow> rows = <DataRow>[
      DataRow(cells: cells),
      DataRow(cells: cells),
    ];

    await tester.pumpWidget(
      MaterialApp(
        home: Material(
          child: Center(
            child: SizedBox(
              width: 117.0,
              child: DataTable(
                border: TableBorder.all(width: 2, color: Colors.red),
                columns: columns,
                rows: rows,
              ),
            ),
          ),
        ),
      ),
    );

    // Go without crashes.

  });
}
