import 'package:flutter_test/flutter_test.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:dio/dio.dart'; import 'package:lanebow/services/event_service.dart'; import 'package:lanebow/services/api_service.dart'; import 'package:lanebow/config/api_config.dart'; import 'package:lanebow/models/participant_model.dart'; void main() { group('EventService participants API contract', () { late ApiService api; late Dio dio; late List captured; setUp(() async { SharedPreferences.setMockInitialValues({ ApiConfig.userIdKey: 'user-1', ApiConfig.clubIdKey: 'club-1', }); api = ApiService(); dio = Dio(BaseOptions(baseUrl: ApiConfig.baseUrl)); captured = []; dio.interceptors.add(InterceptorsWrapper( onRequest: (options, handler) { captured.add(options); // 라우트 분기 if (options.path.endsWith('/events/evt-1/participants/list')) { // participants: 배열로 응답 return handler.resolve(Response( requestOptions: options, statusCode: 200, data: [ { 'id': 'p1', 'eventId': 'evt-1', 'memberId': 'm1', 'status': 'confirmed', 'paymentStatus': 'paid', 'Member': { 'name': '홍길동', 'email': 'hong@example.com', 'phone': '010-1111-2222', } } ], )); } if (options.path.endsWith('/events/evt-1/participants')) { final req = options.data as Map? ?? {}; return handler.resolve(Response( requestOptions: options, statusCode: 200, data: { 'participant': { 'id': 'new-1', 'eventId': req['eventId'] ?? 'evt-1', 'memberId': 'mX', 'name': req['name'], 'status': req['status'], 'paymentStatus': req['paymentStatus'] ?? (req['isPaid'] == true ? 'paid' : 'unpaid'), } }, )); } if (options.path.endsWith('/events/evt-1/participants/p1')) { final req = options.data as Map? ?? {}; return handler.resolve(Response( requestOptions: options, statusCode: 200, data: { 'participant': { 'id': 'p1', 'eventId': 'evt-1', 'memberId': 'm1', 'name': req['name'] ?? '홍길동', 'status': req['status'] ?? 'confirmed', 'paymentStatus': req['paymentStatus'] ?? 'paid', } }, )); } // 기본: 404 return handler.resolve(Response( requestOptions: options, statusCode: 404, data: {'error': 'not found', 'path': options.path}, )); }, )); api.setDio(dio); api.setToken('test-token'); }); test('fetchEventParticipants posts to list endpoint with clubId/userId and parses participants', () async { final svc = EventService.forTest(api); // 내부 상태에 clubId 세팅 svc.setClubId('club-1'); await svc.initialize('test-token'); final list = await svc.fetchEventParticipants('evt-1'); // 요청 검증 expect(captured.isNotEmpty, true); final req = captured.first; expect(req.method, 'POST'); expect(req.path, '${ApiConfig.clubs}/events/evt-1/participants/list'); final body = req.data as Map; expect(body['clubId'], 'club-1'); expect(body['userId'], 'user-1'); expect(body['eventId'], 'evt-1'); // 파싱 검증 expect(list, isA>()); expect(list.length, 1); final p = list.first; expect(p.name, '홍길동'); expect(p.email, 'hong@example.com'); expect(p.phoneNumber, '010-1111-2222'); expect(p.status, 'confirmed'); expect(p.isPaid, isTrue); }); test('addParticipant posts to correct endpoint and merges clubId into payload', () async { final svc = EventService.forTest(api); svc.setClubId('club-1'); await svc.initialize('test-token'); final created = await svc.addParticipant('evt-1', { 'eventId': 'evt-1', 'name': '새 참가자', 'status': 'registered', 'isPaid': false, 'paymentStatus': 'unpaid', }); // 마지막 요청 검증 final req = captured.last; expect(req.method, 'POST'); expect(req.path, '${ApiConfig.clubs}/events/evt-1/participants'); final body = req.data as Map; expect(body['clubId'], 'club-1'); expect(body['name'], '새 참가자'); expect(body['status'], 'registered'); expect(body['paymentStatus'], 'unpaid'); expect(created.id, 'new-1'); expect(created.status, 'registered'); expect(created.isPaid, isFalse); }); test('updateParticipant puts to correct endpoint and returns updated model', () async { final svc = EventService.forTest(api); svc.setClubId('club-1'); await svc.initialize('test-token'); final updated = await svc.updateParticipant('evt-1', 'p1', { 'name': '수정된', 'status': 'confirmed', 'paymentStatus': 'paid', }); final req = captured.last; expect(req.method, 'PUT'); expect(req.path, '${ApiConfig.clubs}/events/evt-1/participants/p1'); final body = req.data as Map; expect(body['name'], '수정된'); expect(body['status'], 'confirmed'); expect(body['paymentStatus'], 'paid'); expect(updated.id, 'p1'); expect(updated.name, '수정된'); expect(updated.status, 'confirmed'); expect(updated.isPaid, isTrue); }); }); }