import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:tatlock_ui/features/front_hall/presentation/pages/front_hall_page.dart'; import 'package:tatlock_ui/shared/widgets/air_quality_widget.dart'; import 'package:tatlock_ui/shared/widgets/forecast_widget.dart'; import 'package:tatlock_ui/shared/widgets/sun_position_widget.dart'; import 'package:tatlock_ui/shared/widgets/weather_widget.dart'; import '../../harness/screen_sizes.dart'; import '../../harness/test_harness.dart'; void main() { final harness = TestHarness(); setUp(() => harness.setUp()); tearDown(() => harness.tearDown()); // Set larger window size and suppress overflow errors Future setLargeWindowSize(WidgetTester tester) async { tester.view.physicalSize = const Size(1400, 900); tester.view.devicePixelRatio = 1.0; addTearDown(() => tester.view.resetPhysicalSize()); // Suppress overflow errors - not what we're testing final originalOnError = FlutterError.onError; FlutterError.onError = (details) { if (details.exceptionAsString().contains('overflowed')) { return; } originalOnError?.call(details); }; addTearDown(() => FlutterError.onError = originalOnError); } group('Environment Widgets', () { testWidgets('displays Sun Position widget', (tester) async { await setLargeWindowSize(tester); harness.givenAuthenticatedUser(); harness.givenQuickLinks(); harness.givenSystemStats(); harness.givenEnvironment(); await tester.pumpWidget(harness.wrap(const FrontHallPage())); await tester.pumpAndSettle(); expect(find.byType(SunPositionWidget), findsOneWidget); expect(find.text('Sun Position'), findsOneWidget); }); testWidgets('displays Weather widget', (tester) async { await setLargeWindowSize(tester); harness.givenAuthenticatedUser(); harness.givenQuickLinks(); harness.givenSystemStats(); harness.givenEnvironment(); await tester.pumpWidget(harness.wrap(const FrontHallPage())); await tester.pumpAndSettle(); expect(find.byType(WeatherWidget), findsOneWidget); }); testWidgets('displays Forecast widget', (tester) async { await setLargeWindowSize(tester); harness.givenAuthenticatedUser(); harness.givenQuickLinks(); harness.givenSystemStats(); harness.givenEnvironment(); await tester.pumpWidget(harness.wrap(const FrontHallPage())); await tester.pumpAndSettle(); expect(find.byType(ForecastWidget), findsOneWidget); expect(find.text('Forecast'), findsOneWidget); }); testWidgets('displays Air Quality widget when data available', (tester) async { await setLargeWindowSize(tester); harness.givenAuthenticatedUser(); harness.givenQuickLinks(); harness.givenSystemStats(); harness.givenEnvironment(); // Has air quality data await tester.pumpWidget(harness.wrap(const FrontHallPage())); await tester.pumpAndSettle(); expect(find.byType(AirQualityWidget), findsOneWidget); expect(find.text('Air Quality'), findsOneWidget); }); testWidgets('hides Air Quality widget when no data', (tester) async { await setLargeWindowSize(tester); harness.givenAuthenticatedUser(); harness.givenQuickLinks(); harness.givenSystemStats(); harness.givenEnvironmentNoAirQuality(); // No air quality data await tester.pumpWidget(harness.wrap(const FrontHallPage())); await tester.pumpAndSettle(); // Air Quality widget should not be present expect(find.byType(AirQualityWidget), findsNothing); }); testWidgets('calls environment API on mount', (tester) async { await setLargeWindowSize(tester); harness.givenAuthenticatedUser(); harness.givenQuickLinks(); harness.givenSystemStats(); harness.givenEnvironment(); await tester.pumpWidget(harness.wrap(const FrontHallPage())); await tester.pumpAndSettle(); harness.verifyApiCalled('GET', '/tools/environment'); }); testWidgets('displays error state when environment fails', (tester) async { await setLargeWindowSize(tester); harness.givenAuthenticatedUser(); harness.givenQuickLinks(); harness.givenSystemStats(); harness.givenApiError( method: 'GET', path: '/tools/environment', statusCode: 500, message: 'Internal server error', ); await tester.pumpWidget(harness.wrap(const FrontHallPage())); await tester.pumpAndSettle(); // Should show environment error message or error indicator expect( find.text('Failed to load environment data').evaluate().isNotEmpty || find.byIcon(Icons.error_outline).evaluate().isNotEmpty, isTrue, reason: 'Should display environment error', ); }); testWidgets('displays sunrise and sunset times', (tester) async { await setLargeWindowSize(tester); harness.givenAuthenticatedUser(); harness.givenQuickLinks(); harness.givenSystemStats(); harness.givenEnvironment(); await tester.pumpWidget(harness.wrap(const FrontHallPage())); await tester.pumpAndSettle(); // Should display sunrise/sunset labels expect(find.text('Sunrise'), findsOneWidget); expect(find.text('Sunset'), findsOneWidget); }); testWidgets('displays daylight duration', (tester) async { await setLargeWindowSize(tester); harness.givenAuthenticatedUser(); harness.givenQuickLinks(); harness.givenSystemStats(); harness.givenEnvironment(); await tester.pumpWidget(harness.wrap(const FrontHallPage())); await tester.pumpAndSettle(); // Should display daylight label expect(find.text('Daylight'), findsOneWidget); }); }); group('Environment Widgets Responsive', () { testWidgets('renders environment widgets at desktop size', (tester) async { configureScreenSize(tester, ScreenSizes.desktopLarge); harness.givenAuthenticatedUser(); harness.givenQuickLinks(); harness.givenSystemStats(); harness.givenEnvironment(); await tester.pumpWidget(harness.wrap(const FrontHallPage())); await tester.pumpAndSettle(); expect(find.byType(SunPositionWidget), findsOneWidget); expect(find.byType(WeatherWidget), findsOneWidget); expect(find.byType(ForecastWidget), findsOneWidget); }); testWidgets('renders environment widgets at tablet size', (tester) async { configureScreenSize(tester, ScreenSizes.tabletLandscape); harness.givenAuthenticatedUser(); harness.givenQuickLinks(); harness.givenSystemStats(); harness.givenEnvironment(); await tester.pumpWidget(harness.wrap(const FrontHallPage())); await tester.pumpAndSettle(); expect(find.byType(SunPositionWidget), findsOneWidget); expect(find.byType(WeatherWidget), findsOneWidget); expect(find.byType(ForecastWidget), findsOneWidget); }); testWidgets('renders environment widgets at mobile size', (tester) async { configureScreenSize(tester, ScreenSizes.mobile); harness.givenAuthenticatedUser(); harness.givenQuickLinks(); harness.givenSystemStats(); harness.givenEnvironment(); await tester.pumpWidget(harness.wrap(const FrontHallPage())); await tester.pumpAndSettle(); // Page should render without crashing at mobile size // Widgets may be below the fold due to scrolling expect(find.byType(FrontHallPage), findsOneWidget); }); }); }