From f9d4257c0d287764a9b78d68a1ca07d7fca96db8 Mon Sep 17 00:00:00 2001 From: RyuJongJin <266630912+RyuJongJin@users.noreply.github.com> Date: Sat, 24 Oct 2026 05:49:46 +0900 Subject: [PATCH] =?UTF-8?q?=ED=86=B5=ED=95=A9=20=EC=8B=9C=ED=97=98=204?= =?UTF-8?q?=EA=B0=9C:=20E6=20(Windows=20=EC=B2=98=EC=9D=8C=20=EB=AA=A8?= =?UTF-8?q?=EC=96=91=20TC)=20=EB=92=A4=EB=A1=9C=20=EC=8B=A4=ED=8C=A8?= =?UTF-8?q?=ED=95=98=EB=8D=98=20=EA=B2=83=20-=20X-plore=20=EB=A5=BC=20?= =?UTF-8?q?=EC=A7=81=EC=A0=91=20=EA=B3=A0=EB=A5=B4=EA=B3=A0,=20TC=20?= =?UTF-8?q?=EB=A1=9C=20=EC=93=B0=EB=8A=94=20=ED=99=94=EB=A9=B4=EC=9D=80=20?= =?UTF-8?q?TC=20=EB=8B=A8=EA=B3=84=EB=A5=BC=20=EB=8D=94=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - windows_b6_input · rsync_page: 시험이 X-plore 모양을 직접 고름 (TC 는 폴더를 [이름], 파일은 이름 · 확장자를 다른 칸에 보여 이름 글을 찾지 못했다) - windows_move_left_shot · windows_rsync_narrow_shot: X-plore 시험은 그대로 두고, Total Commander 모양으로 같은 일을 보는 단계를 더함 (관리자 10/24: 사용자가 TC 로 쓰므로). move_left TC: [D] 고르기 → F6 이동 → 알림 → Enter 로 원본 D 에 들어가 남은 것만. rsync_narrow TC: [sub] · [rsub] 고르기 → 좌 → 우 확인 창. 캡처 이름은 …_tc_… 확인: analyze 0 · b6_input 2 ×2 · move_left 12 ×2 · rsync_narrow 12 ×2 · rsync_page 3 ×3 (rsync_page 1회째는 시작 4초 만에 시험 앱이 끝나 did not complete - 시험 논리와 무관, 그 뒤 3회 모두 통과) Co-Authored-By: Claude Opus 5.5 --- integration_test/rsync_page_test.dart | 2 + integration_test/windows_b6_input_test.dart | 1 + .../windows_move_left_shot_test.dart | 67 ++++++++++++++----- .../windows_rsync_narrow_shot_test.dart | 17 +++-- 4 files changed, 65 insertions(+), 22 deletions(-) diff --git a/integration_test/rsync_page_test.dart b/integration_test/rsync_page_test.dart index deb8ae5..cd68422 100644 --- a/integration_test/rsync_page_test.dart +++ b/integration_test/rsync_page_test.dart @@ -124,6 +124,7 @@ void main() { await tester.runAsync(findBundledRsync); final c = AppController(PlatformServices.create()); c.settings + ..explorer.style = 'xplore' // 이 시험은 X-plore 모양 (E6 부터 Windows 처음 값은 Total Commander - 폴더는 [이름], 파일은 이름 · 확장자가 다른 칸) ..copy.rsyncPaths = [tmp.path, tmp.path] ..copy.rsyncOptions = '-avPog --delete --exclude=*.log --exclude=build/ --exclude=/sub/deep/'; final key = GlobalKey(); @@ -194,6 +195,7 @@ void main() { await tester.runAsync(findBundledRsync); final c = AppController(PlatformServices.create()); c.settings + ..explorer.style = 'xplore' // 이 시험은 X-plore 모양 (E6 부터 Windows 처음 값은 Total Commander - 폴더는 [이름], 파일은 이름 · 확장자가 다른 칸) ..copy.rsyncPaths = [tmp.path, tmp.path] ..copy.liveSyncPairs = [LiveSyncPair(cDir, d, method: 'rsync', delete: true)]; final key = GlobalKey(); diff --git a/integration_test/windows_b6_input_test.dart b/integration_test/windows_b6_input_test.dart index 846e5e1..e93063c 100644 --- a/integration_test/windows_b6_input_test.dart +++ b/integration_test/windows_b6_input_test.dart @@ -47,6 +47,7 @@ void main() { ..writeAsStringSync('x'); c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService())); c.settings + ..explorer.style = 'xplore' // 이 시험은 X-plore 모양 (E6 부터 Windows 처음 값은 Total Commander - 폴더는 [이름], 파일은 이름 · 확장자가 다른 칸) ..explorer.paths = [left, right] ..explorer.dropAction = 'ask'; }); diff --git a/integration_test/windows_move_left_shot_test.dart b/integration_test/windows_move_left_shot_test.dart index fef9f3a..cb62d42 100644 --- a/integration_test/windows_move_left_shot_test.dart +++ b/integration_test/windows_move_left_shot_test.dart @@ -3,6 +3,7 @@ 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:integration_test/integration_test.dart'; import 'package:jj_mkvmaker/app/app_controller.dart'; @@ -26,9 +27,12 @@ void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); final out = Platform.environment['JJ_SHOT_DIR'] ?? ''; + // 두 모양: X-plore (예전 캡처 그대로) · Total Commander (Windows 처음 값 - 관리자 10/24: 사용자가 TC 로 쓰므로 같은 일을 TC 로도) + for (final style in ['xplore', 'totalcmd']) { + final tc = style == 'totalcmd'; for (final lang in ['ko', 'en', 'ja']) { for (final (w, h) in [(960, 600), (1400, 800)]) { - testWidgets('264 · 265 이동 뒤 $lang ${w}x$h', (t) async { + testWidgets('264 · 265 이동 뒤 $style $lang ${w}x$h', (t) async { t.view.physicalSize = Size(w.toDouble(), h.toDouble()); t.view.devicePixelRatio = 1; addTearDown(t.view.reset); @@ -47,6 +51,7 @@ void main() { ..writeAsStringSync('NEWER'); final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService())); c.settings + ..explorer.style = style ..explorer.paths = [left, right] ..copy.conflict = 'overwrite'; final root = p.rootPrefix(tmp.path); @@ -71,28 +76,56 @@ void main() { 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, 'moveleft_${name}_${lang}_$w.png')).writeAsBytesSync(bytes!.buffer.asUint8List()); + File(p.join(out, 'moveleft_${tc ? 'tc_' : ''}${name}_${lang}_$w.png')).writeAsBytesSync(bytes!.buffer.asUint8List()); } - await settle(() => find.text('D').evaluate().length >= 2); - // 왼쪽 D 를 눌러 펼치고 (고른 것) 안의 add.txt 가 보이게 - await t.tap(find.text('D').first); - await settle(() => find.text('add.txt').evaluate().isNotEmpty); - await shot('1_before'); - await t.tap(find.text(tr('이동')).first); - await settle(() => find.widgetWithText(FilledButton, tr('이동')).evaluate().isNotEmpty); - await t.tap(find.widgetWithText(FilledButton, tr('이동'))); - await settle(() => find.byType(LinearProgressIndicator).evaluate().isEmpty && find.byType(SnackBar).evaluate().isNotEmpty); - await settle(() => false, rounds: 10); // 알림이 다 올라오게 - expect(File(p.join(right, 'D', 'add.txt')).existsSync(), isTrue); - expect(File(p.join(d, 'same.txt')).readAsStringSync(), 'old', reason: '받는 쪽이 더 새것이라 원본에 남음'); - expect(find.textContaining(trf('{0}개는 원본에 남았습니다 (건너뜀).', [1])), findsOneWidget, reason: '264: 알림에'); - expect(find.text('add.txt'), findsNothing, reason: '265: 원본 D 를 다시 읽음'); - expect(find.text('same.txt'), findsOneWidget); + if (!tc) { + await settle(() => find.text('D').evaluate().length >= 2); + // 왼쪽 D 를 눌러 펼치고 (고른 것) 안의 add.txt 가 보이게 + await t.tap(find.text('D').first); + await settle(() => find.text('add.txt').evaluate().isNotEmpty); + await shot('1_before'); + await t.tap(find.text(tr('이동')).first); + await settle(() => find.widgetWithText(FilledButton, tr('이동')).evaluate().isNotEmpty); + await t.tap(find.widgetWithText(FilledButton, tr('이동'))); + await settle(() => find.byType(LinearProgressIndicator).evaluate().isEmpty && find.byType(SnackBar).evaluate().isNotEmpty); + await settle(() => false, rounds: 10); // 알림이 다 올라오게 + expect(File(p.join(right, 'D', 'add.txt')).existsSync(), isTrue); + expect(File(p.join(d, 'same.txt')).readAsStringSync(), 'old', reason: '받는 쪽이 더 새것이라 원본에 남음'); + expect(find.textContaining(trf('{0}개는 원본에 남았습니다 (건너뜀).', [1])), findsOneWidget, reason: '264: 알림에'); + expect(find.text('add.txt'), findsNothing, reason: '265: 원본 D 를 다시 읽음'); + expect(find.text('same.txt'), findsOneWidget); + } else { + // TC: 폴더는 [D], 파일은 이름 · 확장자가 다른 칸 (좁으면 한 칸) - 이름 글로 찾는다 + Finder named(String stem, String ext) => + find.byWidgetPredicate((w) => w is Text && (w.data == stem || w.data == '$stem.$ext')); + await settle(() => find.text('[D]').evaluate().length >= 2); + // 왼쪽 [D] 를 한 번 눌러 고르고 (TC: 한 번 = 고르기) F6 = 이동 + await t.tap(find.text('[D]').first); + await settle(() => false, rounds: 5); + await shot('1_before'); + await t.sendKeyEvent(LogicalKeyboardKey.f6); + await settle(() => find.widgetWithText(FilledButton, tr('이동')).evaluate().isNotEmpty); + await t.tap(find.widgetWithText(FilledButton, tr('이동'))); + await settle(() => find.byType(LinearProgressIndicator).evaluate().isEmpty && find.byType(SnackBar).evaluate().isNotEmpty); + await settle(() => false, rounds: 10); // 알림이 다 올라오게 + expect(File(p.join(right, 'D', 'add.txt')).existsSync(), isTrue); + expect(File(p.join(d, 'same.txt')).readAsStringSync(), 'old', reason: '받는 쪽이 더 새것이라 원본에 남음'); + expect(find.textContaining(trf('{0}개는 원본에 남았습니다 (건너뜀).', [1])), findsOneWidget, reason: '264: 알림에'); + // 265: 원본 D 로 들어가면 (TC: Enter = 열기) 옮겨진 것은 없고 남은 것만 + ScaffoldMessenger.of(t.element(find.byType(ExplorerPage))).clearSnackBars(); + await t.tap(find.text('[D]').first); + await settle(() => false, rounds: 5); + await t.sendKeyEvent(LogicalKeyboardKey.enter); + await settle(() => named('same', 'txt').evaluate().isNotEmpty); + expect(named('add', 'txt'), findsNothing, reason: '265: 원본 D 를 다시 읽음'); + expect(named('same', 'txt'), findsOneWidget); + } await shot('2_after'); ScaffoldMessenger.of(t.element(find.byType(ExplorerPage))).clearSnackBars(); await settle(() => false, rounds: 20); }); } } + } } diff --git a/integration_test/windows_rsync_narrow_shot_test.dart b/integration_test/windows_rsync_narrow_shot_test.dart index 317b72d..5853858 100644 --- a/integration_test/windows_rsync_narrow_shot_test.dart +++ b/integration_test/windows_rsync_narrow_shot_test.dart @@ -26,9 +26,14 @@ void main() { setUp(() => device = TestExplorerDevice()); IntegrationTestWidgetsFlutterBinding.ensureInitialized(); final out = Platform.environment['JJ_SHOT_DIR'] ?? p.join(Directory.systemTemp.path, 'jj_shots_rsync_narrow'); + // 두 모양: X-plore (예전 캡처 그대로) · Total Commander (Windows 처음 값 - 관리자 10/24: 사용자가 TC 로 쓰므로 같은 일을 TC 로도) + for (final style in ['xplore', 'totalcmd']) { + final tc = style == 'totalcmd'; + // TC 모양은 폴더를 [이름] 으로 보인다 + String dir(String n) => tc ? '[$n]' : n; for (final lang in ['ko', 'en', 'ja']) { for (final (w, h) in [(412, 900), (960, 600)]) { - testWidgets('좁은 Rsync 화면 $lang ${w}x$h', (t) async { + testWidgets('좁은 Rsync 화면 $style $lang ${w}x$h', (t) async { t.view.physicalSize = Size(w.toDouble(), h.toDouble()); t.view.devicePixelRatio = 1; addTearDown(t.view.reset); @@ -50,6 +55,7 @@ void main() { device.volumes = () => [(tmp.path, 'T:')]; final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService())); c.settings + ..explorer.style = style ..explorer.orientation = 'side' ..copy.rsyncPaths = [l, r]; final shotKey = GlobalKey(); @@ -73,20 +79,20 @@ void main() { 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, 'rsync_narrow_${name}_${lang}_$w.png')).writeAsBytesSync(bytes!.buffer.asUint8List()); + File(p.join(out, 'rsync_narrow_${tc ? 'tc_' : ''}${name}_${lang}_$w.png')).writeAsBytesSync(bytes!.buffer.asUint8List()); } await settle(20); final narrow = find.text('${tr('오른쪽')} · R').evaluate().isNotEmpty; - await t.tap(find.text('sub').hitTestable()); + await t.tap(find.text(dir('sub')).hitTestable()); await settle(); if (narrow) { await t.tap(find.text('${tr('오른쪽')} · R')); await settle(15); - expect(find.text('rsub').hitTestable(), findsOneWidget, reason: '[오른쪽] 탭을 처음 보면 지금 폴더'); + expect(find.text(dir('rsub')).hitTestable(), findsOneWidget, reason: '[오른쪽] 탭을 처음 보면 지금 폴더'); await shot('1_right_tab'); } - await t.tap(find.text('rsub').hitTestable()); + await t.tap(find.text(dir('rsub')).hitTestable()); await settle(); await t.tap(find.text(tr('좌 → 우')).first); await settle(25); @@ -97,4 +103,5 @@ void main() { }); } } + } }