import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:jj_mkvmaker/ui/confirm_dialog.dart'; /// E4 U7 약속 시험 (모듈 하나에 한 장): lib/ui/confirm_dialog.dart 맨 위 약속을 그대로 본다. void main() { testWidgets('[확인] 만 true · [취소] · Esc · 바깥 누르기는 false', (tester) async { for (final (name, close, want) in <(String, Future Function(), bool)>[ ('확인', () => tester.tap(find.text('확인 단추')), true), ('취소', () => tester.tap(find.text('취소')), false), ('Esc', () => tester.sendKeyEvent(LogicalKeyboardKey.escape), false), ('바깥', () => tester.tapAt(const Offset(5, 5)), false), ]) { late BuildContext ctx; await tester.pumpWidget(MaterialApp(home: Builder(builder: (c) { ctx = c; return const Scaffold(body: SizedBox()); }))); bool? got; unawaited(confirmDialog(ctx, title: () => '복사', confirmLabel: () => '확인 단추', body: (c, set) => const Text('내용')) .then((v) => got = v)); await tester.pumpAndSettle(); await close(); await tester.pumpAndSettle(); expect(got, want, reason: name); } }); testWidgets('Enter = 첫 초점: 보통은 [확인], 되돌릴 수 없는 일은 [취소] (관리자 결정 10/22)', (tester) async { for (final (danger, want) in [(false, true), (true, false)]) { late BuildContext ctx; await tester.pumpWidget(MaterialApp(home: Builder(builder: (c) { ctx = c; return const Scaffold(body: SizedBox()); }))); bool? got; unawaited(confirmDialog(ctx, title: () => '지우기', confirmLabel: () => '확인 단추', danger: () => danger, body: (c, set) => const Text('내용')) .then((v) => got = v)); await tester.pumpAndSettle(); await tester.sendKeyEvent(LogicalKeyboardKey.enter); await tester.pumpAndSettle(); expect(got, want, reason: 'danger=$danger'); } }); testWidgets('창 안에서 바뀌면 제목 · 빨강이 따라 바뀌고 첫 초점은 연 때 그대로', (tester) async { final flag = ValueNotifier(false); late BuildContext ctx; await tester.pumpWidget(MaterialApp(home: Builder(builder: (c) { ctx = c; return const Scaffold(body: SizedBox()); }))); bool? got; unawaited(confirmDialog(ctx, title: () => flag.value ? '영구 삭제' : '휴지통으로 보내기', confirmLabel: () => flag.value ? '영구 삭제 단추' : '휴지통으로', danger: () => flag.value, body: (c, set) => CheckboxListTile( value: flag.value, onChanged: (v) => set(() => flag.value = v ?? false), title: const Text('영구로'))) .then((v) => got = v)); await tester.pumpAndSettle(); expect(find.text('휴지통으로 보내기'), findsOneWidget); FilledButton confirm() => tester.widget(find.byType(FilledButton)); expect(confirm().style, isNull, reason: '보통 단추'); await tester.tap(find.text('영구로')); await tester.pumpAndSettle(); expect(find.text('영구 삭제'), findsOneWidget, reason: '제목이 바뀜'); expect(find.text('영구 삭제 단추'), findsOneWidget); expect(confirm().style, isNotNull, reason: '빨강'); expect(tester.widget(find.byType(FilledButton)).autofocus, isTrue, reason: '첫 초점은 연 때 그대로 ([확인])'); await tester.tap(find.text('영구 삭제 단추')); await tester.pumpAndSettle(); expect(got, isTrue); }); }