62 lines
2.4 KiB
Dart
62 lines
2.4 KiB
Dart
// 功能描述:验证 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), '');
|
||
}
|
||
});
|
||
}
|