import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:jj_mkvmaker/app/app_controller.dart'; import 'package:jj_mkvmaker/app/settings.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/explorer_page.dart'; import 'package:path/path.dart' as p; /// X-plore 비교 40 (관리자 지시 10/20): 파일 탐색기 목록만의 글자 크기 (80~150%) · 줄 간격 (좁게 · 보통 · 넓게) void main() { late Directory tmp; setUp(() => tmp = Directory.systemTemp.createTempSync('jj_textscale_')); tearDown(() => tmp.deleteSync(recursive: true)); test('설정: 처음은 100% · 보통 (지금 그대로), 저장 · 읽기, 틀린 값은 그대로 쪽으로 · 범위 밖은 끝으로', () { final s = AppSettings(); expect((s.explorerTextScale, s.explorerRowSpacing), (100, 'normal')); s ..explorerTextScale = 130 ..explorerRowSpacing = 'wide'; final back = AppSettings.fromJson(s.toJson()); expect((back.explorerTextScale, back.explorerRowSpacing), (130, 'wide')); expect(AppSettings.fromJson({}).explorerTextScale, 100); expect(AppSettings.fromJson({'explorerTextScale': 'x', 'explorerRowSpacing': 'huge'}).explorerRowSpacing, 'normal'); expect(AppSettings.fromJson({'explorerTextScale': 300}).explorerTextScale, 150); expect(AppSettings.fromJson({'explorerTextScale': 10}).explorerTextScale, 80); }); /// [name] 글자의 실제 글자 크기 (기기 · 목록 글자 크기를 곱한 것) double shownSize(WidgetTester tester, String name) { final para = tester.renderObject(find.text(name).last); final size = para.text.style?.fontSize ?? 14; return para.textScaler.scale(size); } /// 이름 줄 높이 double rowHeight(WidgetTester tester, String name) => tester.getSize(find.ancestor(of: find.text(name).last, matching: find.byType(KeyedSubtree)).first).height; Future open(WidgetTester tester, String style, String wait, {double device = 1, int scale = 100, String spacing = 'normal'}) async { const pp = MethodChannel('plugins.flutter.io/path_provider'); tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(pp, (_) async => tmp.path); addTearDown(() => tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(pp, null)); File(p.join(tmp.path, '아주 긴 이름의 동영상 파일 - 글자 크기 시험용 2026 최종본.mp4')).writeAsStringSync('v' * 2000); File(p.join(tmp.path, 'a.txt')).writeAsStringSync('a'); Directory(p.join(tmp.path, 'sub')).createSync(); final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService())); c.settings ..explorerPaths = [tmp.path, tmp.path] // 폴더 + 파일 목록: 오른쪽 목록은 그 폴더의 것만이라 짧다 (트리는 Temp 의 다른 폴더가 많아 아래로 밀린다) ..explorerLayout = 'split' ..explorerStyle = style ..explorerTextScale = scale ..explorerRowSpacing = spacing; await tester.runAsync(() => tester.pumpWidget(MaterialApp( builder: (ctx, child) => MediaQuery(data: MediaQuery.of(ctx).copyWith(textScaler: TextScaler.linear(device)), child: child!), home: ExplorerPage(c: c)))); // 목록을 다 읽을 때까지 (다른 시험과 함께 돌면 느리다 - 10초까지) for (var i = 0; i < 200 && (i < 15 || find.text(wait).evaluate().isEmpty); i++) { await tester.runAsync(() => Future.delayed(const Duration(milliseconds: 50))); await tester.pump(); } return c; } Future close(WidgetTester tester) async { await tester.pumpWidget(const SizedBox()); await tester.pump(const Duration(seconds: 1)); } for (final style in ['xplore', 'windows', 'totalcmd']) { final a = style == 'totalcmd' ? 'a' : 'a.txt'; testWidgets('40: $style - 처음 값 (100% · 보통) 은 지금 그대로 · 150% · 넓게는 글자 1.5배 · 줄 높이 늘어남 · 412 폭에서 넘치지 않음', (tester) async { tester.view.physicalSize = const Size(412, 900); tester.view.devicePixelRatio = 1; addTearDown(tester.view.reset); await open(tester, style, a); expect(tester.takeException(), isNull); final base = shownSize(tester, a), baseH = rowHeight(tester, a); expect(baseH, {'xplore': 52.0, 'windows': 34.0, 'totalcmd': 26.0}[style], reason: '처음 값은 예전 줄 높이 그대로'); await close(tester); await open(tester, style, a, scale: 150, spacing: 'wide'); expect(tester.takeException(), isNull, reason: '412 폭 · 150% · 넓게에서 넘치지 않는다'); expect(shownSize(tester, a), closeTo(base * 1.5, 0.01)); expect(rowHeight(tester, a), (baseH * 1.5 * 1.25).roundToDouble()); await close(tester); // 기기 글자 크기 1.3 과 곱해진다 · 좁게 await open(tester, style, a, device: 1.3, scale: 120, spacing: 'compact'); expect(tester.takeException(), isNull); expect(shownSize(tester, a), closeTo(base * 1.3 * 1.2, 0.01)); expect(rowHeight(tester, a), (baseH * 1.3 * 1.2 * 0.8).roundToDouble()); await close(tester); // 80% 는 글자만 작게 (줄은 예전 높이 - 누르기 크기를 줄이지 않음) await open(tester, style, a, scale: 80); expect(shownSize(tester, a), closeTo(base * 0.8, 0.01)); expect(rowHeight(tester, a), baseH); await close(tester); }); } }