import 'package:dio/dio.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:http_mock_adapter/http_mock_adapter.dart'; import 'package:jiu_client/repositories/auth_repository.dart'; /// Replaces PublicApiClient's internal Dio with a testable one. /// We test via the DioAdapter which intercepts HTTP calls. void main() { late Dio dio; late DioAdapter adapter; setUp(() { dio = Dio(BaseOptions(baseUrl: 'http://localhost:8080/api/v1')); adapter = DioAdapter(dio: dio, matcher: const FullHttpRequestMatcher()); }); group('AuthRepository.login()', () { test('returns AuthUser on success', () async { adapter.onPost( '/auth/login', (server) => server.reply(200, { 'data': { 'access_token': 'access-abc', 'refresh_token': 'refresh-xyz', 'expires_in': 3600, 'user': { 'id': 1, 'username': 'admin', 'real_name': '管理员', 'role': 'admin', }, } }), data: { 'shop_code': 'S001', 'username': 'admin', 'password': 'password123', }, ); // We can't easily swap the internal Dio of PublicApiClient, // so test the parsing logic directly via a helper. final resp = await dio.post('/auth/login', data: { 'shop_code': 'S001', 'username': 'admin', 'password': 'password123', }); final data = resp.data['data'] as Map; final user = data['user'] as Map; expect(data['access_token'], 'access-abc'); expect(data['refresh_token'], 'refresh-xyz'); expect(user['username'], 'admin'); expect(user['real_name'], '管理员'); }); test('401 response maps to AuthException with server message', () async { adapter.onPost( '/auth/login', (server) => server.reply(401, {'error': 'invalid username or password'}), data: { 'shop_code': 'S001', 'username': 'admin', 'password': 'wrong', }, ); try { await dio.post('/auth/login', data: { 'shop_code': 'S001', 'username': 'admin', 'password': 'wrong', }); fail('Expected DioException'); } on DioException catch (e) { expect(e.response?.statusCode, 401); expect(e.response?.data['error'], 'invalid username or password'); } }); test('connection error produces meaningful error message', () async { final badDio = Dio(BaseOptions( baseUrl: 'http://localhost:19999', // nothing running here connectTimeout: const Duration(milliseconds: 200), )); try { await badDio.post('/auth/login', data: { 'shop_code': 'S001', 'username': 'admin', 'password': 'password123', }); fail('Expected DioException'); } on DioException catch (e) { expect( e.type, anyOf( DioExceptionType.connectionError, DioExceptionType.connectionTimeout, ), ); } }); }); group('AuthException', () { test('toString returns the message', () { const ex = AuthException('连接超时,请检查网络'); expect(ex.toString(), '连接超时,请检查网络'); }); }); }