75 lines
2.1 KiB
Dart
75 lines
2.1 KiB
Dart
import 'dart:typed_data';
|
|
|
|
import 'package:dio/dio.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:jinzhi_flutter_app/common/network/api_exception.dart';
|
|
import 'package:jinzhi_flutter_app/common/network/kratos_error_interceptor.dart';
|
|
import 'package:jinzhi_flutter_app/models/pb/errors/errors.pb.dart' as errors;
|
|
|
|
void main() {
|
|
test('classifies Kratos invalid token and preserves the raw body', () async {
|
|
final body = errors.Status(
|
|
code: 401,
|
|
reason: 'INVALID_TOKEN',
|
|
message: 'expired',
|
|
).writeToBuffer();
|
|
final dio = Dio()
|
|
..httpClientAdapter = _ErrorAdapter(body, 401)
|
|
..interceptors.add(KratosErrorInterceptor());
|
|
|
|
try {
|
|
await dio.get<List<int>>(
|
|
'/me',
|
|
options: Options(responseType: ResponseType.bytes),
|
|
);
|
|
fail('request should fail');
|
|
} on DioException catch (error) {
|
|
final exception = ApiException.from(error);
|
|
expect(exception.kind, ApiExceptionKind.backend);
|
|
expect(exception.reason, 'INVALID_TOKEN');
|
|
expect(exception.isUnauthorized, isTrue);
|
|
expect(error.response!.data, body);
|
|
}
|
|
});
|
|
|
|
test('classifies transport, retryable server errors, and cancellation', () {
|
|
final request = RequestOptions(path: '/test');
|
|
expect(
|
|
ApiException.fromDio(DioException(requestOptions: request)).kind,
|
|
ApiExceptionKind.transport,
|
|
);
|
|
expect(
|
|
ApiException.fromDio(
|
|
DioException(
|
|
requestOptions: request,
|
|
response: Response<void>(requestOptions: request, statusCode: 503),
|
|
),
|
|
).isRetryable,
|
|
isTrue,
|
|
);
|
|
expect(
|
|
ApiException.fromDio(
|
|
DioException(requestOptions: request, type: DioExceptionType.cancel),
|
|
).kind,
|
|
ApiExceptionKind.cancelled,
|
|
);
|
|
});
|
|
}
|
|
|
|
class _ErrorAdapter implements HttpClientAdapter {
|
|
_ErrorAdapter(this.body, this.status);
|
|
|
|
final List<int> body;
|
|
final int status;
|
|
|
|
@override
|
|
Future<ResponseBody> fetch(
|
|
RequestOptions options,
|
|
Stream<Uint8List>? requestStream,
|
|
Future<void>? cancelFuture,
|
|
) async => ResponseBody.fromBytes(body, status);
|
|
|
|
@override
|
|
void close({bool force = false}) {}
|
|
}
|