import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:metatron_student_erp/features/announcements/announcements_screen.dart';
import 'package:metatron_student_erp/models/announcement.dart';
import 'package:metatron_student_erp/providers/announcement_provider.dart';
import 'package:metatron_student_erp/repositories/announcement_repository.dart';
void main() {
final sampleAnnouncements = [
const AnnouncementItem(
id: 201,
title: 'Fee Payment Deadline',
name: 'Fee Payment Deadline',
date: '2026-10-15',
datePublished: '2026-10-15',
expiryDate: '2026-11-15',
summary: 'Please ensure semester fees are paid before deadline.',
content: '
Please ensure semester fees are paid before deadline.
',
type: 'circular',
priority: '2',
author: 'Finance Office',
hasAttachment: true,
circularFilename: 'fee_notice.pdf',
),
const AnnouncementItem(
id: 202,
title: 'Sports Day 2026',
name: 'Sports Day 2026',
date: '2026-10-18',
datePublished: '2026-10-18',
summary: 'Annual athletics and sports events registrations.',
content: 'Annual athletics and sports events registrations.
',
type: 'event',
priority: '1',
author: 'Sports Committee',
hasAttachment: false,
),
];
Widget buildTestableScreen(List overrides) {
return ProviderScope(
overrides: overrides,
child: const MaterialApp(
home: AnnouncementsScreen(),
),
);
}
testWidgets('AnnouncementsScreen renders loading state initially', (tester) async {
await tester.pumpWidget(
buildTestableScreen([
announcementsProvider.overrideWith((ref) => Future.delayed(
const Duration(seconds: 1),
() => const AnnouncementPageResult(
announcements: [],
totalCount: 0,
page: 1,
limit: 20,
),
)),
]),
);
expect(find.byType(CircularProgressIndicator), findsOneWidget);
await tester.pumpAndSettle();
});
testWidgets('AnnouncementsScreen renders empty state when no notices exist', (tester) async {
await tester.pumpWidget(
buildTestableScreen([
announcementsProvider.overrideWith((ref) => Future.value(
const AnnouncementPageResult(
announcements: [],
totalCount: 0,
page: 1,
limit: 20,
),
)),
]),
);
await tester.pumpAndSettle();
expect(find.text('No announcements found'), findsOneWidget);
});
testWidgets('AnnouncementsScreen renders filter chips and notice cards with priority badges', (tester) async {
await tester.pumpWidget(
buildTestableScreen([
announcementsProvider.overrideWith((ref) => Future.value(
AnnouncementPageResult(
announcements: sampleAnnouncements,
totalCount: 2,
page: 1,
limit: 20,
),
)),
]),
);
await tester.pumpAndSettle();
// Verify filter chips
expect(find.text('All'), findsOneWidget);
expect(find.text('Notices'), findsOneWidget);
expect(find.text('Circulars'), findsOneWidget);
expect(find.text('Events'), findsOneWidget);
// Verify card titles and badges
expect(find.text('Fee Payment Deadline'), findsOneWidget);
expect(find.text('Urgent'), findsOneWidget);
expect(find.text('Circular'), findsOneWidget);
expect(find.text('Sports Day 2026'), findsOneWidget);
expect(find.text('Important'), findsOneWidget);
expect(find.text('Event'), findsOneWidget);
expect(find.text('fee_notice.pdf'), findsOneWidget);
});
testWidgets('AnnouncementsScreen opens detail bottom sheet when card is tapped', (tester) async {
await tester.pumpWidget(
buildTestableScreen([
announcementsProvider.overrideWith((ref) => Future.value(
AnnouncementPageResult(
announcements: sampleAnnouncements,
totalCount: 2,
page: 1,
limit: 20,
),
)),
]),
);
await tester.pumpAndSettle();
// Tap the first card
await tester.tap(find.text('Fee Payment Deadline'));
await tester.pumpAndSettle();
// Check detail sheet elements
expect(find.text('Details'), findsOneWidget);
expect(find.text('Posted by: Finance Office'), findsOneWidget);
expect(find.text('Expires on: 2026-11-15'), findsOneWidget);
expect(find.text('Close'), findsOneWidget);
// Close the sheet
await tester.tap(find.text('Close'));
await tester.pumpAndSettle();
expect(find.text('Details'), findsNothing);
});
testWidgets('AnnouncementsScreen renders error state and retry button on failure', (tester) async {
await tester.pumpWidget(
buildTestableScreen([
announcementsProvider.overrideWith((ref) => Future.error('Connection timeout')),
]),
);
await tester.pumpAndSettle();
expect(find.text('Failed to load announcements'), findsOneWidget);
expect(find.text('Retry'), findsOneWidget);
});
}