JJ_MKVMaker/integration_test/translate_split_test.dart

106 lines
4.9 KiB
Dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:jj_mkvmaker/app/app_controller.dart';
import 'package:jj_mkvmaker/app/bookmarks_controller.dart';
import 'package:jj_mkvmaker/app/download_manager.dart';
import 'package:jj_mkvmaker/core/languages.dart';
import 'package:jj_mkvmaker/core/models.dart';
import 'package:jj_mkvmaker/core/output_paths.dart';
import 'package:jj_mkvmaker/services/platform_services.dart';
import 'package:jj_mkvmaker/ui/browser_page.dart';
import 'support/temp_dir.dart';
import 'package:path/path.dart' as p;
/// 실제 NLLB + 실제 Edge(WebView2): 브라우저를 보면서 영어 자막 → 한국어 번역 → MKV 를
/// 대기열로 돌리고, 화면 분할 "작업 현황" 에서 진행을 확인 (모델이 JJ_MKVMAKER_MODELS 에 있어야 함)
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
testWidgets('브라우저 + 작업 현황: 영어 자막 → 한국어 번역 → MKV (대기열)', (tester) async {
final dir = testTempDir('jj_split_');
final video = p.join(dir.path, 'movie.mp4');
final r = await Process.run('ffmpeg', [
'-y', '-f', 'lavfi', '-i', 'testsrc=size=320x240:rate=10', '-f', 'lavfi', '-i', 'sine',
'-t', '8', '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-c:a', 'aac', video,
]);
expect(r.exitCode, 0, reason: '${r.stderr}');
final en = p.join(dir.path, 'movie.en.srt');
File(en).writeAsStringSync('1\n00:00:01,000 --> 00:00:03,000\nGood morning, how are you today?\n\n'
'2\n00:00:04,000 --> 00:00:06,000\nI want to watch this movie with my family.\n\n');
final c = AppController(PlatformServices.create());
final server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
server.listen((req) async {
req.response
..headers.contentType = ContentType.html
..write('<html><head><title>JJ</title></head><body>hello</body></html>');
await req.response.close();
});
await tester.runAsync(() async {
await c.init();
await c.addVideos([video]);
});
c.settings.webViewDataDir = testTempDir('jj_webview_').path;
final v = c.videos.single;
// 같은 폴더의 movie.en.srt 가 자동으로 잡힘
final s = v.subtitles.firstWhere((x) => x.path != null && p.equals(x.path!, en));
// ignore: avoid_print
print('RESULT 자동 추가된 자막: ${s.displayName} 언어=${s.language.code}');
final bm = BookmarksController(p.join(dir.path, 'bm.json'));
final d = DownloadManager(backends: const [], settings: () => c.settings, readClipboard: () async => null);
await tester.pumpWidget(MaterialApp(
home: BrowserPage(c: c, bookmarks: bm, downloads: d, initialUrl: 'http://127.0.0.1:${server.port}/')));
await tester.pump(const Duration(milliseconds: 500));
// 번역 시작 + 바로 MKV 만들기 (대기열)
final sw = Stopwatch()..start();
final tr = c.translateSubtitle(v, s, {languageOf('ko')});
final mkv = c.buildAll();
await tester.pump();
expect(c.busy, isTrue);
expect(c.pendingJobs, ['MKV 만들기']);
// 화면 분할 열기 → 진행 표시
await tester.tap(find.byTooltip('작업 현황 보기 · 화면 분할 (Ctrl+Shift+J)'));
await tester.pump(const Duration(milliseconds: 300));
expect(find.text('작업 현황'), findsOneWidget);
expect(find.textContaining('▶ 자막 번역'), findsOneWidget);
expect(find.textContaining('MKV 만들기 (대기)'), findsOneWidget);
final phases = <String>{};
while (c.busy) {
await tester.runAsync(() => Future<void>.delayed(const Duration(milliseconds: 200)));
await tester.pump();
if (v.phase != null) phases.add(v.phase!.replaceAll(RegExp(r'\d+%'), '%'));
}
await tester.runAsync(() => Future.wait([tr, mkv]));
await tester.pump();
// ignore: avoid_print
print('RESULT 걸린 시간 ${sw.elapsedMilliseconds}ms, 단계: ${phases.join(' | ')}');
// ignore: avoid_print
print(c.logs.join('\n'));
expect(find.text('쉬는 중'), findsOneWidget);
expect(find.text('MKV 완성'), findsOneWidget);
final koPath = languageSubtitlePath(video, languageOf('ko'));
final ko = File(koPath).readAsStringSync();
// ignore: avoid_print
print('RESULT --- ko ---\n$ko');
expect(RegExp(r'[가-힣]').hasMatch(ko), isTrue);
expect(ko, contains('00:00:04,000 --> 00:00:06,000'));
expect(v.status, JobStatus.done, reason: v.message);
final info = await tester.runAsync(() => c.services.mediaTool.probe(outputMkvPath(video)));
final langs = info!.ofType('subtitle').map((x) => x.language).toList();
// ignore: avoid_print
print('RESULT MKV 자막 언어: $langs');
expect(langs, containsAll(['kor', 'eng']));
await tester.pumpWidget(const SizedBox());
d.dispose();
await server.close(force: true);
}, timeout: const Timeout(Duration(minutes: 15)));
}