// Explicit host-rendered UI evidence; not Android-device verification. import 'dart:io'; import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:reelbox/app.dart'; import 'package:reelbox/state/app_state.dart'; import 'package:reelbox/ui/catalog.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../test/home_banner_widget_test.dart' show HomeBannerFixtureApi; void main() { testWidgets( 'actual home Telegram at 390x844 in English/Persian including API error and tap', (tester) async { await tester.runAsync(() async { final bytes = await File( Platform.environment['REELBOX_TEST_FONT'] ?? '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', ).readAsBytes(); for (final family in ['Roboto', 'Ahem']) { await (FontLoader( family, )..addFont(Future.value(bytes.buffer.asByteData()))).load(); } final icons = await File( Platform.environment['REELBOX_ICON_FONT'] ?? '/root/developer-tools/flutter/bin/cache/artifacts/material_fonts/MaterialIcons-Regular.otf', ).readAsBytes(); await (FontLoader( 'MaterialIcons', )..addFont(Future.value(icons.buffer.asByteData()))).load(); }); tester.view.devicePixelRatio = 1; tester.view.physicalSize = const Size(390, 844); addTearDown(tester.view.resetDevicePixelRatio); addTearDown(tester.view.resetPhysicalSize); final output = Directory( Platform.environment['REELBOX_SCREENSHOT_DIR'] ?? '${Directory.current.path}/build/banner-ui-verification', ); await tester.runAsync(() => output.create(recursive: true)); const channel = MethodChannel('plugins.flutter.io/url_launcher'); final targets = []; tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(channel, ( call, ) async { targets.add(call.arguments['url'] as String); return true; }); addTearDown( () => tester.binding.defaultBinaryMessenger.setMockMethodCallHandler( channel, null, ), ); for (final failed in [false, true]) { for (final locale in ['en', 'fa']) { // ignore: invalid_use_of_visible_for_testing_member SharedPreferences.setMockInitialValues({}); final state = AppState( api: HomeBannerFixtureApi()..fail = failed, storage: await SharedPreferences.getInstance(), ); await state.initialize(discover: false); await state.updateSettings( state.prefs.copyWith(locale: locale, introCompleted: true), ); final boundaryKey = GlobalKey(); await tester.pumpWidget( RepaintBoundary( key: boundaryKey, child: MyApp(state: state), ), ); await tester.pumpAndSettle(); expect(find.byType(DiscoverPage), findsOneWidget); expect(find.byType(NavigationBar), findsOneWidget); final title = locale == 'en' ? 'ReelBox updates' : 'تازه‌های ریل‌باکس'; expect(find.text(title), findsOneWidget); expect( tester .getRect(find.byKey(const Key('home-banner-telegram'))) .bottom, lessThan(844), ); if (failed) expect(find.text('Offline'), findsWidgets); expect(tester.takeException(), isNull); final boundary = boundaryKey.currentContext!.findRenderObject()! as RenderRepaintBoundary; final name = 'home-banner-$locale${failed ? '-error' : ''}'; await tester.runAsync(() async { final image = await boundary.toImage(pixelRatio: 1); expect(image.width, 390); expect(image.height, 844); final bytes = await image.toByteData( format: ui.ImageByteFormat.png, ); await File('${output.path}/$name.png') .writeAsBytes(bytes!.buffer.asUint8List()); image.dispose(); }); await tester.tap(find.byKey(const Key('home-banner-telegram'))); await tester.pumpAndSettle(); expect(targets.last, 'https://t.me/ReelBoxApp'); await tester.pumpWidget(const SizedBox()); state.dispose(); } } expect(targets, List.filled(4, 'https://t.me/ReelBoxApp')); }, ); }