paginated_data_table_test.dart 8.87 KB
Newer Older
1 2 3 4 5 6 7
// 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';

8
import 'data_table_test_utils.dart';
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

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
35
  int get rowCount => 50 * kDesserts.length;
36 37 38 39 40 41 42 43 44

  @override
  bool get isRowCountApproximate => false;

  @override
  int get selectedRowCount => 0;
}

void main() {
45
  testWidgets('PaginatedDataTable paging', (WidgetTester tester) async {
46
    final TestDataSource source = new TestDataSource();
47

48
    final List<String> log = <String>[];
49 50 51

    await tester.pumpWidget(new MaterialApp(
      home: new PaginatedDataTable(
52
        header: const Text('Test table'),
53 54
        source: source,
        rowsPerPage: 2,
55
        availableRowsPerPage: const <int>[
56 57 58 59 60 61 62 63
          2, 4, 8, 16,
        ],
        onRowsPerPageChanged: (int rowsPerPage) {
          log.add('rows-per-page-changed: $rowsPerPage');
        },
        onPageChanged: (int rowIndex) {
          log.add('page-changed: $rowIndex');
        },
64
        columns: const <DataColumn>[
65 66 67
          const DataColumn(label: const Text('Name')),
          const DataColumn(label: const Text('Calories'), numeric: true),
          const DataColumn(label: const Text('Generation')),
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
        ],
      )
    ));

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

83
    await tester.tap(find.byIcon(Icons.chevron_left));
84 85 86 87 88 89 90 91 92 93

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

94
    await tester.tap(find.byIcon(Icons.chevron_left));
95 96 97 98

    expect(log, isEmpty);

    await tester.tap(find.text('2'));
99
    await tester.pumpAndSettle(const Duration(milliseconds: 200));
100 101

    await tester.tap(find.text('8').last);
102
    await tester.pumpAndSettle(const Duration(milliseconds: 200));
103 104 105 106 107

    expect(log, <String>['rows-per-page-changed: 8']);
    log.clear();
  });

108 109 110 111
  testWidgets('PaginatedDataTable control test', (WidgetTester tester) async {
    TestDataSource source = new TestDataSource()
      ..generation = 42;

112
    final List<String> log = <String>[];
113 114 115

    Widget buildTable(TestDataSource source) {
      return new PaginatedDataTable(
116
        header: const Text('Test table'),
117 118 119 120 121
        source: source,
        onPageChanged: (int rowIndex) {
          log.add('page-changed: $rowIndex');
        },
        columns: <DataColumn>[
122 123
          const DataColumn(
            label: const Text('Name'),
124 125 126
            tooltip: 'Name',
          ),
          new DataColumn(
127
            label: const Text('Calories'),
128 129 130 131 132 133
            tooltip: 'Calories',
            numeric: true,
            onSort: (int columnIndex, bool ascending) {
              log.add('column-sort: $columnIndex $ascending');
            }
          ),
134 135
          const DataColumn(
            label: const Text('Generation'),
136 137 138 139 140
            tooltip: 'Generation',
          ),
        ],
        actions: <Widget>[
          new IconButton(
141
            icon: const Icon(Icons.adjust),
142 143 144 145 146 147 148 149 150 151 152 153
            onPressed: () {
              log.add('action: adjust');
            },
          ),
        ],
      );
    }

    await tester.pumpWidget(new MaterialApp(
      home: buildTable(source),
    ));

154
    // the column overflows because we're forcing it to 600 pixels high
155
    expect(tester.takeException(), contains('A RenderFlex overflowed by'));
156

157 158
    expect(find.text('Gingerbread (0)'), findsOneWidget);
    expect(find.text('Gingerbread (1)'), findsNothing);
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
    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));

178
    final PaginatedDataTableState state = tester.state(find.byType(PaginatedDataTable));
179 180 181 182 183 184 185 186

    expect(log, isEmpty);
    state.pageTo(23);
    expect(log, <String>['page-changed: 20']);
    log.clear();

    await tester.pump();

187 188 189
    expect(find.text('Gingerbread (0)'), findsNothing);
    expect(find.text('Gingerbread (1)'), findsNothing);
    expect(find.text('Gingerbread (2)'), findsOneWidget);
190

191
    await tester.tap(find.byIcon(Icons.adjust));
192 193 194
    expect(log, <String>['action: adjust']);
    log.clear();
  });
195 196 197 198 199 200 201

  testWidgets('PaginatedDataTable text alignment', (WidgetTester tester) async {
    await tester.pumpWidget(new MaterialApp(
      home: new PaginatedDataTable(
        header: const Text('HEADER'),
        source: new TestDataSource(),
        rowsPerPage: 8,
202
        availableRowsPerPage: const <int>[
203 204 205
          8, 9,
        ],
        onRowsPerPageChanged: (int rowsPerPage) { },
206
        columns: const <DataColumn>[
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
          const DataColumn(label: const Text('COL1')),
          const DataColumn(label: const Text('COL2')),
          const DataColumn(label: const Text('COL3')),
        ],
      ),
    ));
    expect(find.text('Rows per page:'), findsOneWidget);
    expect(find.text('8'), findsOneWidget);
    expect(tester.getTopRight(find.text('8')).dx, tester.getTopRight(find.text('Rows per page:')).dx + 40.0); // per spec
  });

  testWidgets('PaginatedDataTable with large text', (WidgetTester tester) async {
    final TestDataSource source = new TestDataSource();
    await tester.pumpWidget(new MaterialApp(
      home: new MediaQuery(
        data: const MediaQueryData(
          textScaleFactor: 20.0,
        ),
        child: new PaginatedDataTable(
          header: const Text('HEADER'),
          source: source,
          rowsPerPage: 501,
229
          availableRowsPerPage: const <int>[ 501 ],
230
          onRowsPerPageChanged: (int rowsPerPage) { },
231
          columns: const <DataColumn>[
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
            const DataColumn(label: const Text('COL1')),
            const DataColumn(label: const Text('COL2')),
            const DataColumn(label: const Text('COL3')),
          ],
        ),
      ),
    ));
    // the column overflows because we're forcing it to 600 pixels high
    expect(tester.takeException(), contains('A RenderFlex overflowed by'));
    expect(find.text('Rows per page:'), findsOneWidget);
    // Test that we will show some options in the drop down even if the lowest option is bigger than the source:
    assert(501 > source.rowCount);
    expect(find.text('501'), findsOneWidget);
    // Test that it fits:
    expect(tester.getTopRight(find.text('501')).dx, greaterThanOrEqualTo(tester.getTopRight(find.text('Rows per page:')).dx + 40.0));
  });

  testWidgets('PaginatedDataTable footer scrolls', (WidgetTester tester) async {
    final TestDataSource source = new TestDataSource();
    await tester.pumpWidget(new MaterialApp(
      home: new Align(
        alignment: Alignment.topLeft,
        child: new SizedBox(
          width: 100.0,
          child: new PaginatedDataTable(
            header: const Text('HEADER'),
            source: source,
            rowsPerPage: 5,
260
            availableRowsPerPage: const <int>[ 5 ],
261
            onRowsPerPageChanged: (int rowsPerPage) { },
262
            columns: const <DataColumn>[
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
              const DataColumn(label: const Text('COL1')),
              const DataColumn(label: const Text('COL2')),
              const DataColumn(label: const Text('COL3')),
            ],
          ),
        ),
      ),
    ));
    expect(find.text('Rows per page:'), findsOneWidget);
    expect(tester.getTopLeft(find.text('Rows per page:')).dx, lessThan(0.0)); // off screen
    await tester.dragFrom(
      new Offset(50.0, tester.getTopLeft(find.text('Rows per page:')).dy),
      const Offset(1000.0, 0.0),
    );
    await tester.pump();
    expect(find.text('Rows per page:'), findsOneWidget);
    expect(tester.getTopLeft(find.text('Rows per page:')).dx, 18.0); // 14 padding in the footer row, 4 padding from the card
  });
281
}