docling-studio/document-parser/tests/neo4j/test_schema.py
Pier-Jean Malandrino dfbca40730 feat(neo4j): Day 1 — compose service, driver, schema bootstrap
Add Neo4j as an optional graph-native storage layer (ingestion profile).
Introduces infra/neo4j with a singleton async driver wrapper and an
idempotent bootstrap of constraints + indexes, wired into the FastAPI
lifespan. Integration tests skip when no live Neo4j is reachable.

Refs #186
2026-04-20 10:13:18 +02:00

38 lines
1.5 KiB
Python

"""Schema bootstrap is idempotent and produces the expected constraints/indexes."""
from __future__ import annotations
from infra.neo4j.schema import CONSTRAINTS, FULLTEXT_INDEXES, INDEXES, bootstrap_schema
async def _count_schema(neo4j_driver) -> tuple[int, int]:
async with neo4j_driver.driver.session(database=neo4j_driver.database) as session:
constraints = await (await session.run("SHOW CONSTRAINTS")).data()
indexes = await (await session.run("SHOW INDEXES")).data()
return len(constraints), len(indexes)
async def test_bootstrap_is_idempotent(neo4j_driver):
await bootstrap_schema(neo4j_driver)
first = await _count_schema(neo4j_driver)
# Running a second time must not duplicate anything.
await bootstrap_schema(neo4j_driver)
second = await _count_schema(neo4j_driver)
assert first == second
# Sanity: we created at least what we declared.
assert first[0] >= len(CONSTRAINTS)
assert first[1] >= len(INDEXES) + len(FULLTEXT_INDEXES)
async def test_document_id_is_unique(neo4j_driver):
await bootstrap_schema(neo4j_driver)
async with neo4j_driver.driver.session(database=neo4j_driver.database) as session:
await session.run("CREATE (d:Document {id: 'doc-1', title: 'first'})")
with_err: Exception | None = None
try:
await session.run("CREATE (d:Document {id: 'doc-1', title: 'dup'})")
except Exception as exc:
with_err = exc
assert with_err is not None, "unique constraint on Document.id must reject duplicates"