import 'dart:io'; import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; import 'package:jj_mkvmaker/app/app_controller.dart'; import 'package:jj_mkvmaker/app/i18n_controller.dart'; import 'package:jj_mkvmaker/core/ftp.dart'; import 'package:jj_mkvmaker/platform/windows/desktop_storage_service.dart'; import 'package:jj_mkvmaker/platform/windows/process_media_tool.dart'; import 'package:jj_mkvmaker/services/platform_services.dart'; import 'package:jj_mkvmaker/ui/ftp_settings.dart'; import 'package:jj_mkvmaker/ui/theme.dart'; import 'package:path/path.dart' as p; /// 관리자 지시 (10/18): FTP · FTPS 화면을 PNG 로 (JJ_SHOT_DIR) - 서버 추가 창 (FTPS 처음 값 · 평문 경고) · 인증서 지문 확인 창 · 설정 목록. /// 크기 412 · 960, 언어 ko · en · ja. 설정은 메모리에만. 실행: flutter test integration_test\windows_ftp_shot_test.dart -d windows void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); final out = Platform.environment['JJ_SHOT_DIR'] ?? p.join(Directory.systemTemp.path, 'jj_shots_ftp'); for (final lang in ['ko', 'en', 'ja']) { for (final (w, h) in [(412, 900), (960, 600)]) { testWidgets('FTP 화면 $lang ${w}x$h', (t) async { t.view.physicalSize = Size(w.toDouble(), h.toDouble()); t.view.devicePixelRatio = 1; addTearDown(t.view.reset); await t.runAsync(() => i18n.apply(lang, save: false)); addTearDown(() => i18n.apply('ko', save: false)); final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService())); c.settings.remote.ftpServers = [ const FtpServer(id: 'f1', name: 'NAS FTPS', host: '192.168.0.15', user: 'jj'), const FtpServer(id: 'f2', name: '옛 공유기', host: '192.168.0.1', security: 'none'), ]; final navKey = GlobalKey(); final shotKey = GlobalKey(); await t.pumpWidget(RepaintBoundary( key: shotKey, child: MaterialApp( theme: buildTheme(), debugShowCheckedModeBanner: false, navigatorKey: navKey, home: Scaffold(body: SingleChildScrollView(child: FtpSettings(c: c)))), )); BuildContext ctx() => navKey.currentContext!; Future settle([int n = 8]) async { for (var i = 0; i < n; i++) { await t.runAsync(() => Future.delayed(const Duration(milliseconds: 60))); await t.pump(); } } Future shot(String name) async { await settle(3); final b = shotKey.currentContext!.findRenderObject()! as RenderRepaintBoundary; final img = await t.runAsync(() => b.toImage()); final bytes = await t.runAsync(() => img!.toByteData(format: ui.ImageByteFormat.png)); Directory(out).createSync(recursive: true); File(p.join(out, 'ftp_${name}_${lang}_$w.png')).writeAsBytesSync(bytes!.buffer.asUint8List()); } Future closeAll() async { navKey.currentState!.popUntil((r) => r.isFirst); await settle(4); } await settle(); await shot('list'); // 서버 추가 창 (처음 값 FTPS 명시) editFtpServer(ctx(), c); await settle(); await shot('add'); // 평문 FTP 를 고르면 빨간 경고 await t.tap(find.textContaining(RegExp('FTP \\(|平文|明文|Plain')).last); await settle(); await t.scrollUntilVisible(find.byType(TextField).at(2), 100, scrollable: find.byType(Scrollable).last); await settle(); await shot('add_plain'); await closeAll(); // 자체 서명 인증서 확인 창 askTrustFtpCert( ctx(), 'NAS FTPS', const FtpCertException('x', FtpFailure.certUnknown, fingerprint: 'SHA256:E8:A8:51:BE:6E:78:58:B6:AC:53:03:6D:CB:CE:31:7A:C9:55:D2:55:BA:33:4D:DE:4B:CF:16:4B:6F:C4:90:C1', subject: '/CN=ds1815')); await settle(); await shot('cert'); await closeAll(); }); } } }