JJ_MKVMaker/integration_test/windows_option_problem_shot...

80 lines
3.7 KiB
Dart

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/i18n_controller.dart';
import 'package:jj_mkvmaker/core/sync_tools.dart';
import 'package:jj_mkvmaker/ui/sync_preview_view.dart';
import 'package:jj_mkvmaker/ui/theme.dart';
import 'package:path/path.dart' as p;
/// 관리자 지시 (10/20, 28 지적): 알아볼 수 없는 옵션 안내 - 끝 문구가 문제 종류에 맞는지, 412 에서 넘치지 않는지.
/// 확인 창의 빨간 글 (OptionProblemNote) 과 설정 칸 아래 글 (errorText, 3줄까지) 을 크기 412 · 960, 언어 ko · en · ja 로 찍는다.
/// 실행: flutter test integration_test\windows_option_problem_shot_test.dart -d windows (JJ_SHOT_DIR 에 PNG)
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
final out = Platform.environment['JJ_SHOT_DIR'] ?? p.join(Directory.systemTemp.path, 'jj_shots_optproblem');
const cases = [
'-a --delete --exclude="a.tmp --exclude=keep.txt', // 닫히지 않은 따옴표
'-a delete', // 경로로 읽힘
'-a --delete --exclude', // 값 없음
'-a ---delete «x»', // 이상한 글자
'-av delete --exclude', // 여러 종류
];
for (final lang in ['ko', 'en', 'ja']) {
for (final (w, hh) in [(412, 900), (960, 600)]) {
testWidgets('옵션 안내 $lang ${w}x$hh', (t) async {
t.view.physicalSize = Size(w.toDouble(), hh.toDouble());
t.view.devicePixelRatio = 1;
addTearDown(t.view.reset);
await t.runAsync(() => i18n.apply(lang, save: false));
addTearDown(() => i18n.apply('ko', save: false));
final shotKey = GlobalKey();
await t.pumpWidget(RepaintBoundary(
key: shotKey,
child: MaterialApp(
theme: buildTheme(),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: ListView(padding: const EdgeInsets.all(16), children: [
for (final o in cases) ...[
Text(o, style: const TextStyle(fontFamily: 'monospace', fontSize: 12)),
OptionProblemNote(optionProblems(o)),
const SizedBox(height: 8),
],
// 설정 칸 (copy_sync_settings 의 rsync 옵션 칸과 같은 폭 · 글 줄 수)
SizedBox(
width: 380,
child: TextField(
controller: TextEditingController(text: cases.last),
decoration: InputDecoration(
isDense: true,
border: const OutlineInputBorder(),
errorText: optionProblemText(optionProblems(cases.last)),
errorMaxLines: 3,
),
),
),
]),
),
),
));
for (var i = 0; i < 4; i++) {
await t.runAsync(() => Future<void>.delayed(const Duration(milliseconds: 60)));
await t.pump(const Duration(milliseconds: 60));
}
expect(t.takeException(), isNull, reason: '넘침');
expect(find.byType(OptionProblemNote), findsNWidgets(cases.length));
final b = shotKey.currentContext!.findRenderObject()! as RenderRepaintBoundary;
final img = await t.runAsync(() => b.toImage());
final bytes = await t.runAsync(() => img!.toByteData(format: ui.ImageByteFormat.png));
Directory(out).createSync(recursive: true);
File(p.join(out, 'optproblem_${lang}_$w.png')).writeAsBytesSync(bytes!.buffer.asUint8List());
});
}
}
}