Built the Oracle Tab (#14)
This commit is contained in:
133
backend/tests/oracle/test_canvas_service.py
Normal file
133
backend/tests/oracle/test_canvas_service.py
Normal file
@@ -0,0 +1,133 @@
|
||||
"""
|
||||
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
|
||||
Reference in New Issue
Block a user