Skip to content

Commit 944e01d

Browse files
committed
Restore regression tests
1 parent 02e5823 commit 944e01d

1 file changed

Lines changed: 217 additions & 0 deletions

File tree

packages/two_dimensional_scrollables/test/table_view/table_test.dart

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4176,6 +4176,223 @@ void main() {
41764176
},
41774177
);
41784178

4179+
testWidgets(
4180+
'Merged cells should not unmerge when the first cell is overlaid by a pinned column',
4181+
(WidgetTester tester) async {
4182+
// Regression test for https://github.com/flutter/flutter/issues/174862
4183+
final horizontalController = ScrollController();
4184+
addTearDown(horizontalController.dispose);
4185+
4186+
await tester.pumpWidget(
4187+
MaterialApp(
4188+
home: Scaffold(
4189+
body: SizedBox(
4190+
width: 400,
4191+
height: 400,
4192+
child: TableView.builder(
4193+
cacheExtent: 0.0,
4194+
horizontalDetails: ScrollableDetails.horizontal(
4195+
controller: horizontalController,
4196+
),
4197+
pinnedColumnCount: 1,
4198+
columnCount: 10,
4199+
rowCount: 10,
4200+
columnBuilder: (int index) => TableSpan(
4201+
extent: FixedTableSpanExtent(index == 0 ? 100 : 50),
4202+
),
4203+
rowBuilder: (int index) =>
4204+
const TableSpan(extent: FixedTableSpanExtent(50)),
4205+
cellBuilder: (BuildContext context, TableVicinity vicinity) {
4206+
final isColumn1 = vicinity.column == 1;
4207+
return TableViewCell(
4208+
columnMergeStart: isColumn1 ? 1 : null,
4209+
columnMergeSpan: isColumn1 ? 3 : null,
4210+
child: Center(
4211+
child: Text('Cell ${vicinity.column},${vicinity.row}'),
4212+
),
4213+
);
4214+
},
4215+
),
4216+
),
4217+
),
4218+
),
4219+
);
4220+
4221+
// Initially, column 1 is visible next to pinned column 0.
4222+
expect(find.text('Cell 1,0'), findsOneWidget);
4223+
// Column 2 and 3 should be part of the merge, so they are not built.
4224+
expect(find.text('Cell 2,0'), findsNothing);
4225+
expect(find.text('Cell 3,0'), findsNothing);
4226+
4227+
// Scroll horizontally so that column 1 is entirely behind pinned column 0.
4228+
horizontalController.jumpTo(100);
4229+
await tester.pump();
4230+
4231+
// With the fix, column 1 is still built because it is under the pinned area.
4232+
// Since column 1 is built, its merge info is found and applied to columns 2 and 3.
4233+
expect(find.text('Cell 1,0'), findsOneWidget);
4234+
expect(find.text('Cell 2,0'), findsNothing);
4235+
expect(find.text('Cell 3,0'), findsNothing);
4236+
},
4237+
);
4238+
4239+
testWidgets(
4240+
'Merged cells should not unmerge when the first cell is overlaid by a pinned row',
4241+
(WidgetTester tester) async {
4242+
final verticalController = ScrollController();
4243+
addTearDown(verticalController.dispose);
4244+
4245+
await tester.pumpWidget(
4246+
MaterialApp(
4247+
home: Scaffold(
4248+
body: SizedBox(
4249+
width: 400,
4250+
height: 400,
4251+
child: TableView.builder(
4252+
cacheExtent: 0.0,
4253+
verticalDetails: ScrollableDetails.vertical(
4254+
controller: verticalController,
4255+
),
4256+
pinnedRowCount: 1,
4257+
columnCount: 10,
4258+
rowCount: 10,
4259+
columnBuilder: (int index) =>
4260+
const TableSpan(extent: FixedTableSpanExtent(50)),
4261+
rowBuilder: (int index) => TableSpan(
4262+
extent: FixedTableSpanExtent(index == 0 ? 100 : 50),
4263+
),
4264+
cellBuilder: (BuildContext context, TableVicinity vicinity) {
4265+
// Merged cell spanning rows 1, 2, and 3.
4266+
final isRow1 = vicinity.row == 1;
4267+
return TableViewCell(
4268+
rowMergeStart: isRow1 ? 1 : null,
4269+
rowMergeSpan: isRow1 ? 3 : null,
4270+
child: Center(
4271+
child: Text('Cell ${vicinity.column},${vicinity.row}'),
4272+
),
4273+
);
4274+
},
4275+
),
4276+
),
4277+
),
4278+
),
4279+
);
4280+
4281+
// Initially, row 1 is visible below pinned row 0.
4282+
expect(find.text('Cell 0,1'), findsOneWidget);
4283+
expect(find.text('Cell 0,2'), findsNothing);
4284+
expect(find.text('Cell 0,3'), findsNothing);
4285+
4286+
// Scroll vertically so that row 1 is entirely behind pinned row 0.
4287+
verticalController.jumpTo(100);
4288+
await tester.pump();
4289+
4290+
// Row 1 should still be built, maintaining the merge.
4291+
expect(find.text('Cell 0,1'), findsOneWidget);
4292+
expect(find.text('Cell 0,2'), findsNothing);
4293+
expect(find.text('Cell 0,3'), findsNothing);
4294+
},
4295+
);
4296+
4297+
testWidgets(
4298+
'Table does not crash when focusing outside of the table while focused text field is not in the view',
4299+
(WidgetTester tester) async {
4300+
// Regression test for https://github.com/flutter/flutter/issues/137112
4301+
final verticalController = ScrollController();
4302+
final horizontalController = ScrollController();
4303+
addTearDown(() {
4304+
verticalController.dispose();
4305+
horizontalController.dispose();
4306+
});
4307+
4308+
await tester.pumpWidget(
4309+
MaterialApp(
4310+
home: Scaffold(
4311+
body: Column(
4312+
children: [
4313+
const TextField(key: Key('outside_textfield')),
4314+
Expanded(
4315+
child: TableView.builder(
4316+
verticalDetails: ScrollableDetails.vertical(
4317+
controller: verticalController,
4318+
),
4319+
horizontalDetails: ScrollableDetails.horizontal(
4320+
controller: horizontalController,
4321+
),
4322+
cellBuilder:
4323+
(BuildContext context, TableVicinity vicinity) {
4324+
return TableViewCell(
4325+
child: Center(
4326+
child: TextField(
4327+
key: Key(
4328+
'cell_${vicinity.row}_${vicinity.column}',
4329+
),
4330+
),
4331+
),
4332+
);
4333+
},
4334+
columnCount: 20,
4335+
columnBuilder: (int index) {
4336+
return const TableSpan(
4337+
foregroundDecoration: TableSpanDecoration(
4338+
border: TableSpanBorder(trailing: BorderSide()),
4339+
),
4340+
extent: FixedTableSpanExtent(100),
4341+
);
4342+
},
4343+
rowCount: 40,
4344+
rowBuilder: (int index) {
4345+
return TableSpan(
4346+
backgroundDecoration: TableSpanDecoration(
4347+
color: index.isEven ? Colors.purple[100] : null,
4348+
border: const TableSpanBorder(
4349+
trailing: BorderSide(width: 3),
4350+
),
4351+
),
4352+
extent: const FixedTableSpanExtent(50),
4353+
);
4354+
},
4355+
),
4356+
),
4357+
],
4358+
),
4359+
),
4360+
),
4361+
);
4362+
4363+
// 1. Select a TextField in the table.
4364+
// Use the vicinity from the original crash report.
4365+
const vicinity = TableVicinity(row: 5, column: 6);
4366+
final Finder cellTextField = find.byKey(
4367+
Key('cell_${vicinity.row}_${vicinity.column}'),
4368+
);
4369+
// Bring it into view.
4370+
verticalController.jumpTo(250);
4371+
horizontalController.jumpTo(600);
4372+
await tester.pumpAndSettle();
4373+
4374+
await tester.tap(cellTextField);
4375+
await tester.pumpAndSettle();
4376+
expect(FocusManager.instance.primaryFocus, isNotNull);
4377+
4378+
// 2. Scroll until it disappears from the view, without unfocusing it.
4379+
verticalController.jumpTo(verticalController.offset + 1000);
4380+
await tester.pumpAndSettle();
4381+
4382+
// 3. Select another TextField outside of the table.
4383+
final Finder outsideTextField = find.byKey(
4384+
const Key('outside_textfield'),
4385+
);
4386+
await tester.tap(outsideTextField);
4387+
await tester.pumpAndSettle();
4388+
4389+
// 4. Scroll back and ensure the table does not crash.
4390+
verticalController.jumpTo(verticalController.offset - 1000);
4391+
await tester.pumpAndSettle();
4392+
expect(cellTextField, findsOneWidget);
4393+
},
4394+
);
4395+
41794396
testWidgets('Trailing pinned columns and rows - smoke test', (
41804397
WidgetTester tester,
41814398
) async {

0 commit comments

Comments
 (0)