296 lines
10 KiB
Python
296 lines
10 KiB
Python
"""
|
||
API 端点测试
|
||
"""
|
||
|
||
from routers.api import file_service
|
||
|
||
|
||
def test_root_endpoint(client):
|
||
"""测试根路径"""
|
||
response = client.get("/")
|
||
assert response.status_code == 200
|
||
data = response.json()
|
||
assert data["status"] == "running"
|
||
assert "swagger_docs" in data
|
||
|
||
|
||
def test_health_check(client):
|
||
"""测试健康检查端点"""
|
||
response = client.get("/health")
|
||
assert response.status_code == 200
|
||
data = response.json()
|
||
assert data["status"] == "healthy"
|
||
|
||
|
||
def test_get_token_success(client, sample_token_request):
|
||
"""测试获取 Token - 成功场景"""
|
||
response = client.post("/account/common/getToken", data=sample_token_request)
|
||
assert response.status_code == 200
|
||
data = response.json()
|
||
assert data["code"] == "200"
|
||
assert "token" in data["data"]
|
||
assert "projectId" in data["data"]
|
||
|
||
|
||
def test_get_token_error_40101(client):
|
||
"""测试获取 Token - 错误场景 40101"""
|
||
request_data = {
|
||
"projectNo": "test_error_40101",
|
||
"entityName": "测试企业",
|
||
"userId": "902001",
|
||
"userName": "902001",
|
||
"appId": "remote_app",
|
||
"appSecretCode": "test_secret_code_12345",
|
||
"role": "VIEWER",
|
||
"orgCode": "902000",
|
||
"departmentCode": "902000",
|
||
}
|
||
response = client.post("/account/common/getToken", data=request_data)
|
||
assert response.status_code == 200
|
||
data = response.json()
|
||
assert data["code"] == "40101"
|
||
assert data["successResponse"] == False
|
||
|
||
|
||
def test_fetch_inner_flow_success(client, sample_inner_flow_request):
|
||
"""测试拉取行内流水 - 成功场景"""
|
||
response = client.post(
|
||
"/watson/api/project/getJZFileOrZjrcuFile",
|
||
data=sample_inner_flow_request
|
||
)
|
||
assert response.status_code == 200
|
||
data = response.json()
|
||
assert data["code"] == "200"
|
||
assert data["successResponse"] == True
|
||
assert isinstance(data["data"], list)
|
||
assert len(data["data"]) == 1
|
||
assert isinstance(data["data"][0], int)
|
||
assert 10000 <= data["data"][0] <= 99999
|
||
|
||
|
||
def test_fetch_inner_flow_error_501014(client):
|
||
"""测试拉取行内流水 - 错误场景 501014"""
|
||
request_data = {
|
||
"groupId": 1001,
|
||
"customerNo": "test_error_501014",
|
||
"dataChannelCode": "test_code",
|
||
"requestDateId": 20240101,
|
||
"dataStartDateId": 20240101,
|
||
"dataEndDateId": 20240131,
|
||
"uploadUserId": 902001,
|
||
}
|
||
response = client.post(
|
||
"/watson/api/project/getJZFileOrZjrcuFile",
|
||
data=request_data
|
||
)
|
||
assert response.status_code == 200
|
||
data = response.json()
|
||
assert data["code"] == "501014"
|
||
assert data["successResponse"] == False
|
||
|
||
|
||
def test_fetch_inner_flow_followed_by_upload_status(client):
|
||
"""拉取行内流水后,上传状态查询应命中同一条绑定记录。"""
|
||
response = client.post(
|
||
"/watson/api/project/getJZFileOrZjrcuFile",
|
||
data={
|
||
"groupId": 1001,
|
||
"customerNo": "test_customer_002",
|
||
"dataChannelCode": "test_code",
|
||
"requestDateId": 20240101,
|
||
"dataStartDateId": 20240101,
|
||
"dataEndDateId": 20240131,
|
||
"uploadUserId": 902001,
|
||
},
|
||
)
|
||
assert response.status_code == 200
|
||
log_id = response.json()["data"][0]
|
||
|
||
assert log_id in file_service.file_records
|
||
record = file_service.file_records[log_id]
|
||
|
||
upload_response = client.get(
|
||
f"/watson/api/project/bs/upload?groupId=1001&logId={log_id}"
|
||
)
|
||
assert upload_response.status_code == 200
|
||
upload_data = upload_response.json()
|
||
|
||
assert upload_data["code"] == "200"
|
||
assert upload_data["successResponse"] is True
|
||
assert len(upload_data["data"]["logs"]) == 1
|
||
|
||
log = upload_data["data"]["logs"][0]
|
||
assert log["enterpriseNameList"] == [record.primary_enterprise_name]
|
||
assert log["accountNoList"] == [record.primary_account_no]
|
||
assert log["enterpriseNameList"][0] == record.primary_enterprise_name
|
||
assert log["accountNoList"][0] == record.primary_account_no
|
||
|
||
|
||
def test_upload_file_followed_by_upload_status_reads_real_record(client, monkeypatch):
|
||
"""上传文件后,上传状态查询应优先返回真实记录而不是 deterministic 回退。"""
|
||
monkeypatch.setattr(
|
||
file_service,
|
||
"_generate_primary_binding",
|
||
lambda: ("上传主体", "6222777788889999"),
|
||
)
|
||
|
||
upload_response = client.post(
|
||
"/watson/api/project/remoteUploadSplitFile",
|
||
data={"groupId": 1001},
|
||
files={"files": ("测试文件.csv", b"mock", "text/csv")},
|
||
)
|
||
assert upload_response.status_code == 200
|
||
upload_data = upload_response.json()
|
||
upload_log = upload_data["data"]["uploadLogList"][0]
|
||
|
||
log_id = upload_log["logId"]
|
||
status_response = client.get(f"/watson/api/project/bs/upload?groupId=1001&logId={log_id}")
|
||
assert status_response.status_code == 200
|
||
status_data = status_response.json()
|
||
status_log = status_data["data"]["logs"][0]
|
||
|
||
assert status_log["enterpriseNameList"] == upload_log["enterpriseNameList"]
|
||
assert status_log["accountNoList"] == upload_log["accountNoList"]
|
||
assert status_log["enterpriseNameList"] == ["上传主体"]
|
||
assert status_log["accountNoList"] == ["6222777788889999"]
|
||
assert len(status_log["enterpriseNameList"]) == 1
|
||
assert len(status_log["accountNoList"]) == 1
|
||
|
||
|
||
def test_fetch_inner_flow_marks_pending_complete(client):
|
||
"""拉取行内流水后,getpendings 应返回未解析状态。"""
|
||
response = client.post(
|
||
"/watson/api/project/getJZFileOrZjrcuFile",
|
||
data={
|
||
"groupId": 1001,
|
||
"customerNo": "test_customer_003",
|
||
"dataChannelCode": "test_code",
|
||
"requestDateId": 20240101,
|
||
"dataStartDateId": 20240101,
|
||
"dataEndDateId": 20240131,
|
||
"uploadUserId": 902001,
|
||
},
|
||
)
|
||
assert response.status_code == 200
|
||
log_id = response.json()["data"][0]
|
||
|
||
pending_response = client.post(
|
||
"/watson/api/project/upload/getpendings",
|
||
data={"groupId": 1001, "inprogressList": str(log_id)},
|
||
)
|
||
assert pending_response.status_code == 200
|
||
pending_data = pending_response.json()
|
||
|
||
assert pending_data["data"]["parsing"] is False
|
||
assert len(pending_data["data"]["pendingList"]) == 1
|
||
assert pending_data["data"]["pendingList"][0]["logId"] == log_id
|
||
|
||
|
||
def test_get_upload_status_with_log_id(client):
|
||
"""测试带 logId 参数查询返回非空 logs"""
|
||
response = client.get("/watson/api/project/bs/upload?groupId=1000&logId=13994")
|
||
|
||
assert response.status_code == 200
|
||
data = response.json()
|
||
|
||
# 验证基本响应结构
|
||
assert data["code"] == "200"
|
||
assert data["status"] == "200"
|
||
assert data["successResponse"] is True
|
||
|
||
# 验证 logs 不为空
|
||
assert len(data["data"]["logs"]) == 1
|
||
|
||
# 验证返回的 logId 正确
|
||
log = data["data"]["logs"][0]
|
||
assert log["logId"] == 13994
|
||
|
||
# 验证固定成功状态
|
||
assert log["status"] == -5
|
||
assert log["uploadStatusDesc"] == "data.wait.confirm.newaccount"
|
||
|
||
# 验证 logMeta 格式正确
|
||
assert log["logMeta"] == "{\"lostHeader\":[],\"balanceAmount\":\"-1\"}"
|
||
|
||
|
||
def test_get_upload_status_without_log_id(client):
|
||
"""测试不带 logId 参数查询返回空 logs 数组"""
|
||
response = client.get("/watson/api/project/bs/upload?groupId=1000")
|
||
|
||
assert response.status_code == 200
|
||
data = response.json()
|
||
|
||
# 验证基本响应结构
|
||
assert data["code"] == "200"
|
||
assert data["status"] == "200"
|
||
assert data["successResponse"] is True
|
||
|
||
# 验证 logs 为空
|
||
assert len(data["data"]["logs"]) == 0
|
||
|
||
# 验证其他字段存在
|
||
assert data["data"]["status"] == ""
|
||
assert data["data"]["accountId"] == 8954
|
||
assert data["data"]["currency"] == "CNY"
|
||
|
||
|
||
def test_deterministic_data_generation(client):
|
||
"""测试相同 logId 多次查询返回相同的核心字段值"""
|
||
# 第一次查询
|
||
response1 = client.get("/watson/api/project/bs/upload?groupId=1000&logId=13994")
|
||
log1 = response1.json()["data"]["logs"][0]
|
||
|
||
# 第二次查询
|
||
response2 = client.get("/watson/api/project/bs/upload?groupId=1000&logId=13994")
|
||
log2 = response2.json()["data"]["logs"][0]
|
||
|
||
# 验证关键字段相同
|
||
assert log1["logId"] == log2["logId"]
|
||
assert log1["bankName"] == log2["bankName"]
|
||
assert log1["accountNoList"] == log2["accountNoList"]
|
||
assert log1["enterpriseNameList"] == log2["enterpriseNameList"]
|
||
assert len(log1["accountNoList"]) == 1
|
||
assert len(log1["enterpriseNameList"]) == 1
|
||
assert log1["status"] == log2["status"]
|
||
assert log1["logMeta"] == log2["logMeta"]
|
||
assert log1["templateName"] == log2["templateName"]
|
||
assert log1["fileUploadTime"] == log2["fileUploadTime"]
|
||
assert log1["trxDateStartId"] == log2["trxDateStartId"]
|
||
assert log1["trxDateEndId"] == log2["trxDateEndId"]
|
||
|
||
|
||
def test_field_completeness(client):
|
||
"""测试返回数据包含完整的 26 个字段"""
|
||
response = client.get("/watson/api/project/bs/upload?groupId=1000&logId=13994")
|
||
log = response.json()["data"]["logs"][0]
|
||
|
||
# 验证所有必需字段存在
|
||
required_fields = [
|
||
"accountNoList", "bankName", "dataTypeInfo", "downloadFileName",
|
||
"enterpriseNameList", "fileSize", "fileUploadBy", "fileUploadByUserName",
|
||
"fileUploadTime", "isSplit", "leId", "logId", "logMeta", "logType",
|
||
"loginLeId", "lostHeader", "realBankName", "rows", "source", "status",
|
||
"templateName", "totalRecords", "trxDateEndId", "trxDateStartId",
|
||
"uploadFileName", "uploadStatusDesc"
|
||
]
|
||
|
||
for field in required_fields:
|
||
assert field in log, f"缺少字段: {field}"
|
||
|
||
|
||
def test_delete_files_accepts_array_style_log_ids(client):
|
||
"""测试删除文件接口兼容数组风格的 logIds 入参"""
|
||
response = client.post(
|
||
"/watson/api/project/batchDeleteUploadFile",
|
||
data={
|
||
"groupId": 1000,
|
||
"logIds": "[50689]",
|
||
"userId": 902001,
|
||
}
|
||
)
|
||
|
||
assert response.status_code == 200
|
||
data = response.json()
|
||
assert data["code"] == "200 OK"
|
||
assert data["message"] == "delete.files.success"
|