109 lines
4.7 KiB
Dart
109 lines
4.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/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/explorer_controller.dart';
|
||
import 'package:jj_mkvmaker/ui/explorer/explorer_host.dart';
|
||
import 'package:jj_mkvmaker/ui/explorer/explorer_pane.dart';
|
||
import 'package:path/path.dart' as p;
|
||
|
||
/// E5d-1 약속 시험: lib/ui/explorer/explorer_controller.dart · explorer_host.dart 맨 위 약속.
|
||
/// Host 는 실제 화면이 해 준다 (실제 ScaffoldMessenger 의 알림 · 실제 다음 그리기). 폴더는 실제 시험 폴더, 설정은 메모리에만.
|
||
void main() {
|
||
late Directory tmp;
|
||
late String a, b, show;
|
||
setUp(() {
|
||
tmp = Directory.systemTemp.createTempSync('jj_ctl_');
|
||
a = p.join(tmp.path, 'A');
|
||
b = p.join(tmp.path, 'B');
|
||
show = p.join(a, 'Show');
|
||
Directory(show).createSync(recursive: true);
|
||
Directory(b).createSync();
|
||
File(p.join(show, 'ep1.mkv')).writeAsStringSync('1');
|
||
File(p.join(a, 'big.bin')).writeAsBytesSync(List.filled(3000, 0));
|
||
File(p.join(a, 'small.txt')).writeAsStringSync('s');
|
||
});
|
||
tearDown(() => tmp.deleteSync(recursive: true));
|
||
|
||
Future<(ExplorerController, _HostState)> open(WidgetTester t) async {
|
||
final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService()));
|
||
final key = GlobalKey<_HostState>();
|
||
await t.pumpWidget(MaterialApp(home: _Host(key: key)));
|
||
final ctl = ExplorerController(c, rsync: false, host: key.currentState!);
|
||
ctl.local = [(a, 'A:'), (b, 'B:')];
|
||
addTearDown(ctl.dispose);
|
||
return (ctl, key.currentState!);
|
||
}
|
||
|
||
testWidgets('이동: 장치부터 펼치고 읽음 · 지금 폴더 · 기억 · 스크롤 부탁 · 뒤로/앞으로', (t) async {
|
||
final (ctl, host) = await open(t);
|
||
final q = ctl.panes[0];
|
||
await t.runAsync(() => ctl.goTo(q, show));
|
||
expect(q.root, a);
|
||
expect(q.current, show);
|
||
expect(q.expanded, containsAll([a, show]));
|
||
expect([for (final e in q.cache[show]!) p.basename(e.path)], ['ep1.mkv']);
|
||
expect(host.revealed, [show], reason: 'Host 에 스크롤 부탁');
|
||
expect(ctl.c.settings.explorer.paths.first, show, reason: '마지막 폴더 기억');
|
||
await t.runAsync(() => ctl.goTo(q, b));
|
||
expect(q.root, b, reason: '다른 장치');
|
||
await t.runAsync(() => ctl.travel(q, forward: false));
|
||
expect(q.current, show);
|
||
await t.runAsync(() => ctl.travel(q, forward: true));
|
||
expect(q.current, b);
|
||
});
|
||
|
||
testWidgets('뒤로 갈 곳이 지워졌으면 내역에서 빼고 실제 알림으로 까닭 · 정렬 바꾸기 · 숨기기 토글', (t) async {
|
||
final (ctl, host) = await open(t);
|
||
final q = ctl.panes[0];
|
||
await t.runAsync(() => ctl.goTo(q, show));
|
||
await t.runAsync(() => ctl.goTo(q, b));
|
||
Directory(show).deleteSync(recursive: true);
|
||
await t.runAsync(() => ctl.travel(q, forward: false));
|
||
await t.pump();
|
||
expect(q.current, b);
|
||
expect(find.textContaining('내역에서 뺐습니다'), findsOneWidget, reason: '실제 ScaffoldMessenger 알림');
|
||
await t.runAsync(() => ctl.goTo(q, a));
|
||
await t.runAsync(() => ctl.setSort(a, 'size', true));
|
||
expect(p.basename(q.cache[a]!.where((e) => !e.isDir).first.path), 'big.bin');
|
||
expect(ctl.sortOf(a), ('size', true));
|
||
var n = 0;
|
||
ctl.addListener(() => n++);
|
||
ctl.toggleAppHidden();
|
||
expect([ctl.showAppHidden, n], [true, 1]);
|
||
expect(host.alive, isTrue);
|
||
});
|
||
|
||
testWidgets('화면 밖 글: 경로 보이기 · 서버 목록 · 장치 맞추기', (t) async {
|
||
final (ctl, _) = await open(t);
|
||
expect(ctl.volumeOf(p.join(b, 'x')), b);
|
||
expect(ctl.volumes.take(2).map((v) => v.$2), ['A:', 'B:']);
|
||
expect(ctl.displayPath(show), Platform.isAndroid ? 'A: › Show' : show);
|
||
});
|
||
}
|
||
|
||
/// 실제 화면이 해 주는 Host (실제 ScaffoldMessenger 알림 · 실제 다음 그리기)
|
||
class _Host extends StatefulWidget {
|
||
const _Host({super.key});
|
||
@override
|
||
State<_Host> createState() => _HostState();
|
||
}
|
||
|
||
class _HostState extends State<_Host> implements ExplorerHost {
|
||
final revealed = <String>[];
|
||
@override
|
||
bool get alive => mounted;
|
||
@override
|
||
void snack(String text) => ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(text)));
|
||
@override
|
||
void reveal(ExplorerPane pane, String path) => revealed.add(path);
|
||
@override
|
||
void afterFrame(VoidCallback f) => WidgetsBinding.instance.addPostFrameCallback((_) => f());
|
||
@override
|
||
Widget build(BuildContext context) => const Scaffold(body: SizedBox());
|
||
}
|