JJ_MKVMaker/integration_test/windows_bigtext_shot_test.dart

118 lines
6.1 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 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.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/download_manager.dart';
import 'package:jj_mkvmaker/app/i18n_controller.dart';
import 'package:jj_mkvmaker/app/settings.dart';
import 'package:jj_mkvmaker/core/models.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/downloads_page.dart';
import 'package:jj_mkvmaker/ui/explorer_page.dart';
import 'package:jj_mkvmaker/ui/home_page.dart';
import 'package:jj_mkvmaker/ui/monitor_page.dart';
import 'package:jj_mkvmaker/ui/settings_page.dart';
import 'package:jj_mkvmaker/ui/theme.dart';
import 'package:path/path.dart' as p;
import 'support/temp_dir.dart';
/// 253 · 255 · 256 (관리자 지시 10/21): test/large_text_test 의 화면들을 실제 글꼴로 - 글자 1.6배 (412×900 · 900×412 · 1280×800) 와
/// 폰 크기 글자 1.0 (412×900 세로 · 900×412 가로) 에서 넘치지 않고, 누르는 것 (단추 · 고르기 · 입력 칸) 이 화면 폭 안에 있다. ko · ja
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
final out = Platform.environment['JJ_SHOT_DIR'] ?? '';
final pages = <String, Widget Function(AppController, DownloadManager)>{
'mkv': (c, d) => HomePage(c: c),
'explorer': (c, d) => ExplorerPage(c: c),
'rsync': (c, d) => ExplorerPage(c: c, rsync: true),
'monitor': (c, d) => MonitorPage(c: c),
'downloads': (c, d) => DownloadsPage(d: d),
'settings': (c, d) => SettingsPage(c: c),
};
final cases = [
for (final s in [const Size(412, 900), const Size(900, 412), const Size(1280, 800)]) (s, 1.6),
for (final s in [const Size(412, 900), const Size(900, 412)]) (s, 1.0),
];
for (final lang in ['ko', 'ja']) {
for (final MapEntry(key: name, value: page) in pages.entries) {
for (final (size, scale) in cases) {
final tag = '${name}_${lang}_${size.width.round()}x${size.height.round()}_s$scale';
testWidgets('253 · 255 · 256 $tag', (t) async {
t.view.physicalSize = size;
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_bigtext_');
appTempInto(tmp);
final video = p.join(tmp.path, '아주 긴 이름의 동영상 파일 - 시험용 2026.mp4');
File(video).writeAsStringSync('v');
Directory(p.join(tmp.path, 'sub')).createSync();
final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService()));
c.settings
..explorerPaths = [tmp.path, tmp.path]
..rsyncPaths = [tmp.path, tmp.path]
..copyTasks = [CopyTask(id: '1', sources: [tmp.path], dest: p.join(tmp.path, 'sub'), method: 'rsync', options: '-av')]
..liveSyncPairs = [LiveSyncPair(tmp.path, p.join(tmp.path, 'x'))];
c.videos.add(VideoItem(video));
// 256: 폰 가로에서 작업 기록을 켜도 목록이 여러 줄 보이는지 - 동영상 5개 · 기록 몇 줄
for (var i = 2; i <= 5; i++) {
final f = p.join(tmp.path, '에피소드 0$i.mp4');
File(f).writeAsStringSync('v');
c.videos.add(VideoItem(f));
}
for (var i = 1; i <= 3; i++) {
c.note('시험 기록 $i');
}
c.selected = c.videos.first;
final d = DownloadManager(backends: const [], settings: () => c.settings, readClipboard: () async => null);
addTearDown(d.dispose);
final shotKey = GlobalKey();
await t.pumpWidget(RepaintBoundary(
key: shotKey,
child: MaterialApp(
theme: buildTheme(),
debugShowCheckedModeBanner: false,
builder: (ctx, child) => MediaQuery(data: MediaQuery.of(ctx).copyWith(textScaler: TextScaler.linear(scale)), child: child!),
home: page(c, d),
),
));
for (var i = 0; i < 15; i++) {
await t.runAsync(() => Future<void>.delayed(const Duration(milliseconds: 40)));
await t.pump();
}
if (out.isNotEmpty) {
final r = shotKey.currentContext!.findRenderObject()! as RenderRepaintBoundary;
final img = await t.runAsync(() => r.toImage());
final bytes = await t.runAsync(() => img!.toByteData(format: ui.ImageByteFormat.png));
Directory(out).createSync(recursive: true);
File(p.join(out, 'bigtext_$tag.png')).writeAsBytesSync(bytes!.buffer.asUint8List());
}
expect(t.takeException(), isNull, reason: '$tag 넘침');
// 넘침 오류 없이 옆으로 밀려나는 것도 본다: 누르는 것은 화면 폭 안 (가로로 넘기는 막대 안의 것은 빼고)
final hit = find.byWidgetPredicate((w) =>
w is ButtonStyleButton || w is IconButton || w is Checkbox || w is DropdownButton || w is TextField || w is ChoiceChip || w is Radio);
final off = <String>[];
for (final e in hit.evaluate()) {
final inRow = e.findAncestorWidgetOfExactType<SingleChildScrollView>()?.scrollDirection == Axis.horizontal ||
e.findAncestorWidgetOfExactType<ListView>()?.scrollDirection == Axis.horizontal;
if (inRow) continue;
final r = t.getRect(find.byElementPredicate((x) => x == e));
if (r.left < -0.5 || r.right > size.width + 0.5) off.add('${e.widget.runtimeType} $r');
}
expect(off, isEmpty, reason: '$tag: 화면 밖 ${off.join(' · ')}');
await t.pumpWidget(const SizedBox());
await t.pump(const Duration(seconds: 1));
});
}
}
}
}