修复工作人员端令牌失效后的登录恢复
This commit is contained in:
115
apps/service_app/test/data/api_client_test.dart
Normal file
115
apps/service_app/test/data/api_client_test.dart
Normal file
@@ -0,0 +1,115 @@
|
||||
// 功能描述:验证工作人员端统一请求的鉴权失效通知和上传处理。
|
||||
// 版本:1.0.0
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http/testing.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:service_app/data/services/api_client.dart';
|
||||
|
||||
/// 覆盖 HTTP 状态、业务码、匿名请求、请求令牌快照和上传场景。
|
||||
void main() {
|
||||
test('受保护接口返回 HTTP 401 时通知会话并抛出专用异常', () async {
|
||||
final rejectedTokens = <String>[];
|
||||
final client = ApiClient(
|
||||
() => 'JWT expired-token',
|
||||
baseUrl: 'https://api.example.com',
|
||||
onUnauthorized: rejectedTokens.add,
|
||||
client: MockClient((request) async => http.Response('', 401)),
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
client.get('/protected'),
|
||||
throwsA(isA<SessionExpiredException>()),
|
||||
);
|
||||
expect(rejectedTokens, ['JWT expired-token']);
|
||||
});
|
||||
|
||||
test('受保护接口返回鉴权业务码时通知会话', () async {
|
||||
final rejectedTokens = <String>[];
|
||||
final client = ApiClient(
|
||||
() => 'JWT expired-token',
|
||||
baseUrl: 'https://api.example.com',
|
||||
onUnauthorized: rejectedTokens.add,
|
||||
client: MockClient(
|
||||
(request) async => http.Response(
|
||||
'{"code":1308,"message":"Token Expired","details":null}',
|
||||
200,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
client.get('/protected'),
|
||||
throwsA(isA<SessionExpiredException>()),
|
||||
);
|
||||
expect(rejectedTokens, ['JWT expired-token']);
|
||||
});
|
||||
|
||||
test('未鉴权接口返回 401 时不得清理已有会话', () async {
|
||||
final rejectedTokens = <String>[];
|
||||
final client = ApiClient(
|
||||
() => 'JWT current-token',
|
||||
baseUrl: 'https://api.example.com',
|
||||
onUnauthorized: rejectedTokens.add,
|
||||
client: MockClient((request) async => http.Response('', 401)),
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
client.post('/login', authenticated: false),
|
||||
throwsA(
|
||||
isA<ApiException>()
|
||||
.having((error) => error.code, 'code', 401)
|
||||
.having((error) => error is SessionExpiredException, 'session expired', isFalse),
|
||||
),
|
||||
);
|
||||
expect(rejectedTokens, isEmpty);
|
||||
});
|
||||
|
||||
test('请求发送后令牌变化时仍上报实际被拒绝的旧令牌', () async {
|
||||
var currentToken = 'JWT old-token';
|
||||
final rejectedTokens = <String>[];
|
||||
final client = ApiClient(
|
||||
() => currentToken,
|
||||
baseUrl: 'https://api.example.com',
|
||||
onUnauthorized: rejectedTokens.add,
|
||||
client: MockClient((request) async {
|
||||
currentToken = 'JWT new-token';
|
||||
return http.Response('', 401);
|
||||
}),
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
client.get('/protected'),
|
||||
throwsA(isA<SessionExpiredException>()),
|
||||
);
|
||||
expect(rejectedTokens, ['JWT old-token']);
|
||||
});
|
||||
|
||||
test('文件上传返回鉴权业务码时同样触发统一会话失效', () async {
|
||||
final rejectedTokens = <String>[];
|
||||
final client = ApiClient(
|
||||
() => 'JWT expired-token',
|
||||
baseUrl: 'https://api.example.com',
|
||||
onUnauthorized: rejectedTokens.add,
|
||||
client: MockClient(
|
||||
(request) async => http.Response(
|
||||
'{"code":1715,"message":"Unauthorized","details":null}',
|
||||
200,
|
||||
),
|
||||
),
|
||||
);
|
||||
final file = XFile.fromData(
|
||||
Uint8List.fromList(const [1, 2, 3]),
|
||||
name: 'proof.jpg',
|
||||
mimeType: 'image/jpeg',
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
client.upload(file),
|
||||
throwsA(isA<SessionExpiredException>()),
|
||||
);
|
||||
expect(rejectedTokens, ['JWT expired-token']);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user