Added a service that can get all current tournaments list

This commit is contained in:
Stanislas Jouffroy 2024-03-23 11:56:31 +01:00
parent e6023e0687
commit 3d0bd47079
26 changed files with 4305 additions and 204 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,21 @@
{
"Inscription tournois:school-outline": {
"1174": {
"id": 1174,
"sport": "padel",
"clubName": "toulouse padel club",
"nom": "Tournoi",
"dateNextSession": "25\/03\/2024",
"dateDebut": "01\/08\/2022",
"dateFin": "01\/10\/2024",
"logo": "TCP_Ligue_Arcanthe2-01-min.png",
"nbSession": 14,
"icon": "school-outline",
"playerCanSeeThisEvent": null,
"type": "tournoi",
"isJp": false,
"isCiup": false,
"sqlDate": "2024-03-25 13:30:00"
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@ from pathlib import Path
import config
import pendulum
import pytest
from connectors import GestionSportsConnector
from gestion_sport_connector import GestionSportsConnector
from models import BookingFilter, Club, User
TEST_FOLDER = Path(__file__).parent.parent
@ -36,11 +36,17 @@ def booking_filter() -> BookingFilter:
@pytest.fixture
def booking_success_response() -> dict:
booking_success_file = RESPONSES_FOLDER / "booking_success.json"
booking_success_file = RESPONSES_FOLDER / "booking-success.json"
return json.loads(booking_success_file.read_text(encoding="utf-8"))
@pytest.fixture
def booking_failure_response() -> dict:
booking_failure_file = RESPONSES_FOLDER / "booking_failure.json"
return json.loads(booking_failure_file.read_text(encoding="utf-8"))
file = RESPONSES_FOLDER / "booking-failure.json"
return json.loads(file.read_text(encoding="utf-8"))
@pytest.fixture
def tournament_sessions_json() -> str:
file = RESPONSES_FOLDER / "tournament-sessions.json"
return file.read_text(encoding="utf-8")

View file

@ -1,36 +1,15 @@
import json
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 aiohttp import ClientSession
from gestion_sport_connector import GestionSportsConnector
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"},
@ -57,6 +36,10 @@ def test_urls(connector):
connector.booking_cancellation_url
== "https://toulousepadelclub.gestion-sports.com/membre/mesresas.html"
)
assert (
connector.tournaments_sessions_url
== "https://toulousepadelclub.gestion-sports.com/membre/index.php"
)
@patch.dict(
@ -76,11 +59,15 @@ def test_urls_payload_templates(connector):
connector.booking_cancel_template
== resources_folder / "booking-cancellation-payload.txt"
)
assert (
connector.tournaments_sessions_template
== resources_folder / "tournament-sessions-payload.txt"
)
@pytest.mark.asyncio
async def test_landing_page(connector):
async with aiohttp.ClientSession() as session:
async with ClientSession() as session:
response = await connector.land(session)
assert response.status == 200
@ -93,7 +80,7 @@ async def test_landing_page(connector):
@pytest.mark.asyncio
async def test_login(connector, user):
async with aiohttp.ClientSession() as session:
async with ClientSession() as session:
await connector.land(session)
response = await connector.login(session, user)
@ -128,7 +115,7 @@ def test_get_booked_court(
@pytest.mark.asyncio
async def test_book_one_court(connector, user, booking_filter):
async with aiohttp.ClientSession() as session:
async with ClientSession() as session:
await connector.land(session)
await connector.login(session, user)
@ -156,28 +143,9 @@ def test_build_booking_datetime(connector, booking_filter):
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:
async with ClientSession() as session:
await connector.land(session)
await connector.login(session, user)
@ -197,7 +165,7 @@ def test_get_hash_input():
@pytest.mark.asyncio
async def test_get_bookings(connector, user):
async with aiohttp.ClientSession() as session:
async with ClientSession() as session:
await connector.land(session)
await connector.login(session, user)
@ -210,7 +178,7 @@ async def test_get_bookings(connector, user):
@pytest.mark.asyncio
async def test_get_ongoing_bookings(connector, user):
async with aiohttp.ClientSession() as session:
async with ClientSession() as session:
await connector.land(session)
await connector.login(session, user)
@ -218,20 +186,15 @@ async def test_get_ongoing_bookings(connector, user):
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:
async with 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)
response = await connector.cancel_booking_id(session, 666)
assert len(await connector.get_ongoing_bookings(session)) == 0
@ -245,7 +208,33 @@ def test_find_court(connector):
@pytest.mark.asyncio
async def test_cancel_booking(connector, user, booking_filter):
async with aiohttp.ClientSession() as session:
async with ClientSession() as session:
await connector.land(session)
await connector.login(session, user)
await connector.cancel_booking(session, booking_filter)
@pytest.mark.asyncio
async def test_tournament_sessions(connector, user):
async with ClientSession() as session:
await connector.land(session)
await connector.login(session, user)
response = await connector.send_tournaments_sessions_request(session)
assert response.status == 200
all_sessions = json.loads(await response.text())
sessions = all_sessions.get("Inscription tournois:school-outline")
assert len(sessions) == 1
@pytest.mark.asyncio
async def test_send_tournaments_request(connector, user):
async with ClientSession() as session:
await connector.land(session)
await connector.login(session, user)
tournament_session_id = "1174"
response = await connector.send_tournaments_request(
session, tournament_session_id
)
assert "<span class='nb_place_libre'>Complet</span>" in await response.text()

View file

@ -18,3 +18,9 @@ async def test_user_has_available_slots(club, user):
@pytest.mark.asyncio
async def test_cancel_booking(club, user, booking_filter):
await GestionSportsServices.cancel_booking(user, club, booking_filter)
@pytest.mark.asyncio
async def test_get_all_tournaments(user, club):
tournaments = await GestionSportsServices.get_all_tournaments(user, club)
assert len(tournaments) == 14

View file

@ -3,7 +3,7 @@ from pathlib import Path
import pendulum
import pytest
from connectors import GestionSportsConnector
from gestion_sport_connector import GestionSportsConnector
from gestion_sports_services import GestionSportsServices
from models import (
BookingFilter,
@ -43,7 +43,7 @@ def court14() -> Court:
@pytest.fixture
def sport1(court11, court12, court13, court14) -> Sport:
def sport1(court11: Court, court12: Court, court13: Court, court14: Court) -> Sport:
return Sport(
name="Sport1",
id=8,
@ -75,7 +75,7 @@ def court24() -> Court:
@pytest.fixture
def sport2(court21, court22, court23, court24) -> Sport:
def sport2(court21: Court, court22: Court, court23: Court, court24: Court) -> Sport:
return Sport(
name="Sport 2",
id=10,
@ -130,9 +130,26 @@ def cancellation_url() -> Url:
)
@pytest.fixture
def tournament_sessions_url() -> Url:
return Url(
name="tournament-sessions",
path="/tournaments_sessions.php",
payloadTemplate="gestion-sports/tournament-sessions-payload.txt",
)
@pytest.fixture
def tournaments_list_url() -> Url:
return Url(
name="tournaments-list",
path="/tournaments_list.html?event=",
)
@pytest.fixture
def booking_opening() -> BookingOpening:
return BookingOpening(daysBefore=10, time="03:27")
return BookingOpening(daysBefore=7, time="00:00")
@pytest.fixture
@ -142,15 +159,17 @@ def total_bookings() -> TotalBookings:
@pytest.fixture
def booking_platform(
booking_opening,
total_bookings,
sport1,
sport2,
landing_url,
login_url,
booking_url,
user_bookings_url,
cancellation_url,
booking_opening: BookingOpening,
total_bookings: TotalBookings,
sport1: Sport,
sport2: Sport,
landing_url: str,
login_url: str,
booking_url: str,
user_bookings_url: str,
cancellation_url: str,
tournament_sessions_url: str,
tournaments_list_url: str,
) -> BookingPlatform:
return BookingPlatform(
id="gestion-sports",
@ -166,12 +185,14 @@ def booking_platform(
"booking": booking_url,
"user-bookings": user_bookings_url,
"cancellation": cancellation_url,
"tournament-sessions": tournament_sessions_url,
"tournaments-list": tournaments_list_url,
},
)
@pytest.fixture
def club(booking_platform) -> Club:
def club(booking_platform: BookingPlatform) -> Club:
return Club(
id="super_club",
name="Super Club",
@ -204,42 +225,42 @@ def booking_filter() -> BookingFilter:
@pytest.fixture
def landing_response() -> str:
landing_response_file = RESPONSES_FOLDER / "landing_response.html"
return landing_response_file.read_text(encoding="utf-8")
file = RESPONSES_FOLDER / "landing-response.html"
return file.read_text(encoding="utf-8")
@pytest.fixture
def login_success_response() -> dict:
login_success_file = RESPONSES_FOLDER / "login_success.json"
login_success_file = RESPONSES_FOLDER / "login-success.json"
return json.loads(login_success_file.read_text(encoding="utf-8"))
@pytest.fixture
def login_failure_response() -> dict:
login_failure_file = RESPONSES_FOLDER / "login_failure.json"
return json.loads(login_failure_file.read_text(encoding="utf-8"))
file = RESPONSES_FOLDER / "login-failure.json"
return json.loads(file.read_text(encoding="utf-8"))
@pytest.fixture
def booking_success_response() -> dict:
booking_success_file = RESPONSES_FOLDER / "booking_success.json"
return json.loads(booking_success_file.read_text(encoding="utf-8"))
file = RESPONSES_FOLDER / "booking-success.json"
return json.loads(file.read_text(encoding="utf-8"))
@pytest.fixture
def booking_failure_response() -> dict:
booking_failure_file = RESPONSES_FOLDER / "booking_failure.json"
return json.loads(booking_failure_file.read_text(encoding="utf-8"))
file = RESPONSES_FOLDER / "booking-failure.json"
return json.loads(file.read_text(encoding="utf-8"))
@pytest.fixture
def booked_courts_response(
court11,
court12,
court13,
court14,
booking_success_response,
booking_failure_response,
court11: int,
court12: int,
court13: int,
court14: int,
booking_success_response: dict,
booking_failure_response: dict,
) -> list[tuple[int, dict]]:
court1_resp = court11.id, booking_failure_response
court2_resp = court12.id, booking_failure_response
@ -250,10 +271,10 @@ def booked_courts_response(
@pytest.fixture
def booking_success_from_start(
landing_response,
login_success_response,
booking_success_response,
booking_failure_response,
landing_response: str,
login_success_response: str,
booking_success_response: str,
booking_failure_response: str,
):
return [
landing_response,
@ -267,10 +288,10 @@ def booking_success_from_start(
@pytest.fixture
def booking_failure_from_start(
landing_response,
login_success_response,
booking_success_response,
booking_failure_response,
landing_response: str,
login_success_response: str,
booking_success_response: str,
booking_failure_response: str,
):
return [
landing_response,
@ -284,22 +305,22 @@ def booking_failure_from_start(
@pytest.fixture
def user_bookings_get_response() -> str:
user_bookings_file = RESPONSES_FOLDER / "user_bookings_get.html"
return user_bookings_file.read_text(encoding="utf-8")
file = RESPONSES_FOLDER / "user-bookings-get.html"
return file.read_text(encoding="utf-8")
@pytest.fixture
def user_bookings_list() -> list:
user_bookings_file = RESPONSES_FOLDER / "user_bookings_post.json"
return json.loads(user_bookings_file.read_text(encoding="utf-8"))
def user_bookings_list() -> str:
file = RESPONSES_FOLDER / "user-bookings-post.json"
return json.loads(file.read_text(encoding="utf-8"))
@pytest.fixture
def user_has_ongoing_bookings_from_start(
landing_response,
login_success_response,
user_bookings_get_response,
user_bookings_list,
landing_response: str,
login_success_response: str,
user_bookings_get_response: str,
user_bookings_list: str,
) -> list:
return [
landing_response,
@ -316,10 +337,10 @@ def user_bookings_empty_list() -> list:
@pytest.fixture
def user_has_no_ongoing_bookings_from_start(
landing_response,
login_success_response,
user_bookings_get_response,
user_bookings_empty_list,
landing_response: str,
login_success_response: str,
user_bookings_get_response: str,
user_bookings_empty_list: str,
) -> list:
return [
landing_response,
@ -331,16 +352,16 @@ def user_has_no_ongoing_bookings_from_start(
@pytest.fixture
def cancellation_response() -> list:
cancellation_response_file = RESPONSES_FOLDER / "cancellation_response.json"
return json.loads(cancellation_response_file.read_text(encoding="utf-8"))
file = RESPONSES_FOLDER / "cancellation-response.json"
return json.loads(file.read_text(encoding="utf-8"))
@pytest.fixture
def cancellation_by_id_from_start(
landing_response,
login_success_response,
user_bookings_get_response,
cancellation_response,
landing_response: str,
login_success_response: str,
user_bookings_get_response: str,
cancellation_response: str,
):
return [
landing_response,
@ -352,11 +373,11 @@ def cancellation_by_id_from_start(
@pytest.fixture
def cancellation_success_from_start(
landing_response,
login_success_response,
user_bookings_get_response,
user_bookings_list,
cancellation_response,
landing_response: str,
login_success_response: str,
user_bookings_get_response: str,
user_bookings_list: str,
cancellation_response: str,
):
return [
landing_response,
@ -377,3 +398,30 @@ def cancellation_success_booking_filter() -> BookingFilter:
@pytest.fixture
def service() -> GestionSportsServices:
return GestionSportsServices()
@pytest.fixture
def tournament_sessions_json() -> str:
file = RESPONSES_FOLDER / "tournament-sessions.json"
return file.read_text(encoding="utf-8")
@pytest.fixture
def tournaments_html() -> str:
file = RESPONSES_FOLDER / "tournaments.html"
return file.read_text(encoding="utf-8")
@pytest.fixture
def full_tournaments_responses(
landing_response: str,
login_success_response: str,
tournament_sessions_json: str,
tournaments_html: str,
) -> list[str]:
return [
landing_response,
login_success_response,
tournament_sessions_json,
tournaments_html,
]

View file

@ -1,31 +1,24 @@
import json
from pathlib import Path
from unittest.mock import patch
import pytest
from aiohttp import ClientSession
from connectors import GestionSportsConnector
from gestion_sport_connector import GestionSportsConnector
from tests.unit_tests import responses
def test_urls(connector, club):
base_url = club.booking_platform.url
relative_urls = club.booking_platform.urls
base_url = "https://ptf1.com"
relative_landing_url = relative_urls.get("landing-page").path
assert connector.landing_url == f"{base_url}/{relative_landing_url}"
relative_login_url = relative_urls.get("login").path
assert connector.login_url == f"{base_url}/{relative_login_url}"
relative_booking_url = relative_urls.get("booking").path
assert connector.booking_url == f"{base_url}/{relative_booking_url}"
relative_user_bookings_url = relative_urls.get("user-bookings").path
assert connector.user_bookings_url == f"{base_url}/{relative_user_bookings_url}"
relative_cancel_url = relative_urls.get("cancellation").path
assert connector.booking_cancellation_url == f"{base_url}/{relative_cancel_url}"
assert connector.landing_url == f"{base_url}/landing.html"
assert connector.login_url == f"{base_url}/login.html"
assert connector.booking_url == f"{base_url}/booking.html"
assert connector.user_bookings_url == f"{base_url}/user_bookings.html"
assert connector.booking_cancellation_url == f"{base_url}/cancel.html"
assert connector.tournaments_sessions_url == f"{base_url}/tournaments_sessions.php"
assert connector.tournaments_list_url == f"{base_url}/tournaments_list.html?event="
@patch("config.get_resources_folder")
@ -34,19 +27,27 @@ def test_urls_payload_templates(mock_resources, club):
mock_resources.return_value = path_to_resources
connector = GestionSportsConnector(club)
relative_urls = club.booking_platform.urls
login_payload = relative_urls.get("login").payload_template
assert connector.login_template == path_to_resources / login_payload
booking_payload = relative_urls.get("booking").payload_template
assert connector.booking_template == path_to_resources / booking_payload
user_bookings_payload = relative_urls.get("user-bookings").payload_template
assert connector.user_bookings_template == path_to_resources / user_bookings_payload
cancel_payload = relative_urls.get("cancellation").payload_template
assert connector.booking_cancel_template == path_to_resources / cancel_payload
assert (
connector.login_template
== path_to_resources / "gestion-sports/login-payload.txt"
)
assert (
connector.booking_template
== path_to_resources / "gestion-sports/booking-payload.txt"
)
assert (
connector.user_bookings_template
== path_to_resources / "gestion-sports/user-bookings-payload.txt"
)
assert (
connector.booking_cancel_template
== path_to_resources / "gestion-sports/booking-cancellation-payload.txt"
)
assert (
connector.tournaments_sessions_template
== path_to_resources / "gestion-sports/tournament-sessions-payload.txt"
)
@pytest.mark.asyncio
@ -143,3 +144,35 @@ async def test_cancel_booking_success(
)
assert await response.json() == cancellation_success_from_start[4]
@pytest.mark.asyncio
async def test_tournament_sessions(
aioresponses, connector, user, tournament_sessions_json
):
responses.set_tournaments_sessions_response(
aioresponses, connector, tournament_sessions_json
)
async with ClientSession() as session:
response = await connector.send_tournaments_sessions_request(session)
assert response.status == 200
all_sessions = json.loads(await response.text())
sessions = all_sessions.get("Inscription tournois:school-outline")
assert len(sessions) == 1
@pytest.mark.asyncio
async def test_send_tournaments_request(
aioresponses, connector, user, tournaments_html
):
tournament_session_id = "255"
responses.set_tournaments_list_response(
aioresponses, connector, tournament_session_id, tournaments_html
)
async with ClientSession() as session:
response = await connector.send_tournaments_request(
session, tournament_session_id
)
assert "<span class='nb_place_libre'>Complet</span>" in await response.text()

View file

@ -1,5 +1,9 @@
from unittest.mock import patch
import pendulum
import pytest
from gestion_sports_services import GestionSportsServices
from models import BookingFilter, BookingOpening
from tests.unit_tests import responses
@ -108,3 +112,65 @@ async def test_cancel_booking_id(
)
await gs_services.cancel_booking_id(user, club, 65464)
@patch("pendulum.now")
def test_wait_until_booking_time(mock_now, club, user):
booking_filter = BookingFilter(
sport_name="Sport1", date=pendulum.parse("2024-03-21T13:30:00+01:00")
)
booking_datetime = pendulum.parse("2024-03-14T00:00:00+01:00")
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
booking_opening = club.booking_platform.booking_opening
GestionSportsServices.wait_until_booking_time(booking_filter, booking_opening)
assert pendulum.now() == booking_datetime.add(microseconds=1)
def test_build_booking_time():
booking_filter = BookingFilter(
sport_name="Sport1", date=pendulum.parse("2024-03-21T13:30:00+01:00")
)
booking_opening = BookingOpening(daysBefore=7, time="00:00")
booking_time = GestionSportsServices.build_booking_datetime(
booking_filter, booking_opening
)
assert booking_time == pendulum.parse("2024-03-13T23:00:00Z")
def test_retrieve_tournament_id(tournament_sessions_json):
session_id = GestionSportsServices.retrieve_tournament_session(
tournament_sessions_json
)
assert session_id == "1174"
def test_retrieve_tournaments(tournaments_html):
tournaments = GestionSportsServices.retrieve_tournaments(tournaments_html)
assert len(tournaments) == 14
@pytest.mark.asyncio
async def test_get_all_tournaments(
aioresponses, user, connector, club, full_tournaments_responses
):
responses.set_full_tournaments_requests(
aioresponses, connector, full_tournaments_responses, 1174
)
tournaments = await GestionSportsServices.get_all_tournaments(user, club)
assert len(tournaments) == 14