import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:tasq/models/programmer_day_sheet.model.dart'; import 'package:tasq/providers/profile_provider.dart'; import 'package:tasq/providers/programmer_day_sheets_provider.dart'; import 'package:tasq/screens/programmer_tasks/day_sheets/approvals_tab.dart'; import 'package:tasq/screens/programmer_tasks/day_sheets/day_sheet_snapshot_builder.dart'; import 'package:tasq/theme/app_theme.dart'; import 'package:tasq/utils/app_time.dart'; // --------------------------------------------------------------------------- // Helpers // --------------------------------------------------------------------------- ProgrammerDaySheet _sheet({ required String id, required String status, DateTime? workDate, bool autoSubmitted = false, int resubmissions = 0, }) { final now = AppTime.now(); final date = workDate ?? DateTime.utc(now.year, now.month, 15); return ProgrammerDaySheet( id: id, programmerId: 'prog-1', status: status, workDate: date, autoSubmitted: autoSubmitted, resubmissions: resubmissions, createdAt: now, updatedAt: now, ); } Widget _buildApp(Widget child, {List overrides = const []}) { return ProviderScope( overrides: overrides, child: MaterialApp( theme: AppTheme.light(), home: Scaffold(body: child), ), ); } // --------------------------------------------------------------------------- // Tests // --------------------------------------------------------------------------- void main() { setUpAll(AppTime.initialize); // ── groupSheetsByDate ──────────────────────────────────────────────────── group('groupSheetsByDate', () { test('groups by workDate, keys descending', () { final d1 = DateTime.utc(2024, 1, 3); final d2 = DateTime.utc(2024, 1, 2); final d3 = DateTime.utc(2024, 1, 1); final sheets = [ _sheet(id: 'a', status: DaySheetStatus.pending, workDate: d2), _sheet(id: 'b', status: DaySheetStatus.approved, workDate: d1), _sheet(id: 'c', status: DaySheetStatus.draft, workDate: d3), _sheet(id: 'd', status: DaySheetStatus.pending, workDate: d2), ]; final grouped = groupSheetsByDate(sheets); final keys = grouped.keys.toList(); expect(keys, [d1, d2, d3]); expect(grouped[d1]!.map((s) => s.id).toList(), ['b']); expect(grouped[d2]!.map((s) => s.id).toList(), ['a', 'd']); expect(grouped[d3]!.map((s) => s.id).toList(), ['c']); }); test('single sheet returns single-entry map', () { final d = DateTime.utc(2024, 6, 1); final result = groupSheetsByDate([_sheet(id: 'x', status: DaySheetStatus.pending, workDate: d)]); expect(result.keys.toList(), [d]); expect(result[d]!.length, 1); }); test('empty list returns empty map', () { expect(groupSheetsByDate([]), isEmpty); }); }); // ── approvalCounts ─────────────────────────────────────────────────────── group('approvalCounts', () { test('counts pending, awaiting (disapproved) and approved', () { final sheets = [ _sheet(id: '1', status: DaySheetStatus.pending), _sheet(id: '2', status: DaySheetStatus.pending), _sheet(id: '3', status: DaySheetStatus.disapproved), _sheet(id: '4', status: DaySheetStatus.approved), _sheet(id: '5', status: DaySheetStatus.draft), ]; final counts = approvalCounts(sheets); expect(counts.pending, 2); expect(counts.awaiting, 1); expect(counts.approved, 1); }); test('all zero for empty list', () { final counts = approvalCounts([]); expect(counts.pending, 0); expect(counts.awaiting, 0); expect(counts.approved, 0); }); test('draft sheets are not counted', () { final counts = approvalCounts([ _sheet(id: '1', status: DaySheetStatus.draft), _sheet(id: '2', status: DaySheetStatus.draft), ]); expect(counts.pending, 0); expect(counts.awaiting, 0); expect(counts.approved, 0); }); }); // ── ApprovalsTab widget ────────────────────────────────────────────────── group('ApprovalsTab', () { List _pendingSheets(int n) { final now = AppTime.now(); return List.generate( n, (i) => _sheet( id: 'sheet-$i', status: DaySheetStatus.pending, workDate: DateTime.utc(now.year, now.month, 15), ), ); } testWidgets( 'selecting 2 of 3 pending cards shows Approve selected (2)', (tester) async { final sheets = _pendingSheets(3); await tester.pumpWidget( _buildApp( const ApprovalsTab(), overrides: [ allDaySheetsProvider.overrideWith( (ref) => Stream.value(sheets), ), profilesProvider.overrideWith( (ref) => Stream.value([]), ), isStrictAdminProvider.overrideWith((ref) => true), currentUserIdProvider.overrideWith((ref) => 'admin-1'), ], ), ); // Let the stream settle. await tester.pump(); await tester.pump(); // All 3 pending cards should be visible with checkboxes. final checkboxes = find.byType(Checkbox); expect(checkboxes, findsAtLeastNWidgets(2)); // Select two cards. await tester.tap(checkboxes.at(0)); await tester.pump(); await tester.tap(checkboxes.at(1)); await tester.pump(); // The approve button must reflect the selection count. expect(find.text('Approve selected (2)'), findsOneWidget); }); }); }