utils/design_system/test/section_header_test.dart
Krzysztof kuhy Rudnicki db1ce8c378 design_system 0.4.0: import material_ui
Flutter 3.50 deprecates package:flutter/material.dart for the
material_ui package; its ThemeData is a different type, so apps on
3.50 need the theme builders to return material_ui's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 09:35:00 +01:00

86 lines
2.9 KiB
Dart

import 'package:design_system/design_system.dart';
import 'package:material_ui/material_ui.dart';
import 'package:flutter_test/flutter_test.dart';
Future<void> _pumpHeader(
WidgetTester tester, {
Widget? action,
EdgeInsetsGeometry? padding,
}) {
return tester.pumpWidget(
MaterialApp(
theme: buildDarkTheme(),
home: Scaffold(
body: SectionHeader('Filters', action: action, padding: padding),
),
),
);
}
void main() {
testWidgets('shows the title at titleMedium', (tester) async {
await _pumpHeader(tester);
expect(find.text('Filters'), findsOneWidget);
// Compare the resolved size, not the whole TextStyle: the localization
// delegate merges geometry (weight, letter spacing, line height) into
// the theme's style before it reaches the widget, so the two objects are
// never `==` even when the widget is doing exactly the right thing.
final text = tester.widget<Text>(find.text('Filters'));
expect(text.style?.fontSize, AppTextSize.subtitle);
expect(
text.style?.fontSize,
buildDarkTheme().textTheme.titleMedium?.fontSize,
);
});
testWidgets('has no padding of its own by default', (tester) async {
await _pumpHeader(tester);
expect(
find.descendant(
of: find.byType(SectionHeader),
matching: find.byType(Padding),
),
findsNothing,
);
});
testWidgets('applies padding when asked', (tester) async {
await _pumpHeader(tester, padding: SectionHeader.defaultPadding);
final padding = tester.widget<Padding>(
find
.descendant(
of: find.byType(SectionHeader),
matching: find.byType(Padding),
)
.first,
);
expect(padding.padding, SectionHeader.defaultPadding);
});
testWidgets('omits the action slot by default', (tester) async {
await _pumpHeader(tester);
expect(find.byType(IconButton), findsNothing);
});
testWidgets('renders a trailing action beside the title', (tester) async {
await _pumpHeader(
tester,
action: IconButton(onPressed: () {}, icon: const Icon(Icons.add)),
);
expect(find.byIcon(Icons.add), findsOneWidget);
// The action sits to the right of the title, not below it.
final titleRight = tester.getTopRight(find.text('Filters')).dx;
final actionLeft = tester.getTopLeft(find.byIcon(Icons.add)).dx;
expect(actionLeft, greaterThanOrEqualTo(titleRight));
});
test('defaultPadding groups the title with the content below it', () {
// Tighter below than above, so the header reads as belonging to the
// section it labels rather than floating between two of them.
expect(SectionHeader.defaultPadding.bottom, AppSpacing.xs);
expect(SectionHeader.defaultPadding.top, AppSpacing.md);
expect(SectionHeader.defaultPadding.left, AppSpacing.md);
expect(SectionHeader.defaultPadding.right, AppSpacing.md);
});
}