Files
soul-yongping/scripts/test/web/test_upload.py
卡若 76965adb23 chore: 清理敏感与开发文档,仅同步代码
- 永久忽略并从仓库移除 开发文档/
- 移除并忽略 .env 与小程序私有配置
- 同步小程序/管理端/API与脚本改动

Made-with: Cursor
2026-03-17 17:50:12 +08:00

122 lines
4.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
"""
文件上传测试。POST /api/upload 上传图片DELETE /api/upload 删除。
验证本地存储OSS 未配置时)、响应格式、删除流程。
"""
import io
import pytest
import requests
# 最小有效 JPEG1x1 像素,约 100 字节)
_MIN_JPEG = (
b"\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00"
b"\xff\xdb\x00C\x00\x08\x06\x06\x07\x06\x05\x08\x07\x07\x07\t\t\x08\n\x0c\x14\r\x0c\x0b\x0b\x0c\x19\x12\x13\x0f\x14\x1d\x1a\x1f\x1e\x1d\x1a\x1c\x1c"
b" $.' \",#\x1c\x1c(7),01444\x1f'9=82<.342\xff\xc0\x00\x0b\x08\x00\x01\x00\x01\x01\x01\x11\x00\xff\xc4\x00\x1f\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\xff\xda\x00\x08\x01\x01\x00\x00\x00?\x00\xfe\x02\x1f\xff\xd9"
)
def test_upload_post_success(base_url):
"""POST /api/upload 上传图片成功,返回 url、fileName、size、type"""
files = {"file": ("test_upload.jpg", io.BytesIO(_MIN_JPEG), "image/jpeg")}
data = {"folder": "test"}
r = requests.post(
f"{base_url}/api/upload",
files=files,
data=data,
timeout=10,
)
assert r.status_code == 200, f"期望 200实际 {r.status_code}: {r.text}"
body = r.json()
assert body.get("success") is True, body
assert "url" in body, body
assert body["url"], "url 不应为空"
data_out = body.get("data", {})
assert "url" in data_out
assert "fileName" in data_out
assert "size" in data_out
assert data_out["size"] == len(_MIN_JPEG)
assert "type" in data_out
assert "image" in str(data_out.get("type", "")).lower()
def test_upload_post_with_admin_token(base_url, admin_token):
"""POST /api/upload 带管理端 token 也可上传(接口不强制鉴权)"""
if not admin_token:
pytest.skip("admin 登录失败")
files = {"file": ("avatar.jpg", io.BytesIO(_MIN_JPEG), "image/jpeg")}
# multipart 上传不设 Content-Type让 requests 自动带 boundary
headers = {"Authorization": f"Bearer {admin_token}"}
r = requests.post(
f"{base_url}/api/upload",
files=files,
headers=headers,
timeout=10,
)
assert r.status_code == 200
body = r.json()
assert body.get("success") is True
assert body.get("url")
def test_upload_post_no_file(base_url):
"""POST /api/upload 无 file 返回 400"""
r = requests.post(
f"{base_url}/api/upload",
data={"folder": "test"},
timeout=10,
)
assert r.status_code == 400
body = r.json()
assert body.get("success") is False
assert "error" in body or "请选择" in body.get("error", "")
def test_upload_post_invalid_type(base_url):
"""POST /api/upload 非图片格式返回 400"""
files = {"file": ("test.txt", io.BytesIO(b"hello"), "text/plain")}
r = requests.post(
f"{base_url}/api/upload",
files=files,
timeout=10,
)
assert r.status_code == 400
body = r.json()
assert body.get("success") is False
def test_upload_delete_local(base_url):
"""DELETE /api/upload 删除本地文件:先上传再删除"""
# 1. 上传
files = {"file": ("del_test.jpg", io.BytesIO(_MIN_JPEG), "image/jpeg")}
r1 = requests.post(
f"{base_url}/api/upload",
files=files,
data={"folder": "test"},
timeout=10,
)
assert r1.status_code == 200
url = r1.json().get("url")
assert url, "上传应返回 url"
# path 支持 /uploads/xxx 或含 /uploads/ 的完整 URL
path = url
# 2. 删除
r2 = requests.delete(
f"{base_url}/api/upload",
params={"path": path},
timeout=10,
)
assert r2.status_code == 200
body = r2.json()
assert body.get("success") is True
assert "删除成功" in body.get("message", "")
def test_upload_delete_no_path(base_url):
"""DELETE /api/upload 无 path 返回 400"""
r = requests.delete(f"{base_url}/api/upload", timeout=10)
assert r.status_code == 400
body = r.json()
assert body.get("success") is False