Files
HermesMessages/backend/tests/test_calendar.py
Hanzo_dev 798bd14312 feat: initial commit — HermesMessages SaaS platform
Backend (FastAPI + Python 3.12):
- Multi-tenant auth with JWT: login, register, refresh, Meta OAuth
- Business & BusinessConfig management
- WhatsApp webhook with HMAC signature verification
- Bot engine powered by Claude AI
- Calendar availability with Redis caching
- Reservations CRUD with status management
- Dashboard analytics (stats, agenda, peak hours)
- Billing & plan management
- Admin panel with platform-wide stats
- Async bcrypt via asyncio.to_thread
- IntegrityError handling for concurrent registration race conditions

Frontend (React 18 + Vite + Tailwind CSS):
- Multi-step guided registration form with helper text on every field
- Login page with show/hide password toggle
- Protected routes with AuthContext
- Dashboard with stats cards, bar chart, and daily agenda
- Reservations list with search, filters, and inline status actions
- Calendar with weekly view, slot availability, and date blocking
- Config page: business info, schedules, bot personality
- Billing page with plan comparison and usage bar

Design system:
- Bricolage Grotesque + DM Sans typography
- Emerald primary palette with semantic color tokens
- scale(0.97) button press feedback, ease-out animations
- Skeleton loaders, stagger animations, prefers-reduced-motion support
- Accessible: aria-labels, visible focus rings, 4.5:1 contrast

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 09:49:41 -05:00

82 lines
2.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from datetime import date, time
import pytest
from app.modules.calendar.service import _generate_slots, get_available_slots
from tests.conftest import make_business
def test_generate_slots_basic():
slots = _generate_slots(time(9, 0), time(12, 0), 60)
assert len(slots) == 3
assert slots[0] == (time(9, 0), time(10, 0))
assert slots[1] == (time(10, 0), time(11, 0))
assert slots[2] == (time(11, 0), time(12, 0))
def test_generate_slots_30min():
slots = _generate_slots(time(9, 0), time(10, 0), 30)
assert len(slots) == 2
assert slots[0] == (time(9, 0), time(9, 30))
assert slots[1] == (time(9, 30), time(10, 0))
def test_generate_slots_exact_fit():
slots = _generate_slots(time(9, 0), time(9, 30), 30)
assert len(slots) == 1
def test_generate_slots_no_fit():
# slot_duration mayor que el rango → lista vacía
slots = _generate_slots(time(9, 0), time(9, 20), 30)
assert len(slots) == 0
async def test_availability_closed_day(db, redis_mock):
business = await make_business(db, name="Test Cerrado")
# open_days = [0,1,2,3,4] → domingo (6) está cerrado
sunday = date(2026, 4, 26) # domingo
result = await get_available_slots(db, redis_mock, business.id, sunday)
assert result.is_open is False
assert result.slots == []
async def test_availability_open_day_no_reservations(db, redis_mock):
business = await make_business(db, name="Test Abierto")
monday = date(2026, 4, 27) # lunes
result = await get_available_slots(db, redis_mock, business.id, monday)
assert result.is_open is True
assert len(result.slots) == 9 # 09:0018:00 en slots de 60 min
assert all(s.available == 2 for s in result.slots) # max_per_slot=2, sin reservas
async def test_availability_blocked_date(db, redis_mock):
from datetime import date as d
business = await make_business(db, name="Test Bloqueado")
# Bloquear el lunes
monday = date(2026, 4, 27)
from app.modules.business.service import get_business_config
config = await get_business_config(db, business.id)
config.blocked_dates = [monday]
await db.commit()
result = await get_available_slots(db, redis_mock, business.id, monday)
assert result.is_open is False
async def test_availability_cached(db, redis_mock):
import json
from app.modules.calendar.schemas import DayAvailability
business = await make_business(db, name="Test Cache")
monday = date(2026, 4, 27)
cached_data = DayAvailability(date=monday, is_open=False, slots=[])
redis_mock.get = pytest.AsyncMock(return_value=cached_data.model_dump_json())
result = await get_available_slots(db, redis_mock, business.id, monday)
assert result.is_open is False
# Redis.get fue llamado → no consulta DB
redis_mock.get.assert_called_once()