100 lines
2.8 KiB
Dart
100 lines
2.8 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:live_recorder_mobile/core/network/api_client.dart';
|
|
import 'package:live_recorder_mobile/core/network/api_exception.dart';
|
|
|
|
void main() {
|
|
group('ApiClient', () {
|
|
test('injects bearer token into request headers', () async {
|
|
final client = ApiClient(
|
|
baseUrl: 'https://example.com',
|
|
tokenProvider: () => 'token-123',
|
|
onUnauthorized: () async {},
|
|
client: _FakeHttpClient((http.BaseRequest request) async {
|
|
expect(request.headers['Authorization'], 'Bearer token-123');
|
|
return _jsonResponse(<String, dynamic>{'ok': true});
|
|
}),
|
|
);
|
|
|
|
final response = await client.getJson('/api/test') as Map<String, dynamic>;
|
|
|
|
expect(response['ok'], isTrue);
|
|
});
|
|
|
|
test('preserves backend subpath when building request URLs', () async {
|
|
final client = ApiClient(
|
|
baseUrl: 'https://example.com/live-recorder',
|
|
tokenProvider: () => null,
|
|
onUnauthorized: () async {},
|
|
client: _FakeHttpClient((http.BaseRequest request) async {
|
|
expect(
|
|
request.url.toString(),
|
|
'https://example.com/live-recorder/api/test',
|
|
);
|
|
return _jsonResponse(<String, dynamic>{'ok': true});
|
|
}),
|
|
);
|
|
|
|
await client.getJson('/api/test');
|
|
});
|
|
|
|
test('triggers unauthorized callback on 401 response', () async {
|
|
var unauthorizedCalled = false;
|
|
|
|
final client = ApiClient(
|
|
baseUrl: 'https://example.com',
|
|
tokenProvider: () => null,
|
|
onUnauthorized: () async {
|
|
unauthorizedCalled = true;
|
|
},
|
|
client: _FakeHttpClient((http.BaseRequest request) async {
|
|
return _jsonResponse(
|
|
<String, dynamic>{'message': 'unauthorized'},
|
|
statusCode: 401,
|
|
);
|
|
}),
|
|
);
|
|
|
|
await expectLater(
|
|
client.getJson('/api/test'),
|
|
throwsA(
|
|
isA<ApiException>().having(
|
|
(ApiException error) => error.message,
|
|
'message',
|
|
'unauthorized',
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(unauthorizedCalled, isTrue);
|
|
});
|
|
});
|
|
}
|
|
|
|
class _FakeHttpClient extends http.BaseClient {
|
|
_FakeHttpClient(this._handler);
|
|
|
|
final Future<http.StreamedResponse> Function(http.BaseRequest request) _handler;
|
|
|
|
@override
|
|
Future<http.StreamedResponse> send(http.BaseRequest request) {
|
|
return _handler(request);
|
|
}
|
|
}
|
|
|
|
http.StreamedResponse _jsonResponse(
|
|
Map<String, dynamic> body, {
|
|
int statusCode = 200,
|
|
}) {
|
|
final bytes = utf8.encode(jsonEncode(body));
|
|
return http.StreamedResponse(
|
|
Stream<List<int>>.value(bytes),
|
|
statusCode,
|
|
headers: const <String, String>{
|
|
'content-type': 'application/json',
|
|
},
|
|
);
|
|
}
|