169 lines
6.1 KiB
Dart
169 lines
6.1 KiB
Dart
import 'dart:async';
|
|
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/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';
|
|
|
|
void main() {
|
|
group('ClubDetailScreen Discovery UI State Tests', () {
|
|
const testUser = AuthUser(uid: 'rider_alice', isAnonymous: false);
|
|
|
|
final testClub = Club(
|
|
id: 'club_alpha',
|
|
name: 'Alpha Riders',
|
|
slug: 'alpha-riders',
|
|
description: 'The premier Alpha motorcycle community',
|
|
ownerUid: 'owner_bob',
|
|
memberCount: 15,
|
|
visibility: ClubVisibility.public,
|
|
admissionPolicy: ClubAdmissionPolicy.open,
|
|
createdAt: DateTime(2026, 1, 1),
|
|
updatedAt: DateTime(2026, 1, 1),
|
|
);
|
|
|
|
final activeMember = ClubMember(
|
|
clubId: 'club_alpha',
|
|
uid: 'rider_alice',
|
|
role: ClubRole.member,
|
|
status: ClubMemberStatus.active,
|
|
joinedAt: DateTime(2026, 1, 1),
|
|
updatedAt: DateTime(2026, 1, 1),
|
|
);
|
|
|
|
Widget buildTestWidget({
|
|
bool overrideMember = false,
|
|
ClubMember? memberOverride,
|
|
required AsyncValue<List<ClubRideDiscovery>> discoveryOverride,
|
|
}) {
|
|
return ProviderScope(
|
|
overrides: [
|
|
currentUserProvider.overrideWithValue(testUser),
|
|
clubDetailProvider('club_alpha').overrideWith((ref) => Stream.value(testClub)),
|
|
currentMemberProvider('club_alpha').overrideWith(
|
|
(ref) => Stream.value(overrideMember ? memberOverride : activeMember),
|
|
),
|
|
clubDiscoveryRidesProvider('club_alpha').overrideWith((ref) => discoveryOverride.when(
|
|
data: (data) => Future.value(data),
|
|
error: (e, s) => Future.error(e, s),
|
|
loading: () => Completer<List<ClubRideDiscovery>>().future,
|
|
)),
|
|
],
|
|
child: MaterialApp(
|
|
theme: ThemeData.dark().copyWith(
|
|
extensions: [MotorSignalThemeColors.dark],
|
|
),
|
|
home: const ClubDetailScreen(clubId: 'club_alpha'),
|
|
),
|
|
);
|
|
}
|
|
|
|
testWidgets('Non-member sees active members only notice', (tester) async {
|
|
await tester.binding.setSurfaceSize(const Size(800, 2400));
|
|
addTearDown(() => tester.binding.setSurfaceSize(null));
|
|
|
|
await tester.pumpWidget(
|
|
buildTestWidget(
|
|
overrideMember: true,
|
|
memberOverride: null,
|
|
discoveryOverride: const AsyncValue.data([]),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('CLUB RIDES'), findsOneWidget);
|
|
expect(find.text('Club rides are visible to active members only.'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('Active member sees loading progress indicator during discovery fetch', (tester) async {
|
|
await tester.binding.setSurfaceSize(const Size(800, 2400));
|
|
addTearDown(() => tester.binding.setSurfaceSize(null));
|
|
|
|
await tester.pumpWidget(
|
|
buildTestWidget(
|
|
discoveryOverride: const AsyncValue.loading(),
|
|
),
|
|
);
|
|
await tester.pump();
|
|
|
|
expect(find.text('CLUB RIDES'), findsOneWidget);
|
|
expect(find.byType(CircularProgressIndicator), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('Active member sees empty state when 0 upcoming rides found', (tester) async {
|
|
await tester.binding.setSurfaceSize(const Size(800, 2400));
|
|
addTearDown(() => tester.binding.setSurfaceSize(null));
|
|
|
|
await tester.pumpWidget(
|
|
buildTestWidget(
|
|
discoveryOverride: const AsyncValue.data([]),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('CLUB RIDES'), findsOneWidget);
|
|
expect(find.text('No upcoming club rides scheduled.'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('Active member sees populated discovery ride cards', (tester) async {
|
|
await tester.binding.setSurfaceSize(const Size(800, 2400));
|
|
addTearDown(() => tester.binding.setSurfaceSize(null));
|
|
|
|
final testRides = [
|
|
ClubRideDiscovery(
|
|
rideId: 'ride_101',
|
|
clubId: 'club_alpha',
|
|
title: 'Sunday Morning Twisties',
|
|
scheduledStartAt: DateTime(2026, 9, 27, 9, 0),
|
|
departureAt: DateTime(2026, 9, 27, 9, 30),
|
|
joinPolicy: 'requestToJoin',
|
|
participantCount: 6,
|
|
participantLimit: 12,
|
|
meetingLocationLabel: 'Lookout Point Parking',
|
|
paceClassification: 'Moderate',
|
|
organizerDisplayName: 'Captain Dan',
|
|
),
|
|
];
|
|
|
|
await tester.pumpWidget(
|
|
buildTestWidget(
|
|
discoveryOverride: AsyncValue.data(testRides),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('CLUB RIDES'), findsOneWidget);
|
|
expect(find.text('Sunday Morning Twisties'), findsOneWidget);
|
|
expect(find.text('REQUEST TO JOIN'), findsOneWidget);
|
|
expect(find.text('Lookout Point Parking'), findsOneWidget);
|
|
expect(find.text('6 / 12 riders'), findsOneWidget);
|
|
expect(find.text('Moderate'), findsOneWidget);
|
|
expect(find.text('Captain Dan'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('Active member sees error state with retry button on failure', (tester) async {
|
|
await tester.binding.setSurfaceSize(const Size(800, 2400));
|
|
addTearDown(() => tester.binding.setSurfaceSize(null));
|
|
|
|
await tester.pumpWidget(
|
|
buildTestWidget(
|
|
discoveryOverride: const AsyncValue.error(
|
|
ClubOperationException('Network error', code: 'network_error'),
|
|
StackTrace.empty,
|
|
),
|
|
),
|
|
);
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(find.text('CLUB RIDES'), findsOneWidget);
|
|
expect(find.text('Network connection issue. Please check your connection and try again.'), findsOneWidget);
|
|
expect(find.widgetWithText(OutlinedButton, 'Retry'), findsOneWidget);
|
|
});
|
|
});
|
|
}
|