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), '');
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|