이벤트 가져오기 위젯 테스트 추가 및 테스트 훅 도입
This commit is contained in:
@@ -0,0 +1,209 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:lanebow/screens/club/event_details_screen.dart';
|
||||
import 'package:lanebow/models/event_model.dart';
|
||||
import 'package:lanebow/models/participant_model.dart';
|
||||
import 'package:lanebow/models/score_model.dart';
|
||||
import 'package:lanebow/models/member_model.dart';
|
||||
import 'package:lanebow/models/club_model.dart';
|
||||
import 'package:lanebow/models/team_model.dart';
|
||||
import 'package:lanebow/services/event_service.dart';
|
||||
import 'package:lanebow/services/club_service.dart';
|
||||
import 'package:lanebow/services/member_service.dart';
|
||||
import 'package:lanebow/widgets/loading_indicator.dart';
|
||||
|
||||
// 간단한 테스트 더블 구현 (ChangeNotifier 유지)
|
||||
class FakeEventService extends EventService {
|
||||
@override
|
||||
List<Participant> participants = [];
|
||||
@override
|
||||
List<Score> scores = [];
|
||||
|
||||
@override
|
||||
Future<List<Participant>> fetchEventParticipants(String eventId) async {
|
||||
return participants;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Score>> fetchEventScores(String eventId) async {
|
||||
return scores;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Team>> fetchEventTeams(String eventId) async {
|
||||
// 팀 기능은 테스트에서 필수가 아니므로 빈 리스트를 즉시 반환하여 네트워크 의존성을 제거
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
class FakeClubService extends ClubService {
|
||||
Club? club;
|
||||
@override
|
||||
Future<Club> fetchClub(String clubId) async {
|
||||
return club ?? Club(name: '클럽', id: clubId);
|
||||
}
|
||||
}
|
||||
|
||||
class FakeMemberService extends MemberService {
|
||||
List<Member> membersByIds = [];
|
||||
@override
|
||||
Future<List<Member>> fetchMembersByIds(String clubId, List<String> ids) async {
|
||||
return membersByIds;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setClubId(String clubId) async {
|
||||
// no-op: 테스트에서는 내부 상태 주입만 필요하며 네트워크 호출 불필요
|
||||
return;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> fetchClubMembers() async {
|
||||
// no-op: 테스트에서는 네트워크 호출 없이 즉시 완료
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
// ChangeNotifier 서브타입에 Provider.value 사용 허용(자동 업데이트 불필요한 테스트 시나리오)
|
||||
Provider.debugCheckInvalidValueType = null;
|
||||
|
||||
group('EventDetailsScreen', () {
|
||||
late FakeEventService eventService;
|
||||
late FakeClubService clubService;
|
||||
late FakeMemberService memberService;
|
||||
|
||||
final event = Event(
|
||||
id: 'e1',
|
||||
clubId: 'c1',
|
||||
title: '테스트 이벤트',
|
||||
description: '설명입니다',
|
||||
startDate: DateTime(2025, 1, 2, 19, 30),
|
||||
endDate: DateTime(2025, 1, 2, 22, 00),
|
||||
location: '강남볼링장',
|
||||
type: '정기전',
|
||||
status: '진행중',
|
||||
maxParticipants: 24,
|
||||
currentParticipants: 2,
|
||||
gameCount: 3,
|
||||
participantFee: 10000,
|
||||
registrationDeadline: DateTime(2024, 12, 31, 23, 59),
|
||||
publicHash: 'hash123',
|
||||
accessPassword: '1234',
|
||||
isActive: true,
|
||||
);
|
||||
|
||||
setUp(() {
|
||||
eventService = FakeEventService();
|
||||
clubService = FakeClubService();
|
||||
memberService = FakeMemberService();
|
||||
|
||||
// Participants
|
||||
eventService.participants = [
|
||||
Participant(
|
||||
id: 'p1',
|
||||
eventId: 'e1',
|
||||
memberId: 'm1',
|
||||
registeredAt: DateTime(2025, 1, 1),
|
||||
),
|
||||
Participant(
|
||||
id: 'p2',
|
||||
eventId: 'e1',
|
||||
memberId: 'm2',
|
||||
registeredAt: DateTime(2025, 1, 1),
|
||||
),
|
||||
];
|
||||
// Scores
|
||||
eventService.scores = [
|
||||
Score(
|
||||
id: 's1',
|
||||
eventId: 'e1',
|
||||
memberId: 'm1',
|
||||
clubId: 'c1',
|
||||
frames: const [100, 100, 100, 100, 100],
|
||||
totalScore: 500,
|
||||
handicap: 0,
|
||||
date: DateTime(2025, 1, 2),
|
||||
),
|
||||
];
|
||||
// Club
|
||||
clubService.club = Club(id: 'c1', name: '볼링클럽', ownerId: 'u1');
|
||||
// Members
|
||||
memberService.membersByIds = [
|
||||
Member(
|
||||
id: 'm1',
|
||||
userId: 'u1',
|
||||
clubId: 'c1',
|
||||
name: '철수',
|
||||
email: 'a@b.com',
|
||||
isActive: true,
|
||||
gender: 'M',
|
||||
birthDate: DateTime(1990, 1, 1),
|
||||
),
|
||||
Member(
|
||||
id: 'm2',
|
||||
userId: 'u2',
|
||||
clubId: 'c1',
|
||||
name: '영희',
|
||||
email: 'c@d.com',
|
||||
isActive: true,
|
||||
gender: 'F',
|
||||
birthDate: DateTime(1992, 1, 1),
|
||||
),
|
||||
];
|
||||
});
|
||||
|
||||
Widget wrapWithProviders(Widget child) {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
Provider<EventService>.value(value: eventService),
|
||||
Provider<ClubService>.value(value: clubService),
|
||||
Provider<MemberService>.value(value: memberService),
|
||||
],
|
||||
child: MaterialApp(home: child),
|
||||
);
|
||||
}
|
||||
|
||||
testWidgets('로딩 후 기본 정보 탭 렌더링 및 핵심 정보 표시', (tester) async {
|
||||
await tester.pumpWidget(wrapWithProviders(EventDetailsScreen(event: event)));
|
||||
|
||||
// 초기 로딩 표시
|
||||
expect(find.byType(LoadingIndicator), findsOneWidget);
|
||||
|
||||
// async 로딩/초기 빌드가 끝나도록 약간 더 대기 (무한 대기 방지)
|
||||
await tester.pump(const Duration(milliseconds: 200));
|
||||
await tester.pump(const Duration(milliseconds: 200));
|
||||
|
||||
// AppBar 제목
|
||||
expect(find.text('테스트 이벤트'), findsOneWidget);
|
||||
|
||||
// 탭 존재 확인
|
||||
expect(find.text('기본 정보'), findsOneWidget);
|
||||
expect(find.text('참가자'), findsOneWidget);
|
||||
expect(find.text('점수'), findsOneWidget);
|
||||
expect(find.text('팀'), findsOneWidget);
|
||||
|
||||
// 기본 정보 섹션이 렌더링되고 공유 버튼이 존재
|
||||
expect(find.byIcon(Icons.share), findsOneWidget);
|
||||
// 장소/날짜와 같은 텍스트 일부가 표시되는지(정확한 포맷 대신 포함 여부만 확인)
|
||||
expect(find.textContaining('강남'), findsWidgets);
|
||||
});
|
||||
|
||||
testWidgets('참가자 탭: 참가자 수와 리스트 표시', (tester) async {
|
||||
await tester.pumpWidget(wrapWithProviders(EventDetailsScreen(event: event)));
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
|
||||
// 참가자 탭으로 이동: 탭 터치 대신 TabBarView를 드래그로 넘김(제스처 경로 단순화)
|
||||
await tester.drag(find.byType(TabBarView), const Offset(-400, 0));
|
||||
await tester.pump(const Duration(milliseconds: 250));
|
||||
await tester.pump(const Duration(milliseconds: 250));
|
||||
|
||||
// 리스트가 렌더링되는지(정확한 항목 텍스트 대신 리스트 존재 확인)
|
||||
expect(find.byType(ListView), findsWidgets);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user