""" 文件管理模块测试 """ import pytest import os from io import BytesIO from fastapi.testclient import TestClient from PIL import Image def test_upload_file(client: TestClient, auth_headers: dict): """测试文件上传""" # 创建测试图片 img = Image.new('RGB', (100, 100), color='red') img_io = BytesIO() img.save(img_io, 'JPEG') img_io.seek(0) response = client.post( "/api/v1/files/upload", headers=auth_headers, files={"file": ("test.jpg", img_io, "image/jpeg")}, data={"remark": "测试文件"} ) assert response.status_code == 200 data = response.json() assert data["original_name"] == "test.jpg" assert data["file_type"] == "image/jpeg" assert data["message"] == "上传成功" assert "id" in data assert "download_url" in data def test_upload_large_file(client: TestClient, auth_headers: dict): """测试大文件上传(应失败)""" # 创建超过限制的文件(11MB) large_content = b"x" * (11 * 1024 * 1024) response = client.post( "/api/v1/files/upload", headers=auth_headers, files={"file": ("large.jpg", BytesIO(large_content), "image/jpeg")} ) assert response.status_code == 400 def test_upload_invalid_type(client: TestClient, auth_headers: dict): """测试不支持的文件类型(应失败)""" response = client.post( "/api/v1/files/upload", headers=auth_headers, files={"file": ("test.exe", BytesIO(b"test"), "application/x-msdownload")} ) assert response.status_code == 400 def test_get_file_list(client: TestClient, auth_headers: dict): """测试获取文件列表""" response = client.get( "/api/v1/files/", headers=auth_headers, params={"page": 1, "page_size": 20} ) assert response.status_code == 200 data = response.json() assert isinstance(data, list) def test_get_file_detail(client: TestClient, auth_headers: dict): """测试获取文件详情""" # 先上传一个文件 img = Image.new('RGB', (100, 100), color='blue') img_io = BytesIO() img.save(img_io, 'PNG') img_io.seek(0) upload_response = client.post( "/api/v1/files/upload", headers=auth_headers, files={"file": ("test.png", img_io, "image/png")} ) file_id = upload_response.json()["id"] # 获取文件详情 response = client.get( f"/api/v1/files/{file_id}", headers=auth_headers ) assert response.status_code == 200 data = response.json() assert data["id"] == file_id assert "download_url" in data def test_get_file_statistics(client: TestClient, auth_headers: dict): """测试获取文件统计""" response = client.get( "/api/v1/files/statistics", headers=auth_headers ) assert response.status_code == 200 data = response.json() assert "total_files" in data assert "total_size" in data assert "type_distribution" in data def test_create_share_link(client: TestClient, auth_headers: dict): """测试生成分享链接""" # 先上传一个文件 img = Image.new('RGB', (100, 100), color='green') img_io = BytesIO() img.save(img_io, 'JPEG') img_io.seek(0) upload_response = client.post( "/api/v1/files/upload", headers=auth_headers, files={"file": ("share.jpg", img_io, "image/jpeg")} ) file_id = upload_response.json()["id"] # 生成分享链接 response = client.post( f"/api/v1/files/{file_id}/share", headers=auth_headers, json={"expire_days": 7} ) assert response.status_code == 200 data = response.json() assert "share_code" in data assert "share_url" in data assert "expire_time" in data def test_delete_file(client: TestClient, auth_headers: dict): """测试删除文件""" # 先上传一个文件 img = Image.new('RGB', (100, 100), color='yellow') img_io = BytesIO() img.save(img_io, 'JPEG') img_io.seek(0) upload_response = client.post( "/api/v1/files/upload", headers=auth_headers, files={"file": ("delete.jpg", img_io, "image/jpeg")} ) file_id = upload_response.json()["id"] # 删除文件 response = client.delete( f"/api/v1/files/{file_id}", headers=auth_headers ) assert response.status_code == 204 def test_batch_delete_files(client: TestClient, auth_headers: dict): """测试批量删除文件""" # 上传多个文件 file_ids = [] for i in range(3): img = Image.new('RGB', (100, 100), color='red') img_io = BytesIO() img.save(img_io, 'JPEG') img_io.seek(0) upload_response = client.post( "/api/v1/files/upload", headers=auth_headers, files={"file": (f"batch_{i}.jpg", img_io, "image/jpeg")} ) file_ids.append(upload_response.json()["id"]) # 批量删除 response = client.delete( "/api/v1/files/batch", headers=auth_headers, json={"file_ids": file_ids} ) assert response.status_code == 204 def test_chunk_upload_init(client: TestClient, auth_headers: dict): """测试初始化分片上传""" response = client.post( "/api/v1/files/chunks/init", headers=auth_headers, json={ "file_name": "large_file.zip", "file_size": 10485760, # 10MB "file_type": "application/zip", "total_chunks": 2 } ) assert response.status_code == 200 data = response.json() assert "upload_id" in data def test_access_shared_file(client: TestClient, auth_headers: dict): """测试访问分享文件""" # 先上传一个文件 img = Image.new('RGB', (100, 100), color='purple') img_io = BytesIO() img.save(img_io, 'JPEG') img_io.seek(0) upload_response = client.post( "/api/v1/files/upload", headers=auth_headers, files={"file": ("shared.jpg", img_io, "image/jpeg")} ) file_id = upload_response.json()["id"] # 生成分享链接 share_response = client.post( f"/api/v1/files/{file_id}/share", headers=auth_headers, json={"expire_days": 7} ) share_code = share_response.json()["share_code"] # 访问分享文件(无需认证) response = client.get(f"/api/v1/files/share/{share_code}") assert response.status_code == 200 # 运行测试的fixtures @pytest.fixture def auth_headers(client: TestClient): """获取认证头""" # 先登录 response = client.post( "/api/v1/auth/login", json={ "username": "admin", "password": "admin123" } ) if response.status_code == 200: token = response.json()["access_token"] return {"Authorization": f"Bearer {token}"} # 如果登录失败,使用测试token return {"Authorization": "Bearer test_token"}