Files
leaudit-platform-backend/tests/release/test_g6_rule_version_management.py
T

160 lines
6.6 KiB
Python

from __future__ import annotations
import os
import re
import time
from typing import Any
import pytest
from .helpers import ReleaseApiClient
def _select_rule_set(client: ReleaseApiClient) -> dict[str, Any]:
preferred_rule_type = os.getenv("LEAUDIT_TEST_RULE_TYPE", "contract.entrust").strip()
rule_sets = ReleaseApiClient.json_data(client.get("/api/rule-sets"))
assert isinstance(rule_sets, list)
assert rule_sets, "当前环境没有规则集,无法测试版本管理"
for item in rule_sets:
if str(item.get("ruleType") or "") == preferred_rule_type and item.get("currentVersionId"):
return item
for item in rule_sets:
if item.get("currentVersionId"):
return item
pytest.skip("当前环境没有带 currentVersionId 的规则集,无法测试发布/回滚闭环")
def _set_metadata_version(yaml_text: str, version_no: str) -> str:
lines = yaml_text.splitlines()
metadata_index: int | None = None
version_pattern = re.compile(r"^(\s*)version\s*:")
for index, line in enumerate(lines):
if line.strip() == "metadata:":
metadata_index = index
continue
if metadata_index is None:
continue
if line and not line.startswith((" ", "\t")):
break
match = version_pattern.match(line)
if match:
lines[index] = f"{match.group(1)}version: '{version_no}'"
return "\n".join(lines) + ("\n" if yaml_text.endswith("\n") else "")
if metadata_index is None:
return f"metadata:\n version: '{version_no}'\n{yaml_text}"
lines.insert(metadata_index + 1, f" version: '{version_no}'")
return "\n".join(lines) + ("\n" if yaml_text.endswith("\n") else "")
def _rule_set_by_type(client: ReleaseApiClient, rule_type: str) -> dict[str, Any]:
rule_sets = ReleaseApiClient.json_data(client.get("/api/rule-sets"))
for item in rule_sets:
if str(item.get("ruleType") or "") == rule_type:
return item
raise AssertionError(f"规则集不存在: {rule_type}")
@pytest.mark.release
def test_g6_rule_detail_version_management_save_publish_and_rollback(admin_client: ReleaseApiClient) -> None:
"""覆盖规则配置详情页的版本管理闭环。
该用例会创建一个真实历史版本并短暂发布,最后回滚到执行前的 currentVersionId。
"""
target_rule_set = _select_rule_set(admin_client)
rule_type = str(target_rule_set["ruleType"])
original_rule_set_id = int(target_rule_set["id"])
original_current_version_id = int(target_rule_set["currentVersionId"])
original_tenant_code = str(target_rule_set.get("effectiveTenantCode") or "")
versions_before = ReleaseApiClient.json_data(admin_client.get(f"/api/rule-sets/{rule_type}/versions"))
assert isinstance(versions_before, list)
assert {int(item["ruleSetId"]) for item in versions_before} == {original_rule_set_id}
assert original_current_version_id in {int(item["id"]) for item in versions_before}
content = ReleaseApiClient.json_data(admin_client.get(f"/api/rule-sets/versions/{original_current_version_id}/content"))
assert int(content["ruleSetId"]) == original_rule_set_id
assert str(content["ruleType"]) == rule_type
assert str(content["yamlText"]).strip()
new_version_no = f"pytest-vm-{int(time.time())}"
yaml_text = _set_metadata_version(str(content["yamlText"]), new_version_no)
created_version_id: int | None = None
try:
created = ReleaseApiClient.json_data(
admin_client.post(
f"/api/rule-sets/{rule_type}/versions",
json={
"yamlText": yaml_text,
"changeNote": f"pytest rule detail version management smoke {new_version_no}",
},
expected_status=200,
)
)
created_version_id = int(created["id"])
assert int(created["ruleSetId"]) == original_rule_set_id
assert str(created["versionNo"]) == new_version_no
assert str(created["status"]) == "draft"
versions_after_create = ReleaseApiClient.json_data(admin_client.get(f"/api/rule-sets/{rule_type}/versions"))
assert created_version_id in {int(item["id"]) for item in versions_after_create}
assert {int(item["ruleSetId"]) for item in versions_after_create} == {original_rule_set_id}
published = ReleaseApiClient.json_data(
admin_client.post(
f"/api/rule-sets/{rule_type}/publish",
json={"versionId": created_version_id},
expected_status=200,
)
)
assert int(published["id"]) == created_version_id
assert int(published["ruleSetId"]) == original_rule_set_id
assert str(published["status"]) == "published"
current_after_publish = _rule_set_by_type(admin_client, rule_type)
assert int(current_after_publish["id"]) == original_rule_set_id
assert int(current_after_publish["currentVersionId"]) == created_version_id
assert str(current_after_publish.get("effectiveTenantCode") or "") == original_tenant_code
finally:
if created_version_id:
admin_client.post(
f"/api/rule-sets/{rule_type}/rollback",
json={"versionId": original_current_version_id},
expected_status=200,
)
restored = _rule_set_by_type(admin_client, rule_type)
assert int(restored["id"]) == original_rule_set_id
assert int(restored["currentVersionId"]) == original_current_version_id
assert str(restored.get("effectiveTenantCode") or "") == original_tenant_code
@pytest.mark.release
def test_g6_rule_detail_version_management_rejects_cross_rule_set_publish(admin_client: ReleaseApiClient) -> None:
"""发布接口必须拒绝把其他规则集的版本发布到当前规则类型。"""
rule_sets = ReleaseApiClient.json_data(admin_client.get("/api/rule-sets"))
candidates = [item for item in rule_sets if item.get("currentVersionId")]
if len(candidates) < 2:
pytest.skip("当前环境少于两个带 currentVersionId 的规则集,无法测试跨规则集发布拦截")
left = candidates[0]
right = next((item for item in candidates[1:] if str(item["ruleType"]) != str(left["ruleType"])), None)
if right is None:
pytest.skip("当前环境没有可用于跨规则类型发布拦截的第二个规则集")
response = admin_client.post(
f"/api/rule-sets/{left['ruleType']}/publish",
json={"versionId": int(right["currentVersionId"])},
expected_status=403,
)
assert "当前租户不能发布或回滚其他租户的规则版本" in response.text