"""Tests for REST API.""" import pytest import json import os import tempfile from http.client import HTTPConnection from threading import Thread from time import sleep from rule_engine.api import create_app from rule_engine.store import RuleStore @pytest.fixture def temp_db(): fd, path = tempfile.mkstemp(suffix=".db") os.close(fd) yield path os.unlink(path) @pytest.fixture def store(temp_db): return RuleStore(temp_db) @pytest.fixture def server(store): srv = create_app(store, host="127.0.0.1", port=18000) thread = Thread(target=srv.serve_forever, daemon=True) thread.start() sleep(0.1) # 等待服务器启动 yield srv srv.shutdown() @pytest.fixture def client(server): return HTTPConnection("127.0.0.1", 18000) def test_health(client): """验证健康检查。""" client.request("GET", "/health") resp = client.getresponse() assert resp.status == 200 data = json.loads(resp.read()) assert data["status"] == "ok" def test_create_rule(client): """验证创建规则。""" body = json.dumps({ "name": "test_rule", "description": "测试规则", "condition_template": "如果用户是会员则打折" }) client.request("POST", "/api/rules", body=body, headers={"Content-Type": "application/json"}) resp = client.getresponse() assert resp.status == 201 data = json.loads(resp.read()) assert data["name"] == "test_rule" assert "id" in data def test_create_rule_missing_fields(client): """验证缺少必填字段返回错误。""" body = json.dumps({"name": "only_name"}) client.request("POST", "/api/rules", body=body, headers={"Content-Type": "application/json"}) resp = client.getresponse() assert resp.status == 400 def test_get_rule(client): """验证获取规则。""" # 先创建 body = json.dumps({"name": "get_test", "condition_template": "test"}) client.request("POST", "/api/rules", body=body, headers={"Content-Type": "application/json"}) resp = client.getresponse() data = json.loads(resp.read()) rule_id = data["id"] # 再获取 client.request("GET", f"/api/rules/{rule_id}") resp = client.getresponse() data = json.loads(resp.read()) assert data["name"] == "get_test" def test_get_rule_not_found(client): """验证获取不存在的规则。""" client.request("GET", "/api/rules/nonexistent") resp = client.getresponse() assert resp.status == 404 def test_list_rules(client): """验证列出规则。""" # 创建两条规则 for name in ["list_r1", "list_r2"]: body = json.dumps({"name": name, "condition_template": "test"}) client.request("POST", "/api/rules", body=body, headers={"Content-Type": "application/json"}) client.getresponse() # 列出 client.request("GET", "/api/rules") resp = client.getresponse() assert resp.status == 200 data = json.loads(resp.read()) assert "rules" in data assert len(data["rules"]) >= 2 def test_delete_rule(client): """验证删除规则。""" # 先创建 body = json.dumps({"name": "delete_test", "condition_template": "test"}) client.request("POST", "/api/rules", body=body, headers={"Content-Type": "application/json"}) resp = client.getresponse() rule_id = json.loads(resp.read())["id"] # 删除 client.request("DELETE", f"/api/rules/{rule_id}") resp = client.getresponse() assert resp.status == 200 # 确认已删除 client.request("GET", f"/api/rules/{rule_id}") resp = client.getresponse() assert resp.status == 404 def test_evaluate_not_implemented(client): """验证 evaluate 接口返回 placeholder。""" body = json.dumps({"facts": {"user_id": "u123"}}) client.request("POST", "/api/rules/evaluate", body=body, headers={"Content-Type": "application/json"}) resp = client.getresponse() assert resp.status == 200 data = json.loads(resp.read()) assert data["matched"] is False assert "Executor not implemented" in data["message"]