Main coves client
1import 'package:coves_flutter/services/api_exceptions.dart';
2import 'package:coves_flutter/services/vote_service.dart';
3import 'package:dio/dio.dart';
4import 'package:flutter_test/flutter_test.dart';
5
6void main() {
7 group('VoteService', () {
8 group('createVote', () {
9
10 test('should create vote successfully', () async {
11 // Create a real VoteService instance that we can test with
12 // We'll use a minimal test to verify the VoteResponse parsing logic
13
14 const response = VoteResponse(
15 uri: 'at://did:plc:test/social.coves.interaction.vote/456',
16 cid: 'bafy123',
17 rkey: '456',
18 deleted: false,
19 );
20
21 expect(response.uri, 'at://did:plc:test/social.coves.interaction.vote/456');
22 expect(response.cid, 'bafy123');
23 expect(response.rkey, '456');
24 expect(response.deleted, false);
25 });
26
27 test('should return deleted response when vote is toggled off', () {
28 const response = VoteResponse(deleted: true);
29
30 expect(response.deleted, true);
31 expect(response.uri, null);
32 expect(response.cid, null);
33 });
34
35 test('should throw ApiException on Dio network error', () {
36 // Test ApiException.fromDioError for connection errors
37 final dioError = DioException(
38 requestOptions: RequestOptions(path: '/test'),
39 type: DioExceptionType.connectionError,
40 );
41
42 final exception = ApiException.fromDioError(dioError);
43
44 expect(exception, isA<NetworkException>());
45 expect(
46 exception.message,
47 contains('Connection failed'),
48 );
49 });
50
51 test('should throw ApiException on Dio timeout', () {
52 final dioError = DioException(
53 requestOptions: RequestOptions(path: '/test'),
54 type: DioExceptionType.connectionTimeout,
55 );
56
57 final exception = ApiException.fromDioError(dioError);
58
59 expect(exception, isA<NetworkException>());
60 expect(exception.message, contains('timeout'));
61 });
62
63 test('should throw AuthenticationException on 401 response', () {
64 final dioError = DioException(
65 requestOptions: RequestOptions(path: '/test'),
66 type: DioExceptionType.badResponse,
67 response: Response(
68 requestOptions: RequestOptions(path: '/test'),
69 statusCode: 401,
70 data: {'message': 'Unauthorized'},
71 ),
72 );
73
74 final exception = ApiException.fromDioError(dioError);
75
76 expect(exception, isA<AuthenticationException>());
77 expect(exception.statusCode, 401);
78 expect(exception.message, 'Unauthorized');
79 });
80
81 test('should throw NotFoundException on 404 response', () {
82 final dioError = DioException(
83 requestOptions: RequestOptions(path: '/test'),
84 type: DioExceptionType.badResponse,
85 response: Response(
86 requestOptions: RequestOptions(path: '/test'),
87 statusCode: 404,
88 data: {'message': 'Post not found'},
89 ),
90 );
91
92 final exception = ApiException.fromDioError(dioError);
93
94 expect(exception, isA<NotFoundException>());
95 expect(exception.statusCode, 404);
96 expect(exception.message, 'Post not found');
97 });
98
99 test('should throw ServerException on 500 response', () {
100 final dioError = DioException(
101 requestOptions: RequestOptions(path: '/test'),
102 type: DioExceptionType.badResponse,
103 response: Response(
104 requestOptions: RequestOptions(path: '/test'),
105 statusCode: 500,
106 data: {'error': 'Internal server error'},
107 ),
108 );
109
110 final exception = ApiException.fromDioError(dioError);
111
112 expect(exception, isA<ServerException>());
113 expect(exception.statusCode, 500);
114 expect(exception.message, 'Internal server error');
115 });
116
117 test('should extract error message from response data', () {
118 final dioError = DioException(
119 requestOptions: RequestOptions(path: '/test'),
120 type: DioExceptionType.badResponse,
121 response: Response(
122 requestOptions: RequestOptions(path: '/test'),
123 statusCode: 400,
124 data: {'message': 'Invalid post URI'},
125 ),
126 );
127
128 final exception = ApiException.fromDioError(dioError);
129
130 expect(exception.message, 'Invalid post URI');
131 expect(exception.statusCode, 400);
132 });
133
134 test('should use default message if no error message in response', () {
135 final dioError = DioException(
136 requestOptions: RequestOptions(path: '/test'),
137 type: DioExceptionType.badResponse,
138 response: Response(
139 requestOptions: RequestOptions(path: '/test'),
140 statusCode: 400,
141 data: {},
142 ),
143 );
144
145 final exception = ApiException.fromDioError(dioError);
146
147 expect(exception.message, 'Server error');
148 });
149
150 test('should handle cancelled requests', () {
151 final dioError = DioException(
152 requestOptions: RequestOptions(path: '/test'),
153 type: DioExceptionType.cancel,
154 );
155
156 final exception = ApiException.fromDioError(dioError);
157
158 expect(exception.message, contains('cancelled'));
159 });
160
161 test('should handle bad certificate errors', () {
162 final dioError = DioException(
163 requestOptions: RequestOptions(path: '/test'),
164 type: DioExceptionType.badCertificate,
165 );
166
167 final exception = ApiException.fromDioError(dioError);
168
169 expect(exception, isA<NetworkException>());
170 expect(exception.message, contains('certificate'));
171 });
172
173 test('should handle unknown errors', () {
174 final dioError = DioException(
175 requestOptions: RequestOptions(path: '/test'),
176 );
177
178 final exception = ApiException.fromDioError(dioError);
179
180 expect(exception, isA<NetworkException>());
181 expect(exception.message, contains('Network error'));
182 });
183 });
184
185 group('VoteResponse', () {
186 test('should create response with uri, cid, and rkey', () {
187 const response = VoteResponse(
188 uri: 'at://vote/123',
189 cid: 'bafy123',
190 rkey: '123',
191 deleted: false,
192 );
193
194 expect(response.uri, 'at://vote/123');
195 expect(response.cid, 'bafy123');
196 expect(response.rkey, '123');
197 expect(response.deleted, false);
198 });
199
200 test('should create response with rkey extracted from uri', () {
201 const response = VoteResponse(
202 uri: 'at://vote/456',
203 cid: 'bafy456',
204 rkey: '456',
205 deleted: false,
206 );
207
208 expect(response.uri, 'at://vote/456');
209 expect(response.cid, 'bafy456');
210 expect(response.rkey, '456');
211 expect(response.deleted, false);
212 });
213
214 test('should create deleted response', () {
215 const response = VoteResponse(deleted: true);
216
217 expect(response.deleted, true);
218 expect(response.uri, null);
219 expect(response.cid, null);
220 expect(response.rkey, null);
221 });
222 });
223 });
224}