import os from pathlib import Path from unittest.mock import patch import aiohttp import pendulum import pytest from connectors import GestionSportsConnector from models import BookingFilter, Club from pendulum import DateTime from yarl import URL def retrieve_booking_datetime( a_booking_filter: BookingFilter, a_club: Club ) -> DateTime: """ Utility to retrieve the booking datetime from the booking filter and the club :param a_booking_filter: the booking filter that contains the date to book :param a_club: the club which has the number of days before the date and the booking time """ booking_opening = a_club.booking_platform.booking_opening opening_time = pendulum.parse(booking_opening.opening_time) booking_hour = opening_time.hour booking_minute = opening_time.minute date_to_book = a_booking_filter.date return date_to_book.subtract(days=booking_opening.days_before).at( booking_hour, booking_minute ) @patch.dict( os.environ, {"CLUB_ID": "tpc"}, clear=True, ) def test_urls(connector): assert ( connector.landing_url == "https://toulousepadelclub.gestion-sports.com/connexion.php" ) assert ( connector.login_url == "https://toulousepadelclub.gestion-sports.com/connexion.php" ) assert ( connector.booking_url == "https://toulousepadelclub.gestion-sports.com/membre/reservation.html" ) assert ( connector.user_bookings_url == "https://toulousepadelclub.gestion-sports.com/membre/mesresas.html" ) assert ( connector.booking_cancellation_url == "https://toulousepadelclub.gestion-sports.com/membre/mesresas.html" ) @patch.dict( os.environ, {"RESOURCES_FOLDER": "/some/path"}, clear=True, ) def test_urls_payload_templates(connector): resources_folder = Path("/some", "path", "gestion-sports") assert connector.login_template == resources_folder / "login-payload.txt" assert connector.booking_template == resources_folder / "booking-payload.txt" assert ( connector.user_bookings_template == resources_folder / "user-bookings-payload.txt" ) assert ( connector.booking_cancel_template == resources_folder / "booking-cancellation-payload.txt" ) @pytest.mark.asyncio async def test_landing_page(connector): async with aiohttp.ClientSession() as session: response = await connector.land(session) assert response.status == 200 assert response.request_info.method == "GET" assert response.content_type == "text/html" assert response.request_info.url == URL(connector.landing_url) assert response.charset == "UTF-8" assert response.cookies.get("PHPSESSID") is not None @pytest.mark.asyncio async def test_login(connector, user): async with aiohttp.ClientSession() as session: await connector.land(session) response = await connector.login(session, user) assert response.status == 200 assert response.request_info.method == "POST" assert response.content_type == "text/html" assert response.request_info.url == URL(connector.landing_url) assert response.charset == "UTF-8" assert response.cookies.get("COOK_COMPTE") is not None assert response.cookies.get("COOK_ID_CLUB").value == "88" assert response.cookies.get("COOK_ID_USER").value == "232382" def test_get_booked_court( connector, booking_success_response, booking_failure_response ): bookings = [ (601, booking_failure_response), (602, booking_failure_response), (603, booking_failure_response), (614, booking_failure_response), (605, booking_failure_response), (606, booking_success_response), (607, booking_failure_response), (608, booking_failure_response), ] court = connector.get_booked_court(bookings, "padel") assert court.number == 9 @pytest.mark.asyncio async def test_book_one_court(connector, user, booking_filter): async with aiohttp.ClientSession() as session: await connector.land(session) await connector.login(session, user) court_id, response = await connector.send_booking_request( session, pendulum.parse("2024-03-21T13:30:00+01:00"), 610, 217 ) assert court_id == 610 assert response.get("status") == "ok" @pytest.mark.asyncio async def test_book(connector, user, booking_filter): booked_court = await connector.book(user, booking_filter) assert booked_court is not None def test_build_booking_datetime(connector, booking_filter): opening_datetime = connector.build_booking_datetime(booking_filter) assert opening_datetime.year == 2024 assert opening_datetime.month == 3 assert opening_datetime.day == 14 assert opening_datetime.hour == 0 assert opening_datetime.minute == 0 @patch("pendulum.now") def test_wait_until_booking_time(mock_now, connector, booking_filter, club): booking_datetime = retrieve_booking_datetime(booking_filter, club) seconds = [ booking_datetime.subtract(seconds=3), booking_datetime.subtract(seconds=2), booking_datetime.subtract(seconds=1), booking_datetime, booking_datetime.add(microseconds=1), booking_datetime.add(microseconds=2), ] mock_now.side_effect = seconds connector.wait_until_booking_time(booking_filter) assert pendulum.now() == booking_datetime.add(microseconds=1) @pytest.mark.asyncio async def test_get_hash(connector, user): async with aiohttp.ClientSession() as session: await connector.land(session) await connector.login(session, user) hash_value = await connector.send_hash_request(session) assert hash_value is not None def test_get_hash_input(): resources_folder = Path(__file__).parent / "data" html_file = resources_folder / "user_bookings_html_response.html" html = html_file.read_text(encoding="utf-8") hash_value = GestionSportsConnector.get_hash_input(html) assert hash_value == "63470fa38e300fd503de1ee21a71b3bdb6fb206b" @pytest.mark.asyncio async def test_get_bookings(connector, user): async with aiohttp.ClientSession() as session: await connector.land(session) await connector.login(session, user) hash_value = await connector.send_hash_request(session) payload = f"ajax=loadResa&hash={hash_value}" bookings = await connector.send_user_bookings_request(session, payload) print(bookings) @pytest.mark.asyncio async def test_get_ongoing_bookings(connector, user): async with aiohttp.ClientSession() as session: await connector.land(session) await connector.login(session, user) bookings = await connector.get_ongoing_bookings(session) print(bookings) @pytest.mark.asyncio async def test_has_user_ongoing_bookings(connector, user): assert await connector.has_user_ongoing_booking(user) @pytest.mark.asyncio async def test_cancel_booking_id(connector, user): async with aiohttp.ClientSession() as session: await connector.land(session) await connector.login(session, user) ongoing_bookings = await connector.get_ongoing_bookings(session) booking_id = ongoing_bookings[0].id response = await connector.cancel_booking_id(user, booking_id) assert len(await connector.get_ongoing_bookings(session)) == 0 @pytest.mark.asyncio def test_find_court(connector): court = connector.find_court(603, "Padel") assert court.number == 6 @pytest.mark.asyncio async def test_cancel_booking(connector, user, booking_filter): async with aiohttp.ClientSession() as session: await connector.land(session) await connector.login(session, user) await connector.cancel_booking(session, booking_filter)