Skip to content

Commit 314ce48

Browse files
committed
fake_api: Add apiException parameter; switch to it where needed
1 parent a933232 commit 314ce48

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

test/api/fake_api.dart

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'dart:convert';
44
import 'package:flutter/foundation.dart';
55
import 'package:http/http.dart' as http;
66
import 'package:zulip/api/core.dart';
7+
import 'package:zulip/api/exception.dart';
78
import 'package:zulip/model/store.dart';
89

910
import '../example_data.dart' as eg;
@@ -211,27 +212,47 @@ class FakeApiConnection extends ApiConnection {
211212

212213
/// Prepare the HTTP response for the next request.
213214
///
214-
/// If `httpException` is null, the next request will produce an [http.Response]
215+
/// If `httpException` and `apiException` are both null, then
216+
/// the next request will produce an [http.Response]
215217
/// with the given `httpStatus`, defaulting to 200. The body of the response
216218
/// will be `body` if non-null, or `jsonEncode(json)` if `json` is non-null,
217219
/// or else ''. The `body` and `json` parameters must not both be non-null.
218220
///
219-
/// If `httpException` is non-null, then
221+
/// If `httpException` is non-null, then `apiException`,
220222
/// `httpStatus`, `body`, and `json` must all be null, and the next request
221223
/// will throw the given exception within the HTTP client layer,
222224
/// causing the API request to throw a [NetworkException]
223225
/// wrapping the given exception.
224226
///
225-
/// In either case, the next request will complete a duration of `delay`
227+
/// If `apiException` is non-null, then `httpException`,
228+
/// `httpStatus`, `body`, and `json` must all be null, and the next request
229+
/// will throw an exception equivalent to the given exception
230+
/// (except [ApiRequestException.routeName], which is ignored).
231+
///
232+
/// In each case, the next request will complete a duration of `delay`
226233
/// after being started.
227234
void prepare({
228235
Object? httpException,
236+
ZulipApiException? apiException,
229237
int? httpStatus,
230238
Map<String, dynamic>? json,
231239
String? body,
232240
Duration delay = Duration.zero,
233241
}) {
234242
assert(isOpen);
243+
244+
if (apiException != null) {
245+
assert(httpException == null
246+
&& httpStatus == null && json == null && body == null);
247+
httpStatus = apiException.httpStatus;
248+
json = {
249+
'result': 'error',
250+
'code': apiException.code,
251+
'msg': apiException.message,
252+
...apiException.data,
253+
};
254+
}
255+
235256
client.prepare(
236257
exception: httpException,
237258
httpStatus: httpStatus, json: json, body: body,

test/api/fake_api_test.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,22 @@ void main() {
3434
..cause.identicalTo(exception));
3535
});
3636

37+
test('prepare API exception', () async {
38+
final connection = FakeApiConnection();
39+
final exception = ZulipApiException(routeName: 'someRoute',
40+
httpStatus: 456, code: 'SOME_ERROR',
41+
data: {'foo': ['bar']}, message: 'Something failed');
42+
connection.prepare(apiException: exception);
43+
await check(connection.get('aRoute', (json) => json, '/', null))
44+
.throws((it) => it.isA<ZulipApiException>()
45+
..routeName.equals('aRoute') // actual route, not the prepared one
46+
..routeName.not((it) => it.equals(exception.routeName))
47+
..httpStatus.equals(exception.httpStatus)
48+
..code.equals(exception.code)
49+
..data.deepEquals(exception.data)
50+
..message.equals(exception.message));
51+
});
52+
3753
test('delay success', () => awaitFakeAsync((async) async {
3854
final connection = FakeApiConnection();
3955
connection.prepare(delay: const Duration(seconds: 2),

test/model/actions_test.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ void main() {
103103
assert(unregisterDelay > TestGlobalStore.removeAccountDuration);
104104
final exception = eg.apiExceptionUnauthorized(routeName: 'removeEtcEtcToken');
105105
final newConnection = separateConnection()
106-
..prepare(delay: unregisterDelay, httpException: exception); // TODO this isn't an HTTP exception
106+
..prepare(delay: unregisterDelay, apiException: exception);
107107

108108
final future = logOutAccount(testBinding.globalStore, eg.selfAccount.id);
109109
// Unregister-token request and account removal dispatched together
@@ -165,7 +165,7 @@ void main() {
165165

166166
final exception = eg.apiExceptionUnauthorized(routeName: 'removeEtcEtcToken');
167167
final newConnection = separateConnection()
168-
..prepare(httpException: exception); // TODO this isn't an HTTP exception
168+
..prepare(apiException: exception);
169169
final future = unregisterToken(testBinding.globalStore, eg.selfAccount.id);
170170
async.elapse(Duration.zero);
171171
await future;

0 commit comments

Comments
 (0)