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({'ok': true}); }), ); final response = await client.getJson('/api/test') as Map; 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({'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( {'message': 'unauthorized'}, statusCode: 401, ); }), ); await expectLater( client.getJson('/api/test'), throwsA( isA().having( (ApiException error) => error.message, 'message', 'unauthorized', ), ), ); expect(unauthorizedCalled, isTrue); }); }); } class _FakeHttpClient extends http.BaseClient { _FakeHttpClient(this._handler); final Future Function(http.BaseRequest request) _handler; @override Future send(http.BaseRequest request) { return _handler(request); } } http.StreamedResponse _jsonResponse( Map body, { int statusCode = 200, }) { final bytes = utf8.encode(jsonEncode(body)); return http.StreamedResponse( Stream>.value(bytes), statusCode, headers: const { 'content-type': 'application/json', }, ); }