"""Integration tests for the FreeRooms endpoint.""" from __future__ import annotations import asyncio import gzip import urllib.parse from datetime import UTC, datetime from unittest.mock import patch import pytest from fastapi.testclient import TestClient from sqlalchemy import select from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine from alpine_bits_python.alpinebits_server import AlpineBitsServer from alpine_bits_python.api import app from alpine_bits_python.const import HttpStatusCode from alpine_bits_python.db import Base, Hotel, RoomAvailability def build_request_xml(body: str, include_unique_id: bool = True) -> str: unique = ( '' if include_unique_id else "" ) return f""" {unique} {body} """ INVENTORY_A = """ """ INVENTORY_B = """ """ @pytest.fixture def freerooms_test_config(): return { "server": { "codecontext": "ADVERTISING", "code": "70597314", "companyname": "99tales Gmbh", "res_id_source_context": "99tales", }, "alpine_bits_auth": [ { "hotel_id": "HOTEL123", "hotel_name": "Integration Hotel", "username": "testuser", "password": "testpass", } ], "database": {"url": "sqlite+aiosqlite:///:memory:"}, } @pytest.fixture def freerooms_client(freerooms_test_config): engine = create_async_engine("sqlite+aiosqlite:///:memory:", echo=False) async def create_tables(): async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) asyncio.run(create_tables()) with patch("alpine_bits_python.api.load_config", return_value=freerooms_test_config), patch( "alpine_bits_python.api.create_database_engine", return_value=engine ): app.state.engine = engine app.state.async_sessionmaker = async_sessionmaker(engine, expire_on_commit=False) app.state.config = freerooms_test_config app.state.alpine_bits_server = AlpineBitsServer(freerooms_test_config) with TestClient(app) as test_client: yield test_client @pytest.fixture def freerooms_headers(): return { "Authorization": "Basic dGVzdHVzZXI6dGVzdHBhc3M=", "X-AlpineBits-ClientProtocolVersion": "2024-10", } def seed_hotel_if_missing(client: TestClient): async def _seed(): async_sessionmaker = client.app.state.async_sessionmaker async with async_sessionmaker() as session: result = await session.execute( select(Hotel).where(Hotel.hotel_id == "HOTEL123") ) if result.scalar_one_or_none(): return session.add( Hotel( hotel_id="HOTEL123", hotel_name="Integration Hotel", username="testuser", password_hash="integration-hash", created_at=datetime.now(UTC), updated_at=datetime.now(UTC), is_active=True, ) ) await session.commit() asyncio.run(_seed()) def fetch_availability(client: TestClient): async def _fetch(): async_sessionmaker = client.app.state.async_sessionmaker async with async_sessionmaker() as session: result = await session.execute( select(RoomAvailability).order_by(RoomAvailability.date) ) return result.scalars().all() return asyncio.run(_fetch()) def test_freerooms_endpoint_complete_set(freerooms_client: TestClient, freerooms_headers): seed_hotel_if_missing(freerooms_client) xml = build_request_xml(INVENTORY_A, include_unique_id=True) response = freerooms_client.post( "/api/alpinebits/server-2024-10", data={"action": "OTA_HotelInvCountNotif:FreeRooms", "request": xml}, headers=freerooms_headers, ) assert response.status_code == HttpStatusCode.OK assert "