Files
kooltab/test/tab_panel_index_test.dart
T

231 lines
7.4 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:kooltap/l10n/app_localizations.dart';
import 'package:kooltap/models/bar_tab.dart';
import 'package:kooltap/utils/name_index.dart';
import 'package:kooltap/views/bar/selected_tab_details.dart';
import 'package:kooltap/views/bar/tab_panel.dart';
const _names = [
'Zoë', 'anna', 'Émile', 'Bram', 'Mieke', 'Marc', 'Ward', 'Tom', 'Sofie', //
'Lotte', 'Koen', 'Jan', 'Inge', 'Hanne', 'Greet', 'Frank', 'Dirk', 'Chris',
'Nele', 'Olaf', 'Pieter', 'Rik', 'Vera', 'Yves', '2de tafel', 'Eva',
];
void main() {
group('name index', () {
test('folds case and accents into the index letter', () {
expect(indexLetterOf('émile'), 'E');
expect(indexLetterOf('Zoë'), 'Z');
expect(indexLetterOf(' anna'), 'A');
expect(indexLetterOf('2de tafel'), '#');
expect(indexLetterOf(''), '#');
});
test('sorts A–Z regardless of case and accents, # last', () {
final sorted = ['Zoë', 'émile', 'Eva', 'anna', '2de tafel', 'Bram']
..sort(compareByIndex);
expect(sorted, ['anna', 'Bram', 'émile', 'Eva', 'Zoë', '2de tafel']);
});
});
group('TabPanel letter index', () {
final tabs = [
for (final (index, name) in _names.indexed)
BarTab(
id: 'tab-$index',
customerName: name,
openedAt: DateTime(2026, 10, 11, 12, index),
items: const [],
),
];
Future<void> pumpPanel(
WidgetTester tester, {
bool showSearch = false,
BarTab? selectedTab,
}) async {
tester.view.physicalSize = const Size(500, 800);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.reset);
await tester.pumpWidget(
MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: Scaffold(
body: TabPanel(
tabs: tabs,
selectedTab: selectedTab,
selectedTabId: selectedTab?.id,
showSearch: showSearch,
onTabSelected: (_) {},
onItemQuantityChanged: (_, _) async {},
onCloseTabPressed: () {},
onTabEdited: (_) async {},
onTabDeleted: (_) async {},
),
),
),
);
}
String firstVisibleName(WidgetTester tester) {
final list = tester.getRect(find.byType(OpenTabsList));
final visible = _names.where((name) {
final finder = find.text(name);
if (finder.evaluate().isEmpty) return false;
final rect = tester.getRect(finder);
return rect.top >= list.top && rect.bottom <= list.bottom;
}).toList();
return visible.reduce(
(a, b) =>
tester.getRect(find.text(a)).top < tester.getRect(find.text(b)).top
? a
: b,
);
}
Future<void> tapLetter(WidgetTester tester, String letter) async {
await tester.tap(
find.descendant(
of: find.byWidgetPredicate(
(widget) => widget.runtimeType.toString() == '_LetterIndexBar',
),
matching: find.text(letter),
),
);
await tester.pumpAndSettle();
}
testWidgets('lists the tabs alphabetically', (tester) async {
await pumpPanel(tester);
expect(firstVisibleName(tester), 'anna');
});
testWidgets('tapping a letter scrolls to its first name', (tester) async {
await pumpPanel(tester);
await tapLetter(tester, 'M');
expect(firstVisibleName(tester), 'Marc');
await tapLetter(tester, 'E');
expect(firstVisibleName(tester), 'Émile');
});
testWidgets('shows the search bar only when asked', (tester) async {
await pumpPanel(tester);
expect(find.byType(TextField), findsNothing);
await pumpPanel(tester, showSearch: true);
expect(find.byType(TextField), findsOneWidget);
});
testWidgets('closing the search clears the filter', (tester) async {
await pumpPanel(tester, showSearch: true);
await tester.enterText(find.byType(TextField), 'Marc');
await tester.pump();
expect(find.text('anna'), findsNothing);
await pumpPanel(tester);
expect(find.text('anna'), findsOneWidget);
});
group('collapsing', () {
double namesHeight(WidgetTester tester) =>
tester.getSize(find.byType(OpenTabsList)).height;
testWidgets('starts with the names at their usual height', (
tester,
) async {
await pumpPanel(tester, selectedTab: tabs.first);
expect(namesHeight(tester), 246);
});
testWidgets('tapping a name collapses the names', (tester) async {
await pumpPanel(tester, selectedTab: tabs.first);
await tester.tap(find.text('Bram'));
await tester.pumpAndSettle();
expect(namesHeight(tester), lessThan(200));
});
testWidgets('touching the items collapses the names', (tester) async {
await pumpPanel(tester, selectedTab: tabs.first);
await tester.tap(find.byType(SelectedTabDetails), warnIfMissed: false);
await tester.pumpAndSettle();
expect(namesHeight(tester), lessThan(200));
});
testWidgets('lines the selected name up on top of its items', (
tester,
) async {
final marc = tabs.firstWhere((tab) => tab.customerName == 'Marc');
await pumpPanel(tester, selectedTab: marc);
await tester.tap(find.byType(SelectedTabDetails), warnIfMissed: false);
await tester.pumpAndSettle();
final list = tester.getRect(find.byType(OpenTabsList));
final details = tester.getRect(find.byType(SelectedTabDetails));
final tile = tester.getRect(
find
.ancestor(of: find.text('Marc'), matching: find.byType(ClipRRect))
.first,
);
expect(tile.bottom, closeTo(list.bottom, 1));
expect(details.top, greaterThan(tile.bottom));
expect(
find.byWidgetPredicate(
(widget) => widget is Divider && widget.height == 28,
),
findsNothing,
);
});
testWidgets('browsing the names shows the divider again', (tester) async {
final marc = tabs.firstWhere((tab) => tab.customerName == 'Marc');
await pumpPanel(tester, selectedTab: marc);
await tester.tap(find.byType(SelectedTabDetails), warnIfMissed: false);
await tester.pumpAndSettle();
await tester.drag(find.byType(OpenTabsList), const Offset(0, -40));
await tester.pumpAndSettle();
expect(
find.byWidgetPredicate(
(widget) => widget is Divider && widget.height == 28,
),
findsOneWidget,
);
});
testWidgets('scrolling the names collapses the items', (tester) async {
await pumpPanel(tester, selectedTab: tabs.first);
await tester.tap(find.byType(SelectedTabDetails), warnIfMissed: false);
await tester.pumpAndSettle();
await tester.drag(find.byType(OpenTabsList), const Offset(0, -40));
await tester.pumpAndSettle();
final panel = tester.getSize(find.byType(TabPanel)).height;
expect(namesHeight(tester), greaterThan(panel * 0.75));
});
});
testWidgets('a letter without names goes to the next one', (tester) async {
await pumpPanel(tester);
await tapLetter(tester, 'Q');
expect(firstVisibleName(tester), 'Rik');
});
});
}