JJ_MKVMaker/integration_test/cef_dns_real_test.dart

81 lines
4.1 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/net_guard.dart';
import 'package:jj_mkvmaker/platform/windows/cef_runtime.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/app_actions.dart';
import 'package:jj_mkvmaker/ui/browser_page.dart';
import 'package:path/path.dart' as p;
/// 실제 망 (Windows): DNS 강제 (8.8.8.8) 상태에서 Chrome 엔진 (CEF) 이 앱 안 프록시의 인증 (비밀값) 에 답해 페이지를 여는지.
/// Chrome 엔진은 실행 파일 옆 cef 폴더에 설치되고 다음 실행부터 쓰이므로 두 번 돌린다:
/// 1번째: 없으면 받아서 설치하고 끝 ("RESULT 설치함")
/// 2번째: 엔진을 Chrome 으로 바꿔 example.com 이 열리고 8.8.8.8 이 이름을 푸는지
/// 데이터는 JJ_MKVMAKER_DATA (없으면 임시 폴더) 에만. 끝나면 시험한 사람이 cef 폴더 (빌드 폴더 안) 와 데이터 폴더를 지운다.
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
testWidgets('DNS 강제 · Chrome 엔진 실제 연결', (tester) async {
if (!CefRuntime.installed) {
await tester.runAsync(() => CefRuntime.install(onProgress: (_, _) {}));
// ignore: avoid_print
print('RESULT 설치함 (${CefRuntime.dir}) - 다시 실행하면 Chrome 엔진으로 시험');
expect(CefRuntime.installed, isTrue);
return;
}
CefRuntime.rememberStartState();
expect(CefRuntime.readyThisRun, isTrue);
final data = Platform.environment['JJ_MKVMAKER_DATA'] ?? Directory.systemTemp.createTempSync('jj_cef_real_').path;
Directory(data).createSync(recursive: true);
final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService()));
c.settings
..webViewDataDir = p.join(data, 'webview')
..browserEngine = 'chrome';
final answered = <String>[];
final logs = <String>[];
final g = NetGuard.instance
..config = (() => c.settings.dnsConfig)
..log = logs.add;
g.resolver.onAnswer = (h, s) => answered.add('$h@$s');
// 원인 가르기: JJ_CEF_NO_PROXY=1 이면 프록시 없이 (Chrome 엔진만)
final noProxy = Platform.environment['JJ_CEF_NO_PROXY'] == '1';
if (noProxy) c.settings.dnsMode = 'system';
expect(c.settings.dnsMode, noProxy ? 'system' : 'custom');
await tester.runAsync(g.ensure);
HttpOverrides.global = JjHttpOverrides();
Future<void> wait(int ms) async {
for (var i = 0; i < ms ~/ 200; i++) {
await tester.runAsync(() => Future<void>.delayed(const Duration(milliseconds: 200)));
await tester.pump();
}
}
final bm = BookmarksController(p.join(data, 'bm.json'));
await tester.pumpWidget(MaterialApp(
builder: (context, child) => AppScope(controller: c, bookmarks: bm, child: child!),
home: BrowserPage(c: c, bookmarks: bm, initialUrl: 'https://example.com/'),
));
String title = '';
for (var i = 0; i < 90 && !title.contains('Example'); i++) {
await wait(500);
title = '${await tester.runAsync(() async => BrowserPage.debugNav?.evaluate('document.title'))}';
}
// ignore: avoid_print
print('RESULT Chrome 엔진 example.com 제목: $title, 답한 DNS: ${answered.where((a) => a.startsWith('example.com'))}\n'
'RESULT 웹 뷰: ${BrowserPage.debugNav.runtimeType} / 기록: ${logs.take(8).join(' | ')}');
// ignore: avoid_print
print('RESULT 화면 글: ${find.byType(Text).evaluate().map((e) => (e.widget as Text).data).whereType<String>().take(30).join(' / ')}');
expect(title, contains('Example'));
if (!noProxy) expect(answered, contains('example.com@8.8.8.8'));
await tester.pumpWidget(const SizedBox());
await wait(1000);
}, timeout: const Timeout(Duration(minutes: 10)));
}