131 lines
6.8 KiB
Dart
131 lines
6.8 KiB
Dart
import 'dart:async';
|
|
import 'dart:io';
|
|
|
|
import 'package:flutter/gestures.dart';
|
|
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/file_ops.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 'explorer_test.dart' show calm;
|
|
void main() {
|
|
late Directory tmp;
|
|
late AppController c;
|
|
late Completer<bool> stuck;
|
|
var dead = <String>{};
|
|
|
|
setUp(() {
|
|
tmp = Directory.systemTemp.createTempSync('jj_drives_');
|
|
File(p.join(tmp.path, 'left', 'doc.txt'))
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('x');
|
|
Directory(p.join(tmp.path, 'right')).createSync();
|
|
c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService()));
|
|
c.settings.explorerPaths = [p.join(tmp.path, 'left'), p.join(tmp.path, 'right')];
|
|
stuck = Completer<bool>();
|
|
dead = {r'R:\'};
|
|
// T: 시험 폴더 (정상) · Q: 응답 없는 네트워크 드라이브 · R: 연결 안 된 드라이브
|
|
ExplorerPage.debugVolumes = () => [(tmp.path, 'T:'), (r'Q:\', 'Q:'), (r'R:\', 'R:')];
|
|
ExplorerPage.probeDrive = (path) => path == r'Q:\' ? stuck.future : Future.value(!dead.contains(path));
|
|
});
|
|
tearDown(() {
|
|
ExplorerPage.debugVolumes = null;
|
|
ExplorerPage.probeDrive = (path) => Directory(path).exists();
|
|
if (!stuck.isCompleted) stuck.complete(false);
|
|
tmp.deleteSync(recursive: true);
|
|
});
|
|
|
|
Future<void> settle(WidgetTester tester, bool Function() done) async {
|
|
for (var i = 0; i < 50 && !done(); i++) {
|
|
await tester.runAsync(() => Future<void>.delayed(const Duration(milliseconds: 50)));
|
|
await tester.pump();
|
|
}
|
|
}
|
|
|
|
testWidgets('165: 응답 없는 드라이브가 있어도 첫 화면이 바로 뜨고, 연결 안 된 드라이브는 숨기지 않고 "연결 안 됨" · 누르면 다시 연결', (tester) async {
|
|
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('doc.txt').evaluate().isNotEmpty);
|
|
// Q: 는 끝내 대답하지 않지만 목록 · 두 창은 바로 (Q: 를 기다리지 않음)
|
|
expect(find.text('doc.txt'), findsOneWidget);
|
|
// 걸린 시간 (전체 시험 중 바쁘면 늘어난다) 대신: Q: 가 끝내 대답하지 않은 채로 목록이 떴다
|
|
expect(stuck.isCompleted, isFalse);
|
|
expect(find.text('Q:'), findsWidgets, reason: '응답 없는 드라이브도 목록에 (확인 중)');
|
|
// R: 는 숨기지 않고 "연결 안 됨"
|
|
await settle(tester, () => find.textContaining('연결 안 됨').evaluate().isNotEmpty);
|
|
expect(find.textContaining('R: · 연결 안 됨'), findsWidgets);
|
|
// 누르면 다시 연결: 아직 안 되면 알림
|
|
await tester.tap(find.textContaining('R: · 연결 안 됨').first);
|
|
await settle(tester, () => find.textContaining('R:\\ 에 연결할 수 없습니다').evaluate().isNotEmpty);
|
|
expect(find.textContaining(r'R:\ 에 연결할 수 없습니다'), findsOneWidget);
|
|
// 연결되면 "연결 안 됨" 이 사라진다
|
|
dead = {};
|
|
await tester.tap(find.textContaining('R: · 연결 안 됨').first);
|
|
await settle(tester, () => find.textContaining('R: · 연결 안 됨').evaluate().isEmpty);
|
|
expect(find.textContaining('R: · 연결 안 됨'), findsNothing);
|
|
});
|
|
|
|
testWidgets('202: 드라이브가 많아 탭이 넘쳐도 [경로 입력] · WebDAV 를 누를 수 있고, 휠로 탭이 옆으로 · 빈 드라이브는 뒤로', (tester) async {
|
|
// 빈 (연결 안 된) 드라이브가 앞쪽에 많은 PC
|
|
final empties = [for (final l in 'GHIJKLNOPS'.split('')) ('$l:\\', '$l:')];
|
|
dead = {for (final e in empties) e.$1};
|
|
ExplorerPage.debugVolumes = () => [...empties, (tmp.path, 'T:')];
|
|
ExplorerPage.probeDrive = (path) => Future.value(!dead.contains(path));
|
|
c.settings
|
|
..explorerLayout = 'dual'
|
|
..explorerOrientation = 'side';
|
|
tester.view.physicalSize = const Size(1280, 800);
|
|
tester.view.devicePixelRatio = 1;
|
|
addTearDown(tester.view.reset);
|
|
await tester.runAsync(() => tester.pumpWidget(MaterialApp(home: ExplorerPage(c: c))));
|
|
await settle(tester, () => find.text('doc.txt').evaluate().isNotEmpty);
|
|
await settle(tester, () => find.textContaining('S: ·').evaluate().isNotEmpty);
|
|
// 넓은 창: 끝 버튼이 화면 안에 (눌러서 창이 뜬다)
|
|
final pathBtn = find.byTooltip('경로 입력');
|
|
expect(pathBtn, findsNWidgets(2));
|
|
for (final e in pathBtn.evaluate()) {
|
|
expect(tester.getRect(find.byWidget(e.widget).first).right, lessThanOrEqualTo(1280));
|
|
}
|
|
await tester.tap(pathBtn.first);
|
|
await calm(tester);
|
|
expect(find.byType(AlertDialog), findsOneWidget);
|
|
await tester.tap(find.text('취소').last);
|
|
await calm(tester);
|
|
// 정상 드라이브 (T:) 가 빈 드라이브들보다 앞
|
|
expect(tester.getTopLeft(find.text('T:').first).dx, lessThan(tester.getTopLeft(find.textContaining('G: ·').first).dx));
|
|
// 휠 (위 · 아래) 로 탭 줄이 옆으로 (왼쪽 창의 T: 탭이 왼쪽으로 밀린다)
|
|
final before = tester.getTopLeft(find.text('T:').first).dx;
|
|
final pointer = TestPointer(1, PointerDeviceKind.mouse);
|
|
await tester.sendEventToBinding(pointer.hover(tester.getCenter(find.text('T:').first)));
|
|
await tester.sendEventToBinding(pointer.scroll(const Offset(0, 120)));
|
|
await tester.pump();
|
|
expect(tester.getTopLeft(find.text('T:').first).dx, lessThan(before - 10));
|
|
// 좁은 창 (위아래 두 창 · 폰): 끝 버튼은 [⋮] 하나로 늘 보임 → 경로 입력
|
|
tester.view.physicalSize = const Size(560, 900);
|
|
await calm(tester);
|
|
expect(find.byTooltip('경로 입력 · 네트워크 서버'), findsWidgets);
|
|
await tester.tap(find.byTooltip('경로 입력 · 네트워크 서버').first);
|
|
await calm(tester);
|
|
await tester.tap(find.text('경로 입력').last);
|
|
await calm(tester);
|
|
expect(find.byType(AlertDialog), findsOneWidget);
|
|
await tester.tap(find.text('취소').last);
|
|
await calm(tester);
|
|
expect(tester.takeException(), isNull, reason: '넘침 (RenderFlex overflow) 없음');
|
|
});
|
|
|
|
test('165: 드라이브 목록은 열어 보지 않고 Windows 에게 받는다 (빠름)', () {
|
|
final sw = Stopwatch()..start();
|
|
final d = windowsDrives();
|
|
expect(sw.elapsedMilliseconds, lessThan(500));
|
|
expect(d.map((e) => e.$2), contains('C:'));
|
|
}, skip: !Platform.isWindows);
|
|
}
|