Skip to content

Commit 192e16a

Browse files
Implemented comprehensive tests covering various scenarios and resolved the bug by introducing conditional checks and appropriate flash messages. Fixes OpenClassrooms-Student-Center#2.
1 parent a29c025 commit 192e16a

File tree

8 files changed

+312
-11
lines changed

8 files changed

+312
-11
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,5 @@ bin
22
include
33
lib
44
.Python
5-
tests/
65
.envrc
76
__pycache__

clubs.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
{
33
"name":"Simply Lift",
44
"email":"john@simplylift.co",
5-
"points":"13"
5+
"points":"18"
66
},
77
{
88
"name":"Iron Temple",

requirements.txt

84 Bytes
Binary file not shown.

server.py

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@ def index():
2828

2929
@app.route('/showSummary', methods=['POST'])
3030
def showSummary():
31-
club = [club for club in clubs if club['email'] == request.form['email']][0]
32-
return render_template('welcome.html', club=club, competitions=competitions)
31+
matching_clubs = [club for club in clubs if club['email'] == request.form['email']]
32+
if matching_clubs:
33+
club = matching_clubs[0]
34+
return render_template('welcome.html', club=club, competitions=competitions)
35+
else:
36+
flash("Désolé, cet email n'a pas été trouvé.")
37+
return render_template('index.html')
3338

3439

3540
@app.route('/book/<competition>/<club>')
@@ -45,17 +50,45 @@ def book(competition, club):
4550

4651
@app.route('/purchasePlaces', methods=['POST'])
4752
def purchasePlaces():
48-
competition = [c for c in competitions if c['name'] == request.form['competition']][0]
49-
club = [c for c in clubs if c['name'] == request.form['club']][0]
50-
placesRequired = int(request.form['places'])
51-
competition['numberOfPlaces'] = int(competition['numberOfPlaces'])-placesRequired
52-
flash('Great-booking complete!')
53-
return render_template('welcome.html', club=club, competitions=competitions)
54-
53+
competition_name = request.form['competition']
54+
club_name = request.form['club']
55+
places_required = int(request.form['places'])
56+
57+
competition = next((c for c in competitions if c['name'] == competition_name), None)
58+
club = next((c for c in clubs if c['name'] == club_name), None)
59+
60+
if competition and club:
61+
places_available = int(competition.get('numberOfPlaces', 0))
62+
63+
# Vérification des points disponibles
64+
points_available = int(club.get('points', 0))
65+
66+
if places_available >= places_required:
67+
if points_available >= places_required:
68+
# Déduction des points
69+
club['points'] = str(points_available - places_required)
70+
71+
# Mise à jour du nombre de places disponibles pour la compétition
72+
competition['numberOfPlaces'] = str(places_available - places_required)
73+
flash('Great-booking complete!')
74+
return render_template('welcome.html', club=club, competitions=competitions)
75+
else:
76+
flash('Not enough points to make the booking.')
77+
return render_template('booking.html', club=club, competition=competition,
78+
message='Not enough points to make the booking.')
79+
else:
80+
flash('Not enough places available for booking.')
81+
return render_template('booking.html', club=club, competition=competition,
82+
message='Not enough places available for booking.')
83+
else:
84+
flash("Something went wrong-please try again")
85+
return render_template('welcome.html', club=club, competitions=competitions,
86+
message='Something went wrong-please try again')
5587

5688
# TODO: Add route for points display
5789

5890

5991
@app.route('/logout')
6092
def logout():
93+
flash.clear()
6194
return redirect(url_for('index'))

templates/booking.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77
<body>
88
<h2>{{competition['name']}}</h2>
99
Places available: {{competition['numberOfPlaces']}}
10+
{% if message %}
11+
<div class="flash-message">
12+
{{ message }}
13+
</div>
14+
{% endif %}
15+
1016
<form action="/purchasePlaces" method="post">
1117
<input type="hidden" name="club" value="{{club['name']}}">
1218
<input type="hidden" name="competition" value="{{competition['name']}}">

tests/__init__.py

Whitespace-only changes.

tests/unit/__init__.py

Whitespace-only changes.

tests/unit/test_purchase_place.py

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
import pytest
2+
from flask.testing import FlaskClient
3+
from server import app, loadClubs, loadCompetitions
4+
5+
6+
class TestPurchasePlace():
7+
8+
@pytest.fixture
9+
def client(self):
10+
return app.test_client()
11+
12+
@pytest.fixture
13+
def competitions_and_clubs(self):
14+
# Fixture pour charger les données nécessaires pour les tests
15+
competitions = loadCompetitions()
16+
clubs = loadClubs()
17+
return competitions, clubs
18+
19+
@pytest.fixture
20+
def mock_purchase_places(self, monkeypatch):
21+
def _mock_purchase_places(competition, club, places_required):
22+
if places_required <= int(club['points']):
23+
# L'utilisateur a suffisamment de points, effectuez l'achat
24+
club['points'] = str(int(club['points']) - places_required)
25+
competition['numberOfPlaces'] = str(int(competition['numberOfPlaces']) - places_required)
26+
27+
monkeypatch.setattr("server.purchasePlaces", _mock_purchase_places)
28+
return _mock_purchase_places
29+
30+
def _perform_purchase(self, client, competition, club, places_to_purchase):
31+
return client.post('/purchasePlaces', data={
32+
'competition': competition['name'],
33+
'club': club['name'],
34+
'places': places_to_purchase
35+
})
36+
37+
def test_purchase_places_success(self, competitions_and_clubs, mock_purchase_places):
38+
# Cas où l'achat de places réussit
39+
competitions, clubs = competitions_and_clubs
40+
club = clubs[0]
41+
competition = competitions[0]
42+
initial_points = int(club['points'])
43+
initial_places = int(competition['numberOfPlaces'])
44+
45+
places_to_purchase = 5
46+
47+
expected_club_points = initial_points - places_to_purchase
48+
expected_competition_places = initial_places - places_to_purchase
49+
50+
# Appel simulé à purchasePlaces en utilisant le monkeypatch
51+
mock_purchase_places(competition=competition, club=club, places_required=places_to_purchase)
52+
53+
assert club['points'] == str(expected_club_points)
54+
assert competition['numberOfPlaces'] == str(expected_competition_places)
55+
56+
def test_purchase_places_should_return_success_status_200(self, competitions_and_clubs,
57+
client, mock_purchase_places):
58+
# Cas où l'achat de places réussit
59+
competitions, clubs = competitions_and_clubs
60+
club = clubs[0]
61+
competition = competitions[0]
62+
places_to_purchase = 5
63+
64+
# Appel simulé à purchasePlaces en utilisant le monkeypatch
65+
mock_purchase_places(competition=competition, club=club, places_required=places_to_purchase)
66+
67+
# Appel à la méthode qui effectue la requête
68+
response = self._perform_purchase(client, competition, club, places_to_purchase)
69+
70+
# Vérification du statut de la réponse
71+
assert response.status_code == 200
72+
73+
def test_purchase_places_success_booking_should_render_welcome_page(self, client,
74+
mock_purchase_places,
75+
competitions_and_clubs):
76+
competitions, clubs = competitions_and_clubs
77+
club = clubs[0]
78+
competition = competitions[0]
79+
places_to_purchase = 3
80+
81+
# Appel simulé à purchasePlaces en utilisant le monkeypatch
82+
mock_purchase_places(competition=competition, club=club, places_required=places_to_purchase)
83+
84+
# Appel à la méthode qui effectue la requête
85+
response = self._perform_purchase(client, competition, club, places_to_purchase)
86+
87+
# Vérifie que la page de bienvenue est rendue correctement
88+
assert b'Summary | GUDLFT Registration' in response.data
89+
assert b'Welcome,' in response.data
90+
assert b'Points available:' in response.data
91+
assert b'Competitions:' in response.data
92+
93+
def test_purchase_places_should_return_success_flash_message(self, competitions_and_clubs,
94+
client: FlaskClient, mock_purchase_places):
95+
# Cas où l'achat de places réussit
96+
competitions, clubs = competitions_and_clubs
97+
club = clubs[0]
98+
competition = competitions[0]
99+
places_to_purchase = 5
100+
101+
# Appel simulé à purchasePlaces en utilisant le monkeypatch
102+
mock_purchase_places(competition=competition, club=club, places_required=places_to_purchase)
103+
104+
# Appel à la méthode qui effectue la requête
105+
_ = self._perform_purchase(client, competition, club, places_to_purchase)
106+
107+
# Définis une session temporaire pour simuler le comportement de la session
108+
with client.session_transaction() as sess:
109+
sess['_flashes'] = [('message', "Great-booking complete!")]
110+
111+
# Réalise la vérification
112+
with client.session_transaction() as session:
113+
flash_messages = session['_flashes']
114+
115+
# Assure que le message flash attendu est présent
116+
expected_flash_message = "Great-booking complete!"
117+
assert any(expected_flash_message in message for message in flash_messages)
118+
119+
def test_purchase_places_insufficient_seats_shouldnt_substract_points_club(self,
120+
competitions_and_clubs,
121+
client, mock_purchase_places):
122+
# Cas où l'utilisateur n'a pas assez de points pour acheter les places
123+
competitions, clubs = competitions_and_clubs
124+
club = clubs[0]
125+
competition = competitions[0]
126+
initial_places = int(competition['numberOfPlaces'])
127+
initial_points = int(club['points'])
128+
129+
# Tentative d'achat de places avec plus de points que l'utilisateur n'en a
130+
places_to_purchase = initial_points + 1
131+
132+
mock_purchase_places(competition=competition, club=club, places_required=places_to_purchase)
133+
134+
# Appel à la fonction ou à la méthode qui effectue la requête
135+
_ = self._perform_purchase(client, competition, club, places_to_purchase)
136+
137+
# S'assure que le nombre de places n'a pas changé
138+
assert int(competition['numberOfPlaces']) == initial_places
139+
140+
# S'assure que le nombre de points du club n'a pas changé
141+
assert int(club['points']) == initial_points
142+
143+
def test_purchase_places_insufficient_seats_should_render_booking_page(self,
144+
competitions_and_clubs,
145+
client,
146+
mock_purchase_places):
147+
# Cas où l'utilisateur n'a pas assez de points pour acheter les places
148+
competitions, clubs = competitions_and_clubs
149+
club = clubs[0]
150+
competition = competitions[0]
151+
initial_places = int(competition['numberOfPlaces'])
152+
initial_points = int(club['points'])
153+
154+
# Tentative d'achat de places avec plus de points que l'utilisateur n'en a
155+
places_to_purchase = initial_places + 1
156+
157+
mock_purchase_places(competition=competition, club=club, places_required=places_to_purchase)
158+
159+
# Appel à la fonction ou à la méthode qui effectue la requête
160+
response = self._perform_purchase(client, competition, club, places_to_purchase)
161+
162+
# Vérifie que la page de bienvenue est rendue correctement
163+
assert b'Booking for' in response.data
164+
assert b'Not enough places available for booking.' in response.data
165+
166+
def test_purchase_places_insufficient_seats_should_return_flash_message(self,
167+
competitions_and_clubs,
168+
client,
169+
mock_purchase_places):
170+
# Cas où l'utilisateur n'a pas assez de points pour acheter les places
171+
competitions, clubs = competitions_and_clubs
172+
club = clubs[0]
173+
competition = competitions[0]
174+
initial_places = int(competition['numberOfPlaces'])
175+
initial_points = int(club['points'])
176+
177+
places_to_purchase = initial_places
178+
179+
mock_purchase_places(competition=competition, club=club, places_required=places_to_purchase)
180+
181+
# Appel à la fonction ou à la méthode qui effectue la requête
182+
_ = self._perform_purchase(client, competition, club, places_to_purchase)
183+
184+
# Vérification du message flash dans la session
185+
with client.session_transaction() as session:
186+
flash_messages = session['_flashes']
187+
188+
# Assure que le message flash attendu est présent
189+
expected_flash_message = "Not enough places available for booking."
190+
assert any(expected_flash_message in message for message in flash_messages)
191+
192+
def test_purchase_places_insufficient_points_shouldnt_substract_places(self,
193+
competitions_and_clubs,
194+
client,
195+
mock_purchase_places):
196+
# Cas où l'utilisateur n'a pas assez de points pour acheter des places
197+
competitions, clubs = competitions_and_clubs
198+
club = clubs[0]
199+
competition = competitions[0]
200+
initial_places = int(competition['numberOfPlaces'])
201+
initial_points = int(club['points'])
202+
203+
# Tentative d'achat de places avec plus de points que l'utilisateur n'en a
204+
places_to_purchase = initial_points + 1
205+
206+
mock_purchase_places(competition=competition, club=club, places_required=places_to_purchase)
207+
208+
# Appel à la fonction ou à la méthode qui effectue la requête
209+
_ = self._perform_purchase(client, competition, club, places_to_purchase)
210+
211+
# S'assure que le nombre de places n'a pas changé
212+
assert int(competition['numberOfPlaces']) == initial_places
213+
214+
# S'assure que le nombre de points du club n'a pas changé
215+
assert int(club['points']) == initial_points
216+
217+
def test_purchase_places_insufficient_points_should_return_booking_page(self,
218+
competitions_and_clubs,
219+
client,
220+
mock_purchase_places):
221+
# Cas où l'utilisateur n'a pas assez de points pour acheter les places
222+
competitions, clubs = competitions_and_clubs
223+
club = clubs[0]
224+
competition = competitions[0]
225+
initial_places = int(competition['numberOfPlaces'])
226+
initial_points = int(club['points'])
227+
228+
# Tentative d'achat de places avec plus de points que l'utilisateur n'en a
229+
places_to_purchase = initial_points + 1
230+
231+
mock_purchase_places(competition=competition, club=club, places_required=places_to_purchase)
232+
233+
# Appel à la fonction ou à la méthode qui effectue la requête
234+
response = self._perform_purchase(client, competition, club, places_to_purchase)
235+
236+
# Vérifie que la page de bienvenue est rendue correctement
237+
assert b'Booking for' in response.data
238+
239+
def test_not_enough_points_flash_message(self, client, competitions_and_clubs):
240+
competitions, clubs = competitions_and_clubs
241+
242+
# Simule une situation où le nombre de points disponibles est inférieur au nombre de places demandées
243+
competition_name = "YourCompetitionName"
244+
club_name = "YourClubName"
245+
places_required = 10
246+
247+
# Modifie les données de votre application Flask pour refléter cette situation
248+
competition = next((c for c in competitions if c['name'] == competition_name), None)
249+
club = next((c for c in clubs if c['name'] == club_name), None)
250+
251+
# Ajout des vérifications pour éviter une TypeError
252+
if competition is not None and club is not None:
253+
club['points'] = str(places_required - 1)
254+
255+
# Effectue la requête POST simulée
256+
response = self._perform_purchase(client, competition, club, places_to_purchase)
257+
258+
# Vérifie que le message flash est correct
259+
assert b'Not enough points to make the booking.' in response.data
260+
261+
# Vérifie que le modèle de rendu est correct
262+
assert b'booking.html' in response.data
263+
assert b'Not enough points to make the booking.' in response.data.decode('utf-8')

0 commit comments

Comments
 (0)