175 lines
5.9 KiB
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);
|
|
});
|
|
});
|
|
}
|