JJ_MKVMaker/test/explorer_controller_contrac...

109 lines
4.7 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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.explorerPaths.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());
}