test: room and slots creation/edition

This commit is contained in:
imperosol
2025-06-30 22:36:17 +02:00
parent 0baaf69714
commit 72bb4788f2
10 changed files with 249 additions and 74 deletions

View File

@ -0,0 +1,113 @@
import pytest
from django.contrib.auth.models import Permission
from django.test import Client
from django.urls import reverse
from model_bakery import baker
from pytest_django.asserts import assertNumQueries, assertRedirects
from club.models import Club
from core.models import User
from reservation.forms import RoomUpdateForm
from reservation.models import Room
@pytest.mark.django_db
class TestFetchRoom:
@pytest.fixture
def user(self):
return baker.make(
User,
user_permissions=[Permission.objects.get(codename="view_room")],
)
def test_fetch_simple(self, client: Client, user: User):
rooms = baker.make(Room, _quantity=3, _bulk_create=True)
client.force_login(user)
response = client.get(reverse("api:fetch_reservable_rooms"))
assert response.status_code == 200
assert response.json() == [
{
"id": room.id,
"name": room.name,
"description": room.description,
"location": room.location,
"club": {"id": room.club.id, "name": room.club.name},
}
for room in rooms
]
def test_nb_queries(self, client: Client, user: User):
client.force_login(user)
with assertNumQueries(5):
# 4 for authentication
# 1 to fetch the actual data
client.get(reverse("api:fetch_reservable_rooms"))
@pytest.mark.django_db
class TestCreateRoom:
def test_ok(self, client: Client):
perm = Permission.objects.get(codename="add_room")
club = baker.make(Club)
client.force_login(
baker.make(User, user_permissions=[perm], groups=[club.board_group])
)
response = client.post(
reverse("reservation:room_create"),
data={"club": club.id, "name": "test", "location": "BELFORT"},
)
assertRedirects(response, reverse("club:tools", kwargs={"club_id": club.id}))
room = Room.objects.last()
assert room is not None
assert room.club == club
assert room.name == "test"
assert room.location == "BELFORT"
def test_permission_denied(self, client: Client):
club = baker.make(Club)
client.force_login(baker.make(User))
response = client.get(reverse("reservation:room_create"))
assert response.status_code == 403
response = client.post(
reverse("reservation:room_create"),
data={"club": club.id, "name": "test", "location": "BELFORT"},
)
assert response.status_code == 403
@pytest.mark.django_db
class TestUpdateRoom:
def test_ok(self, client: Client):
club = baker.make(Club)
room = baker.make(Room, club=club)
client.force_login(baker.make(User, groups=[club.board_group]))
url = reverse("reservation:room_edit", kwargs={"room_id": room.id})
response = client.post(url, data={"name": "test", "location": "BELFORT"})
assertRedirects(response, url)
room.refresh_from_db()
assert room.club == club
assert room.name == "test"
assert room.location == "BELFORT"
def test_permission_denied(self, client: Client):
club = baker.make(Club)
room = baker.make(Room, club=club)
client.force_login(baker.make(User))
url = reverse("reservation:room_edit", kwargs={"room_id": room.id})
response = client.get(url)
assert response.status_code == 403
response = client.post(url, data={"name": "test", "location": "BELFORT"})
assert response.status_code == 403
@pytest.mark.django_db
class TestUpdateRoomForm:
def test_form_club_edition_rights(self):
"""The club field should appear only if the request user can edit it."""
room = baker.make(Room)
perm = Permission.objects.get(codename="change_room")
user_authorized = baker.make(User, user_permissions=[perm])
assert "club" in RoomUpdateForm(request_user=user_authorized).fields
user_forbidden = baker.make(User, groups=[room.club.board_group])
assert "club" not in RoomUpdateForm(request_user=user_forbidden).fields

View File

@ -1,42 +0,0 @@
import pytest
from django.contrib.auth.models import Permission
from django.test import Client
from django.urls import reverse
from model_bakery import baker
from pytest_django.asserts import assertNumQueries
from core.models import User
from reservation.models import Room
@pytest.mark.django_db
class TestFetchRoom:
@pytest.fixture
def user(self):
return baker.make(
User,
user_permissions=[Permission.objects.get(codename="view_room")],
)
def test_fetch_simple(self, client: Client, user: User):
rooms = baker.make(Room, _quantity=3, _bulk_create=True)
client.force_login(user)
response = client.get(reverse("api:fetch_reservable_rooms"))
assert response.status_code == 200
assert response.json() == [
{
"id": room.id,
"name": room.name,
"description": room.description,
"location": room.location,
"club": {"id": room.club.id, "name": room.club.name},
}
for room in rooms
]
def test_nb_queries(self, client: Client, user: User):
client.force_login(user)
with assertNumQueries(5):
# 4 for authentication
# 1 to fetch the actual data
client.get(reverse("api:fetch_reservable_rooms"))

View File

@ -17,10 +17,8 @@ from reservation.models import ReservationSlot, Room
class TestFetchReservationSlotsApi:
@pytest.fixture
def user(self):
return baker.make(
User,
user_permissions=[Permission.objects.get(codename="view_reservationslot")],
)
perm = Permission.objects.get(codename="view_reservationslot")
return baker.make(User, user_permissions=[perm])
def test_fetch_simple(self, client: Client, user: User):
slots = baker.make(ReservationSlot, _quantity=5, _bulk_create=True)
@ -55,6 +53,67 @@ class TestFetchReservationSlotsApi:
client.get(reverse("api:fetch_reservation_slots"))
@pytest.mark.django_db
class TestUpdateReservationSlotApi:
@pytest.fixture
def user(self):
perm = Permission.objects.get(codename="change_reservationslot")
return baker.make(User, user_permissions=[perm])
@pytest.fixture
def slot(self):
return baker.make(
ReservationSlot,
start_at=now() + timedelta(hours=2),
end_at=now() + timedelta(hours=4),
)
def test_ok(self, client: Client, user: User, slot: ReservationSlot):
client.force_login(user)
new_start = (slot.start_at + timedelta(hours=1)).replace(microsecond=0)
response = client.patch(
reverse("api:change_reservation_slot", kwargs={"slot_id": slot.id}),
{"start_at": new_start, "end_at": new_start + timedelta(hours=2)},
content_type="application/json",
)
assert response.status_code == 200
slot.refresh_from_db()
assert slot.start_at.replace(microsecond=0) == new_start
assert slot.end_at.replace(microsecond=0) == new_start + timedelta(hours=2)
def test_change_past_event(self, client, user: User, slot: ReservationSlot):
"""Test that moving a slot that already began is impossible."""
client.force_login(user)
new_start = now() - timedelta(hours=1)
response = client.patch(
reverse("api:change_reservation_slot", kwargs={"slot_id": slot.id}),
{"start_at": new_start, "end_at": new_start + timedelta(hours=2)},
content_type="application/json",
)
assert response.status_code == 422
def test_move_event_to_occupied_slot(
self, client: Client, user: User, slot: ReservationSlot
):
client.force_login(user)
other_slot = baker.make(
ReservationSlot,
room=slot.room,
start_at=slot.end_at + timedelta(hours=1),
end_at=slot.end_at + timedelta(hours=3),
)
response = client.patch(
reverse("api:change_reservation_slot", kwargs={"slot_id": slot.id}),
{
"start_at": other_slot.start_at - timedelta(hours=1),
"end_at": other_slot.start_at + timedelta(hours=1),
},
content_type="application/json",
)
assert response.status_code == 409
@pytest.mark.django_db
class TestReservationForm:
def test_ok(self):
@ -109,3 +168,40 @@ class TestReservationForm:
assert form.errors == {
"__all__": ["Il y a déjà une réservation sur ce créneau."]
}
@pytest.mark.django_db
class TestCreateReservationSlot:
@pytest.fixture
def user(self):
perms = Permission.objects.filter(
codename__in=["add_reservationslot", "view_reservationslot"]
)
return baker.make(User, user_permissions=list(perms))
def test_ok(self, client: Client, user: User):
client.force_login(user)
start = now() + timedelta(hours=2)
end = start + timedelta(hours=1)
room = baker.make(Room)
response = client.post(
reverse("reservation:make_reservation"),
{"room": room.id, "start_at": start, "end_at": end},
)
assert response.status_code == 200
assert response.headers.get("HX-Redirect", "") == reverse("reservation:main")
slot = ReservationSlot.objects.filter(room=room).last()
assert slot is not None
assert slot.start_at == start
assert slot.end_at == end
assert slot.author == user
def test_permissions_denied(self, client: Client):
client.force_login(baker.make(User))
start = now() + timedelta(hours=2)
end = start + timedelta(hours=1)
response = client.post(
reverse("reservation:make_reservation"),
{"room": baker.make(Room), "start_at": start, "end_at": end},
)
assert response.status_code == 403