import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:jj_mkvmaker/app/app_controller.dart'; import 'package:jj_mkvmaker/core/wifi_share.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/wifi_share_page.dart'; /// 89: Wi-Fi 공유 화면 - 처음엔 꺼짐 · [켜기] 뒤 6자리 코드 · 주소 · 남은 시간 · [끄기] 로 꺼짐. 설정 파일은 쓰지 않는다 (저장소 없음) void main() { late Directory tmp; setUp(() { WifiShare.debugLoopbackOnly = true; tmp = Directory.systemTemp.createTempSync('jj_wifipage_'); File('${tmp.path}${Platform.pathSeparator}a.txt').writeAsStringSync('a'); }); tearDown(() async { await WifiShare.instance?.stop(); WifiShare.debugLoopbackOnly = false; try { tmp.deleteSync(recursive: true); } catch (_) {} }); testWidgets('꺼짐 → [켜기] → 코드 · 남은 시간 → [끄기] → 꺼짐', (tester) async { final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService())); expect(c.settings.wifiShareMinutes, 30, reason: '처음 값 30분 (관리자 지시)'); // 폰 세로처럼 좁고 긴 화면 (아래 줄까지 다 그려지게) tester.view.physicalSize = const Size(412, 1600); tester.view.devicePixelRatio = 1; addTearDown(tester.view.reset); await tester.pumpWidget(MaterialApp(home: WifiSharePage(c: c, folder: tmp.path))); expect(find.text('켜기'), findsOneWidget); expect(find.text('30분 뒤'), findsOneWidget); expect(WifiShare.instance, isNull, reason: '화면을 열기만 해서는 켜지지 않는다 (기본 꺼짐)'); await tester.tap(find.text('켜기')); for (var i = 0; i < 20 && WifiShare.instance == null; i++) { await tester.runAsync(() => Future.delayed(const Duration(milliseconds: 50))); await tester.pump(); } await tester.pump(); final s = WifiShare.instance!; expect(find.text(s.code), findsOneWidget); expect(find.textContaining('분 뒤에 저절로 꺼집니다'), findsOneWidget); expect(find.text('아직 접속한 기기가 없습니다'), findsOneWidget); expect(c.settings.wifiShareFolder, tmp.path); await tester.tap(find.text('끄기')); await tester.runAsync(() => Future.delayed(const Duration(milliseconds: 100))); await tester.pump(); expect(WifiShare.instance, isNull); expect(find.text('켜기'), findsOneWidget); }); testWidgets('Windows: 켜기 전에 방화벽 안내 · 펼치면 "개인 네트워크 허용" 하는 법과 설정 · 제어판을 여는 버튼 (관리자 지시 10/19)', (tester) async { if (!Platform.isWindows) return; final launched = []; final old = WifiSharePage.debugLaunch; WifiSharePage.debugLaunch = (exe, args) async => launched.add('$exe ${args.join(' ')}'); addTearDown(() => WifiSharePage.debugLaunch = old); final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService())); tester.view.physicalSize = const Size(412, 1600); tester.view.devicePixelRatio = 1; addTearDown(tester.view.reset); await tester.pumpWidget(MaterialApp(home: WifiSharePage(c: c, folder: tmp.path))); expect(find.textContaining('"개인 네트워크" 에 체크하고 [허용]'), findsOneWidget, reason: '켜기 전에 미리'); expect(find.text('방화벽 허용 앱 열기'), findsNothing, reason: '도움말은 접혀 있음'); await tester.tap(find.text('다른 기기에서 열리지 않으면 (Windows 방화벽)')); await tester.pumpAndSettle(); expect(find.textContaining('네트워크 프로필 유형 = 개인'), findsOneWidget); await tester.tap(find.text('네트워크 설정 열기')); await tester.tap(find.text('방화벽 허용 앱 열기')); await tester.pump(); expect(launched, ['explorer.exe ms-settings:network-status', 'control.exe /name Microsoft.WindowsFirewall /page pageConfigureApps']); }); }