import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:tasq/theme/app_theme.dart'; import 'package:tasq/theme/app_surfaces.dart'; import 'package:tasq/widgets/tasq_adaptive_list.dart'; void main() { testWidgets('AppTheme sets cardTheme elevation to 1 (M3 tonal)', ( WidgetTester tester, ) async { await tester.pumpWidget( MaterialApp( theme: AppTheme.light(), home: Builder( builder: (context) { final elevation = Theme.of(context).cardTheme.elevation; expect(elevation, isNotNull); // M3 Expressive uses tonal elevation — minimal 0-1 shadow. expect(elevation, inInclusiveRange(0.0, 2.0)); expect(elevation, equals(1)); return const SizedBox.shrink(); }, ), ), ); }); testWidgets('Card without explicit elevation uses theme elevation', ( WidgetTester tester, ) async { await tester.pumpWidget( MaterialApp( theme: AppTheme.light(), home: const Scaffold( body: Card(child: SizedBox(width: 20, height: 20)), ), ), ); // Find the Material that actually paints the Card and assert elevation final materialFinder = find.descendant( of: find.byType(Card), matching: find.byType(Material), ); expect(materialFinder, findsWidgets); final material = tester.widget(materialFinder.first); expect(material.elevation, isNotNull); // M3 Expressive: tonal elevation is 0-2, not the M2 range of 2-4. expect(material.elevation, inInclusiveRange(0.0, 2.0)); }); testWidgets( 'TasQAdaptiveList mobile Card inherits theme elevation and uses compact radius', (WidgetTester tester) async { final theme = AppTheme.light(); await tester.pumpWidget( MaterialApp( theme: theme, home: MediaQuery( data: const MediaQueryData(size: Size(320, 800)), child: Scaffold( body: Center( child: SizedBox( width: 320, child: TasQAdaptiveList( items: const [1], columns: const [], mobileTileBuilder: (context, item, actions) => const Card(child: SizedBox(width: 100, height: 40)), ), ), ), ), ), ), ); // the Card returned by the mobile tile builder should be re-wrapped by // _MobileTile; assert that the visible Card uses theme elevation and a // compact 12px radius (per mobile rules). final cardFinder = find.byType(Card); expect(cardFinder, findsWidgets); final Card cardWidget = tester.widget(cardFinder.first); final shape = cardWidget.shape as RoundedRectangleBorder; final radius = (shape.borderRadius as BorderRadius).topLeft.x; expect( radius, equals( AppSurfaces.of(tester.element(cardFinder.first)).compactCardRadius, ), ); // Verify the painted Material has the theme elevation final materialFinder = find.descendant( of: find.byType(Card), matching: find.byType(Material), ); final material = tester.widget(materialFinder.first); expect(material.elevation, equals(theme.cardTheme.elevation)); }, ); // new regression tests for desktop layout adjustments testWidgets( 'Desktop adaptive list responsive width and horizontal scrollbar', (tester) async { final theme = AppTheme.light(); Future contentWidthFor(double screenWidth) async { await tester.pumpWidget( MaterialApp( theme: theme, home: MediaQuery( data: MediaQueryData(size: Size(screenWidth, 800)), child: Scaffold( body: TasQAdaptiveList( items: List.generate(100, (i) => i), columns: List.generate( 20, (i) => TasQColumn( header: 'C$i', cellBuilder: (c, t) => Text('$t'), ), ), mobileTileBuilder: (c, t, a) => const SizedBox.shrink(), rowActions: (_) => [], ), ), ), ), ); await tester.pumpAndSettle(); final box = tester.widget( find.byKey(const Key('adaptive_list_content')), ); return box.width!; } final narrow = await contentWidthFor(1000); final wide = await contentWidthFor(2000); expect(find.byType(Scrollbar), findsWidgets); expect(narrow / 1000, greaterThan(wide / 2000)); }, ); testWidgets('Desktop pagination forwards onPageChanged callback', ( WidgetTester tester, ) async { int? receivedIndex; await tester.pumpWidget( MaterialApp( theme: AppTheme.light(), home: MediaQuery( data: const MediaQueryData(size: Size(1200, 800)), child: Scaffold( body: TasQAdaptiveList( items: List.generate(60, (i) => i), columns: [ TasQColumn(header: 'C', cellBuilder: (c, t) => Text('$t')), ], mobileTileBuilder: (c, t, a) => const SizedBox.shrink(), rowsPerPage: 10, onPageChanged: (firstRow) { receivedIndex = firstRow; }, ), ), ), ), ); // locate the PaginatedDataTable and manually invoke the callback to // simulate the user requesting the second page final table = tester.widget( find.byType(PaginatedDataTable), ); expect(table.onPageChanged, isNotNull); table.onPageChanged!(10); expect(receivedIndex, equals(10)); }); testWidgets('AppSurfaces tokens are present and dialog/card radii differ', ( WidgetTester tester, ) async { await tester.pumpWidget( MaterialApp( theme: AppTheme.light(), home: Builder( builder: (context) { final surfaces = AppSurfaces.of(context); expect(surfaces.compactCardRadius, lessThan(surfaces.cardRadius)); expect(surfaces.dialogRadius, greaterThanOrEqualTo(18)); final dialogShape = (surfaces.dialogShape.borderRadius as BorderRadius).topLeft.x; final compactShape = (surfaces.compactShape.borderRadius as BorderRadius).topLeft.x; expect(dialogShape, greaterThan(compactShape)); return const SizedBox.shrink(); }, ), ), ); }); }