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/models.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/home_page.dart'; /// 15 지적 (10/17, 시험 캡처 412 · 960) · 관리자 판단: /// ① 동영상이 있는데 고른 것이 없으면 빈 목록 안내가 아니라 "목록에서 누르세요" /// ② 폭 412 위 버튼 줄이 잘리면 "더 있음" 표시 ([›]) /// ③ 폰 세로 목록은 32% 고정이 아니라 내용만큼 (자세히 칸 자리는 남김) · 설정 "폰 세로 목록 크기" void main() { AppController make(int n, {String size = 'auto', bool pick = false}) { final c = AppController(PlatformServices( mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService(), createRecognizer: () => throw UnimplementedError(), createTranslator: () => throw UnimplementedError(), )); c.settings ..showLog = true ..mkvCompactList = size; for (var i = 0; i < n; i++) { c.videos.add(VideoItem('D:/v/v$i.mp4')); } if (pick) c.selected = c.videos.first; return c; } Future show(WidgetTester tester, AppController c, Size size) async { tester.view.physicalSize = size; tester.view.devicePixelRatio = 1; addTearDown(tester.view.reset); await tester.pumpWidget(MaterialApp(home: HomePage(c: c))); await tester.pump(); expect(tester.takeException(), isNull); } /// 목록 (v0.mp4 가 있는 스크롤) 의 높이 double listHeight(WidgetTester tester) => tester.getRect(find.ancestor(of: find.text('v0.mp4'), matching: find.byType(Scrollable)).first).height; for (final size in const [Size(412, 869), Size(1280, 800)]) { testWidgets('① ${size.width.toInt()}: 동영상이 있고 고른 것이 없으면 "목록에서 누르세요" (빈 목록 안내 아님)', (tester) async { await show(tester, make(50), size); expect(find.text('고른 동영상이 없습니다'), findsOneWidget); expect(find.text('"동영상 추가" 로 파일을 선택하세요'), findsNothing); }); } testWidgets('빈 목록이면 예전처럼 [동영상 추가] 안내', (tester) async { await show(tester, make(0), const Size(412, 869)); expect(find.text('"동영상 추가" 로 파일을 선택하세요'), findsOneWidget); expect(find.text('고른 동영상이 없습니다'), findsNothing); }); testWidgets('③ 자동 · 50개 · 고른 것 없음: 목록이 화면 대부분 (예전 32% 는 4~5줄)', (tester) async { await show(tester, make(50), const Size(412, 869)); // 예전: 목록 칸이 화면 높이의 32% (869 → 278, 머리 줄을 빼면 스크롤 약 234). // 이제는 위 막대 · 인코딩 줄 · 작업 기록을 뺀 칸에서 안내 자리 (120) 만 남긴다 expect(listHeight(tester), greaterThan(869 * 0.32 - 44 + 60)); expect(find.text('v4.mp4'), findsOneWidget); expect(find.text('고른 동영상이 없습니다'), findsOneWidget, reason: '안내 자리는 남는다'); }); testWidgets('③ 자동 · 3개: 목록은 줄 수만큼 - 안내가 목록 바로 아래 칸에 (빈 칸 없음)', (tester) async { await show(tester, make(3), const Size(412, 869)); final list = listHeight(tester); final rows = tester.getRect(find.text('v2.mp4')).bottom - tester.getRect(find.text('v0.mp4')).top; expect(list, lessThan(rows + 120), reason: '목록 $list · 줄 $rows - 남는 칸을 목록이 차지하지 않는다'); }); testWidgets('③ 설정: 작게 < 크게 < 자동 (50개 · 고른 것 없음)', (tester) async { final h = {}; for (final s in const ['small', 'large', 'auto']) { await show(tester, make(50, size: s), const Size(412, 869)); h[s] = listHeight(tester); } expect(h['small']!, lessThan(h['large']!)); expect(h['large']!, lessThan(h['auto']!)); }); testWidgets('③ 자동 · 고른 동영상: 자세히 칸이 화면 높이의 절반 넘게 (261 · 266 의 버튼이 밀리지 않게)', (tester) async { await show(tester, make(50, pick: true), const Size(412, 869)); expect(listHeight(tester), lessThan(869 * 0.4)); }); testWidgets('② 폭 412: 위 버튼 줄이 넘치면 [›] - 누르면 밀리고 [‹] 가 생긴다', (tester) async { await show(tester, make(5, pick: true), const Size(412, 869)); expect(find.byTooltip('버튼 더 보기'), findsOneWidget); expect(find.byTooltip('앞의 버튼 보기'), findsNothing); await tester.tap(find.byTooltip('버튼 더 보기')); await tester.pumpAndSettle(); expect(find.byTooltip('앞의 버튼 보기'), findsOneWidget); }); testWidgets('작업 기록이 비었으면 무엇이 들어오는 칸인지 적는다', (tester) async { final c = make(3); c.logs.clear(); await show(tester, c, const Size(412, 869)); expect(find.textContaining('작업 기록이 아직 없습니다'), findsOneWidget); }); }