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/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/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 final DownloadKind kind; _Backend(this.kind); @override Future<(String, List)?> expandPlaylist(String url) async => null; @override Future start(DownloadTask t, void Function() changed) async { t ..state = DownloadState.downloading ..progress = 0.4 ..speed = '1.2MB/s' ..title = kind == DownloadKind.video ? 'Test video' : 'ubuntu-24.04.1-desktop-amd64.iso'; changed(); } @override Future pause(DownloadTask t) async => t.state = DownloadState.paused; @override Future cancel(DownloadTask t) async => t.state = DownloadState.cancelled; @override Future shutdown() async {} } /// 185 (관리자 지시 10/21): [다운로드 취소] 를 누르면 묻는 창 - [계속 받기] 면 그대로 받는다. ko · en · ja × 412 · 960 void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); final out = Platform.environment['JJ_SHOT_DIR'] ?? ''; for (final lang in ['ko', 'en', 'ja']) { for (final (w, h) in [(412, 900), (960, 600)]) { testWidgets('185 계속 받기 $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_dlcancel_'); final d = DownloadManager( backends: [_Backend(DownloadKind.video), _Backend(DownloadKind.torrent)], settings: () => AppSettings()..downloadRoot = tmp.path, readClipboard: () async => null, ); final shotKey = GlobalKey(); await t.pumpWidget(RepaintBoundary( key: shotKey, child: MaterialApp(theme: buildTheme(), debugShowCheckedModeBanner: false, home: DownloadsPage(d: d)), )); Future settle([int n = 8]) async { for (var i = 0; i < n; i++) { await t.runAsync(() => Future.delayed(const Duration(milliseconds: 60))); await t.pump(); } } Future shot(String name) async { await settle(3); expect(t.takeException(), isNull, reason: '$name 넘침'); if (out.isEmpty) return; 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, 'dlcancel_${name}_${lang}_$w.png')).writeAsBytesSync(bytes!.buffer.asUint8List()); } d.add('https://youtu.be/AAA111'); d.add('magnet:?xt=urn:btih:0123456789abcdef0123456789abcdef01234567'); await settle(); await t.tap(find.text(tr('전체 선택'))); await settle(); await t.tap(find.text(tr('다운로드 취소'))); await settle(); expect(find.text(trf('선택한 다운로드 {0}개를 취소할까요? 잠깐 멈추려면 [일시정지] 를 쓰세요.', [2])), findsOneWidget); await shot('1_ask'); await t.tap(find.text(tr('계속 받기'))); await settle(); expect(d.tasks.every((x) => x.state == DownloadState.downloading), isTrue, reason: '[계속 받기] 면 그대로'); await shot('2_kept'); expect(p.basename(tmp.path), startsWith('jj_dlcancel_')); }); } } }