- Run tests for all 10 services via per-service pytest subprocesses - Group results by service with section headers - Clickable summary cards filter by outcome (passed/failed/errors/skipped) - Service filter nav using ~nav-link buttons in menu bar - Full menu integration: ~header-row + ~header-child + ~menu-row - Show logo image via cart-mini rendering - Mount full service directories in docker-compose for test access - Add 24 unit test files across 9 services Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
58 lines
2.3 KiB
Python
58 lines
2.3 KiB
Python
"""Unit tests for entry cost calculation."""
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime, time
|
|
from decimal import Decimal
|
|
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
|
|
from events.bp.calendar_entries.routes import calculate_entry_cost
|
|
|
|
|
|
def _slot(cost=None, flexible=False, time_start=None, time_end=None):
|
|
return SimpleNamespace(
|
|
cost=cost,
|
|
flexible=flexible,
|
|
time_start=time_start or time(9, 0),
|
|
time_end=time_end or time(17, 0),
|
|
)
|
|
|
|
|
|
class TestCalculateEntryCost:
|
|
def test_no_cost(self):
|
|
assert calculate_entry_cost(_slot(cost=None),
|
|
datetime(2025, 1, 1, 9), datetime(2025, 1, 1, 17)) == Decimal("0")
|
|
|
|
def test_fixed_slot(self):
|
|
result = calculate_entry_cost(_slot(cost=100, flexible=False),
|
|
datetime(2025, 1, 1, 10), datetime(2025, 1, 1, 12))
|
|
assert result == Decimal("100")
|
|
|
|
def test_flexible_full_duration(self):
|
|
slot = _slot(cost=80, flexible=True, time_start=time(9, 0), time_end=time(17, 0))
|
|
# 8 hours slot, booking full 8 hours
|
|
result = calculate_entry_cost(slot,
|
|
datetime(2025, 1, 1, 9, 0), datetime(2025, 1, 1, 17, 0))
|
|
assert result == Decimal("80")
|
|
|
|
def test_flexible_half_duration(self):
|
|
slot = _slot(cost=80, flexible=True, time_start=time(9, 0), time_end=time(17, 0))
|
|
# 4 hours of 8-hour slot = half
|
|
result = calculate_entry_cost(slot,
|
|
datetime(2025, 1, 1, 9, 0), datetime(2025, 1, 1, 13, 0))
|
|
assert result == Decimal("40")
|
|
|
|
def test_flexible_no_time_end(self):
|
|
slot = _slot(cost=50, flexible=True, time_end=None)
|
|
result = calculate_entry_cost(slot,
|
|
datetime(2025, 1, 1, 9), datetime(2025, 1, 1, 12))
|
|
# When time_end is None, function still calculates based on booking duration
|
|
assert isinstance(result, Decimal)
|
|
|
|
def test_flexible_zero_slot_duration(self):
|
|
slot = _slot(cost=50, flexible=True, time_start=time(9, 0), time_end=time(9, 0))
|
|
result = calculate_entry_cost(slot,
|
|
datetime(2025, 1, 1, 9, 0), datetime(2025, 1, 1, 10, 0))
|
|
assert result == Decimal("0")
|