已完成用户APP首期功能开发
交付用户端首期页面、配套接口、后台资源及测试文档。用户APP构建、静态分析和三个管理后台构建通过;完整测试仍有2项失败,后端模型注释检查未通过,详见交付记录。
This commit is contained in:
61
apps/user_app/test/data/avatar_upload_test.dart
Normal file
61
apps/user_app/test/data/avatar_upload_test.dart
Normal file
@@ -0,0 +1,61 @@
|
||||
// 功能描述:验证 multipart 文件上传鉴权、会话过期与资源路径解析。
|
||||
// 版本: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:user_app/data/repositories/client_repository.dart';
|
||||
import 'package:user_app/data/services/api_client.dart';
|
||||
|
||||
void main() {
|
||||
test('上传携带鉴权和文件内容,不使用 JSON 包装二进制', () async {
|
||||
final api = ApiClient(
|
||||
() => 'test-token',
|
||||
baseUrl: 'https://api.example.com',
|
||||
client: MockClient((request) async {
|
||||
expect(request.headers['authorization'], 'test-token');
|
||||
expect(request.url.path, '/upload/avatar');
|
||||
expect(request.headers['content-type'], startsWith('multipart/form-data; boundary='));
|
||||
expect(request.body, contains('name="file"; filename="avatar.png"'));
|
||||
return http.Response('{"code":0,"details":{"uri":"/uploads/avatars/test.png"}}', 200);
|
||||
}),
|
||||
);
|
||||
expect(
|
||||
await ClientRepository(api).uploadAvatar(Uint8List.fromList([1, 2, 3]), 'avatar.png'),
|
||||
'/uploads/avatars/test.png',
|
||||
);
|
||||
});
|
||||
test('超过大小限制不会发起请求;上传过期使会话失效', () async {
|
||||
var requests = 0;
|
||||
final rejected = <String>[];
|
||||
final api = ApiClient(
|
||||
() => 'expired',
|
||||
onUnauthorized: rejected.add,
|
||||
client: MockClient((request) async {
|
||||
requests++;
|
||||
return http.Response('', 401);
|
||||
}),
|
||||
);
|
||||
await expectLater(
|
||||
api.uploadAvatar(Uint8List(2 * 1024 * 1024 + 1), 'x.png'),
|
||||
throwsA(isA<ApiException>()),
|
||||
);
|
||||
expect(requests, 0);
|
||||
await expectLater(
|
||||
api.uploadAvatar(Uint8List.fromList([1]), 'x.png'),
|
||||
throwsA(isA<SessionExpiredException>()),
|
||||
);
|
||||
expect(rejected, ['expired']);
|
||||
});
|
||||
test('图片相对路径使用配置的 API 域名,拒绝非网络协议', () {
|
||||
final repo = ClientRepository(ApiClient(() => '', baseUrl: 'https://api.example.com'));
|
||||
expect(
|
||||
repo.resolveImageUrl('/uploads/product.png'),
|
||||
'https://api.example.com/uploads/product.png',
|
||||
);
|
||||
expect(repo.resolveImageUrl('https://cdn.example.com/a.png'), 'https://cdn.example.com/a.png');
|
||||
for (final value in ['//other.example.com/a', 'javascript:x', 'file:///secret']) {
|
||||
expect(repo.resolveImageUrl(value), '');
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user