Big refactoring.
- clubs, booking platforms and user are now defined in customization files -> there are less environment variables - the responsibility of the session moved - booking cancellation is available
This commit is contained in:
parent
dbda5a158e
commit
0938fb98b7
27 changed files with 3050 additions and 696 deletions
411
tests/test_connectors.py
Normal file
411
tests/test_connectors.py
Normal file
|
@ -0,0 +1,411 @@
|
|||
import os
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
import aiohttp
|
||||
import config
|
||||
import pendulum
|
||||
import pytest
|
||||
from aiohttp import ClientSession
|
||||
from connectors import GestionSportsConnector
|
||||
from models import Booking, BookingFilter, User
|
||||
from yarl import URL
|
||||
|
||||
from tests import utils
|
||||
|
||||
|
||||
@patch.dict(
|
||||
os.environ,
|
||||
{"CLUB_ID": "tpc"},
|
||||
clear=True,
|
||||
)
|
||||
def test_urls():
|
||||
club = config.get_club()
|
||||
connector = GestionSportsConnector(club)
|
||||
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,
|
||||
{"CLUB_ID": "tpc", "RESOURCES_FOLDER": "/some/path"},
|
||||
clear=True,
|
||||
)
|
||||
def test_urls_payload_templates():
|
||||
club = config.get_club()
|
||||
connector = GestionSportsConnector(club)
|
||||
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_cancellation_template
|
||||
== resources_folder / "booking-cancellation-payload.txt"
|
||||
)
|
||||
|
||||
|
||||
@patch.dict(
|
||||
os.environ,
|
||||
{"CLUB_ID": "tpc"},
|
||||
clear=True,
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_landing_page():
|
||||
club = config.get_club()
|
||||
connector = GestionSportsConnector(club)
|
||||
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
|
||||
|
||||
|
||||
@patch.dict(
|
||||
os.environ,
|
||||
{"CLUB_ID": "tpc"},
|
||||
clear=True,
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_login():
|
||||
club = config.get_club()
|
||||
connector = GestionSportsConnector(club)
|
||||
user = User(login="padel.testing@jouf.fr", password="ridicule")
|
||||
|
||||
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"
|
||||
|
||||
|
||||
@patch.dict(
|
||||
os.environ,
|
||||
{"CLUB_ID": "tpc"},
|
||||
clear=True,
|
||||
)
|
||||
def test_get_booked_court():
|
||||
club = config.get_club()
|
||||
connector = GestionSportsConnector(club)
|
||||
|
||||
session = ClientSession()
|
||||
bookings = [
|
||||
(session, 601, False),
|
||||
(session, 602, False),
|
||||
(session, 603, False),
|
||||
(session, 614, False),
|
||||
(session, 605, False),
|
||||
(session, 606, True),
|
||||
(session, 607, False),
|
||||
(session, 608, False),
|
||||
]
|
||||
|
||||
court = connector.get_booked_court(bookings, "padel")
|
||||
assert court.number == 9
|
||||
|
||||
|
||||
@patch.dict(
|
||||
os.environ,
|
||||
{"CLUB_ID": "tpc"},
|
||||
clear=True,
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_book_one_court():
|
||||
club = config.get_club()
|
||||
connector = GestionSportsConnector(club)
|
||||
user = User(login="padel.testing@jouf.fr", password="ridicule")
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
await connector.land(session)
|
||||
await connector.login(session, user)
|
||||
response, court_id, ok = await connector.send_booking_request(
|
||||
session, pendulum.parse("2024-03-21T13:30:00Z"), 610, 217
|
||||
)
|
||||
|
||||
assert response.status == 200
|
||||
assert response.request_info.method == "POST"
|
||||
assert response.content_type == "text/html"
|
||||
assert response.request_info.url == URL(connector.booking_url)
|
||||
assert response.charset == "UTF-8"
|
||||
assert response.text is not None
|
||||
assert court_id == 610
|
||||
assert ok is True
|
||||
|
||||
|
||||
@patch.dict(
|
||||
os.environ,
|
||||
{"CLUB_ID": "tpc"},
|
||||
clear=True,
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_book():
|
||||
club = config.get_club()
|
||||
connector = GestionSportsConnector(club)
|
||||
user = User(login="padel.testing@jouf.fr", password="ridicule")
|
||||
booking_filter = BookingFilter(
|
||||
sport_name="Padel", date=pendulum.parse("2024-03-21T13:30:00Z")
|
||||
)
|
||||
|
||||
booked_court = await connector.book(user, booking_filter)
|
||||
|
||||
assert booked_court is not None
|
||||
|
||||
|
||||
@patch.dict(
|
||||
os.environ,
|
||||
{"CLUB_ID": "tpc"},
|
||||
clear=True,
|
||||
)
|
||||
def test_build_booking_datetime():
|
||||
club = config.get_club()
|
||||
connector = GestionSportsConnector(club)
|
||||
booking_filter = BookingFilter(
|
||||
sport_name="Padel", date=pendulum.parse("2024-03-21T13:30:00Z")
|
||||
)
|
||||
|
||||
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.dict(
|
||||
os.environ,
|
||||
{"CLUB_ID": "tpc"},
|
||||
clear=True,
|
||||
)
|
||||
@patch("pendulum.now")
|
||||
def test_wait_until_booking_time(mock_now):
|
||||
club = config.get_club()
|
||||
connector = GestionSportsConnector(club)
|
||||
booking_filter = BookingFilter(
|
||||
sport_name="Padel", date=pendulum.parse("2024-03-21T13:30:00Z")
|
||||
)
|
||||
|
||||
booking_datetime = utils.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)
|
||||
|
||||
|
||||
@patch.dict(
|
||||
os.environ,
|
||||
{"CLUB_ID": "tpc"},
|
||||
clear=True,
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_hash():
|
||||
club = config.get_club()
|
||||
connector = GestionSportsConnector(club)
|
||||
user = User(login="padel.testing@jouf.fr", password="ridicule")
|
||||
|
||||
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"
|
||||
|
||||
|
||||
@patch.dict(
|
||||
os.environ,
|
||||
{"CLUB_ID": "tpc"},
|
||||
clear=True,
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_bookings():
|
||||
club = config.get_club()
|
||||
connector = GestionSportsConnector(club)
|
||||
user = User(login="padel.testing@jouf.fr", password="ridicule")
|
||||
|
||||
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)
|
||||
|
||||
|
||||
@patch.dict(
|
||||
os.environ,
|
||||
{"CLUB_ID": "tpc"},
|
||||
clear=True,
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_ongoing_bookings():
|
||||
club = config.get_club()
|
||||
connector = GestionSportsConnector(club)
|
||||
user = User(login="padel.testing@jouf.fr", password="ridicule")
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
await connector.land(session)
|
||||
await connector.login(session, user)
|
||||
|
||||
bookings = await connector.get_ongoing_bookings(session)
|
||||
print(bookings)
|
||||
|
||||
|
||||
@patch.dict(
|
||||
os.environ,
|
||||
{"CLUB_ID": "tpc"},
|
||||
clear=True,
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_has_user_ongoing_bookings():
|
||||
club = config.get_club()
|
||||
connector = GestionSportsConnector(club)
|
||||
user = User(login="padel.testing@jouf.fr", password="ridicule")
|
||||
|
||||
assert await connector.has_user_ongoing_booking(user)
|
||||
|
||||
|
||||
@patch.dict(
|
||||
os.environ,
|
||||
{"CLUB_ID": "tpc"},
|
||||
clear=True,
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_cancel_booking_id():
|
||||
club = config.get_club()
|
||||
connector = GestionSportsConnector(club)
|
||||
user = User(login="padel.testing@jouf.fr", password="ridicule")
|
||||
|
||||
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
|
||||
|
||||
|
||||
@patch.dict(
|
||||
os.environ,
|
||||
{"CLUB_ID": "tpc"},
|
||||
clear=True,
|
||||
)
|
||||
def test_is_booking_matching_filter():
|
||||
club = config.get_club()
|
||||
connector = GestionSportsConnector(club)
|
||||
filter_date = pendulum.parse("2024-03-02T15:00:00+01:00")
|
||||
booking = Booking(
|
||||
id=1,
|
||||
dateResa="02/03/2024",
|
||||
startTime="15:00",
|
||||
sport="Padel",
|
||||
court="10",
|
||||
)
|
||||
booking_filter = BookingFilter(date=filter_date, sport_name="Padel")
|
||||
|
||||
assert connector.is_booking_matching_filter(booking, booking_filter)
|
||||
|
||||
|
||||
@patch.dict(
|
||||
os.environ,
|
||||
{"CLUB_ID": "tpc"},
|
||||
clear=True,
|
||||
)
|
||||
def test_is_booking_not_matching_filter():
|
||||
club = config.get_club()
|
||||
connector = GestionSportsConnector(club)
|
||||
filter_date = pendulum.parse("2024-03-02T15:00:00+01:00")
|
||||
booking = Booking(
|
||||
id=1,
|
||||
dateResa="02/03/2024",
|
||||
startTime="16:00",
|
||||
sport="Padel",
|
||||
court="10",
|
||||
)
|
||||
booking_filter = BookingFilter(date=filter_date, sport_name="Padel")
|
||||
|
||||
assert not connector.is_booking_matching_filter(booking, booking_filter)
|
||||
|
||||
|
||||
@patch.dict(
|
||||
os.environ,
|
||||
{"CLUB_ID": "tpc"},
|
||||
clear=True,
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
def test_find_court():
|
||||
club = config.get_club()
|
||||
connector = GestionSportsConnector(club)
|
||||
|
||||
court = connector.find_court(603, "Padel")
|
||||
|
||||
assert court.number == 6
|
||||
|
||||
|
||||
@patch.dict(
|
||||
os.environ,
|
||||
{"CLUB_ID": "tpc"},
|
||||
clear=True,
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_cancel_booking():
|
||||
club = config.get_club()
|
||||
connector = GestionSportsConnector(club)
|
||||
user = User(login="padel.testing@jouf.fr", password="ridicule")
|
||||
filter_date = pendulum.parse("2024-03-21T13:30:00+01:00")
|
||||
booking_filter = BookingFilter(date=filter_date, sport_name="Padel")
|
||||
await connector.cancel_booking(user, booking_filter)
|
Loading…
Add table
Add a link
Reference in a new issue