mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Test PaginatedDataTable (#7594)
This patch contains some basic tests for PaginatedDataTable.
This commit is contained in:
parent
4bec9cd940
commit
134096022c
@ -84,8 +84,11 @@ class PaginatedDataTable extends StatefulWidget {
|
||||
assert(sortAscending != null);
|
||||
assert(rowsPerPage != null);
|
||||
assert(rowsPerPage > 0);
|
||||
assert(availableRowsPerPage != null);
|
||||
assert(availableRowsPerPage.contains(rowsPerPage));
|
||||
assert(() {
|
||||
if (onRowsPerPageChanged != null)
|
||||
assert(availableRowsPerPage != null && availableRowsPerPage.contains(rowsPerPage));
|
||||
return true;
|
||||
});
|
||||
assert(source != null);
|
||||
}
|
||||
|
||||
@ -346,6 +349,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
|
||||
new IconButton(
|
||||
icon: new Icon(Icons.chevron_left),
|
||||
padding: EdgeInsets.zero,
|
||||
tooltip: 'Previous page',
|
||||
onPressed: _firstRowIndex <= 0 ? null : () {
|
||||
pageTo(math.max(_firstRowIndex - config.rowsPerPage, 0));
|
||||
}
|
||||
@ -354,6 +358,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
|
||||
new IconButton(
|
||||
icon: new Icon(Icons.chevron_right),
|
||||
padding: EdgeInsets.zero,
|
||||
tooltip: 'Next page',
|
||||
onPressed: (!_rowCountApproximate && (_firstRowIndex + config.rowsPerPage >= _rowCount)) ? null : () {
|
||||
pageTo(_firstRowIndex + config.rowsPerPage);
|
||||
}
|
||||
@ -363,7 +368,8 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
|
||||
|
||||
// CARD
|
||||
return new Card(
|
||||
child: new BlockBody(
|
||||
child: new Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
new DefaultTextStyle(
|
||||
// These typographic styles aren't quite the regular ones. We pick the closest ones from the regular
|
||||
|
192
packages/flutter/test/material/paginated_data_table_test.dart
Normal file
192
packages/flutter/test/material/paginated_data_table_test.dart
Normal file
@ -0,0 +1,192 @@
|
||||
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'data_table_test.dart' show Dessert, kDesserts;
|
||||
|
||||
class TestDataSource extends DataTableSource {
|
||||
int get generation => _generation;
|
||||
int _generation = 0;
|
||||
set generation(int value) {
|
||||
if (_generation == value)
|
||||
return;
|
||||
_generation = value;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@override
|
||||
DataRow getRow(int index) {
|
||||
final Dessert dessert = kDesserts[index % kDesserts.length];
|
||||
final int page = index ~/ kDesserts.length;
|
||||
return new DataRow.byIndex(
|
||||
index: index,
|
||||
cells: <DataCell>[
|
||||
new DataCell(new Text('${dessert.name} ($page)')),
|
||||
new DataCell(new Text('${dessert.calories}')),
|
||||
new DataCell(new Text('$generation')),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
int get rowCount => 500 * kDesserts.length;
|
||||
|
||||
@override
|
||||
bool get isRowCountApproximate => false;
|
||||
|
||||
@override
|
||||
int get selectedRowCount => 0;
|
||||
}
|
||||
|
||||
void main() {
|
||||
testWidgets('PaginatedDataTable control test', (WidgetTester tester) async {
|
||||
TestDataSource source = new TestDataSource()
|
||||
..generation = 42;
|
||||
|
||||
List<String> log = <String>[];
|
||||
|
||||
Widget buildTable(TestDataSource source) {
|
||||
return new PaginatedDataTable(
|
||||
header: new Text('Test table'),
|
||||
source: source,
|
||||
onPageChanged: (int rowIndex) {
|
||||
log.add('page-changed: $rowIndex');
|
||||
},
|
||||
columns: <DataColumn>[
|
||||
new DataColumn(
|
||||
label: new Text('Name'),
|
||||
tooltip: 'Name',
|
||||
),
|
||||
new DataColumn(
|
||||
label: new Text('Calories'),
|
||||
tooltip: 'Calories',
|
||||
numeric: true,
|
||||
onSort: (int columnIndex, bool ascending) {
|
||||
log.add('column-sort: $columnIndex $ascending');
|
||||
}
|
||||
),
|
||||
new DataColumn(
|
||||
label: new Text('Generation'),
|
||||
tooltip: 'Generation',
|
||||
),
|
||||
],
|
||||
actions: <Widget>[
|
||||
new IconButton(
|
||||
icon: new Icon(Icons.adjust),
|
||||
onPressed: () {
|
||||
log.add('action: adjust');
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(new MaterialApp(
|
||||
home: buildTable(source),
|
||||
));
|
||||
|
||||
expect(find.text('Gingerbread (0)'), findsOneWidget);
|
||||
expect(find.text('Gingerbread (1)'), findsNothing);
|
||||
expect(find.text('42'), findsNWidgets(10));
|
||||
|
||||
source.generation = 43;
|
||||
await tester.pump();
|
||||
|
||||
expect(find.text('42'), findsNothing);
|
||||
expect(find.text('43'), findsNWidgets(10));
|
||||
|
||||
source = new TestDataSource()
|
||||
..generation = 15;
|
||||
|
||||
await tester.pumpWidget(new MaterialApp(
|
||||
home: buildTable(source),
|
||||
));
|
||||
|
||||
expect(find.text('42'), findsNothing);
|
||||
expect(find.text('43'), findsNothing);
|
||||
expect(find.text('15'), findsNWidgets(10));
|
||||
|
||||
PaginatedDataTableState state = tester.state(find.byType(PaginatedDataTable));
|
||||
|
||||
expect(log, isEmpty);
|
||||
state.pageTo(23);
|
||||
expect(log, <String>['page-changed: 20']);
|
||||
log.clear();
|
||||
|
||||
await tester.pump();
|
||||
|
||||
expect(find.text('Gingerbread (0)'), findsNothing);
|
||||
expect(find.text('Gingerbread (1)'), findsNothing);
|
||||
expect(find.text('Gingerbread (2)'), findsOneWidget);
|
||||
|
||||
await tester.tap(find.icon(Icons.adjust));
|
||||
expect(log, <String>['action: adjust']);
|
||||
log.clear();
|
||||
});
|
||||
|
||||
testWidgets('PaginatedDataTable paging', (WidgetTester tester) async {
|
||||
TestDataSource source = new TestDataSource();
|
||||
|
||||
List<String> log = <String>[];
|
||||
|
||||
await tester.pumpWidget(new MaterialApp(
|
||||
home: new PaginatedDataTable(
|
||||
header: new Text('Test table'),
|
||||
source: source,
|
||||
rowsPerPage: 2,
|
||||
availableRowsPerPage: <int>[
|
||||
2, 4, 8, 16,
|
||||
],
|
||||
onRowsPerPageChanged: (int rowsPerPage) {
|
||||
log.add('rows-per-page-changed: $rowsPerPage');
|
||||
},
|
||||
onPageChanged: (int rowIndex) {
|
||||
log.add('page-changed: $rowIndex');
|
||||
},
|
||||
columns: <DataColumn>[
|
||||
new DataColumn(label: new Text('Name')),
|
||||
new DataColumn(label: new Text('Calories'), numeric: true),
|
||||
new DataColumn(label: new Text('Generation')),
|
||||
],
|
||||
)
|
||||
));
|
||||
|
||||
await tester.tap(find.byTooltip('Next page'));
|
||||
|
||||
expect(log, <String>['page-changed: 2']);
|
||||
log.clear();
|
||||
|
||||
await tester.pump();
|
||||
|
||||
expect(find.text('Frozen yogurt (0)'), findsNothing);
|
||||
expect(find.text('Eclair (0)'), findsOneWidget);
|
||||
expect(find.text('Gingerbread (0)'), findsNothing);
|
||||
|
||||
await tester.tap(find.icon(Icons.chevron_left));
|
||||
|
||||
expect(log, <String>['page-changed: 0']);
|
||||
log.clear();
|
||||
|
||||
await tester.pump();
|
||||
|
||||
expect(find.text('Frozen yogurt (0)'), findsOneWidget);
|
||||
expect(find.text('Eclair (0)'), findsNothing);
|
||||
expect(find.text('Gingerbread (0)'), findsNothing);
|
||||
|
||||
await tester.tap(find.icon(Icons.chevron_left));
|
||||
|
||||
expect(log, isEmpty);
|
||||
|
||||
await tester.tap(find.text('2'));
|
||||
await tester.pumpUntilNoTransientCallbacks(const Duration(milliseconds: 200));
|
||||
|
||||
await tester.tap(find.text('8').last);
|
||||
await tester.pumpUntilNoTransientCallbacks(const Duration(milliseconds: 200));
|
||||
|
||||
expect(log, <String>['rows-per-page-changed: 8']);
|
||||
log.clear();
|
||||
});
|
||||
}
|
@ -32,6 +32,17 @@ class CommonFinders {
|
||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
||||
Finder text(String text, { bool skipOffstage: true }) => new _TextFinder(text, skipOffstage: skipOffstage);
|
||||
|
||||
/// Finds [Icon] widgets containing icon data equal to the `icon`
|
||||
/// argument.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// expect(tester, hasWidget(find.icon(Icons.chevron_left)));
|
||||
///
|
||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
||||
Finder icon(IconData icon, { bool skipOffstage: true }) => new _IconFinder(icon, skipOffstage: skipOffstage);
|
||||
|
||||
/// Looks for widgets that contain a [Text] descendant with `text`
|
||||
/// in it.
|
||||
///
|
||||
@ -318,6 +329,23 @@ class _TextFinder extends MatchFinder {
|
||||
}
|
||||
}
|
||||
|
||||
class _IconFinder extends MatchFinder {
|
||||
_IconFinder(this.icon, { bool skipOffstage: true }) : super(skipOffstage: skipOffstage);
|
||||
|
||||
final IconData icon;
|
||||
|
||||
@override
|
||||
String get description => 'icon "$icon"';
|
||||
|
||||
@override
|
||||
bool matches(Element candidate) {
|
||||
if (candidate.widget is! Icon)
|
||||
return false;
|
||||
Icon iconWidget = candidate.widget;
|
||||
return iconWidget.icon == icon;
|
||||
}
|
||||
}
|
||||
|
||||
class _WidgetWithTextFinder extends Finder {
|
||||
_WidgetWithTextFinder(this.widgetType, this.text, { bool skipOffstage: true }) : super(skipOffstage: skipOffstage);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user