""" 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"