JJ_MKVMaker/integration_test/windows_hdr360_shot_test.dart

122 lines
5.2 KiB
Dart
Raw Permalink 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:async';
import 'dart:io';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:image/image.dart' as img;
import 'package:integration_test/integration_test.dart';
import 'package:jj_mkvmaker/app/download_manager.dart';
import 'package:jj_mkvmaker/app/i18n_controller.dart';
import 'package:jj_mkvmaker/app/settings.dart';
import 'package:jj_mkvmaker/core/download_detect.dart';
import 'package:jj_mkvmaker/l10n/tr.dart';
import 'package:jj_mkvmaker/services/downloader.dart';
import 'package:jj_mkvmaker/ui/ai_upscale_ui.dart';
import 'package:jj_mkvmaker/ui/downloads_page.dart';
import 'package:jj_mkvmaker/ui/theme.dart';
import 'package:path/path.dart' as p;
import 'support/temp_dir.dart';
/// 받는 중에서 멈춰 있는 받기 (네트워크 없음)
class _Backend implements DownloadBackend {
@override
DownloadKind get kind => DownloadKind.video;
@override
Future<(String, List<PlaylistEntry>)?> expandPlaylist(String url) async => null;
@override
Future<void> start(DownloadTask t, void Function() changed) async {
t.state = DownloadState.downloading;
changed();
}
@override
Future<void> pause(DownloadTask t) async {}
@override
Future<void> cancel(DownloadTask t) async {}
@override
Future<void> shutdown() async {}
}
/// 관리자 지시 (10/21, F11 다음): "제목 + 단추 + ✕" 모양의 다른 창도 360 에서 - ① 다운로드 종료 확인 창 ② AI 해상도 비교 화면.
/// 넘치지 않고 ✕ (닫기 · 종료) 와 [저장] 이 화면 안. ko · ja × 360 · 412
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
final out = Platform.environment['JJ_SHOT_DIR'] ?? '';
for (final lang in ['ko', 'ja']) {
for (final (w, h) in [(360, 780), (412, 900)]) {
testWidgets('제목 줄 $lang ${w}x$h', (t) async {
t.view.physicalSize = Size(w.toDouble(), h.toDouble());
t.view.devicePixelRatio = 1;
addTearDown(t.view.reset);
await t.runAsync(() => i18n.apply(lang, save: false));
addTearDown(() => i18n.apply('ko', save: false));
final tmp = testTempDir('jj_hdr360_');
final shotKey = GlobalKey();
final navKey = GlobalKey<NavigatorState>();
await t.pumpWidget(MaterialApp(
theme: buildTheme(),
debugShowCheckedModeBanner: false,
navigatorKey: navKey,
builder: (context, child) => RepaintBoundary(key: shotKey, child: child),
home: const Scaffold(body: SizedBox.expand()),
));
Future<void> settle([int n = 8]) async {
for (var i = 0; i < n; i++) {
await t.runAsync(() => Future<void>.delayed(const Duration(milliseconds: 50)));
await t.pump();
}
}
Future<void> shot(String name) async {
await settle(3);
if (out.isNotEmpty) {
final b = shotKey.currentContext!.findRenderObject()! as RenderRepaintBoundary;
final im = await t.runAsync(() => b.toImage());
final bytes = await t.runAsync(() => im!.toByteData(format: ui.ImageByteFormat.png));
Directory(out).createSync(recursive: true);
File(p.join(out, 'hdr_${name}_${lang}_$w.png')).writeAsBytesSync(bytes!.buffer.asUint8List());
}
expect(t.takeException(), isNull, reason: '$name 넘침');
}
void inside(Finder f, String what) {
final r = t.getRect(f);
expect(r.left >= -0.5 && r.right <= w + 0.5, isTrue, reason: '$what 화면 안 ($r)');
}
// ① 다운로드 종료 확인 창 (받는 중 2개)
final s = AppSettings()..downloadRoot = tmp.path;
final d = DownloadManager(backends: [_Backend()], settings: () => s, readClipboard: () async => null);
addTearDown(d.dispose);
d.addPage('https://cdn.example.com/a')!.title = 'アップロードされた とても長い 動画のタイトル - 第1話 高画質版';
d.addPage('https://cdn.example.com/b')!.title = 'Test video 2';
await settle();
unawaited(confirmExit(navKey.currentContext!, d));
await settle();
inside(find.byTooltip(tr('종료')), '✕ (종료)');
await shot('1_exit');
navKey.currentState!.popUntil((r) => r.isFirst);
await settle();
// ② AI 해상도 비교 화면 - 긴 그림 이름
final a = p.join(tmp.path, 'a.png');
final b = p.join(tmp.path, 'b.png');
File(a).writeAsBytesSync(img.encodePng(img.Image(width: 40, height: 30)));
File(b).writeAsBytesSync(img.encodePng(img.Image(width: 80, height: 60)));
unawaited(navKey.currentState!.push<bool>(MaterialPageRoute(
builder: (_) => UpscaleCompareView(original: a, upscaled: b, title: '아주 긴 이름의 만화 스캔 - 제1권 012쪽_x2.png'))));
await settle(12);
inside(find.byTooltip(tr('닫기')), '✕ (닫기)');
inside(find.text(tr('저장')), '[저장]');
inside(find.text(tr('올린 것')), '[올린 것]');
expect(t.getRect(find.text('아주 긴 이름의 만화 스캔 - 제1권 012쪽_x2.png')).width > 40, isTrue, reason: '제목이 보임');
await shot('2_compare');
});
}
}
}