Files
Salon_Assistant/tests/unit/test_domain.py
T
Ty 15f6a6c713 Implement S6 doctor and A1 daily-board with fixtures.
Add operator health checks (make doctor) wrapping platform CLIs, and the fixtures-only daily board skill library with unit tests (make verify).
2026-07-27 12:41:40 -07:00

183 lines
5.5 KiB
Python

"""Tests for lumina_skills.domain types."""
from __future__ import annotations
import json
from datetime import datetime, time
import pytest
import sys
import pathlib
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[2] / "skills" / "_lib"))
from lumina_skills.domain import (
Appointment,
AppointmentStatus,
DayBoard,
Gap,
)
# ── Appointment ────────────────────────────────────────────────────────────
def test_appointment_duration():
apt = Appointment(
appointment_id="APT-001",
start_time=datetime(2026, 7, 28, 9, 0),
end_time=datetime(2026, 7, 28, 10, 30),
client_name="Elena Rossi",
service_name="Balayage + Cut",
staff_name="Claire Bennett",
status=AppointmentStatus.CONFIRMED,
)
assert apt.duration_minutes() == 90
def test_appointment_duration_one_hour():
apt = Appointment(
appointment_id="APT-002",
start_time=datetime(2026, 7, 28, 13, 0),
end_time=datetime(2026, 7, 28, 14, 0),
client_name="Chris Nguyen",
service_name="Men's Cut",
staff_name="Claire Bennett",
status=AppointmentStatus.PENDING,
)
assert apt.duration_minutes() == 60
def test_appointment_time_only():
apt = Appointment(
appointment_id="APT-003",
start_time=datetime(2026, 7, 28, 11, 15),
end_time=datetime(2026, 7, 28, 12, 45),
client_name="Jasmine Patel",
service_name="Root Touch-Up",
staff_name="Maya Torres",
status=AppointmentStatus.CONFIRMED,
)
assert apt.start_time_only() == time(11, 15)
assert apt.end_time_only() == time(12, 45)
def test_appointment_frozen():
"""Appointment is immutable."""
apt = Appointment(
appointment_id="APT-001",
start_time=datetime(2026, 7, 28, 9, 0),
end_time=datetime(2026, 7, 28, 10, 0),
client_name="Test",
service_name="Test",
staff_name="Test",
status=AppointmentStatus.CONFIRMED,
)
with pytest.raises(Exception): # FrozenInstanceError
apt.client_name = "Hacker"
def test_appointment_needs_confirmation_default():
apt = Appointment(
appointment_id="APT-001",
start_time=datetime(2026, 7, 28, 9, 0),
end_time=datetime(2026, 7, 28, 10, 0),
client_name="Test",
service_name="Test",
staff_name="Test",
status=AppointmentStatus.PENDING,
)
assert apt.needs_confirmation is False
def test_appointment_status_enum():
assert AppointmentStatus.CONFIRMED.value == "confirmed"
assert AppointmentStatus.PENDING.value == "pending"
assert AppointmentStatus.CANCELLED.value == "cancelled"
assert AppointmentStatus.COMPLETED.value == "completed"
assert AppointmentStatus.NO_SHOW.value == "no_show"
# ── Gap ────────────────────────────────────────────────────────────────────
def test_gap_creation():
gap = Gap(
start_time=time(12, 0),
end_time=time(13, 30),
duration_minutes=90,
staff_name="Claire Bennett",
)
assert gap.duration_minutes == 90
assert gap.staff_name == "Claire Bennett"
def test_gap_with_references():
gap = Gap(
start_time=time(12, 0),
end_time=time(13, 0),
duration_minutes=60,
staff_name="Claire Bennett",
preceding_appointment_id="APT-001",
following_appointment_id="APT-002",
)
assert gap.preceding_appointment_id == "APT-001"
assert gap.following_appointment_id == "APT-002"
# ── DayBoard ───────────────────────────────────────────────────────────────
def test_dayboard_to_dict():
apt = Appointment(
appointment_id="APT-001",
start_time=datetime(2026, 7, 28, 9, 0),
end_time=datetime(2026, 7, 28, 10, 0),
client_name="Elena Rossi",
service_name="Cut",
staff_name="Claire Bennett",
status=AppointmentStatus.CONFIRMED,
needs_confirmation=False,
)
board = DayBoard(
date="2026-07-28",
salon_name="Lumina Hair Studio & Spa",
source="fixtures",
is_offline=True,
appointments=[apt],
gaps=[],
needs_confirmation=[],
total_booked_minutes=60,
total_gap_minutes=0,
)
d = board.to_dict()
assert d["date"] == "2026-07-28"
assert d["salon_name"] == "Lumina Hair Studio & Spa"
assert d["source"] == "fixtures"
assert d["is_offline"] is True
assert len(d["appointments"]) == 1
assert d["appointments"][0]["client"] == "Elena Rossi"
assert d["total_booked_minutes"] == 60
def test_dayboard_to_dict_serializable():
"""to_dict output must be JSON-serializable."""
board = DayBoard(
date="2026-07-28",
salon_name="Test Salon",
source="fixtures",
is_offline=True,
)
d = board.to_dict()
# Should not raise.
json.dumps(d)
def test_dayboard_empty():
board = DayBoard(
date="2026-07-28",
salon_name="Empty Salon",
source="offline",
is_offline=True,
)
assert len(board.appointments) == 0
assert len(board.gaps) == 0
assert board.total_booked_minutes == 0