Files
Project_Velocity/backend/tests/oracle/test_canvas_service.py
2026-04-12 02:01:36 +05:30

134 lines
4.6 KiB
Python

"""
test_canvas_service.py — Unit tests for CanvasService (demo mode in-memory store).
"""
import asyncio
import pytest
import sys
import os
# Ensure backend is on path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", ".."))
from oracle.canvas_service import CanvasService
TENANT = "tenant_test_001"
ACTOR = "user_test_001"
def run(coro):
return asyncio.get_event_loop().run_until_complete(coro)
@pytest.fixture
def svc():
"""Fresh CanvasService instance with empty demo store per test."""
from oracle import canvas_service as _mod
_mod._DEMO_PAGES.clear()
_mod._DEMO_REVISIONS.clear()
_mod._DEMO_COMPONENTS.clear()
return CanvasService()
def test_create_page(svc):
page = run(svc.create_page(tenant_id=TENANT, owner_id=ACTOR, title="Test Canvas"))
assert page["tenantId"] == TENANT
assert page["ownerId"] == ACTOR
assert page["title"] == "Test Canvas"
assert page["headRevision"] == 0
assert page["pageType"] == "main"
assert page["branchName"] == "main"
def test_get_page_not_found(svc):
result = run(svc.get_page("nonexistent_id", TENANT))
assert result is None
def test_get_page_returns_page(svc):
page = run(svc.create_page(tenant_id=TENANT, owner_id=ACTOR))
retrieved = run(svc.get_page(page["pageId"], TENANT))
assert retrieved is not None
assert retrieved["pageId"] == page["pageId"]
def test_commit_revision_advances_head(svc):
page = run(svc.create_page(tenant_id=TENANT, owner_id=ACTOR))
comps = [{"componentId": "cmp_001", "type": "barChart", "title": "Test"}]
rev = run(svc.commit_revision(
page_id=page["pageId"],
tenant_id=TENANT,
actor_id=ACTOR,
commit_kind="prompt",
commit_summary="Test prompt",
components=comps,
idempotency_key="ikey_001",
))
assert rev["revisionNumber"] == 1
updated = run(svc.get_page(page["pageId"], TENANT))
assert updated["headRevision"] == 1
assert len(updated["components"]) == 1
def test_idempotency_key_prevents_double_commit(svc):
page = run(svc.create_page(tenant_id=TENANT, owner_id=ACTOR))
comps = [{"componentId": "cmp_001", "type": "barChart", "title": "Test"}]
rev1 = run(svc.commit_revision(
page_id=page["pageId"], tenant_id=TENANT, actor_id=ACTOR,
commit_kind="prompt", commit_summary="First", components=comps,
idempotency_key="ikey_idempotent",
))
rev2 = run(svc.commit_revision(
page_id=page["pageId"], tenant_id=TENANT, actor_id=ACTOR,
commit_kind="prompt", commit_summary="Duplicate", components=comps,
idempotency_key="ikey_idempotent",
))
assert rev1["revisionId"] == rev2["revisionId"]
# Head should still be 1
updated = run(svc.get_page(page["pageId"], TENANT))
assert updated["headRevision"] == 1
def test_rollback_creates_new_revision(svc):
page = run(svc.create_page(tenant_id=TENANT, owner_id=ACTOR))
comps_v1 = [{"componentId": "cmp_v1", "type": "barChart", "title": "V1"}]
comps_v2 = [{"componentId": "cmp_v2", "type": "lineChart", "title": "V2"}]
run(svc.commit_revision(
page_id=page["pageId"], tenant_id=TENANT, actor_id=ACTOR,
commit_kind="prompt", commit_summary="V1", components=comps_v1, idempotency_key="key_v1",
))
run(svc.commit_revision(
page_id=page["pageId"], tenant_id=TENANT, actor_id=ACTOR,
commit_kind="prompt", commit_summary="V2", components=comps_v2, idempotency_key="key_v2",
))
# Rollback to revision 1
rollback_rev = run(svc.rollback(
page_id=page["pageId"], tenant_id=TENANT, actor_id=ACTOR,
target_revision=1, idempotency_key="key_rollback",
))
assert rollback_rev["revisionNumber"] == 3
assert rollback_rev["commitKind"] == "rollback"
revisions = run(svc.list_revisions(page["pageId"], TENANT))
assert len(revisions) == 3 # 3 revisions total
def test_list_revisions_returns_newest_first(svc):
page = run(svc.create_page(tenant_id=TENANT, owner_id=ACTOR))
for i in range(3):
run(svc.commit_revision(
page_id=page["pageId"], tenant_id=TENANT, actor_id=ACTOR,
commit_kind="prompt", commit_summary=f"Rev {i+1}",
components=[], idempotency_key=f"key_{i}",
))
revisions = run(svc.list_revisions(page["pageId"], TENANT))
assert revisions[0]["revisionNumber"] > revisions[-1]["revisionNumber"]
def test_tenant_isolation(svc):
page = run(svc.create_page(tenant_id=TENANT, owner_id=ACTOR))
# Different tenant cannot access the page
result = run(svc.get_page(page["pageId"], "tenant_different_999"))
assert result is None