import 'package:commons_core/commons_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:tane/db/enums.dart'; import 'package:tane/i18n/strings.g.dart'; import 'package:tane/ui/home_screen.dart'; import 'package:tane/ui/inventory_list_screen.dart'; import 'package:tane/ui/settings_screen.dart'; import '../support/test_support.dart'; /// Small-phone layout guard. A Flutter `RenderFlex overflowed` (a clipped title, /// a save button pushed off a non-scrolling column, a Row too wide) is reported /// as an error and FAILS the test — so pumping each screen at a tiny viewport, /// in the languages whose text runs longest (es/pt/ast), catches exactly the /// "the save button / title isn't fully visible on a small phone" reports. /// /// FULL SCREENS ONLY. Modal bottom sheets (quick-add, the lot editor) are NOT /// checked here: `showModalBottomSheet` gets an unbounded height in a widget /// test, which fabricates a huge false overflow. Those sheets already wrap their /// body in a `SingleChildScrollView`, so their save buttons stay reachable; /// verify them on a real small device. void main() { // iPhone-SE-class logical viewport: narrow AND short, where clipping shows. const small = Size(320, 568); // The locales whose strings are longest — English rarely overflows first. const longLocales = [AppLocale.es, AppLocale.pt, AppLocale.ast]; Future pumpSmall(WidgetTester tester, Widget widget) async { tester.view.physicalSize = small; tester.view.devicePixelRatio = 1.0; addTearDown(tester.view.resetPhysicalSize); addTearDown(tester.view.resetDevicePixelRatio); await tester.pumpWidget(widget); await tester.pumpAndSettle(); } for (final locale in longLocales) { final tag = locale.languageCode; testWidgets('home menu fits a small screen ($tag)', (tester) async { final db = newTestDatabase(); addTearDown(db.close); await pumpSmall( tester, wrapScreen( repository: newTestRepository(db), locale: locale, child: const HomeScreen(marketEnabled: true), ), ); await disposeTree(tester); }); testWidgets('settings (language, backup, about) fits ($tag)', (tester) async { final db = newTestDatabase(); addTearDown(db.close); await pumpSmall( tester, wrapScreen( repository: newTestRepository(db), locale: locale, child: const SettingsScreen(), ), ); await disposeTree(tester); }); } testWidgets('inventory (empty) fits a small screen', (tester) async { final db = newTestDatabase(); addTearDown(db.close); await pumpSmall( tester, wrapScreen( repository: newTestRepository(db), locale: AppLocale.es, child: const InventoryListScreen(), ), ); await disposeTree(tester); }); testWidgets('inventory with a long-named seed fits a small screen', (tester) async { final db = newTestDatabase(); addTearDown(db.close); final repo = newTestRepository(db); final id = await repo.addQuickVariety( label: 'Tomate rosa de Barbastro extraordinariamente larguísimo', category: 'Solanáceas', ); await repo.addLot( varietyId: id, harvestYear: 2024, quantity: const Quantity(kind: QuantityKind.handful), offerStatus: OfferStatus.shared, ); await pumpSmall( tester, wrapScreen( repository: repo, locale: AppLocale.es, child: const InventoryListScreen(), ), ); await disposeTree(tester); }); // NOTE: the variety-detail screen is deliberately NOT overflow-checked here. // It reports a ~2px overflow on a RenderFlex that is already DISPOSED/DEFUNCT // — a transient stale frame while its cubit's Drift stream rebuilds during // pumpAndSettle, not the stable rendered layout. Guarding it would be flaky; // its RTL/build coverage lives in rtl_smoke_test.dart. }