MotorSignal-App/test/club_wall_and_roster_test.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);
});
});
}