import 'package:fintracker_api/fintracker_api.dart'; import 'package:fintracker_app/core/api/common_providers.dart'; import 'package:fintracker_app/core/cache/cached.dart'; import 'package:fintracker_app/features/home/providers.dart'; import 'package:fintracker_app/features/shell/app_shell.dart'; import 'package:fintracker_app/features/shell/nav_destinations.dart'; import 'package:fintracker_app/features/shell/nav_sidebar.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; DataQualityRow _dataQualityRow(int id) => DataQualityRow( checkName: 'x', computedAt: DateTime(2026, 9, 19), count: 1, detail: 'issue $id', id: id, ref: null, severity: 'warning', ); void main() { // The sidebar (>=1200) watches meProvider and dataQualityProvider for the profile // footer and the Здоровье counter — every wide-breakpoint pump needs both overridden. Widget wrap(double width, {String location = '/'}) { return ProviderScope( overrides: [ meProvider.overrideWith((ref) async => UserOut(email: 'ada@example.com', id: 1)), dataQualityProvider.overrideWith((ref) async => const Cached([])), ], child: MediaQuery( data: MediaQueryData(size: Size(width, 800)), child: MaterialApp( home: AppShell(location: location, child: Container()), ), ), ); } testWidgets('shows the grouped sidebar on a wide surface', (tester) async { await tester.pumpWidget(wrap(1280)); await tester.pump(); expect(find.byType(NavSidebar), findsOneWidget); expect(find.byType(NavigationRail), findsNothing); expect(find.byType(NavigationBar), findsNothing); for (final label in navGroupLabels.values) { expect(find.text(label), findsOneWidget); } }); testWidgets('shows a collapsed NavigationRail on a medium surface', (tester) async { await tester.pumpWidget(wrap(900)); expect(find.byType(NavigationRail), findsOneWidget); expect(find.byType(NavSidebar), findsNothing); expect(find.byType(NavigationBar), findsNothing); }); testWidgets('shows a bottom NavigationBar on a narrow surface', (tester) async { await tester.pumpWidget(wrap(400)); expect(find.byType(NavigationBar), findsOneWidget); expect(find.byType(NavigationRail), findsNothing); expect(find.byType(NavSidebar), findsNothing); }); testWidgets('the resolve screen keeps Импорт selected', (tester) async { await tester.pumpWidget(wrap(900, location: '/instruments/pending')); final rail = tester.widget(find.byType(NavigationRail)); expect( (rail.destinations[rail.selectedIndex!].label as Text).data, 'Импорт', ); }); testWidgets('a nested route keeps its own section selected', (tester) async { await tester.pumpWidget(wrap(900, location: '/portfolio/instrument/311')); final rail = tester.widget(find.byType(NavigationRail)); expect( (rail.destinations[rail.selectedIndex!].label as Text).data, 'Портфель', ); }); testWidgets('the sidebar keeps Импорт selected on the resolve screen', (tester) async { await tester.pumpWidget(wrap(1280, location: '/instruments/pending')); await tester.pump(); final sidebar = tester.widget(find.byType(NavSidebar)); expect(navDestinations[sidebar.selectedIndex].label, 'Импорт'); }); testWidgets('the sidebar shows the Здоровье issue count', (tester) async { await tester.pumpWidget( ProviderScope( overrides: [ meProvider.overrideWith((ref) async => UserOut(email: 'ada@example.com', id: 1)), dataQualityProvider.overrideWith( (ref) async => Cached([ _dataQualityRow(1), _dataQualityRow(2), ]), ), ], child: MediaQuery( data: const MediaQueryData(size: Size(1280, 800)), child: MaterialApp(home: AppShell(location: '/', child: Container())), ), ), ); await tester.pump(); expect(find.text('2'), findsOneWidget); }); }