1import 'package:coves_flutter/models/coves_session.dart'; 2import 'package:coves_flutter/providers/vote_provider.dart'; 3import 'package:flutter/foundation.dart'; 4 5/// Mock CommentsProvider for testing 6class MockCommentsProvider extends ChangeNotifier { 7 final String postUri; 8 final String postCid; 9 10 MockCommentsProvider({ 11 required this.postUri, 12 required this.postCid, 13 }); 14 15 final ValueNotifier<DateTime?> currentTimeNotifier = ValueNotifier(null); 16 17 @override 18 void dispose() { 19 currentTimeNotifier.dispose(); 20 super.dispose(); 21 } 22} 23 24/// Mock AuthProvider for testing 25class MockAuthProvider extends ChangeNotifier { 26 bool _isAuthenticated = false; 27 bool _isLoading = false; 28 String? _error; 29 String? _did; 30 String? _handle; 31 CovesSession? _session; 32 33 bool get isAuthenticated => _isAuthenticated; 34 bool get isLoading => _isLoading; 35 String? get error => _error; 36 String? get did => _did; 37 String? get handle => _handle; 38 CovesSession? get session => _session; 39 40 void setAuthenticated({required bool value, String? did}) { 41 _isAuthenticated = value; 42 _did = did ?? 'did:plc:testuser'; 43 notifyListeners(); 44 } 45 46 Future<void> signIn(String handle) async { 47 _isAuthenticated = true; 48 _handle = handle; 49 _did = 'did:plc:testuser'; 50 notifyListeners(); 51 } 52 53 Future<void> signOut() async { 54 _isAuthenticated = false; 55 _did = null; 56 _handle = null; 57 _session = null; 58 notifyListeners(); 59 } 60 61 Future<void> initialize() async { 62 _isLoading = false; 63 } 64 65 Future<String?> getAccessToken() async { 66 return _isAuthenticated ? 'mock_access_token' : null; 67 } 68 69 void clearError() { 70 _error = null; 71 notifyListeners(); 72 } 73} 74 75/// Mock VoteProvider for testing 76class MockVoteProvider extends ChangeNotifier { 77 final Map<String, VoteState> _votes = {}; 78 final Map<String, int> _scoreAdjustments = {}; 79 final Map<String, bool> _pendingRequests = {}; 80 81 bool isLiked(String postUri) { 82 return _votes[postUri]?.direction == 'up' && 83 !(_votes[postUri]?.deleted ?? false); 84 } 85 86 int getAdjustedScore(String postUri, int originalScore) { 87 final adjustment = _scoreAdjustments[postUri] ?? 0; 88 return originalScore + adjustment; 89 } 90 91 VoteState? getVoteState(String postUri) => _votes[postUri]; 92 93 bool isPending(String postUri) => _pendingRequests[postUri] ?? false; 94 95 Future<bool> toggleVote({ 96 required String postUri, 97 required String postCid, 98 String direction = 'up', 99 }) async { 100 final currentlyLiked = isLiked(postUri); 101 102 if (currentlyLiked) { 103 // Removing vote 104 _votes[postUri] = VoteState(direction: direction, deleted: true); 105 _scoreAdjustments[postUri] = (_scoreAdjustments[postUri] ?? 0) - 1; 106 } else { 107 // Adding vote 108 _votes[postUri] = VoteState(direction: direction, deleted: false); 109 _scoreAdjustments[postUri] = (_scoreAdjustments[postUri] ?? 0) + 1; 110 } 111 112 notifyListeners(); 113 return !currentlyLiked; 114 } 115 116 void setVoteState({required String postUri, required bool liked}) { 117 if (liked) { 118 _votes[postUri] = const VoteState(direction: 'up', deleted: false); 119 } else { 120 _votes.remove(postUri); 121 } 122 notifyListeners(); 123 } 124 125 void setInitialVoteState({ 126 required String postUri, 127 String? voteDirection, 128 String? voteUri, 129 }) { 130 if (voteDirection != null) { 131 String? rkey; 132 if (voteUri != null) { 133 final parts = voteUri.split('/'); 134 if (parts.isNotEmpty) { 135 rkey = parts.last; 136 } 137 } 138 139 _votes[postUri] = VoteState( 140 direction: voteDirection, 141 uri: voteUri, 142 rkey: rkey, 143 deleted: false, 144 ); 145 146 _scoreAdjustments.remove(postUri); 147 } else { 148 _votes.remove(postUri); 149 } 150 } 151 152 void clear() { 153 _votes.clear(); 154 _pendingRequests.clear(); 155 _scoreAdjustments.clear(); 156 notifyListeners(); 157 } 158}