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/core/api/api_client.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); group('ApiClient 403 拦截 → onForbidden 回调', () { test('写请求收到 403 时,onForbidden 收到响应体(code=READONLY_USER)', () async { dynamic captured; final client = ApiClient( token: 'test-token', onForbidden: (body) => captured = body, ); final adapter = DioAdapter( dio: client.dioForTest, matcher: const FullHttpRequestMatcher(), ); adapter.onPost( '/products', (server) => server .reply(403, {'error': 'readonly user', 'code': 'READONLY_USER'}), data: {'name': '测试'}, ); await expectLater( client.post('/products', data: {'name': '测试'}), throwsA(isA()), ); expect(captured, isA()); expect(captured['code'], 'READONLY_USER'); }); test('授权过期 403(phase=readonly)时,onForbidden 收到 phase 字段', () async { dynamic captured; final client = ApiClient( token: 'test-token', onForbidden: (body) => captured = body, ); final adapter = DioAdapter( dio: client.dioForTest, matcher: const FullHttpRequestMatcher(), ); adapter.onPost( '/stock-in', (server) => server .reply(403, {'error': 'license expired', 'phase': 'readonly'}), data: {'x': 1}, ); await expectLater( client.post('/stock-in', data: {'x': 1}), throwsA(isA()), ); expect(captured, isA()); expect(captured['phase'], 'readonly'); }); test('非 403 错误不触发 onForbidden', () async { var called = false; final client = ApiClient( token: 'test-token', onForbidden: (_) => called = true, ); final adapter = DioAdapter( dio: client.dioForTest, matcher: const FullHttpRequestMatcher(), ); adapter.onGet( '/products', (server) => server.reply(404, {'error': 'not found'}), ); await expectLater( client.get('/products'), throwsA(isA()), ); expect(called, isFalse); }); }); }