diff --git a/test/vault_page_test.dart b/test/vault_page_test.dart index d5bef84..d43f02b 100644 --- a/test/vault_page_test.dart +++ b/test/vault_page_test.dart @@ -52,8 +52,12 @@ void main() { return c; } - Future until(WidgetTester t, bool Function() ok, {int rounds = 200}) async { - for (var i = 0; i < rounds && !ok(); i++) { + /// 실제 시간으로 기다린다 (암호화 · 파일 쓰기는 실제 IO - 시험을 여럿 함께 돌려 느릴 때 횟수로 끊으면 일이 덜 끝난 채 넘어가, + /// 시험이 끝난 뒤 남은 쓰기가 파일을 연 채 멈춰 임시 폴더를 지우지 못했다 - errno 32). 끝내 안 되면 그 자리에서 실패 + Future until(WidgetTester t, bool Function() ok, {Duration limit = const Duration(seconds: 60)}) async { + final w = Stopwatch()..start(); + while (!ok()) { + if (w.elapsed > limit) fail('기다린 일이 ${limit.inSeconds}초 안에 끝나지 않음'); await t.runAsync(() => Future.delayed(const Duration(milliseconds: 20))); await t.pump(const Duration(milliseconds: 20)); } @@ -63,6 +67,17 @@ void main() { } } + /// 보관함의 쓰기가 다 끝날 때까지: 쓰는 중인 파일 (.tmp) 이 없는 것이 10번 잇달아일 때 (사이마다 pump). + /// 한 번만 보면 목록 저장 → 빈 폴더 목록 저장 사이에 맞아, 남은 쓰기가 파일을 연 채 시험이 끝났다 (errno 32) + Future vaultQuiet(WidgetTester t) async { + var calm = 0; + await until(t, () { + final busy = Directory(p.join(tmp.path, 'vault')).listSync().any((f) => f.path.endsWith('.tmp')); + calm = busy ? 0 : calm + 1; + return calm >= 10; + }); + } + /// 진행 막대 · 글자 칸 깜빡임이 있으면 pumpAndSettle 이 끝나지 않는다 - 정한 만큼만 Future settle(WidgetTester t) async { for (var i = 0; i < 12; i++) { @@ -141,7 +156,7 @@ void main() { await until(t, () => find.text('보관함이 비어 있습니다').evaluate().isNotEmpty); expect(find.text('보관함이 비어 있습니다'), findsOneWidget); // 목록 쓰기 (index.jjv.tmp → index.jjv) 가 끝날 때까지 (화면은 먼저 바뀔 수 있다) - await until(t, () => !Directory(p.join(tmp.path, 'vault')).listSync().any((f) => f.path.endsWith('.tmp'))); + await vaultQuiet(t); await t.pumpWidget(const SizedBox()); }); @@ -202,7 +217,7 @@ void main() { await until(t, () => find.text('보관함이 비어 있습니다').evaluate().isNotEmpty); expect(find.text('보관함이 비어 있습니다'), findsOneWidget); // 목록 쓰기 (index.jjv.tmp → index.jjv) 가 끝날 때까지 (화면은 먼저 바뀔 수 있다) - await until(t, () => !Directory(p.join(tmp.path, 'vault')).listSync().any((f) => f.path.endsWith('.tmp'))); + await vaultQuiet(t); await t.pumpWidget(const SizedBox()); }); testWidgets('파일 탐색기: [보관함에 넣기] 는 보관함을 켰을 때 · 파일과 폴더 (2단계)', (t) async { @@ -414,7 +429,7 @@ void main() { await t.tap(find.widgetWithText(FilledButton, '지우기')); await until(t, () => find.text('album').evaluate().isEmpty); expect(find.text('remote.txt'), findsOneWidget); - await until(t, () => !Directory(p.join(tmp.path, 'vault')).listSync().any((f) => f.path.endsWith('.tmp'))); + await vaultQuiet(t); await t.pumpWidget(const SizedBox()); }); }