이벤트 가져오기 위젯 테스트 추가 및 테스트 훅 도입

This commit is contained in:
2025-09-12 06:33:44 +09:00
parent 107abc963f
commit a5f2544d11
121 changed files with 39277 additions and 3911 deletions
@@ -6,14 +6,20 @@ import '../../services/auth_service.dart';
import '../../services/club_service.dart';
import '../../services/member_service.dart';
import '../../utils/enum_mappings.dart';
import '../../widgets/owner_dropdown.dart';
class ClubSettingsScreen extends StatefulWidget {
static const routeName = '/club-settings';
const ClubSettingsScreen({super.key});
const ClubSettingsScreen({super.key, this.onOwnerItemsBuilt, this.initialMembers});
// 테스트 전용: 모임장 드롭다운 항목 개수 리포트 콜백
final ValueChanged<int>? onOwnerItemsBuilt;
// 테스트 전용: 초기 멤버 목록을 직접 주입하여 로딩을 우회
final List<Member>? initialMembers;
@override
_ClubSettingsScreenState createState() => _ClubSettingsScreenState();
State<ClubSettingsScreen> createState() => _ClubSettingsScreenState();
}
class _ClubSettingsScreenState extends State<ClubSettingsScreen> {
@@ -32,7 +38,14 @@ class _ClubSettingsScreenState extends State<ClubSettingsScreen> {
@override
void initState() {
super.initState();
_loadData();
if (widget.initialMembers != null) {
// 테스트 경로: 초기 데이터 주입
_members = List<Member>.from(widget.initialMembers!);
_isLoading = false;
_hasEditPermission = true; // 테스트에서는 편집 가능 상태로 둠
} else {
_loadData();
}
}
@override
@@ -49,6 +62,11 @@ class _ClubSettingsScreenState extends State<ClubSettingsScreen> {
_isLoading = true;
});
// await 이전에 messenger 캡처 (catch에서 사용)
final messenger = ScaffoldMessenger.of(context);
// await 이전에 authService 캡처 (이후 권한 계산에 사용)
final authService = Provider.of<AuthService>(context, listen: false);
try {
// 클럽 정보 로드
final clubService = Provider.of<ClubService>(context, listen: false);
@@ -72,7 +90,6 @@ class _ClubSettingsScreenState extends State<ClubSettingsScreen> {
});
// 권한 확인
final authService = Provider.of<AuthService>(context, listen: false);
final currentUserId = authService.currentUser?.id;
// 현재 사용자가 클럽 소유자이거나 관리자인지 확인
@@ -98,9 +115,9 @@ class _ClubSettingsScreenState extends State<ClubSettingsScreen> {
});
}
} catch (error) {
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('데이터 로드 중 오류가 발생했습니다: $error')));
messenger.showSnackBar(
SnackBar(content: Text('데이터 로드 중 오류가 발생했습니다: $error')),
);
} finally {
if (mounted) {
setState(() {
@@ -119,6 +136,9 @@ class _ClubSettingsScreenState extends State<ClubSettingsScreen> {
_isLoading = true;
});
// await 이전에 messenger 캡처
final messenger = ScaffoldMessenger.of(context);
try {
final clubService = Provider.of<ClubService>(context, listen: false);
final club = clubService.currentClub;
@@ -185,18 +205,14 @@ class _ClubSettingsScreenState extends State<ClubSettingsScreen> {
await clubService.updateClub(club.id, updates);
if (context.mounted) {
ScaffoldMessenger.of(
context,
).showSnackBar(const SnackBar(content: Text('클럽 정보가 성공적으로 저장되었습니다')));
}
}
} catch (error) {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('클럽 정보 저장 중 오류가 발생했습니다: $error')),
messenger.showSnackBar(
const SnackBar(content: Text('클럽 정보가 성공적으로 저장되었습니다')),
);
}
} catch (error) {
messenger.showSnackBar(
SnackBar(content: Text('클럽 정보 저장 중 오류가 발생했습니다: $error')),
);
} finally {
if (mounted) {
setState(() {
@@ -294,16 +310,22 @@ class _ClubSettingsScreenState extends State<ClubSettingsScreen> {
// 평균 산정 기준
const SizedBox(height: 16),
DropdownButtonFormField<String>(
key: const Key('club_settings_avg_period_dropdown'),
decoration: const InputDecoration(
labelText: '평균 산정 기준',
border: OutlineInputBorder(),
),
value: _selectedAverageCalculationPeriod,
isExpanded: true,
items: averageCalculationPeriodOptions.entries
.map(
(entry) => DropdownMenuItem<String>(
value: entry.key,
child: Text(entry.value),
child: Text(
entry.value,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
)
.toList(),
@@ -317,27 +339,18 @@ class _ClubSettingsScreenState extends State<ClubSettingsScreen> {
),
// 모임장 설정
const SizedBox(height: 16),
DropdownButtonFormField<String>(
decoration: const InputDecoration(
labelText: '모임장 설정',
border: OutlineInputBorder(),
),
OwnerDropdown(
key: const Key('owner_dropdown'),
members: _members,
value: _selectedOwnerId,
items: _members.map((member) {
return DropdownMenuItem<String>(
value: member.userId,
child: Text(
'${member.name} (${getMemberTypeLabel(member.memberType)})',
),
);
}).toList(),
onChanged: _hasEditPermission
? (value) {
setState(() {
_selectedOwnerId = value;
});
}
: null,
enabled: _hasEditPermission,
onChanged: (value) {
if (!_hasEditPermission) return;
setState(() {
_selectedOwnerId = value;
});
},
onItemsBuilt: widget.onOwnerItemsBuilt,
),
// 저장 버튼
const SizedBox(height: 24),