Files
opsxsql/backend/tests/test_instance_fields.py
T
logan 128de64592 feat: 数据源编辑加排除数据库+脱敏字段+审批流关联; 权限组Transfer改为选择实例
- EditInstanceDialog: 新增排除数据库(逗号分隔)、脱敏字段(动态表单+表/字段/规则)、审批流程关联
- Instance: workflow JSON字段改为workflow_id FK关联workflow_definitions表
- InstanceGroupPage: Transfer穿梭框从选数据库改为选实例(数据源)
- 后端instance API返回workflow_name, _get_workflow_names批量查询
- DB迁移: instances表添加workflow_id列
- 37个测试全部通过
2026-05-24 19:36:39 +08:00

145 lines
4.8 KiB
Python

"""测试 Instance 新增字段:access_mode, workflow_id, excluded_databases, mask_fields"""
import pytest
from tests.conftest import auth_header
@pytest.mark.asyncio
async def test_create_instance_with_full_fields(client, admin_token):
"""创建数据源:完整字段"""
res = await client.post("/api/v1/instances", json={
"name": "prod-mysql-只读库",
"db_type": "mysql",
"host": "mysql.example.com",
"port": 3306,
"username": "admin",
"password": "***",
"env": "production",
"access_mode": "read",
"excluded_databases": ["sys", "information_schema", "mysql"],
"mask_fields": [
{"table": "users", "field": "phone", "rule": "mask"},
{"table": "users", "field": "id_card", "rule": "hide"},
],
}, headers=auth_header(admin_token))
assert res.status_code == 201
data = res.json()
assert data["access_mode"] == "read"
assert data["workflow_id"] is None
assert data["excluded_databases"] == ["sys", "information_schema", "mysql"]
assert len(data["mask_fields"]) == 2
assert data["mask_fields"][0]["table"] == "users"
@pytest.mark.asyncio
async def test_create_instance_default_access_mode(client, admin_token):
"""默认连接模式为 readwrite"""
res = await client.post("/api/v1/instances", json={
"name": "test-default",
"db_type": "mysql",
"host": "127.0.0.1",
"port": 3306,
"username": "root",
"password": "***",
}, headers=auth_header(admin_token))
assert res.status_code == 201
assert res.json()["access_mode"] == "readwrite"
@pytest.mark.asyncio
async def test_list_instance_includes_new_fields(client, admin_token):
"""列表接口返回新字段"""
await client.post("/api/v1/instances", json={
"name": "list-test",
"db_type": "postgres",
"host": "10.0.0.1",
"port": 5432,
"username": "postgres",
"password": "***",
"access_mode": "write",
}, headers=auth_header(admin_token))
res = await client.get("/api/v1/instances", headers=auth_header(admin_token))
assert res.status_code == 200
items = res.json()
found = [i for i in items if i["name"] == "list-test"]
assert len(found) == 1
assert found[0]["access_mode"] == "write"
assert "workflow_id" in found[0]
@pytest.mark.asyncio
async def test_update_instance_fields(client, admin_token):
"""更新字段"""
create = await client.post("/api/v1/instances", json={
"name": "update-fields",
"db_type": "mysql",
"host": "127.0.0.1",
"port": 3306,
"username": "root",
"password": "***",
}, headers=auth_header(admin_token))
iid = create.json()["id"]
res = await client.put(f"/api/v1/instances/{iid}", json={
"access_mode": "read",
"excluded_databases": ["test_db"],
}, headers=auth_header(admin_token))
assert res.status_code == 200
data = res.json()
assert data["access_mode"] == "read"
assert data["excluded_databases"] == ["test_db"]
@pytest.mark.asyncio
async def test_instance_null_json_fields(client, admin_token):
"""不传新字段时,返回 null"""
res = await client.post("/api/v1/instances", json={
"name": "minimal",
"db_type": "mysql",
"host": "127.0.0.1",
"port": 3306,
"username": "root",
"password": "***",
}, headers=auth_header(admin_token))
assert res.status_code == 201
data = res.json()
assert data["workflow_id"] is None
assert data["excluded_databases"] is None
assert data["mask_fields"] is None
@pytest.mark.asyncio
async def test_instance_workflow_id_association(client, admin_token):
"""数据源关联审批流程"""
# 创建 workflow
wf_res = await client.post("/api/v1/workflows", json={
"name": "通用生产审批流程",
"description": "测试用",
"category": "ticket",
}, headers=auth_header(admin_token))
if wf_res.status_code == 201:
wf_id = wf_res.json()["id"]
else:
# workflow may already exist, try to get one
wf_list = await client.get("/api/v1/workflows", headers=auth_header(admin_token))
workflows = wf_list.json()
wf_id = workflows[0]["id"] if workflows else None
if not wf_id:
pytest.skip("No workflow available")
# 创建带 workflow_id 的实例
res = await client.post("/api/v1/instances", json={
"name": "wf-instance",
"db_type": "mysql",
"host": "127.0.0.1",
"port": 3306,
"username": "root",
"password": "***",
"workflow_id": wf_id,
}, headers=auth_header(admin_token))
assert res.status_code == 201
data = res.json()
assert data["workflow_id"] == wf_id
assert data["workflow_name"] is not None