import 'package:asciineverdie/l10n/app_localizations.dart'; import 'package:asciineverdie/src/core/model/game_state.dart'; import 'package:asciineverdie/src/features/new_character/new_character_screen.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; /// 테스트용 MaterialApp 래퍼 (localization 포함) /// locale을 영어로 고정하여 테스트 텍스트와 일치시킴 Widget _buildTestApp(Widget child) { return MaterialApp( localizationsDelegates: L10n.localizationsDelegates, supportedLocales: L10n.supportedLocales, locale: const Locale('en'), // 영어 locale 고정 home: child, ); } void main() { testWidgets('NewCharacterScreen renders main sections', (tester) async { await tester.pumpWidget( _buildTestApp( NewCharacterScreen(onCharacterCreated: (_, {bool testMode = false}) {}), ), ); // Localization 로드 대기 await tester.pumpAndSettle(); // 화면 타이틀 확인 (l10n 적용됨) expect(find.text('ASCII NEVER DIE - NEW CHARACTER'), findsOneWidget); // 종족 섹션 확인 (대문자 하드코딩) expect(find.text('RACE'), findsOneWidget); // 직업 섹션 확인 (대문자 하드코딩) expect(find.text('CLASS'), findsOneWidget); // 능력치 섹션 확인 (대문자 하드코딩) expect(find.text('STATS'), findsOneWidget); expect(find.text('STR'), findsOneWidget); expect(find.text('CON'), findsOneWidget); // Sold! 버튼 확인 expect(find.text('SOLD!'), findsOneWidget); }); testWidgets('Undo button exists and can be tapped', (tester) async { await tester.pumpWidget( _buildTestApp( NewCharacterScreen(onCharacterCreated: (_, {bool testMode = false}) {}), ), ); await tester.pumpAndSettle(); // Undo 버튼 확인 (l10n.unroll이 영어에서 "Undo"로 번역되고 대문자로 변환) final undoButton = find.text('UNDO'); expect(undoButton, findsOneWidget); // Undo 버튼 탭 await tester.tap(undoButton); await tester.pumpAndSettle(); // Total이 표시되는지 확인 (TOTAL은 대문자로 표시됨) expect(find.textContaining('TOTAL'), findsOneWidget); }); testWidgets('Sold button creates character with generated name', ( tester, ) async { GameState? createdState; await tester.pumpWidget( _buildTestApp( NewCharacterScreen( onCharacterCreated: (state, {bool testMode = false}) { createdState = state; }, ), ), ); await tester.pumpAndSettle(); // Sold! 버튼이 보이도록 스크롤 await tester.scrollUntilVisible( find.text('SOLD!'), 500.0, scrollable: find.byType(Scrollable).first, ); await tester.pumpAndSettle(); // Sold! 버튼 탭 await tester.tap(find.text('SOLD!')); await tester.pumpAndSettle(); // 콜백이 호출되었는지 확인 expect(createdState, isNotNull); expect(createdState!.traits.name.isNotEmpty, isTrue); expect(createdState!.traits.level, 1); expect(createdState!.traits.race.isNotEmpty, isTrue); expect(createdState!.traits.klass.isNotEmpty, isTrue); }); testWidgets('Stats section displays all six stats', (tester) async { await tester.pumpWidget( _buildTestApp( NewCharacterScreen(onCharacterCreated: (_, {bool testMode = false}) {}), ), ); await tester.pumpAndSettle(); // 능력치 라벨들이 표시되는지 확인 expect(find.text('STR'), findsOneWidget); expect(find.text('CON'), findsOneWidget); expect(find.text('DEX'), findsOneWidget); expect(find.text('INT'), findsOneWidget); expect(find.text('WIS'), findsOneWidget); expect(find.text('CHA'), findsOneWidget); // Total 라벨 확인 (TOTAL은 대문자로 표시됨) expect(find.textContaining('TOTAL'), findsOneWidget); }); testWidgets('Name text field exists', (tester) async { await tester.pumpWidget( _buildTestApp( NewCharacterScreen(onCharacterCreated: (_, {bool testMode = false}) {}), ), ); await tester.pumpAndSettle(); // TextField 확인 (이름 입력 필드) expect(find.byType(TextField), findsOneWidget); }); }