7956b49e28
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
68 lines
2.3 KiB
Python
68 lines
2.3 KiB
Python
from auto_reverse.models import CapturedFlow, Signature
|
|
from auto_reverse.store import FlowStore, ScopeFilter, path_template
|
|
|
|
|
|
def test_collapses_numeric_ids():
|
|
assert path_template("/api/users/4812/orders/99") == "/api/users/{id}/orders/{id}"
|
|
|
|
|
|
def test_collapses_uuid():
|
|
p = "/api/items/550e8400-e29b-41d4-a716-446655440000"
|
|
assert path_template(p) == "/api/items/{id}"
|
|
|
|
|
|
def test_collapses_long_hex_token():
|
|
assert path_template("/files/a1b2c3d4e5f60718293a4b5c") == "/files/{id}"
|
|
|
|
|
|
def test_keeps_short_words():
|
|
assert path_template("/api/users/me/settings") == "/api/users/me/settings"
|
|
|
|
|
|
def test_root_and_empty():
|
|
assert path_template("/") == "/"
|
|
assert path_template("") == "/"
|
|
|
|
|
|
def _post(host: str, path: str, body: bytes) -> CapturedFlow:
|
|
return CapturedFlow(
|
|
method="POST", host=host, path=path, query={},
|
|
req_headers={"content-type": "application/json"}, req_body=body,
|
|
status=201, resp_headers={"content-type": "application/json"},
|
|
resp_body=b'{"ok": true}', timestamp=0.0,
|
|
)
|
|
|
|
|
|
def test_ingest_new_signature_returns_true_once():
|
|
store = FlowStore(ScopeFilter(target_hosts={"ex.com"}))
|
|
assert store.ingest(_post("ex.com", "/api/cart/1", b'{"q": 1}')).is_new is True
|
|
# same template, different id -> not new
|
|
assert store.ingest(_post("ex.com", "/api/cart/2", b'{"q": 2}')).is_new is False
|
|
assert len(store.endpoints()) == 1
|
|
|
|
|
|
def test_out_of_scope_flow_ignored():
|
|
store = FlowStore(ScopeFilter(target_hosts={"ex.com"}))
|
|
result = store.ingest(_post("other.com", "/x", b"{}"))
|
|
assert result.is_new is False
|
|
assert result.in_scope is False
|
|
assert store.endpoints() == []
|
|
|
|
|
|
def test_new_signature_callback_fires_with_signature():
|
|
seen: list[Signature] = []
|
|
store = FlowStore(ScopeFilter(target_hosts={"ex.com"}), on_new_signature=seen.append)
|
|
store.ingest(_post("ex.com", "/api/cart/1", b"{}"))
|
|
store.ingest(_post("ex.com", "/api/cart/2", b"{}"))
|
|
assert len(seen) == 1
|
|
assert seen[0].path_template == "/api/cart/{id}"
|
|
|
|
|
|
def test_search_filters_by_substring():
|
|
store = FlowStore(ScopeFilter(target_hosts={"ex.com"}))
|
|
store.ingest(_post("ex.com", "/api/cart/1", b"{}"))
|
|
store.ingest(_post("ex.com", "/api/login", b"{}"))
|
|
results = store.search("cart")
|
|
assert len(results) == 1
|
|
assert results[0].signature.path_template == "/api/cart/{id}"
|