212 lines
7.4 KiB
Dart
212 lines
7.4 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:motorcycle_dash/core/theme/theme_extensions.dart';
|
|
import 'package:motorcycle_dash/features/social/clubs/club_detail_screen.dart';
|
|
import 'package:motorcycle_dash/features/social/clubs/widgets/officer_badge.dart';
|
|
import 'package:motorcycle_dash/services/auth/auth_providers.dart';
|
|
import 'package:motorcycle_dash/services/auth/auth_user.dart';
|
|
import 'package:motorcycle_dash/services/clubs/club_models.dart';
|
|
import 'package:motorcycle_dash/services/clubs/club_providers.dart';
|
|
import 'package:motorcycle_dash/services/clubs/club_service.dart';
|
|
|
|
class MockClubServiceForRoster extends ClubService {
|
|
String? updatedRank;
|
|
String? updatedTargetUid;
|
|
|
|
@override
|
|
Future<void> updateMemberRoleAndRank(
|
|
String clubId,
|
|
String targetUid, {
|
|
ClubRole? newRole,
|
|
String? newDisplayRank,
|
|
String? callerUid,
|
|
}) async {
|
|
updatedTargetUid = targetUid;
|
|
updatedRank = newDisplayRank;
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
group('MOB-24: Club Wall & Member Roster Interactive Features', () {
|
|
const testUser = AuthUser(uid: 'rider_test_01', isAnonymous: false);
|
|
|
|
final testClub = Club(
|
|
id: 'club_iron_riders',
|
|
name: 'Iron Ridge MC',
|
|
slug: 'iron-ridge',
|
|
description: 'Mountain pass endurance club',
|
|
ownerUid: 'owner_marcus',
|
|
memberCount: 4,
|
|
visibility: ClubVisibility.public,
|
|
admissionPolicy: ClubAdmissionPolicy.open,
|
|
createdAt: DateTime(2026, 1, 1),
|
|
updatedAt: DateTime(2026, 1, 1),
|
|
);
|
|
|
|
final activeMember = ClubMember(
|
|
uid: 'rider_test_01',
|
|
clubId: 'club_iron_riders',
|
|
status: ClubMemberStatus.active,
|
|
role: ClubRole.admin,
|
|
displayRank: 'Road Captain',
|
|
updatedAt: DateTime(2026, 1, 1),
|
|
);
|
|
|
|
final membersRoster = [
|
|
ClubMember(
|
|
uid: 'owner_marcus',
|
|
clubId: 'club_iron_riders',
|
|
status: ClubMemberStatus.active,
|
|
role: ClubRole.owner,
|
|
displayRank: 'President',
|
|
updatedAt: DateTime(2026, 1, 1),
|
|
),
|
|
activeMember,
|
|
ClubMember(
|
|
uid: 'rider_samir',
|
|
clubId: 'club_iron_riders',
|
|
status: ClubMemberStatus.active,
|
|
role: ClubRole.member,
|
|
displayRank: 'Tail Gunner',
|
|
updatedAt: DateTime(2026, 1, 1),
|
|
),
|
|
ClubMember(
|
|
uid: 'rider_dave',
|
|
clubId: 'club_iron_riders',
|
|
status: ClubMemberStatus.active,
|
|
role: ClubRole.member,
|
|
displayRank: 'Full Member',
|
|
updatedAt: DateTime(2026, 1, 1),
|
|
),
|
|
];
|
|
|
|
testWidgets('renders tab bar with Overview, Club Wall, and Roster', (tester) async {
|
|
await tester.pumpWidget(
|
|
ProviderScope(
|
|
overrides: [
|
|
currentUserProvider.overrideWith((ref) => testUser),
|
|
clubDetailProvider('club_iron_riders').overrideWith((ref) => Stream.value(testClub)),
|
|
currentMemberProvider('club_iron_riders').overrideWith((ref) => Stream.value(activeMember)),
|
|
clubMembersProvider('club_iron_riders').overrideWith((ref) => Stream.value(membersRoster)),
|
|
],
|
|
child: MaterialApp(
|
|
theme: ThemeData.dark().copyWith(
|
|
extensions: [MotorSignalThemeColors.dark],
|
|
),
|
|
home: const ClubDetailScreen(clubId: 'club_iron_riders'),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('OVERVIEW'), findsOneWidget);
|
|
expect(find.text('CLUB WALL'), findsOneWidget);
|
|
expect(find.text('ROSTER'), findsOneWidget);
|
|
|
|
// Verify Overview elements exist
|
|
expect(find.text('About the Club'), findsOneWidget);
|
|
expect(find.text('CLUB RIDES'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('switches to Club Wall tab and displays seeded discussion feed', (tester) async {
|
|
await tester.pumpWidget(
|
|
ProviderScope(
|
|
overrides: [
|
|
currentUserProvider.overrideWith((ref) => testUser),
|
|
clubDetailProvider('club_iron_riders').overrideWith((ref) => Stream.value(testClub)),
|
|
currentMemberProvider('club_iron_riders').overrideWith((ref) => Stream.value(activeMember)),
|
|
clubMembersProvider('club_iron_riders').overrideWith((ref) => Stream.value(membersRoster)),
|
|
],
|
|
child: MaterialApp(
|
|
theme: ThemeData.dark().copyWith(
|
|
extensions: [MotorSignalThemeColors.dark],
|
|
),
|
|
home: const ClubDetailScreen(clubId: 'club_iron_riders'),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
// Tap Club Wall tab
|
|
await tester.tap(find.text('CLUB WALL'));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Verify Pinned Announcement
|
|
expect(find.text('PINNED LEADERSHIP ANNOUNCEMENT'), findsOneWidget);
|
|
expect(find.textContaining('SATURDAY RIDE BRIEFING'), findsOneWidget);
|
|
|
|
// Verify discussion posts & fist bump counters
|
|
expect(find.text('Marcus Vance'), findsOneWidget);
|
|
expect(find.text('Samir Chen'), findsOneWidget);
|
|
expect(find.textContaining('Fist Bumps'), findsWidgets);
|
|
});
|
|
|
|
testWidgets('switches to Member Roster tab, filters members, and checks officer badges', (tester) async {
|
|
await tester.pumpWidget(
|
|
ProviderScope(
|
|
overrides: [
|
|
currentUserProvider.overrideWith((ref) => testUser),
|
|
clubDetailProvider('club_iron_riders').overrideWith((ref) => Stream.value(testClub)),
|
|
currentMemberProvider('club_iron_riders').overrideWith((ref) => Stream.value(activeMember)),
|
|
clubMembersProvider('club_iron_riders').overrideWith((ref) => Stream.value(membersRoster)),
|
|
],
|
|
child: MaterialApp(
|
|
theme: ThemeData.dark().copyWith(
|
|
extensions: [MotorSignalThemeColors.dark],
|
|
),
|
|
home: const ClubDetailScreen(clubId: 'club_iron_riders'),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
// Tap Roster tab
|
|
await tester.tap(find.text('ROSTER'));
|
|
await tester.pumpAndSettle();
|
|
|
|
// Verify filter chips
|
|
expect(find.text('All Members'), findsOneWidget);
|
|
expect(find.text('Executive Officers'), findsOneWidget);
|
|
expect(find.text('Road Captains & Sweeps'), findsOneWidget);
|
|
|
|
// Verify members & badges
|
|
expect(find.text('President'), findsWidgets);
|
|
expect(find.text('Road Captain (You)'), findsOneWidget);
|
|
expect(find.text('Tail Gunner'), findsWidgets);
|
|
});
|
|
|
|
testWidgets('tests OfficerBadge rendering across officer ranks', (tester) async {
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
theme: ThemeData.dark().copyWith(
|
|
extensions: [MotorSignalThemeColors.dark],
|
|
),
|
|
home: const Scaffold(
|
|
body: Column(
|
|
children: [
|
|
OfficerBadge(rank: 'President'),
|
|
OfficerBadge(rank: 'Road Captain'),
|
|
OfficerBadge(rank: 'Tail Gunner'),
|
|
OfficerBadge(rank: 'Road Marshal'),
|
|
OfficerBadge(rank: 'Full Member'),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('PRESIDENT'), findsOneWidget);
|
|
expect(find.text('ROAD CAPTAIN'), findsOneWidget);
|
|
expect(find.text('TAIL GUNNER'), findsOneWidget);
|
|
expect(find.text('ROAD MARSHAL'), findsOneWidget);
|
|
expect(find.text('FULL MEMBER'), findsOneWidget);
|
|
});
|
|
});
|
|
}
|