mirror of
https://github.com/RichieCahill/dotfiles.git
synced 2026-04-17 04:58:19 -04:00
Added 35 test files with 502 tests covering all Python modules including API routes, ORM models, splendor game logic/TUI, heater controller, weather service, NixOS installer, ZFS dataset management, and utilities. Coverage improved from 11% to 99% (2540/2564 statements covered). https://claude.ai/code/session_01SVzgLDUS1Cdc4eh1ijETTh
470 lines
15 KiB
Python
470 lines
15 KiB
Python
"""Integration tests for API router using SQLite in-memory database."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from sqlalchemy import create_engine
|
|
from sqlalchemy.orm import Session
|
|
|
|
from python.api.routers.contact import (
|
|
ContactCreate,
|
|
ContactRelationshipCreate,
|
|
ContactRelationshipUpdate,
|
|
ContactUpdate,
|
|
NeedCreate,
|
|
add_contact_relationship,
|
|
add_need_to_contact,
|
|
create_contact,
|
|
create_need,
|
|
delete_contact,
|
|
delete_need,
|
|
get_contact,
|
|
get_contact_relationships,
|
|
get_need,
|
|
get_relationship_graph,
|
|
list_contacts,
|
|
list_needs,
|
|
list_relationship_types,
|
|
RelationshipTypeInfo,
|
|
remove_contact_relationship,
|
|
remove_need_from_contact,
|
|
update_contact,
|
|
update_contact_relationship,
|
|
)
|
|
from python.orm.base import RichieBase
|
|
from python.orm.contact import Contact, ContactNeed, ContactRelationship, Need, RelationshipType
|
|
|
|
import pytest
|
|
|
|
|
|
def _create_db() -> Session:
|
|
"""Create in-memory SQLite database with schema."""
|
|
engine = create_engine("sqlite:///:memory:")
|
|
# Create tables without schema prefix for SQLite
|
|
RichieBase.metadata.create_all(engine, checkfirst=True)
|
|
return Session(engine)
|
|
|
|
|
|
@pytest.fixture
|
|
def db() -> Session:
|
|
"""Database session fixture."""
|
|
engine = create_engine("sqlite:///:memory:")
|
|
# SQLite doesn't support schemas, so we need to drop the schema reference
|
|
from sqlalchemy import MetaData
|
|
|
|
meta = MetaData()
|
|
for table in RichieBase.metadata.sorted_tables:
|
|
# Create table without schema
|
|
table.to_metadata(meta)
|
|
meta.create_all(engine)
|
|
session = Session(engine)
|
|
yield session
|
|
session.close()
|
|
|
|
|
|
# --- Need CRUD tests ---
|
|
|
|
|
|
def test_create_need(db: Session) -> None:
|
|
"""Test creating a need."""
|
|
need = create_need(NeedCreate(name="ADHD", description="Attention deficit"), db)
|
|
assert need.name == "ADHD"
|
|
assert need.id is not None
|
|
|
|
|
|
def test_list_needs(db: Session) -> None:
|
|
"""Test listing needs."""
|
|
create_need(NeedCreate(name="ADHD"), db)
|
|
create_need(NeedCreate(name="Light Sensitive"), db)
|
|
needs = list_needs(db)
|
|
assert len(needs) == 2
|
|
|
|
|
|
def test_get_need(db: Session) -> None:
|
|
"""Test getting a need by ID."""
|
|
created = create_need(NeedCreate(name="ADHD"), db)
|
|
need = get_need(created.id, db)
|
|
assert need.name == "ADHD"
|
|
|
|
|
|
def test_get_need_not_found(db: Session) -> None:
|
|
"""Test getting a need that doesn't exist."""
|
|
from fastapi import HTTPException
|
|
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
get_need(999, db)
|
|
assert exc_info.value.status_code == 404
|
|
|
|
|
|
def test_delete_need(db: Session) -> None:
|
|
"""Test deleting a need."""
|
|
created = create_need(NeedCreate(name="ADHD"), db)
|
|
result = delete_need(created.id, db)
|
|
assert result == {"deleted": True}
|
|
|
|
|
|
def test_delete_need_not_found(db: Session) -> None:
|
|
"""Test deleting a need that doesn't exist."""
|
|
from fastapi import HTTPException
|
|
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
delete_need(999, db)
|
|
assert exc_info.value.status_code == 404
|
|
|
|
|
|
# --- Contact CRUD tests ---
|
|
|
|
|
|
def test_create_contact(db: Session) -> None:
|
|
"""Test creating a contact."""
|
|
contact = create_contact(ContactCreate(name="John"), db)
|
|
assert contact.name == "John"
|
|
assert contact.id is not None
|
|
|
|
|
|
def test_create_contact_with_needs(db: Session) -> None:
|
|
"""Test creating a contact with needs."""
|
|
need = create_need(NeedCreate(name="ADHD"), db)
|
|
contact = create_contact(ContactCreate(name="John", need_ids=[need.id]), db)
|
|
assert len(contact.needs) == 1
|
|
|
|
|
|
def test_list_contacts(db: Session) -> None:
|
|
"""Test listing contacts."""
|
|
create_contact(ContactCreate(name="John"), db)
|
|
create_contact(ContactCreate(name="Jane"), db)
|
|
contacts = list_contacts(db)
|
|
assert len(contacts) == 2
|
|
|
|
|
|
def test_list_contacts_pagination(db: Session) -> None:
|
|
"""Test listing contacts with pagination."""
|
|
for i in range(5):
|
|
create_contact(ContactCreate(name=f"Contact {i}"), db)
|
|
contacts = list_contacts(db, skip=2, limit=2)
|
|
assert len(contacts) == 2
|
|
|
|
|
|
def test_get_contact(db: Session) -> None:
|
|
"""Test getting a contact by ID."""
|
|
created = create_contact(ContactCreate(name="John"), db)
|
|
contact = get_contact(created.id, db)
|
|
assert contact.name == "John"
|
|
|
|
|
|
def test_get_contact_not_found(db: Session) -> None:
|
|
"""Test getting a contact that doesn't exist."""
|
|
from fastapi import HTTPException
|
|
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
get_contact(999, db)
|
|
assert exc_info.value.status_code == 404
|
|
|
|
|
|
def test_update_contact(db: Session) -> None:
|
|
"""Test updating a contact."""
|
|
created = create_contact(ContactCreate(name="John"), db)
|
|
updated = update_contact(created.id, ContactUpdate(name="Jane", age=30), db)
|
|
assert updated.name == "Jane"
|
|
assert updated.age == 30
|
|
|
|
|
|
def test_update_contact_with_needs(db: Session) -> None:
|
|
"""Test updating a contact's needs."""
|
|
need = create_need(NeedCreate(name="ADHD"), db)
|
|
created = create_contact(ContactCreate(name="John"), db)
|
|
updated = update_contact(created.id, ContactUpdate(need_ids=[need.id]), db)
|
|
assert len(updated.needs) == 1
|
|
|
|
|
|
def test_update_contact_not_found(db: Session) -> None:
|
|
"""Test updating a contact that doesn't exist."""
|
|
from fastapi import HTTPException
|
|
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
update_contact(999, ContactUpdate(name="Jane"), db)
|
|
assert exc_info.value.status_code == 404
|
|
|
|
|
|
def test_delete_contact(db: Session) -> None:
|
|
"""Test deleting a contact."""
|
|
created = create_contact(ContactCreate(name="John"), db)
|
|
result = delete_contact(created.id, db)
|
|
assert result == {"deleted": True}
|
|
|
|
|
|
def test_delete_contact_not_found(db: Session) -> None:
|
|
"""Test deleting a contact that doesn't exist."""
|
|
from fastapi import HTTPException
|
|
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
delete_contact(999, db)
|
|
assert exc_info.value.status_code == 404
|
|
|
|
|
|
# --- Need-Contact association tests ---
|
|
|
|
|
|
def test_add_need_to_contact(db: Session) -> None:
|
|
"""Test adding a need to a contact."""
|
|
need = create_need(NeedCreate(name="ADHD"), db)
|
|
contact = create_contact(ContactCreate(name="John"), db)
|
|
result = add_need_to_contact(contact.id, need.id, db)
|
|
assert result == {"added": True}
|
|
|
|
|
|
def test_add_need_to_contact_contact_not_found(db: Session) -> None:
|
|
"""Test adding need to nonexistent contact."""
|
|
from fastapi import HTTPException
|
|
|
|
need = create_need(NeedCreate(name="ADHD"), db)
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
add_need_to_contact(999, need.id, db)
|
|
assert exc_info.value.status_code == 404
|
|
|
|
|
|
def test_add_need_to_contact_need_not_found(db: Session) -> None:
|
|
"""Test adding nonexistent need to contact."""
|
|
from fastapi import HTTPException
|
|
|
|
contact = create_contact(ContactCreate(name="John"), db)
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
add_need_to_contact(contact.id, 999, db)
|
|
assert exc_info.value.status_code == 404
|
|
|
|
|
|
def test_remove_need_from_contact(db: Session) -> None:
|
|
"""Test removing a need from a contact."""
|
|
need = create_need(NeedCreate(name="ADHD"), db)
|
|
contact = create_contact(ContactCreate(name="John", need_ids=[need.id]), db)
|
|
result = remove_need_from_contact(contact.id, need.id, db)
|
|
assert result == {"removed": True}
|
|
|
|
|
|
def test_remove_need_from_contact_contact_not_found(db: Session) -> None:
|
|
"""Test removing need from nonexistent contact."""
|
|
from fastapi import HTTPException
|
|
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
remove_need_from_contact(999, 1, db)
|
|
assert exc_info.value.status_code == 404
|
|
|
|
|
|
def test_remove_need_from_contact_need_not_found(db: Session) -> None:
|
|
"""Test removing nonexistent need from contact."""
|
|
from fastapi import HTTPException
|
|
|
|
contact = create_contact(ContactCreate(name="John"), db)
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
remove_need_from_contact(contact.id, 999, db)
|
|
assert exc_info.value.status_code == 404
|
|
|
|
|
|
# --- Relationship tests ---
|
|
|
|
|
|
def test_add_contact_relationship(db: Session) -> None:
|
|
"""Test adding a relationship between contacts."""
|
|
c1 = create_contact(ContactCreate(name="John"), db)
|
|
c2 = create_contact(ContactCreate(name="Jane"), db)
|
|
rel = add_contact_relationship(
|
|
c1.id,
|
|
ContactRelationshipCreate(related_contact_id=c2.id, relationship_type=RelationshipType.FRIEND),
|
|
db,
|
|
)
|
|
assert rel.contact_id == c1.id
|
|
assert rel.related_contact_id == c2.id
|
|
|
|
|
|
def test_add_contact_relationship_default_weight(db: Session) -> None:
|
|
"""Test relationship uses default weight from type."""
|
|
c1 = create_contact(ContactCreate(name="John"), db)
|
|
c2 = create_contact(ContactCreate(name="Jane"), db)
|
|
rel = add_contact_relationship(
|
|
c1.id,
|
|
ContactRelationshipCreate(related_contact_id=c2.id, relationship_type=RelationshipType.SPOUSE),
|
|
db,
|
|
)
|
|
assert rel.closeness_weight == RelationshipType.SPOUSE.default_weight
|
|
|
|
|
|
def test_add_contact_relationship_custom_weight(db: Session) -> None:
|
|
"""Test relationship with custom weight."""
|
|
c1 = create_contact(ContactCreate(name="John"), db)
|
|
c2 = create_contact(ContactCreate(name="Jane"), db)
|
|
rel = add_contact_relationship(
|
|
c1.id,
|
|
ContactRelationshipCreate(related_contact_id=c2.id, relationship_type=RelationshipType.FRIEND, closeness_weight=8),
|
|
db,
|
|
)
|
|
assert rel.closeness_weight == 8
|
|
|
|
|
|
def test_add_contact_relationship_contact_not_found(db: Session) -> None:
|
|
"""Test adding relationship with nonexistent contact."""
|
|
from fastapi import HTTPException
|
|
|
|
c2 = create_contact(ContactCreate(name="Jane"), db)
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
add_contact_relationship(
|
|
999,
|
|
ContactRelationshipCreate(related_contact_id=c2.id, relationship_type=RelationshipType.FRIEND),
|
|
db,
|
|
)
|
|
assert exc_info.value.status_code == 404
|
|
|
|
|
|
def test_add_contact_relationship_related_not_found(db: Session) -> None:
|
|
"""Test adding relationship with nonexistent related contact."""
|
|
from fastapi import HTTPException
|
|
|
|
c1 = create_contact(ContactCreate(name="John"), db)
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
add_contact_relationship(
|
|
c1.id,
|
|
ContactRelationshipCreate(related_contact_id=999, relationship_type=RelationshipType.FRIEND),
|
|
db,
|
|
)
|
|
assert exc_info.value.status_code == 404
|
|
|
|
|
|
def test_add_contact_relationship_self(db: Session) -> None:
|
|
"""Test cannot relate contact to itself."""
|
|
from fastapi import HTTPException
|
|
|
|
c1 = create_contact(ContactCreate(name="John"), db)
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
add_contact_relationship(
|
|
c1.id,
|
|
ContactRelationshipCreate(related_contact_id=c1.id, relationship_type=RelationshipType.FRIEND),
|
|
db,
|
|
)
|
|
assert exc_info.value.status_code == 400
|
|
|
|
|
|
def test_get_contact_relationships(db: Session) -> None:
|
|
"""Test getting relationships for a contact."""
|
|
c1 = create_contact(ContactCreate(name="John"), db)
|
|
c2 = create_contact(ContactCreate(name="Jane"), db)
|
|
add_contact_relationship(
|
|
c1.id,
|
|
ContactRelationshipCreate(related_contact_id=c2.id, relationship_type=RelationshipType.FRIEND),
|
|
db,
|
|
)
|
|
rels = get_contact_relationships(c1.id, db)
|
|
assert len(rels) == 1
|
|
|
|
|
|
def test_get_contact_relationships_not_found(db: Session) -> None:
|
|
"""Test getting relationships for nonexistent contact."""
|
|
from fastapi import HTTPException
|
|
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
get_contact_relationships(999, db)
|
|
assert exc_info.value.status_code == 404
|
|
|
|
|
|
def test_update_contact_relationship(db: Session) -> None:
|
|
"""Test updating a relationship."""
|
|
c1 = create_contact(ContactCreate(name="John"), db)
|
|
c2 = create_contact(ContactCreate(name="Jane"), db)
|
|
add_contact_relationship(
|
|
c1.id,
|
|
ContactRelationshipCreate(related_contact_id=c2.id, relationship_type=RelationshipType.FRIEND),
|
|
db,
|
|
)
|
|
updated = update_contact_relationship(
|
|
c1.id,
|
|
c2.id,
|
|
ContactRelationshipUpdate(closeness_weight=9),
|
|
db,
|
|
)
|
|
assert updated.closeness_weight == 9
|
|
|
|
|
|
def test_update_contact_relationship_type(db: Session) -> None:
|
|
"""Test updating relationship type."""
|
|
c1 = create_contact(ContactCreate(name="John"), db)
|
|
c2 = create_contact(ContactCreate(name="Jane"), db)
|
|
add_contact_relationship(
|
|
c1.id,
|
|
ContactRelationshipCreate(related_contact_id=c2.id, relationship_type=RelationshipType.FRIEND),
|
|
db,
|
|
)
|
|
updated = update_contact_relationship(
|
|
c1.id,
|
|
c2.id,
|
|
ContactRelationshipUpdate(relationship_type=RelationshipType.BEST_FRIEND),
|
|
db,
|
|
)
|
|
assert updated.relationship_type == "best_friend"
|
|
|
|
|
|
def test_update_contact_relationship_not_found(db: Session) -> None:
|
|
"""Test updating nonexistent relationship."""
|
|
from fastapi import HTTPException
|
|
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
update_contact_relationship(
|
|
999,
|
|
998,
|
|
ContactRelationshipUpdate(closeness_weight=5),
|
|
db,
|
|
)
|
|
assert exc_info.value.status_code == 404
|
|
|
|
|
|
def test_remove_contact_relationship(db: Session) -> None:
|
|
"""Test removing a relationship."""
|
|
c1 = create_contact(ContactCreate(name="John"), db)
|
|
c2 = create_contact(ContactCreate(name="Jane"), db)
|
|
add_contact_relationship(
|
|
c1.id,
|
|
ContactRelationshipCreate(related_contact_id=c2.id, relationship_type=RelationshipType.FRIEND),
|
|
db,
|
|
)
|
|
result = remove_contact_relationship(c1.id, c2.id, db)
|
|
assert result == {"deleted": True}
|
|
|
|
|
|
def test_remove_contact_relationship_not_found(db: Session) -> None:
|
|
"""Test removing nonexistent relationship."""
|
|
from fastapi import HTTPException
|
|
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
remove_contact_relationship(999, 998, db)
|
|
assert exc_info.value.status_code == 404
|
|
|
|
|
|
# --- list_relationship_types ---
|
|
|
|
|
|
def test_list_relationship_types() -> None:
|
|
"""Test listing relationship types."""
|
|
types = list_relationship_types()
|
|
assert len(types) == len(RelationshipType)
|
|
assert all(isinstance(t, RelationshipTypeInfo) for t in types)
|
|
|
|
|
|
# --- graph tests ---
|
|
|
|
|
|
def test_get_relationship_graph(db: Session) -> None:
|
|
"""Test getting relationship graph."""
|
|
c1 = create_contact(ContactCreate(name="John"), db)
|
|
c2 = create_contact(ContactCreate(name="Jane"), db)
|
|
add_contact_relationship(
|
|
c1.id,
|
|
ContactRelationshipCreate(related_contact_id=c2.id, relationship_type=RelationshipType.FRIEND),
|
|
db,
|
|
)
|
|
graph = get_relationship_graph(db)
|
|
assert len(graph.nodes) == 2
|
|
assert len(graph.edges) == 1
|
|
|
|
|
|
def test_get_relationship_graph_empty(db: Session) -> None:
|
|
"""Test getting empty relationship graph."""
|
|
graph = get_relationship_graph(db)
|
|
assert len(graph.nodes) == 0
|
|
assert len(graph.edges) == 0
|