M1-2: lib 의 …ForTest 이름 정리 (실제 기능 · 주입으로)
- SuRoot.resetForTest → forgetGrant (이번 실행의 su 허락 잊기) - ComGuard.releaseForTest → release (ensure 와 짝인 CoUninitialize) - debugUpscalerForTest 전역 → PlatformServices.createUpscaler 주입 - 원격 썸네일 reset…ForTest 3개 → forgetRemoteThumbHub · forgetRemoteRangeSupport · forgetRemoteThumbNet - vaultIterationsForTest 전역 → VaultPage(iterations:) (처음 값 VaultCrypto.defaultIterations) - 남은 recycleBinForTest 는 M2 (TrashBackend) 에서 정리 확인: analyze 0 · 단위 1470 ×2 · 통합 6/6 ×2 · base10 214장 0px · com_guard_test · windows_vault_shot_test ×2 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>modular
parent
2199d7c15f
commit
3434ad4937
|
|
@ -19,11 +19,11 @@ void main() {
|
|||
// ignore: avoid_print
|
||||
print('RESULT 처음 확인: $first (1 = 이미 준비되어 있음 → 같은 스레드)');
|
||||
expect(first, 1);
|
||||
ComGuard.releaseForTest(); // 방금 올린 만큼 내림
|
||||
ComGuard.release(); // 방금 올린 만큼 내림
|
||||
|
||||
// 2. 준비 상태를 끝까지 푼다 (문제 상황). 여러 구성 요소가 겹쳐 준비해 두므로 넉넉히 여러 번.
|
||||
for (var i = 0; i < 8; i++) {
|
||||
ComGuard.releaseForTest();
|
||||
ComGuard.release();
|
||||
}
|
||||
// Edge 가 앱이 끝날 때까지 사용자 데이터 폴더를 잡는다 (test_temp_check 가 찾음, 관리자 지시 10/20)
|
||||
final dir = testTempDir('jj_com_', heldByApp: true).path;
|
||||
|
|
@ -41,7 +41,7 @@ void main() {
|
|||
|
||||
// 3. 앱의 방식 (만들기 전에 다시 준비) 으로는 만들어진다
|
||||
for (var i = 0; i < 8; i++) {
|
||||
ComGuard.releaseForTest();
|
||||
ComGuard.release();
|
||||
}
|
||||
final env = await tester.runAsync(() => browserEnvironment(dir));
|
||||
// ignore: avoid_print
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ void main() {
|
|||
t.view.physicalSize = size;
|
||||
t.view.devicePixelRatio = 1;
|
||||
await t.runAsync(() => t.pumpWidget(RepaintBoundary(
|
||||
key: key, child: MaterialApp(theme: buildTheme(), debugShowCheckedModeBanner: false, home: VaultPage(c: c)))));
|
||||
key: key, child: MaterialApp(theme: buildTheme(), debugShowCheckedModeBanner: false, home: VaultPage(c: c, iterations: 1000)))));
|
||||
for (var i = 0; i < 15; i++) {
|
||||
await t.runAsync(() => Future<void>.delayed(const Duration(milliseconds: 100)));
|
||||
await t.pump(const Duration(milliseconds: 50));
|
||||
|
|
@ -57,13 +57,12 @@ void main() {
|
|||
await v.add(f.path, folder: '여행');
|
||||
await v.mkdir('빈 폴더');
|
||||
});
|
||||
vaultIterationsForTest = 1000;
|
||||
for (final (name, size) in [('open_412', const Size(412, 800)), ('open_960', const Size(960, 600))]) {
|
||||
vaultDirOf = () async => dir;
|
||||
t.view.physicalSize = size;
|
||||
t.view.devicePixelRatio = 1;
|
||||
await t.runAsync(() => t.pumpWidget(RepaintBoundary(
|
||||
key: key, child: MaterialApp(theme: buildTheme(), debugShowCheckedModeBanner: false, home: VaultPage(c: c)))));
|
||||
key: key, child: MaterialApp(theme: buildTheme(), debugShowCheckedModeBanner: false, home: VaultPage(c: c, iterations: 1000)))));
|
||||
for (var i = 0; i < 10; i++) {
|
||||
await t.runAsync(() => Future<void>.delayed(const Duration(milliseconds: 100)));
|
||||
await t.pump(const Duration(milliseconds: 50));
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import 'dart:async';
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart' show visibleForTesting;
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
|
||||
|
|
@ -55,8 +54,8 @@ class SuRoot implements ShizukuBackend {
|
|||
|
||||
static bool _granted = false;
|
||||
|
||||
@visibleForTesting
|
||||
static void resetForTest() => _granted = false;
|
||||
/// 이번 실행에서 받은 허락을 잊는다 (다음 요청에서 su 에 다시 묻는다)
|
||||
static void forgetGrant() => _granted = false;
|
||||
|
||||
Future<(int, String, String)> _run(String exe, List<String> args, {Duration timeout = const Duration(seconds: 60)}) async {
|
||||
final p = await start(exe, args);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ class ComGuard {
|
|||
return hr == 0;
|
||||
}
|
||||
|
||||
/// 시험용: 준비 상태를 한 단계 푼다
|
||||
static void releaseForTest() => _uninit();
|
||||
/// 준비 상태를 한 단계 푼다 ([ensure] 와 짝 - CoUninitialize)
|
||||
static void release() {
|
||||
if (Platform.isWindows) _uninit();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import 'package:path/path.dart' as p;
|
|||
|
||||
import '../platform/common/media_kit_full_player.dart';
|
||||
import '../platform/common/media_kit_player.dart';
|
||||
import '../app/ai_upscale.dart' show AiUpscaler;
|
||||
import '../app/settings.dart';
|
||||
import '../core/download_detect.dart';
|
||||
import '../platform/common/nllb_translator.dart';
|
||||
|
|
@ -64,6 +65,9 @@ class PlatformServices {
|
|||
/// PC 의 CPU · 메모리 사용량 (없으면 표시 숨김)
|
||||
final SystemUsage? usage;
|
||||
|
||||
/// 엔진 · 모델을 이미 정해 둔 해상도 올리기 (없으면 설정대로 준비하고, 없는 엔진 · 모델은 그 자리에서 받는다)
|
||||
final AiUpscaler Function()? createUpscaler;
|
||||
|
||||
/// 이 기기 (Android · Windows · 메모리) - 기기마다 다르게 도는 곳은 이것을 본다 (M1, 처음 값 = 이 기기)
|
||||
final PlatformInfo platform;
|
||||
|
||||
|
|
@ -79,6 +83,7 @@ class PlatformServices {
|
|||
this.createTranslator,
|
||||
this.createDownloadBackends,
|
||||
this.createSubtitleProviders,
|
||||
this.createUpscaler,
|
||||
this.updater,
|
||||
this.usage,
|
||||
ModelStore? models,
|
||||
|
|
|
|||
|
|
@ -54,13 +54,9 @@ Future<(String input, String nameFrom, String outDir)?> readerPageFile(AppContro
|
|||
return null; // PDF 등은 아직
|
||||
}
|
||||
|
||||
/// 시험용: 받기 · 엔진 고르기 없이 쓸 업스케일러 (가짜 엔진)
|
||||
@visibleForTesting
|
||||
AiUpscaler Function()? debugUpscalerForTest;
|
||||
|
||||
/// 준비: 모델 · 엔진이 없으면 그 자리에서 무엇을 받을지 고르고 받는다 (156 - 설정 화면으로 보내지 않음). 못 하면 null
|
||||
Future<AiUpscaler?> readyUpscalerFor(BuildContext context, AppController c) async {
|
||||
if (debugUpscalerForTest case final f?) return f();
|
||||
if (c.services.createUpscaler case final f?) return f();
|
||||
final store = AiStore.instance ??= AiStore(Directory.systemTemp.path);
|
||||
Future<AiUpscaler?> ready() =>
|
||||
prepareUpscaler(store,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import 'ai_upscale/upscale_prep.dart';
|
|||
import 'ai_upscale/upscale_compare.dart';
|
||||
|
||||
export 'ai_upscale/upscale_compare.dart' show UpscaleCompareView, UpscaleCompareViewState;
|
||||
export 'ai_upscale/upscale_prep.dart' show debugUpscalerForTest, readerPageFile, upscaleOptionsOf;
|
||||
export 'ai_upscale/upscale_prep.dart' show readerPageFile, upscaleOptionsOf;
|
||||
|
||||
/// 121: 한 장 올리기 → 진행 (취소) → [원본 / 올린 것] 비교 → [저장] (새 파일, 원본을 덮지 않음). 저장한 경로 (안 하면 null)
|
||||
Future<String?> upscaleOne(BuildContext context, AppController c, {required String input, required String nameFrom, required String outDir}) async {
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ Future<RemoteThumbs> remoteThumbsOf(AppController c) => _hub ??= () async {
|
|||
return h;
|
||||
}();
|
||||
|
||||
/// 시험: 다음에 새로 만든다
|
||||
void resetRemoteThumbsForTest() => _hub = null;
|
||||
/// 썸네일 허브를 잊는다 (다음에 지금 설정 · 폴더로 새로 만든다)
|
||||
void forgetRemoteThumbHub() => _hub = null;
|
||||
|
||||
/// 원격 그림은 이보다 크면 받지 않는다 (썸네일 하나에 큰 파일을 통째로 받지 않게)
|
||||
const remoteThumbImageMax = 30 * 1024 * 1024;
|
||||
|
|
@ -43,8 +43,8 @@ int remoteThumbVideoCap = 8 * 1024 * 1024;
|
|||
/// 서버마다 Range 를 따르는지 (이번 실행 동안 기억 - 앱을 다시 켜면 한 번 다시 봄)
|
||||
final _rangeOk = <String, bool>{};
|
||||
|
||||
/// 시험: Range 기억을 지운다
|
||||
void resetRemoteThumbRangeForTest() => _rangeOk.clear();
|
||||
/// 서버마다 Range 를 따르는지 기억한 것을 지운다 (다음에 다시 물어본다)
|
||||
void forgetRemoteRangeSupport() => _rangeOk.clear();
|
||||
|
||||
/// 동영상 썸네일을 만들어도 되는 원격인지 (28 지적 · 관리자 지시 10/21):
|
||||
/// - WebDAV: Range 를 모르는 서버 (206 이 아님) 는 뒤쪽 한 장면에 파일 전체를 받으므로 만들지 않음 (서버마다 기억, 물어보다 실패하면 기억하지 않음)
|
||||
|
|
@ -89,8 +89,8 @@ Future<bool> remoteThumbsAllowedNow(AppController c) async {
|
|||
return !_metered;
|
||||
}
|
||||
|
||||
/// 시험: 망 판단 기억을 지운다
|
||||
void resetRemoteThumbNetForTest() => _meteredAt = null;
|
||||
/// 망 판단 (데이터 요금제인지) 기억을 지운다 (다음에 다시 본다)
|
||||
void forgetRemoteThumbNet() => _meteredAt = null;
|
||||
|
||||
/// FFmpeg 가 이 기기 안 스트리밍 다리 (127.0.0.1, Range) 에서 필요한 부분만 읽어 가로 160 jpg 로. 비밀번호는 명령 줄에 넣지 않는다.
|
||||
/// MKV 만들기 등 작업 중에는 만들지 않는다 (FFmpeg 를 같이 씀)
|
||||
|
|
|
|||
|
|
@ -37,9 +37,6 @@ Future<Directory> Function() vaultDirOf = () async {
|
|||
/// 꺼낼 폴더 고르기 (시험에서 바꿈)
|
||||
Future<String?> Function() vaultPickFolder = () => FilePicker.getDirectoryPath();
|
||||
|
||||
/// 시험: PBKDF2 반복 수 (새 보관함 · 비밀번호 바꾸기)
|
||||
int vaultIterationsForTest = VaultCrypto.defaultIterations;
|
||||
|
||||
class VaultPage extends StatefulWidget {
|
||||
final AppController c;
|
||||
|
||||
|
|
@ -48,7 +45,10 @@ class VaultPage extends StatefulWidget {
|
|||
|
||||
/// [원본 지우기 (이동)] 일 때 탐색기의 지우기 (확인 창 · [permanent] 가 아니면 휴지통)
|
||||
final Future<void> Function(List<String> paths, {required bool permanent})? deleteOriginals;
|
||||
const VaultPage({super.key, required this.c, this.add = const [], this.deleteOriginals});
|
||||
|
||||
/// 새 보관함 · 비밀번호 바꾸기의 PBKDF2 반복 수
|
||||
final int iterations;
|
||||
const VaultPage({super.key, required this.c, this.add = const [], this.deleteOriginals, this.iterations = VaultCrypto.defaultIterations});
|
||||
|
||||
@override
|
||||
State<VaultPage> createState() => _VaultPageState();
|
||||
|
|
@ -146,7 +146,7 @@ class _VaultPageState extends State<VaultPage> with WidgetsBindingObserver {
|
|||
_stage = _Stage.opening;
|
||||
});
|
||||
try {
|
||||
final v = await Vault.create(_dir!, _pw.text, iterations: vaultIterationsForTest);
|
||||
final v = await Vault.create(_dir!, _pw.text, iterations: widget.iterations);
|
||||
_pw.clear();
|
||||
_pw2.clear();
|
||||
if (!mounted) return;
|
||||
|
|
@ -290,7 +290,7 @@ class _VaultPageState extends State<VaultPage> with WidgetsBindingObserver {
|
|||
tooltip: tr('더 보기'),
|
||||
onSelected: (w) => switch (w) {
|
||||
'mkdir' => vaultMakeFolder(context, _s),
|
||||
'pw' => vaultChangePassword(context, _s, iterations: vaultIterationsForTest),
|
||||
'pw' => vaultChangePassword(context, _s, iterations: widget.iterations),
|
||||
'master' => vaultToggleMasterCopy(context, c, _s, !c.settings.vault.masterCopy),
|
||||
_ => null,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -129,22 +129,22 @@ void main() {
|
|||
final was = activeMeteredOf;
|
||||
tearDown(() {
|
||||
activeMeteredOf = was;
|
||||
resetRemoteThumbNetForTest();
|
||||
forgetRemoteThumbNet();
|
||||
});
|
||||
AppController ctl() => AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService()));
|
||||
test('Wi-Fi 에서만 (처음 값): 데이터 요금제 망이면 아니오 · 아니면 예 · 끔 · 늘', () async {
|
||||
final c = ctl();
|
||||
activeMeteredOf = () async => true;
|
||||
resetRemoteThumbNetForTest();
|
||||
forgetRemoteThumbNet();
|
||||
expect(await remoteThumbsAllowedNow(c), isFalse, reason: '모바일 데이터 (VPN 이어도 그 아래가 모바일 데이터)');
|
||||
activeMeteredOf = () async => false;
|
||||
resetRemoteThumbNetForTest();
|
||||
forgetRemoteThumbNet();
|
||||
expect(await remoteThumbsAllowedNow(c), isTrue, reason: 'Wi-Fi (집 Wi-Fi 위의 Tailscale 포함)');
|
||||
c.settings.explorer.remoteThumbs = 'off';
|
||||
expect(await remoteThumbsAllowedNow(c), isFalse);
|
||||
c.settings.explorer.remoteThumbs = 'always';
|
||||
activeMeteredOf = () async => true;
|
||||
resetRemoteThumbNetForTest();
|
||||
forgetRemoteThumbNet();
|
||||
expect(await remoteThumbsAllowedNow(c), isTrue);
|
||||
});
|
||||
});
|
||||
|
|
@ -187,8 +187,8 @@ void main() {
|
|||
});
|
||||
|
||||
test('28 지적 (10/21): Range 를 모르는 서버 (200) 의 동영상은 썸네일을 받지 않음 · 서버마다 기억 · 206 서버는 만듦 · 시스템 폴더는 안 함', () async {
|
||||
resetRemoteThumbRangeForTest();
|
||||
addTearDown(resetRemoteThumbRangeForTest);
|
||||
forgetRemoteRangeSupport();
|
||||
addTearDown(forgetRemoteRangeSupport);
|
||||
server.ranges = false;
|
||||
for (final n in ['v.mp4', 'w.mp4']) {
|
||||
File(p.join(tmp.path, 'remote', n)).writeAsBytesSync(List.filled(1000, 7));
|
||||
|
|
@ -197,8 +197,8 @@ void main() {
|
|||
final calls = <List<String>>[];
|
||||
final c = AppController(PlatformServices(mediaTool: _Ffmpeg(calls), storage: DesktopStorageService()));
|
||||
c.settings.explorer.remoteThumbs = 'always';
|
||||
resetRemoteThumbsForTest();
|
||||
addTearDown(resetRemoteThumbsForTest);
|
||||
forgetRemoteThumbHub();
|
||||
addTearDown(forgetRemoteThumbHub);
|
||||
final h = await remoteThumbsOf(c);
|
||||
final probes = server.rangeHeaders.length;
|
||||
expect(await h.request('dav://nas/v.mp4', 'k1', wanted: () => true), isNull);
|
||||
|
|
@ -209,7 +209,7 @@ void main() {
|
|||
expect(await remoteVideoThumbOk('shz://sys/storage/emulated/0/a.mp4'), isFalse, reason: '시스템 폴더는 늘 통째 복사');
|
||||
expect(await remoteVideoThumbOk('sftp://s/a.mp4'), isTrue);
|
||||
// 206 서버 (앱을 다시 켠 것처럼 기억을 지우고)
|
||||
resetRemoteThumbRangeForTest();
|
||||
forgetRemoteRangeSupport();
|
||||
server.ranges = true;
|
||||
expect(await remoteVideoThumbOk('dav://nas/v.bin'), isTrue);
|
||||
expect(await h.request('dav://nas/v.mp4', 'k3', wanted: () => true), isNull, reason: '가짜 FFmpeg 는 그림을 만들지 않음');
|
||||
|
|
@ -248,8 +248,8 @@ void main() {
|
|||
server.ranges = true;
|
||||
final c = AppController(PlatformServices(mediaTool: tool, storage: DesktopStorageService()));
|
||||
c.settings.explorer.remoteThumbs = 'always';
|
||||
resetRemoteThumbsForTest();
|
||||
addTearDown(resetRemoteThumbsForTest);
|
||||
forgetRemoteThumbHub();
|
||||
addTearDown(forgetRemoteThumbHub);
|
||||
final h = await remoteThumbsOf(c);
|
||||
final st = File(mp4).statSync();
|
||||
final f = await h.request('dav://nas/clip.mp4', RemoteThumbs.keyOf('dav://nas/clip.mp4', st.size, st.modified), wanted: () => true);
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ void main() {
|
|||
tmp = Directory.systemTemp.createTempSync('jj_root_');
|
||||
su = _Su();
|
||||
SuRoot.start = su.start;
|
||||
SuRoot.resetForTest();
|
||||
SuRoot.forgetGrant();
|
||||
ShizukuRemote.rootBackend = SuRoot();
|
||||
ShizukuRemote.tempDir = () async => tmp.path;
|
||||
rootSupported = () => true;
|
||||
|
|
@ -106,7 +106,7 @@ void main() {
|
|||
await expectLater(r.copyTo('/data/bad', p.join(tmp.path, 'bad')), throwsA(isA<FileSystemException>()));
|
||||
expect(File(p.join(tmp.path, 'bad')).existsSync(), isFalse);
|
||||
// 거절
|
||||
SuRoot.resetForTest();
|
||||
SuRoot.forgetGrant();
|
||||
su.allow = false;
|
||||
expect(await r.request(), isFalse);
|
||||
// su 없음
|
||||
|
|
|
|||
|
|
@ -20,12 +20,13 @@ void main() {
|
|||
late Directory tmp;
|
||||
late String input;
|
||||
late Completer<void> engine;
|
||||
late AiUpscaler Function() upscaler;
|
||||
setUp(() {
|
||||
tmp = Directory.systemTemp.createTempSync('jj_up_job_');
|
||||
input = p.join(tmp.path, 'page.png');
|
||||
File(input).writeAsBytesSync(img.encodePng(img.Image(width: 8, height: 6)));
|
||||
engine = Completer<void>();
|
||||
debugUpscalerForTest = () => AiUpscaler(
|
||||
upscaler = () => AiUpscaler(
|
||||
device: const SdDevice('sd-cli', 'cpu', 'CPU'),
|
||||
modelPath: 'm.pth',
|
||||
modelId: 'esrgan-x4plus',
|
||||
|
|
@ -37,7 +38,6 @@ void main() {
|
|||
);
|
||||
});
|
||||
tearDown(() {
|
||||
debugUpscalerForTest = null;
|
||||
AiJobs.instance.done(''); // 남은 [보기] 정리
|
||||
tmp.deleteSync(recursive: true);
|
||||
});
|
||||
|
|
@ -71,7 +71,7 @@ void main() {
|
|||
});
|
||||
|
||||
testWidgets('[이 장] 은 작업 목록에 오르고, [뒤에서 계속] 으로 화면을 떠나도 끝나며 [보기] 로 비교 · 저장', (tester) async {
|
||||
final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService()));
|
||||
final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService(), createUpscaler: upscaler));
|
||||
var finished = false;
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: Scaffold(
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@ import 'package:path/path.dart' as p;
|
|||
|
||||
/// X-plore 비교 5-2 암호 보관함 화면 (관리자 결정 10/21): 만들기 창의 알림 · 넣기 (복사 / 원본 지우기) · 잠금 · 틀린 비밀번호 ·
|
||||
/// 꺼내기 · 지우기 · [마스터로도 열기] (마스터를 초기화하면 그 길만 없어짐)
|
||||
/// 시험의 PBKDF2 반복 수 (빨리 - 실제 암호화 그대로)
|
||||
const _fastIterations = 1000;
|
||||
|
||||
void main() {
|
||||
late Directory tmp;
|
||||
final was = vaultDirOf;
|
||||
|
|
@ -28,7 +31,6 @@ void main() {
|
|||
vaultDirOf = () async => Directory(p.join(tmp.path, 'vault'));
|
||||
vaultPickFolder = () async => p.join(tmp.path, 'out');
|
||||
Directory(p.join(tmp.path, 'out')).createSync();
|
||||
vaultIterationsForTest = 1000;
|
||||
});
|
||||
tearDown(() async {
|
||||
vaultDirOf = was;
|
||||
|
|
@ -104,7 +106,7 @@ void main() {
|
|||
final permanents = <bool>[];
|
||||
final c = ctl();
|
||||
await t.pumpWidget(MaterialApp(
|
||||
home: VaultPage(c: c, add: [src.path], deleteOriginals: (paths, {required permanent}) async {
|
||||
home: VaultPage(iterations: _fastIterations, c: c, add: [src.path], deleteOriginals: (paths, {required permanent}) async {
|
||||
deleted.add(paths);
|
||||
permanents.add(permanent);
|
||||
})));
|
||||
|
|
@ -171,7 +173,7 @@ void main() {
|
|||
await t.runAsync(() => lock.setMaster('master'));
|
||||
final c = ctl();
|
||||
// 먼저 만들어 둔다
|
||||
await t.pumpWidget(MaterialApp(home: VaultPage(c: c)));
|
||||
await t.pumpWidget(MaterialApp(home: VaultPage(iterations: _fastIterations, c: c)));
|
||||
await until(t, () => find.text('새 보관함 만들기').evaluate().isNotEmpty);
|
||||
await t.enterText(find.byType(TextField).at(0), 'pw');
|
||||
await t.enterText(find.byType(TextField).at(1), 'pw');
|
||||
|
|
@ -269,7 +271,7 @@ void main() {
|
|||
final f = File(p.join(tmp.path, '사라질.pdf'))..writeAsBytesSync(List.filled(100, 3));
|
||||
final e = (await t.runAsync(() => v.add(f.path)))!;
|
||||
File(p.join(dir.path, '${e.blob}.jjv')).deleteSync();
|
||||
await t.pumpWidget(MaterialApp(home: VaultPage(c: ctl())));
|
||||
await t.pumpWidget(MaterialApp(home: VaultPage(iterations: _fastIterations, c: ctl())));
|
||||
await until(t, () => find.widgetWithText(FilledButton, '열기').evaluate().isNotEmpty);
|
||||
await t.enterText(find.byType(TextField), 'pw');
|
||||
await t.tap(find.widgetWithText(FilledButton, '열기'));
|
||||
|
|
@ -304,7 +306,7 @@ void main() {
|
|||
final photo = File(p.join(tmp.path, 'photo.png'))..writeAsBytesSync(img.encodePng(img.Image(width: 20, height: 10)));
|
||||
final clip = File(p.join(tmp.path, 'clip.mp4'))..writeAsBytesSync(List.filled(500, 1));
|
||||
final c = ctl()..settings.vault.autoLockSeconds = 0;
|
||||
await t.pumpWidget(MaterialApp(home: VaultPage(c: c, add: [photo.path, clip.path])));
|
||||
await t.pumpWidget(MaterialApp(home: VaultPage(iterations: _fastIterations, c: c, add: [photo.path, clip.path])));
|
||||
await until(t, () => find.text('새 보관함 만들기').evaluate().isNotEmpty);
|
||||
await t.enterText(find.byType(TextField).at(0), 'pw');
|
||||
await t.enterText(find.byType(TextField).at(1), 'pw');
|
||||
|
|
@ -367,7 +369,7 @@ void main() {
|
|||
final c = ctl();
|
||||
final deleted = <List<String>>[];
|
||||
await t.pumpWidget(MaterialApp(
|
||||
home: VaultPage(c: c, add: [album.path, remotePath], deleteOriginals: (paths, {required permanent}) async => deleted.add(paths))));
|
||||
home: VaultPage(iterations: _fastIterations, c: c, add: [album.path, remotePath], deleteOriginals: (paths, {required permanent}) async => deleted.add(paths))));
|
||||
await until(t, () => find.text('새 보관함 만들기').evaluate().isNotEmpty);
|
||||
await t.enterText(find.byType(TextField).at(0), 'pw');
|
||||
await t.enterText(find.byType(TextField).at(1), 'pw');
|
||||
|
|
|
|||
Loading…
Reference in New Issue