MotorSignal-App/test/clubs_hub_screen_test.dart

175 lines
5.9 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/clubs_hub_screen.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 FakeClubServiceForHub extends ClubService {
final Map<String, Club> clubs;
final Map<String, String> handles;
FakeClubServiceForHub({
this.clubs = const {},
this.handles = const {},
});
@override
Future<Club?> getClubBySlug(String slug) async {
final clubId = handles[slug];
if (clubId == null) return null;
return clubs[clubId];
}
@override
Future<List<Club>> discoverPublicClubs({int limit = 25, dynamic startAfter}) async {
return clubs.values.where((c) => c.visibility == ClubVisibility.public).toList();
}
}
void main() {
group('ClubsHubScreen Widget Tests', () {
testWidgets('renders account-required notice when signed out', (tester) async {
await tester.pumpWidget(
ProviderScope(
overrides: [
currentUserProvider.overrideWith((ref) => null),
],
child: MaterialApp(
theme: ThemeData.dark().copyWith(
extensions: [MotorSignalThemeColors.dark],
),
home: const ClubsHubScreen(),
),
),
);
expect(find.text('Account Required for Clubs'), findsOneWidget);
expect(
find.text('Sign in or create a MotorSignal account to join and manage riding clubs.'),
findsOneWidget,
);
expect(find.text('Sign In / Register'), findsOneWidget);
});
testWidgets('renders tabs, empty my clubs, and public clubs when authenticated', (tester) async {
const user = AuthUser(uid: 'alice', isAnonymous: false);
final publicClub = Club(
id: 'club_pub_1',
name: 'Bay Area Motos',
slug: 'bay-area-motos',
description: 'San Francisco & Bay Area motorcycle rides.',
ownerUid: 'bob',
memberCount: 15,
createdAt: DateTime(2026, 1, 1),
updatedAt: DateTime(2026, 1, 1),
);
final fakeService = FakeClubServiceForHub(
clubs: {'club_pub_1': publicClub},
handles: {'bay-area-motos': 'club_pub_1'},
);
await tester.pumpWidget(
ProviderScope(
overrides: [
currentUserProvider.overrideWith((ref) => user),
clubServiceProvider.overrideWithValue(fakeService),
myClubsProvider.overrideWith((ref) => Stream.value(const [])),
publicClubsProvider.overrideWith((ref) => Future.value([publicClub])),
],
child: MaterialApp(
theme: ThemeData.dark().copyWith(
extensions: [MotorSignalThemeColors.dark],
),
home: const ClubsHubScreen(),
),
),
);
await tester.pumpAndSettle();
// Verify tabs
expect(find.text('MY CLUBS'), findsOneWidget);
expect(find.text('DISCOVER'), findsOneWidget);
// Verify Empty My Clubs state
expect(find.text('No Club Memberships Yet'), findsOneWidget);
expect(find.text('Discover Clubs'), findsOneWidget);
// Tap on DISCOVER tab
await tester.tap(find.text('DISCOVER'));
await tester.pumpAndSettle();
// Verify Public Discovery content
expect(find.text('Public Clubs Directory'), findsOneWidget);
expect(find.text('Bay Area Motos'), findsOneWidget);
expect(find.text('@bay-area-motos'), findsOneWidget);
// Verify search input
expect(find.byType(TextField), findsOneWidget);
});
testWidgets('executes exact handle search in Discover tab', (tester) async {
const user = AuthUser(uid: 'alice', isAnonymous: false);
final targetClub = Club(
id: 'club_norcal',
name: 'NorCal Riders',
slug: 'norcal-riders',
description: 'Northern California twisties.',
ownerUid: 'charlie',
memberCount: 8,
createdAt: DateTime(2026, 1, 1),
updatedAt: DateTime(2026, 1, 1),
);
final fakeService = FakeClubServiceForHub(
clubs: {'club_norcal': targetClub},
handles: {'norcal-riders': 'club_norcal'},
);
await tester.pumpWidget(
ProviderScope(
overrides: [
currentUserProvider.overrideWith((ref) => user),
clubServiceProvider.overrideWithValue(fakeService),
myClubsProvider.overrideWith((ref) => Stream.value(const [])),
publicClubsProvider.overrideWith((ref) => Future.value(const [])),
],
child: MaterialApp(
theme: ThemeData.dark().copyWith(
extensions: [MotorSignalThemeColors.dark],
),
home: const ClubsHubScreen(),
),
),
);
await tester.pumpAndSettle();
// Switch to Discover tab
await tester.tap(find.text('DISCOVER'));
await tester.pumpAndSettle();
// Search for club by slug
await tester.enterText(find.byType(TextField), 'norcal-riders');
await tester.testTextInput.receiveAction(TextInputAction.search);
await tester.pumpAndSettle();
expect(find.text('EXACT MATCH: @norcal-riders'), findsOneWidget);
expect(find.text('NorCal Riders'), findsOneWidget);
// Search for non-existent slug
await tester.enterText(find.byType(TextField), 'unknown-club');
await tester.testTextInput.receiveAction(TextInputAction.search);
await tester.pumpAndSettle();
expect(find.text('No club found with handle @unknown-club'), findsOneWidget);
});
});
}