JJ_MKVMaker/test/sftp_explorer_test.dart

78 lines
3.8 KiB
Dart

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/sftp.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;
import 'support/sftp_server.dart';
/// 88: 파일 탐색기의 SFTP 탭 - 처음 연결하면 서버 키 지문을 보이고 [지문 확인하고 연결] → [믿고 연결] 뒤 목록 (시험 서버 paramiko)
void main() {
late Directory tmp;
SftpTestServer? server;
setUp(() => tmp = Directory.systemTemp.createTempSync('jj_sftp88_ui_'));
tearDown(() async {
SftpRegistry.configure(const []);
await server?.stop();
server = null;
for (var i = 0;; i++) {
try {
if (tmp.existsSync()) tmp.deleteSync(recursive: true);
break;
} on FileSystemException {
if (i > 30) rethrow;
await Future<void>.delayed(const Duration(milliseconds: 100));
}
}
});
Future<void> settle(WidgetTester tester, bool Function() done, {int rounds = 300}) async {
for (var i = 0; i < rounds; i++) {
await tester.runAsync(() => Future<void>.delayed(const Duration(milliseconds: 30)));
await tester.pump();
if (done()) break;
}
await tester.pump(const Duration(milliseconds: 300));
}
testWidgets('처음 연결: 지문 안내 → [지문 확인하고 연결] → [믿고 연결] → 목록 · 지문은 설정에 저장', (tester) async {
final root = Directory(p.join(tmp.path, 'root'))..createSync();
File(p.join(root.path, 'hello.txt')).writeAsStringSync('hi');
final s = await tester.runAsync(() => SftpTestServer.start(root: root.path, hostKeyFile: p.join(tmp.path, 'hk')));
server = s;
final local = Directory(p.join(tmp.path, 'local'))..createSync();
final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService()));
await tester.runAsync(() => c.updateSettings((x) => x
..sftpServers = [SftpServer(id: 's1', name: 'NAS', host: '127.0.0.1', port: s!.port, user: 'jj', password: 'pw')]
..explorerPaths = ['sftp://s1/', local.path]));
tester.view.physicalSize = const Size(1600, 900);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.reset);
await tester.runAsync(() => tester.pumpWidget(MaterialApp(home: ExplorerPage(c: c))));
await settle(tester, () => find.text('지문 확인하고 연결').evaluate().isNotEmpty);
expect(find.textContaining('처음 연결하는 서버입니다'), findsWidgets);
expect(find.textContaining(s!.fingerprint), findsWidgets, reason: '안내에 지문');
expect(find.text('hello.txt'), findsNothing, reason: '믿기 전에는 열지 않는다');
// 탭: 🔑 아이콘 · 서버 이름
expect(find.byIcon(Icons.vpn_key_outlined), findsWidgets);
await tester.tap(find.text('지문 확인하고 연결'));
await settle(tester, () => find.text('믿고 연결').evaluate().isNotEmpty);
expect(find.textContaining(s.fingerprint), findsWidgets, reason: '확인 창에도 지문');
await tester.tap(find.text('믿고 연결'));
await settle(tester, () => find.text('hello.txt').evaluate().isNotEmpty);
expect(find.text('hello.txt'), findsOneWidget);
expect(c.settings.sftpServers.single.hostKeyFingerprint, s.fingerprint);
expect(c.settings.sftpServers.single.hostKeyType, 'ssh-ed25519');
// 화면 내리기 · 연결 닫기
await tester.pumpWidget(const SizedBox());
await tester.runAsync(() async => SftpRegistry.configure(const []));
await tester.pump(const Duration(seconds: 1));
}, skip: !sftpTestServerAvailable);
}