Skip to content

Commit

Permalink
[dio] Test typed responses (#1755)
Browse files Browse the repository at this point in the history
  • Loading branch information
kuhnroyal authored Dec 28, 2023
1 parent b670886 commit 88a0fda
Show file tree
Hide file tree
Showing 14 changed files with 69 additions and 20 deletions.
6 changes: 4 additions & 2 deletions dio/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ See the [Migration Guide][] for the complete breaking changes list.**

- The minimum supported Dart version has been bumped from `2.15.0` to `2.19.0`.
- Remove `DefaultHttpClientAdapter` which was deprecated in `5.0.0`.
- Remove `IOHttpClientAdapter.onHttpClientCreate` which was deprecated in `5.2.0`
- Remove `IOHttpClientAdapter.onHttpClientCreate` which was deprecated in `5.2.0`.
- Remove `DioError` and `DioErrorType` which was deprecated in `5.2.0`.
- Remove `DefaultTransformer` which was deprecated in `5.0.0`.
- `IOHttpClientAdapter` no longer sets a custom `HttpClient.idleTimeout`. A custom `HttpClient` can be provided via
`IOHttpClientAdapter.createHttpClient` if customisation is required.
- Make use of Isolate.run for the BackgroundTransformer
- Make use of `Isolate.run` in the BackgroundTransformer.
- Respect nullability of generic type parameter in `dio`s request methods like `get<String()` vs `get<String?>()`.
Follow the [Migration Guide][] for more details.

## Unreleased

Expand Down
23 changes: 23 additions & 0 deletions dio/doc/migration_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,29 @@ When new content need to be added to the migration guide, make sure they're foll
- `IOHttpClientAdapter.onHttpClientCreate` which was deprecated in `5.2.0` has been removed - use `IOHttpClientAdapter.createHttpClient` instead.
- `DioError` and `DioErrorType` which was deprecated in `5.2.0` has been removed - use `DioException` and `DioExceptionType` instead.
- `DefaultTransformer` which was deprecated in `5.0.0` has been removed - use `BackgroundTransformer` instead.
- The nullability of the generic type parameter in `dio`s request methods is now respected for the responses' `data`.

> [!WARNING]
> The migration depends on your use case and API responses.
> If in doubt make the type nullable and correctly handle the null case.
> DO NOT just delete the null checks if they are shown to be redundant, but think about the impact.
Before:
```dart
Response<String?> response = await Dio().get<String>('https://example.com');
String data = response.data!;
```

After:
```dart
Response<String> response = await Dio().get<String>('https://example.com');
String data = response.data;
```
Or:
```dart
Response<String?> response = await Dio().get<String?>('https://example.com');
String? data = response.data;
```

## 5.0.0

Expand Down
2 changes: 1 addition & 1 deletion dio/lib/src/dio/dio_for_native.dart
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class DioForNative extends DioMixin implements Dio {
int received = 0;

// Stream<Uint8List>
final stream = response.data!.stream;
final stream = response.data.stream;
bool compressed = false;
int total = 0;
final contentEncoding = response.headers.value(
Expand Down
3 changes: 2 additions & 1 deletion dio/lib/src/dio_mixin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,7 @@ abstract class DioMixin implements Dio {
// Make sure headers and [ResponseBody.headers] are the same instance.
responseBody.headers = headers.map;
final ret = Response<dynamic>(
data: null,
headers: headers,
requestOptions: reqOpt,
redirects: responseBody.redirects ?? [],
Expand Down Expand Up @@ -713,7 +714,7 @@ abstract class DioMixin implements Dio {
requestOptions: requestOptions,
);
} else if (response is! Response<T>) {
final T? data = response.data as T?;
final T data = response.data as T;
final Headers headers;
if (data is ResponseBody) {
headers = Headers.fromMap(
Expand Down
4 changes: 2 additions & 2 deletions dio/lib/src/response.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import 'redirect_record.dart';
/// in anytime, typically by [Interceptor] and [Transformer].
class Response<T> {
Response({
this.data,
required this.data,
required this.requestOptions,
this.statusCode,
this.statusMessage,
Expand All @@ -27,7 +27,7 @@ class Response<T> {
///
/// The content could have been transformed by the [Transformer]
/// before it can use eventually.
T? data;
T data;

/// The [RequestOptions] used for the corresponding request.
RequestOptions requestOptions;
Expand Down
4 changes: 2 additions & 2 deletions dio/test/options_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -357,9 +357,9 @@ void main() {
// Regression: https://github.com/cfug/dio/issues/1834
final r11 = await dio.get('');
expect(r11.data, '');
final r12 = await dio.get<Map>('');
final r12 = await dio.get<Map?>('');
expect(r12.data, null);
final r13 = await dio.get<Map<String, Object>>('');
final r13 = await dio.get<Map<String, Object>?>('');
expect(r13.data, null);
});

Expand Down
2 changes: 1 addition & 1 deletion dio/test/request_integration_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ void main() {
);
expect(response.data, isA<List>());
expect(response.data, isNotEmpty);
expect(response.data![0], 1);
expect(response.data[0], 1);
});
});

Expand Down
14 changes: 8 additions & 6 deletions dio/test/timeout_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,16 @@ void main() {
);

dio.options.connectTimeout = Duration(milliseconds: 5);
await dio
.get('/')
.catchError((e) => Response(requestOptions: RequestOptions()));
await dio.get('/').catchError((e) => Response(
requestOptions: RequestOptions(),
data: null,
));
expect(client.connectionTimeout, dio.options.connectTimeout);
dio.options.connectTimeout = Duration(milliseconds: 10);
await dio
.get('/')
.catchError((e) => Response(requestOptions: RequestOptions()));
await dio.get('/').catchError((e) => Response(
requestOptions: RequestOptions(),
data: null,
));
expect(client.connectionTimeout, dio.options.connectTimeout);
}, testOn: 'vm');
});
Expand Down
19 changes: 19 additions & 0 deletions dio/test/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,25 @@ Future<void> startServer() async {
return;
}

if (path == '/null-response') {
response.headers.contentType = ContentType('text', 'plain');
response
..statusCode = 200
..contentLength = -1;
response.close();
return;
}

if (path == '/non-null-response') {
response.headers.contentType = ContentType('text', 'plain');
response
..statusCode = 200
..contentLength = -1
..write('response');
response.close();
return;
}

final requestBodyBytes = await ByteStream(request).toBytes();
final encodingName = request.uri.queryParameters['response-encoding'];
final outputEncoding = encodingName == null
Expand Down
2 changes: 1 addition & 1 deletion example/lib/generic.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@ void main() async {

// This is the recommended way.
final r = await dio.get<String>('https://baidu.com');
print(r.data?.length);
print(r.data.length);
}
2 changes: 1 addition & 1 deletion example_flutter_app/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class _MyHomePageState extends State<MyHomePage> {
.then((r) {
setState(() {
print(r.data);
_text = r.data!.replaceAll(RegExp(r'\s'), '');
_text = r.data.replaceAll(RegExp(r'\s'), '');
});
});
} catch (e) {
Expand Down
2 changes: 1 addition & 1 deletion example_flutter_app/lib/routes/request.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class _RequestRouteState extends State<RequestRoute> {
onPressed: () {
dio.get<String>('https://httpbin.org/get').then((r) {
setState(() {
_text = r.data!;
_text = r.data;
});
});
},
Expand Down
2 changes: 2 additions & 0 deletions plugins/cookie_manager/test/cookies_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ void main() {
final firstRequestOptions = RequestOptions(baseUrl: exampleUrl);

final mockResponse = Response(
data: null,
requestOptions: firstRequestOptions,
headers: Headers.fromMap(
{HttpHeaders.setCookieHeader: mockFirstRequestCookies},
Expand Down Expand Up @@ -77,6 +78,7 @@ void main() {
final requestOptions = RequestOptions(baseUrl: exampleUrl);

final mockResponse = Response(
data: null,
requestOptions: requestOptions,
headers: Headers.fromMap(
{HttpHeaders.setCookieHeader: mockResponseCookies},
Expand Down
4 changes: 2 additions & 2 deletions plugins/native_dio_adapter/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class _MyHomePageState extends State<MyHomePage> {
return AlertDialog(
title: Text('Response ${response.statusCode}'),
content: SingleChildScrollView(
child: Text(response.data ?? 'No response'),
child: Text(response.data),
),
actions: [
MaterialButton(
Expand Down Expand Up @@ -120,7 +120,7 @@ class _MyHomePageState extends State<MyHomePage> {
return AlertDialog(
title: Text('Response ${response.statusCode}'),
content: SingleChildScrollView(
child: Text(response.data ?? 'No response'),
child: Text(response.data),
),
actions: [
MaterialButton(
Expand Down

0 comments on commit 88a0fda

Please sign in to comment.