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