6d91f153d7
Vacation rescue/wrap in allocation_service, new plan models/endpoints, VacationRescueTip, useRescueDayActions, vacationSwaps util, sv+en i18n, Dashboard/Calendar wiring. Conflicts came from main's "day assertions" restructure and the earlier merges; both intents kept: - plan.py: both import sets; main's sync-with-wish handler kept next to the branch's new /rescue-days/dismiss endpoint; HTTP_422_UNPROCESSABLE_CONTENT applied to the branch's code (and a survivor in auth.py). - Accepting a rescue day now goes through POST /api/day-assertions (an ad-hoc 'vacation' assertion, no wish) instead of /plan/apply with an `is_pinned` flag that no longer exists: on main a pin IS a day assertion (see PlanningService.add_planned_day's docstring), and an assertion is what keeps a later sync from retyping the day. useRescueDayActions, its tests, VacationRescueTip's tests and the backend integration flow follow that contract; applyPlan stays as a client for the live endpoint minus the dropped field. The hook also gets the security branch's useLatestRequest guard with an unconditionally cleared busy flag. - Calendar.tsx: `locale` threaded into main's applyWishSyncResult call of buildSyncToastMessage (the branch's new parameter); the branch's swap-visibility toast tests drive the preset path through syncWithWish, which is how main saves a wish now. - types/api.ts: ProposedDayApplyItem kept (used by applyPlan) without isPinned; the Add/UpdatePlannedDayRequest types stay removed as on main. - fixtures/plan.ts: ResourceShortage import dropped (type removed on main). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4wjgbVL4HAC5Rdaw75VbV
578 lines
20 KiB
Python
578 lines
20 KiB
Python
"""Pytest fixtures.
|
|
|
|
Each test gets a fresh in-memory SQLite connection with the FULL schema applied
|
|
(all 9 tables), so all entities can be tested in isolation without Alembic.
|
|
Follow the `vacation_repo` / `vacation_service` pattern to add fixtures for
|
|
other entities.
|
|
"""
|
|
|
|
from collections.abc import AsyncIterator, Iterator
|
|
from dataclasses import dataclass
|
|
from datetime import date, datetime
|
|
from uuid import UUID, uuid4
|
|
|
|
import aiosqlite
|
|
import pytest
|
|
import pytest_asyncio
|
|
from httpx import ASGITransport, AsyncClient
|
|
|
|
from app.db.connection import ensure_schema
|
|
from app.dependencies import get_connection, get_current_user
|
|
from app.entities.child import Child
|
|
from app.entities.personal_data import PersonalData
|
|
from app.entities.user import User
|
|
from app.entities.workspace import Workspace
|
|
from app.main import app
|
|
from app.rate_limit import limiter
|
|
from app.repositories_impl.sqlite.child_repository import SQLiteChildRepository
|
|
from app.repositories_impl.sqlite.day_assertion_repository import SQLiteDayAssertionRepository
|
|
from app.repositories_impl.sqlite.day_override_repository import SQLiteDayOverrideRepository
|
|
from app.repositories_impl.sqlite.leave_wish_repository import SQLiteLeaveWishRepository
|
|
from app.repositories_impl.sqlite.parental_leave_repository import SQLiteParentalLeaveRepository
|
|
from app.repositories_impl.sqlite.personal_data_repository import SQLitePersonalDataRepository
|
|
from app.repositories_impl.sqlite.planned_leave_repository import SQLitePlannedLeaveRepository
|
|
from app.repositories_impl.sqlite.preschool_planning_days_repository import (
|
|
SQLitePreschoolPlanningDaysRepository,
|
|
)
|
|
from app.repositories_impl.sqlite.tip_dismissal_repository import SQLiteTipDismissalRepository
|
|
from app.repositories_impl.sqlite.unit_of_work import SQLiteUnitOfWork
|
|
from app.repositories_impl.sqlite.user_repository import SQLiteUserRepository
|
|
from app.repositories_impl.sqlite.vacation_days_repository import (
|
|
SQLiteVacationDaysRepository,
|
|
)
|
|
from app.repositories_impl.sqlite.workspace_repository import (
|
|
SQLiteWorkspaceInvitationRepository,
|
|
SQLiteWorkspaceRepository,
|
|
)
|
|
from app.services.allocation_service import AllocationInputLoader, PlanningEngineService
|
|
from app.services.analytics_service import AnalyticsService
|
|
from app.services.auth_service import AuthService
|
|
from app.services.child_service import ChildService
|
|
from app.services.day_assertion_service import DayAssertionService
|
|
from app.services.day_override_service import DayOverrideService
|
|
from app.services.leave_wish_service import LeaveWishService
|
|
from app.services.planning_service import PlanningService
|
|
from app.services.preschool_planning_days_service import PreschoolPlanningDaysService
|
|
from app.services.tips_service import TipsService
|
|
from app.services.vacation_days_service import VacationDaysService
|
|
from app.services.workspace_service import WorkspaceService
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Rate limiting — OFF by default for the whole test session.
|
|
#
|
|
# `limiter` (app/rate_limit.py) keys on remote address via slowapi's
|
|
# `get_remote_address`, which assumes one IP == one client. Every test in a
|
|
# pytest run shares the same `app.main.app` instance and drives it through
|
|
# `httpx.ASGITransport`, so the whole session looks like one client to the
|
|
# limiter — the same problem `frontend/playwright.config.ts` already works
|
|
# around for the E2E suite via `APP_RATE_LIMIT_ENABLED=false`. Left on here,
|
|
# `tests/integration/test_user_journey.py` alone makes exactly ten
|
|
# `/api/auth/register` calls, spending the entire 10/minute budget, so any
|
|
# other integration test that registers a user 429s if it happens to run
|
|
# afterwards in the same process — a suite that was only green by accident
|
|
# of file ordering.
|
|
#
|
|
# We flip the already-constructed `limiter` object directly rather than
|
|
# `settings.rate_limit_enabled`: `Limiter(..., enabled=...)` reads that
|
|
# setting once at import time in app/rate_limit.py, so mutating `settings`
|
|
# afterwards would no longer reach the singleton the app actually calls.
|
|
# Production is unaffected — `settings.rate_limit_enabled` still defaults to
|
|
# True, so a deployed process still builds its limiter enabled; only this
|
|
# pytest process ever runs the line below.
|
|
limiter.enabled = False
|
|
|
|
|
|
@pytest.fixture
|
|
def rate_limiting_enabled() -> Iterator[None]:
|
|
"""Opt-in fixture for a test that specifically exercises rate limiting.
|
|
|
|
Turns the shared limiter back on and clears its in-memory counters
|
|
first — in case some earlier test's traffic ever slipped through while
|
|
it was "enabled" — then restores both the disabled default and a clean
|
|
counter set afterwards. `limiter` is a process-global in-memory
|
|
limiter, so without this a test that enables it would leak state into
|
|
whichever test runs next.
|
|
"""
|
|
limiter.reset()
|
|
limiter.enabled = True
|
|
try:
|
|
yield
|
|
finally:
|
|
limiter.enabled = False
|
|
limiter.reset()
|
|
|
|
|
|
@dataclass
|
|
class SeededIds:
|
|
workspace_id: UUID
|
|
personal_data_uuid: UUID
|
|
child_id: UUID
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def connection() -> AsyncIterator[aiosqlite.Connection]:
|
|
conn = await aiosqlite.connect(":memory:")
|
|
conn.row_factory = aiosqlite.Row
|
|
await conn.execute("PRAGMA foreign_keys = ON;")
|
|
await ensure_schema(conn)
|
|
try:
|
|
yield conn
|
|
finally:
|
|
await conn.close()
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# VacationDays (reference slice — keep unchanged)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def vacation_repo(
|
|
connection: aiosqlite.Connection,
|
|
) -> SQLiteVacationDaysRepository:
|
|
return SQLiteVacationDaysRepository(connection)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def vacation_service(
|
|
vacation_repo: SQLiteVacationDaysRepository,
|
|
) -> VacationDaysService:
|
|
return VacationDaysService(vacation_repo)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Auth
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def user_repo(connection: aiosqlite.Connection) -> SQLiteUserRepository:
|
|
return SQLiteUserRepository(connection)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def personal_data_repo(
|
|
connection: aiosqlite.Connection,
|
|
) -> SQLitePersonalDataRepository:
|
|
return SQLitePersonalDataRepository(connection)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def auth_service(
|
|
user_repo: SQLiteUserRepository,
|
|
personal_data_repo: SQLitePersonalDataRepository,
|
|
workspace_repo: SQLiteWorkspaceRepository,
|
|
invitation_repo: SQLiteWorkspaceInvitationRepository,
|
|
) -> AuthService:
|
|
return AuthService(user_repo, personal_data_repo, workspace_repo, inv_repo=invitation_repo)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Workspace
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def workspace_repo(
|
|
connection: aiosqlite.Connection,
|
|
) -> SQLiteWorkspaceRepository:
|
|
return SQLiteWorkspaceRepository(connection)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def invitation_repo(
|
|
connection: aiosqlite.Connection,
|
|
) -> SQLiteWorkspaceInvitationRepository:
|
|
return SQLiteWorkspaceInvitationRepository(connection)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def workspace_service(
|
|
workspace_repo: SQLiteWorkspaceRepository,
|
|
invitation_repo: SQLiteWorkspaceInvitationRepository,
|
|
personal_data_repo: SQLitePersonalDataRepository,
|
|
user_repo: SQLiteUserRepository,
|
|
leave_wish_repo: SQLiteLeaveWishRepository,
|
|
planned_leave_repo: SQLitePlannedLeaveRepository,
|
|
parental_leave_repo: SQLiteParentalLeaveRepository,
|
|
vacation_repo: SQLiteVacationDaysRepository,
|
|
) -> WorkspaceService:
|
|
return WorkspaceService(
|
|
workspace_repo,
|
|
invitation_repo,
|
|
personal_data_repo,
|
|
user_repo,
|
|
leave_wish_repo,
|
|
planned_leave_repo,
|
|
parental_leave_repo,
|
|
vacation_repo,
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Shared FK seed — used by any test that needs real workspace + personal_data rows
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def seeded_ids(
|
|
workspace_repo: SQLiteWorkspaceRepository,
|
|
personal_data_repo: SQLitePersonalDataRepository,
|
|
child_repo: SQLiteChildRepository,
|
|
) -> SeededIds:
|
|
"""Pre-create a workspace + personal_data + child row so FK constraints pass."""
|
|
ws = await workspace_repo.create(
|
|
Workspace(id=uuid4(), name="Test WS", created_at=datetime.now())
|
|
)
|
|
pd = await personal_data_repo.create(
|
|
PersonalData(
|
|
uuid=uuid4(), workspace_id=ws.id, name="Test Parent", created_at=datetime.now()
|
|
)
|
|
)
|
|
child = await child_repo.create(
|
|
Child(
|
|
id=uuid4(),
|
|
workspace_id=ws.id,
|
|
name="Test Child",
|
|
birth_date=date(2024, 1, 1),
|
|
created_at=datetime.now(),
|
|
)
|
|
)
|
|
return SeededIds(workspace_id=ws.id, personal_data_uuid=pd.uuid, child_id=child.id)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Shared authenticated HTTP client — bound to `seeded_ids`'s workspace.
|
|
#
|
|
# T1 authz work: every router now rejects ids outside the caller's workspace,
|
|
# so a router test's `client` must be authenticated as a real member of
|
|
# whatever workspace the test operates on. This fixture is that identity for
|
|
# any router test built around `seeded_ids` (see `tests/unit/test_fetch_data_
|
|
# router.py`). Router tests that seed their own bespoke workspace per test
|
|
# (e.g. `test_plan_router.py`) still define their own local `client`/current-
|
|
# user fixture bound to THAT workspace instead — a single global identity
|
|
# can't satisfy both shapes.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def current_user(seeded_ids: SeededIds) -> User:
|
|
"""A real, logged-in user whose PersonalData is `seeded_ids.personal_data_uuid`."""
|
|
return User(
|
|
id=uuid4(),
|
|
personal_data_uuid=seeded_ids.personal_data_uuid,
|
|
email="seeded-user@example.com",
|
|
hashed_password="not-a-real-hash",
|
|
created_at=datetime.now(),
|
|
)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def authed_client(
|
|
connection: aiosqlite.Connection, current_user: User
|
|
) -> AsyncIterator[AsyncClient]:
|
|
"""An httpx client against the real app, authenticated as `current_user`
|
|
and wired to the test's in-memory `connection` — the same technique
|
|
every router test file uses, consolidated here for tests keyed off
|
|
`seeded_ids`.
|
|
"""
|
|
app.dependency_overrides[get_connection] = lambda: connection
|
|
app.dependency_overrides[get_current_user] = lambda: current_user
|
|
try:
|
|
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as ac:
|
|
yield ac
|
|
finally:
|
|
app.dependency_overrides.pop(get_connection, None)
|
|
app.dependency_overrides.pop(get_current_user, None)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Child & leave
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def child_repo(connection: aiosqlite.Connection) -> SQLiteChildRepository:
|
|
return SQLiteChildRepository(connection)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def parental_leave_repo(
|
|
connection: aiosqlite.Connection,
|
|
) -> SQLiteParentalLeaveRepository:
|
|
return SQLiteParentalLeaveRepository(connection)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def planned_leave_repo(
|
|
connection: aiosqlite.Connection,
|
|
) -> SQLitePlannedLeaveRepository:
|
|
return SQLitePlannedLeaveRepository(connection)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# LeaveWish
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def leave_wish_repo(
|
|
connection: aiosqlite.Connection,
|
|
) -> SQLiteLeaveWishRepository:
|
|
return SQLiteLeaveWishRepository(connection)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def leave_wish_service(
|
|
leave_wish_repo: SQLiteLeaveWishRepository,
|
|
planned_leave_repo: SQLitePlannedLeaveRepository,
|
|
child_repo: SQLiteChildRepository,
|
|
day_assertion_repo: SQLiteDayAssertionRepository,
|
|
) -> LeaveWishService:
|
|
# `child_repo` lets an open-ended ("until the child turns 4") series
|
|
# materialise against the child's real birth date; see LeaveWishService.
|
|
# `day_assertion_repo` lets `delete()` clear a pinned/promoted row's
|
|
# assertion alongside the row itself (restructure step 3b).
|
|
return LeaveWishService(leave_wish_repo, planned_leave_repo, child_repo, day_assertion_repo)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def leave_wish_service_with_uow(
|
|
leave_wish_repo: SQLiteLeaveWishRepository,
|
|
planned_leave_repo: SQLitePlannedLeaveRepository,
|
|
child_repo: SQLiteChildRepository,
|
|
day_assertion_repo: SQLiteDayAssertionRepository,
|
|
sqlite_uow: SQLiteUnitOfWork,
|
|
) -> LeaveWishService:
|
|
"""A `LeaveWishService` wired with a real `SQLiteUnitOfWork` — for tests
|
|
|
|
exercising `create`/`update`/`delete`'s multi-row atomicity (this
|
|
service previously had none at all). See `planning_service_with_uow`
|
|
above for the same pattern.
|
|
"""
|
|
return LeaveWishService(
|
|
leave_wish_repo, planned_leave_repo, child_repo, day_assertion_repo, uow=sqlite_uow
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# DayOverride
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def day_override_repo(
|
|
connection: aiosqlite.Connection,
|
|
) -> SQLiteDayOverrideRepository:
|
|
return SQLiteDayOverrideRepository(connection)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def day_override_service(
|
|
day_override_repo: SQLiteDayOverrideRepository,
|
|
) -> DayOverrideService:
|
|
return DayOverrideService(day_override_repo)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# DayAssertion (restructure step 3 — see app/entities/day_assertion.py)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def day_assertion_repo(
|
|
connection: aiosqlite.Connection,
|
|
) -> SQLiteDayAssertionRepository:
|
|
return SQLiteDayAssertionRepository(connection)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def day_assertion_service(
|
|
day_assertion_repo: SQLiteDayAssertionRepository,
|
|
) -> DayAssertionService:
|
|
return DayAssertionService(day_assertion_repo)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def day_assertion_service_with_uow(
|
|
day_assertion_repo: SQLiteDayAssertionRepository,
|
|
planned_leave_repo: SQLitePlannedLeaveRepository,
|
|
sqlite_uow: SQLiteUnitOfWork,
|
|
) -> DayAssertionService:
|
|
"""A `DayAssertionService` wired with mirroring AND a real `SQLiteUnitOfWork`
|
|
|
|
— for tests that specifically exercise the assert-then-mirror atomicity
|
|
fix (a failure mid-mirror must leave no assertion committed). See
|
|
`planning_service_with_uow` above for the same pattern.
|
|
"""
|
|
return DayAssertionService(
|
|
day_assertion_repo,
|
|
planned_leave_repo=planned_leave_repo,
|
|
uow=sqlite_uow,
|
|
)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def child_service(
|
|
child_repo: SQLiteChildRepository,
|
|
) -> ChildService:
|
|
return ChildService(child_repo)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def analytics_service(
|
|
parental_leave_repo: SQLiteParentalLeaveRepository,
|
|
planned_leave_repo: SQLitePlannedLeaveRepository,
|
|
child_repo: SQLiteChildRepository,
|
|
personal_data_repo: SQLitePersonalDataRepository,
|
|
workspace_repo: SQLiteWorkspaceRepository,
|
|
vacation_repo: SQLiteVacationDaysRepository,
|
|
) -> AnalyticsService:
|
|
return AnalyticsService(
|
|
parental_leave_repo,
|
|
planned_leave_repo,
|
|
child_repo,
|
|
personal_data_repo,
|
|
workspace_repo,
|
|
vacation_repo,
|
|
)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def allocation_input_loader(
|
|
workspace_repo: SQLiteWorkspaceRepository,
|
|
child_repo: SQLiteChildRepository,
|
|
personal_data_repo: SQLitePersonalDataRepository,
|
|
parental_leave_repo: SQLiteParentalLeaveRepository,
|
|
vacation_repo: SQLiteVacationDaysRepository,
|
|
planned_leave_repo: SQLitePlannedLeaveRepository,
|
|
leave_wish_repo: SQLiteLeaveWishRepository,
|
|
day_override_repo: SQLiteDayOverrideRepository,
|
|
day_assertion_repo: SQLiteDayAssertionRepository,
|
|
) -> AllocationInputLoader:
|
|
return AllocationInputLoader(
|
|
workspace_repo=workspace_repo,
|
|
child_repo=child_repo,
|
|
personal_data_repo=personal_data_repo,
|
|
parental_leave_repo=parental_leave_repo,
|
|
vacation_repo=vacation_repo,
|
|
planned_leave_repo=planned_leave_repo,
|
|
leave_wish_repo=leave_wish_repo,
|
|
day_override_repo=day_override_repo,
|
|
day_assertion_repo=day_assertion_repo,
|
|
)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def planning_engine_service(
|
|
allocation_input_loader: AllocationInputLoader,
|
|
) -> PlanningEngineService:
|
|
return PlanningEngineService(allocation_input_loader)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def planning_service(
|
|
planned_leave_repo: SQLitePlannedLeaveRepository,
|
|
analytics_service: AnalyticsService,
|
|
parental_leave_repo: SQLiteParentalLeaveRepository,
|
|
vacation_repo: SQLiteVacationDaysRepository,
|
|
planning_engine_service: PlanningEngineService,
|
|
leave_wish_service: LeaveWishService,
|
|
day_assertion_repo: SQLiteDayAssertionRepository,
|
|
) -> PlanningService:
|
|
return PlanningService(
|
|
planned_leave_repo,
|
|
analytics_service,
|
|
parental_leave_repo,
|
|
vacation_repo,
|
|
planning_engine_service,
|
|
leave_wish_service=leave_wish_service,
|
|
day_assertion_repo=day_assertion_repo,
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Unit of work — a real `SQLiteUnitOfWork` bound to the test's shared
|
|
# `connection`, for tests that specifically exercise atomicity/locking (see
|
|
# `tests/unit/test_db_unit_of_work.py`). `planning_service` above deliberately
|
|
# keeps its default no-op unit of work so every other test's per-write-commit
|
|
# behavior stays exactly as it is; use `planning_service_with_uow` instead
|
|
# when a test needs the real thing.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def sqlite_uow(connection: aiosqlite.Connection) -> SQLiteUnitOfWork:
|
|
return SQLiteUnitOfWork(connection)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def planning_service_with_uow(
|
|
planned_leave_repo: SQLitePlannedLeaveRepository,
|
|
analytics_service: AnalyticsService,
|
|
parental_leave_repo: SQLiteParentalLeaveRepository,
|
|
vacation_repo: SQLiteVacationDaysRepository,
|
|
planning_engine_service: PlanningEngineService,
|
|
leave_wish_service: LeaveWishService,
|
|
sqlite_uow: SQLiteUnitOfWork,
|
|
day_assertion_repo: SQLiteDayAssertionRepository,
|
|
) -> PlanningService:
|
|
return PlanningService(
|
|
planned_leave_repo,
|
|
analytics_service,
|
|
parental_leave_repo,
|
|
vacation_repo,
|
|
planning_engine_service,
|
|
uow=sqlite_uow,
|
|
leave_wish_service=leave_wish_service,
|
|
day_assertion_repo=day_assertion_repo,
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Tips
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def tip_dismissal_repo(
|
|
connection: aiosqlite.Connection,
|
|
) -> SQLiteTipDismissalRepository:
|
|
return SQLiteTipDismissalRepository(connection)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def preschool_planning_days_repo(
|
|
connection: aiosqlite.Connection,
|
|
) -> SQLitePreschoolPlanningDaysRepository:
|
|
return SQLitePreschoolPlanningDaysRepository(connection)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def preschool_planning_days_service(
|
|
preschool_planning_days_repo: SQLitePreschoolPlanningDaysRepository,
|
|
) -> PreschoolPlanningDaysService:
|
|
return PreschoolPlanningDaysService(preschool_planning_days_repo)
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def tips_service(
|
|
parental_leave_repo: SQLiteParentalLeaveRepository,
|
|
planned_leave_repo: SQLitePlannedLeaveRepository,
|
|
child_repo: SQLiteChildRepository,
|
|
personal_data_repo: SQLitePersonalDataRepository,
|
|
vacation_repo: SQLiteVacationDaysRepository,
|
|
leave_wish_repo: SQLiteLeaveWishRepository,
|
|
tip_dismissal_repo: SQLiteTipDismissalRepository,
|
|
) -> TipsService:
|
|
return TipsService(
|
|
parental_leave_repo,
|
|
planned_leave_repo,
|
|
child_repo,
|
|
personal_data_repo,
|
|
vacation_repo,
|
|
leave_wish_repo,
|
|
tip_dismissal_repo,
|
|
)
|