이벤트 가져오기 위젯 테스트 추가 및 테스트 훅 도입
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:lanebow/widgets/import_result_dialog.dart';
|
||||
|
||||
void main() {
|
||||
group('ImportResultDialog', () {
|
||||
testWidgets('기본 정보 및 실패 행/사유 프리뷰를 표시한다', (tester) async {
|
||||
const fileName = 'sample.csv';
|
||||
const processedRows = 12;
|
||||
const createdCount = 8;
|
||||
const invalidRows = 4;
|
||||
final invalidRowIndices = ['2', '5', '7', '10'];
|
||||
// 7개 사유를 제공하여 상위 5개 + 외 N건 동작 검증
|
||||
final invalidRowReasons = <String, String>{
|
||||
'2': 'title 누락',
|
||||
'3': 'startDate 누락',
|
||||
'4': 'title 누락',
|
||||
'5': 'startDate 누락',
|
||||
'6': 'title 누락',
|
||||
'7': 'startDate 누락',
|
||||
'8': 'title 누락',
|
||||
};
|
||||
|
||||
await tester.pumpWidget(
|
||||
const MaterialApp(
|
||||
home: Scaffold(body: SizedBox.shrink()),
|
||||
),
|
||||
);
|
||||
|
||||
showDialog(
|
||||
context: tester.element(find.byType(SizedBox)),
|
||||
builder: (_) => ImportResultDialog(
|
||||
fileName: fileName,
|
||||
processedRows: processedRows,
|
||||
createdCount: createdCount,
|
||||
invalidRows: invalidRows,
|
||||
invalidRowIndices: invalidRowIndices,
|
||||
invalidRowReasons: invalidRowReasons,
|
||||
onClose: () {},
|
||||
),
|
||||
);
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// 기본 정보
|
||||
expect(find.text('파일 처리 결과'), findsOneWidget);
|
||||
expect(find.text('파일명: $fileName'), findsOneWidget);
|
||||
expect(find.text('처리된 행: ${processedRows}개'), findsOneWidget);
|
||||
expect(find.text('생성된 이벤트: ${createdCount}개'), findsOneWidget);
|
||||
expect(find.text('유효하지 않은 행: ${invalidRows}개'), findsOneWidget);
|
||||
|
||||
// 실패 행 번호 프리뷰
|
||||
expect(
|
||||
find.textContaining('실패 행(최대 10개 미리보기): 2, 5, 7, 10'),
|
||||
findsOneWidget,
|
||||
);
|
||||
|
||||
// 실패 사유 상위 5개 + 외 N건
|
||||
expect(find.text('실패 사유(일부):'), findsOneWidget);
|
||||
expect(find.text('행 2: title 누락'), findsOneWidget);
|
||||
expect(find.text('행 3: startDate 누락'), findsOneWidget);
|
||||
expect(find.text('행 4: title 누락'), findsOneWidget);
|
||||
expect(find.text('행 5: startDate 누락'), findsOneWidget);
|
||||
expect(find.text('행 6: title 누락'), findsOneWidget);
|
||||
expect(find.text('... 외 2건'), findsOneWidget);
|
||||
|
||||
// 닫기 버튼 존재
|
||||
expect(find.text('닫기'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:lanebow/widgets/owner_dropdown.dart';
|
||||
import 'package:lanebow/models/member_model.dart';
|
||||
|
||||
void main() {
|
||||
group('OwnerDropdown', () {
|
||||
testWidgets('빌드 시 onItemsBuilt로 항목 수를 보고하고, onChanged로 값이 변경된다', (tester) async {
|
||||
// Arrange: 샘플 멤버 2명
|
||||
final members = <Member>[
|
||||
Member(
|
||||
id: 'm1',
|
||||
userId: 'u1',
|
||||
clubId: 'c1',
|
||||
name: '아무개 A',
|
||||
email: 'a@example.com',
|
||||
gender: 'male',
|
||||
isActive: true,
|
||||
memberType: 'regular',
|
||||
status: 'active',
|
||||
),
|
||||
Member(
|
||||
id: 'm2',
|
||||
userId: 'u2',
|
||||
clubId: 'c1',
|
||||
name: '아무개 B',
|
||||
email: 'b@example.com',
|
||||
gender: 'female',
|
||||
isActive: true,
|
||||
memberType: 'associate',
|
||||
status: 'active',
|
||||
),
|
||||
];
|
||||
|
||||
String? selected = members.first.userId;
|
||||
int? builtCount;
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: OwnerDropdown(
|
||||
members: members,
|
||||
value: selected,
|
||||
onChanged: (v) {
|
||||
selected = v;
|
||||
},
|
||||
onItemsBuilt: (count) => builtCount = count,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// onItemsBuilt는 microtask로 호출되므로 한 번 더 펌프
|
||||
await tester.pump();
|
||||
|
||||
// Assert: 항목 수 콜백이 2로 보고됨
|
||||
expect(builtCount, 2);
|
||||
|
||||
// Act: 오버레이를 열지 않고 DropdownButtonFormField의 onChanged를 직접 호출
|
||||
final field = tester.widget<DropdownButtonFormField<String>>(
|
||||
find.byType(DropdownButtonFormField<String>),
|
||||
);
|
||||
field.onChanged?.call(members[1].userId);
|
||||
|
||||
// 한 프레임 펌프하여 상태 반영
|
||||
await tester.pump();
|
||||
|
||||
// Assert: 선택 값이 두 번째 사용자로 변경됨
|
||||
expect(selected, members[1].userId);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:lanebow/screens/club/participant_form_screen.dart';
|
||||
import 'package:lanebow/services/event_service.dart';
|
||||
|
||||
void main() {
|
||||
group('ParticipantFormScreen - Guest Prefill BottomSheet', () {
|
||||
Widget _buildApp() => MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider(create: (_) => EventService()),
|
||||
],
|
||||
child: const MaterialApp(
|
||||
home: Scaffold(
|
||||
body: ParticipantFormScreen(eventId: 'test_event'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
testWidgets('opens bottom sheet and applies filled values', (tester) async {
|
||||
await tester.pumpWidget(_buildApp());
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// 사전입력 버튼 노출
|
||||
expect(find.text('게스트 사전입력'), findsOneWidget);
|
||||
|
||||
// 버튼 탭으로 BottomSheet 오픈
|
||||
await tester.tap(find.text('게스트 사전입력'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// 필드 입력
|
||||
await tester.enterText(find.byType(TextField).at(0), '홍길동');
|
||||
await tester.enterText(find.byType(TextField).at(1), 'hong@test.com');
|
||||
await tester.enterText(find.byType(TextField).at(2), '01012345678');
|
||||
|
||||
// 적용
|
||||
await tester.tap(find.text('적용'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// 폼 필드에 값 반영 확인
|
||||
expect(find.widgetWithText(TextFormField, '홍길동'), findsOneWidget);
|
||||
expect(find.widgetWithText(TextFormField, 'hong@test.com'), findsOneWidget);
|
||||
expect(find.widgetWithText(TextFormField, '01012345678'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('shows warning when name is empty', (tester) async {
|
||||
await tester.pumpWidget(_buildApp());
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.text('게스트 사전입력'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// 이름 비우고 적용
|
||||
await tester.enterText(find.byType(TextField).at(0), '');
|
||||
await tester.tap(find.text('적용'));
|
||||
await tester.pump();
|
||||
|
||||
expect(find.text('이름은 필수 입력 항목입니다'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user