137 lines
6.7 KiB
Dart
137 lines
6.7 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/webdav.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/app_shell.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 'explorer_test.dart' show act, doubleTap, settle;
|
|
import 'support/dav_server.dart';
|
|
|
|
class _Shell extends NoopShell {
|
|
final opened = <String>[];
|
|
@override
|
|
Future<bool> openWith(String path, {bool choose = false}) async {
|
|
opened.add(path);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
late Directory tmp, remote;
|
|
late String left;
|
|
late TestDavServer server;
|
|
late _Shell shell;
|
|
late AppController c;
|
|
|
|
setUp(() async {
|
|
tmp = Directory.systemTemp.createTempSync('jj_explorer_dav_');
|
|
left = p.join(tmp.path, 'left');
|
|
remote = Directory(p.join(tmp.path, 'remote'))..createSync();
|
|
File(p.join(left, 'doc.txt'))
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('hello');
|
|
File(p.join(left, 'sub', 'inner.txt'))
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('inner');
|
|
File(p.join(remote.path, '원격', 'note.txt'))
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('remote');
|
|
server = TestDavServer(remote);
|
|
await server.start();
|
|
shell = _Shell();
|
|
c = AppController(PlatformServices(
|
|
mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService(), shell: shell));
|
|
});
|
|
tearDown(() async {
|
|
DavRegistry.configure([]);
|
|
await server.stop();
|
|
tmp.deleteSync(recursive: true);
|
|
});
|
|
|
|
Future<void> pump(WidgetTester tester, Widget page) async {
|
|
HttpOverrides.global = null; // testWidgets 는 HttpClient 를 막아 둔다 - 이 시험은 실제 (로컬) 서버에 연결
|
|
tester.view.physicalSize = const Size(1600, 900);
|
|
tester.view.devicePixelRatio = 1;
|
|
addTearDown(tester.view.reset);
|
|
await tester.runAsync(() => tester.pumpWidget(MaterialApp(home: page)));
|
|
}
|
|
|
|
testWidgets('파일 탐색기: WebDAV 탭 → 서버 추가 (연결 확인) → 목록 · 열기 (받아서) · 로컬 → WebDAV 복사', (tester) async {
|
|
c.settings.explorerPaths = [left, left];
|
|
await pump(tester, ExplorerPage(c: c));
|
|
await settle(tester, () => find.text('doc.txt').evaluate().isNotEmpty);
|
|
// 서버가 없으면 위쪽 저장 장치 옆에 "WebDAV" 탭 (창마다)
|
|
expect(find.text('WebDAV'), findsNWidgets(2));
|
|
await act(tester, () => tester.tap(find.text('WebDAV').last));
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('WebDAV 서버 추가'), findsOneWidget);
|
|
await tester.enterText(find.widgetWithText(TextField, '이름 (탭에 보임, 비우면 주소)'), '집 NAS');
|
|
await tester.enterText(find.widgetWithText(TextField, '주소'), server.url);
|
|
await tester.enterText(find.widgetWithText(TextField, '아이디'), 'user');
|
|
await tester.enterText(find.widgetWithText(TextField, '비밀번호'), 'pass');
|
|
await tester.pump();
|
|
await act(tester, () => tester.tap(find.text('연결 확인')));
|
|
await settle(tester, () => find.textContaining('연결됨').evaluate().isNotEmpty);
|
|
expect(find.textContaining('연결됨: 항목 1개'), findsOneWidget);
|
|
await act(tester, () => tester.tap(find.widgetWithText(FilledButton, '저장')));
|
|
// 저장하면 설정에 남고 오른쪽 창이 그 서버로
|
|
await settle(tester, () => find.text('원격').evaluate().isNotEmpty);
|
|
expect(c.settings.webdavServers.single.url, server.url);
|
|
final id = c.settings.webdavServers.single.id;
|
|
expect(find.text('집 NAS'), findsNWidgets(3)); // 두 창의 탭 + 오른쪽 창의 맨 위 줄
|
|
expect(find.text('WebDAV'), findsNothing);
|
|
|
|
// WebDAV 폴더 펼치기 · 파일 두 번 누르기 = 임시 폴더로 받아 기본 앱으로
|
|
await act(tester, () => tester.tap(find.text('원격')));
|
|
await settle(tester, () => find.text('note.txt').evaluate().isNotEmpty);
|
|
await doubleTap(tester, find.text('note.txt'));
|
|
await settle(tester, () => shell.opened.isNotEmpty);
|
|
expect(p.split(shell.opened.single), containsAllInOrder(['jj_webdav', id, '원격', 'note.txt']));
|
|
expect(File(shell.opened.single).readAsStringSync(), 'remote');
|
|
|
|
// 왼쪽 doc.txt → 오른쪽 (WebDAV 원격 폴더) 으로 복사
|
|
await act(tester, () => tester.tap(find.text('원격')));
|
|
await settle(tester, () => false, rounds: 15);
|
|
await act(tester, () => tester.tap(find.text('doc.txt')));
|
|
await settle(tester, () => false, rounds: 15);
|
|
await act(tester, () => tester.tap(find.text('복사').first));
|
|
await tester.pumpAndSettle();
|
|
expect(find.textContaining('☁ 집 NAS/원격'), findsOneWidget);
|
|
await act(tester, () => tester.tap(find.widgetWithText(FilledButton, '복사')));
|
|
final up = File(p.join(remote.path, '원격', 'doc.txt'));
|
|
await settle(tester, () => up.existsSync() && find.byType(LinearProgressIndicator).evaluate().isEmpty);
|
|
expect(up.readAsStringSync(), 'hello');
|
|
});
|
|
|
|
testWidgets('Rsync 화면: 로컬 ↔ WebDAV 폴더 → (앱이 직접 맞춤 · rsync 필요 없음)', (tester) async {
|
|
final s = DavServer(id: 'nas', name: '집 NAS', url: server.url, user: 'user', password: 'pass');
|
|
c.settings
|
|
..webdavServers = [s]
|
|
..rsyncPaths = [left, 'dav://nas/'];
|
|
DavRegistry.configure([s]);
|
|
await pump(tester, ExplorerPage(c: c, rsync: true));
|
|
await settle(tester, () => find.text('sub').evaluate().isNotEmpty && find.text('원격').evaluate().isNotEmpty);
|
|
expect(find.byIcon(Icons.cloud), findsOneWidget); // 오른쪽 창 맨 위 줄
|
|
await act(tester, () => tester.tap(find.text('sub')));
|
|
await act(tester, () => tester.tap(find.text('원격')));
|
|
await settle(tester, () => false, rounds: 5);
|
|
await act(tester, () => tester.tap(find.text('좌 → 우')));
|
|
await tester.pumpAndSettle();
|
|
expect(find.text('→ ☁ 집 NAS/원격/'), findsOneWidget);
|
|
expect(find.textContaining('WebDAV: rsync 대신 앱이 직접 맞춥니다'), findsOneWidget);
|
|
await act(tester, () => tester.tap(find.widgetWithText(FilledButton, '실행')));
|
|
final got = File(p.join(remote.path, '원격', 'inner.txt'));
|
|
await settle(tester, () => got.existsSync() && find.byType(LinearProgressIndicator).evaluate().isEmpty, rounds: 200);
|
|
expect(got.readAsStringSync(), 'inner');
|
|
expect(File(p.join(remote.path, '원격', 'note.txt')).existsSync(), isTrue); // 지우기 없이
|
|
expect(c.settings.copyTasks.single.dest, 'dav://nas/원격'); // 모니터링에 남음
|
|
});
|
|
}
|