Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ lib
.Python
tests/
.envrc
__pycache__
__pycache__
htmlcov/
.coverage

502 changes: 502 additions & 0 deletions .venv/Scripts/Activate.ps1

Large diffs are not rendered by default.

70 changes: 70 additions & 0 deletions .venv/Scripts/activate
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# This file must be used with "source bin/activate" *from bash*
# You cannot run it directly

deactivate () {
# reset old environment variables
if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
PATH="${_OLD_VIRTUAL_PATH:-}"
export PATH
unset _OLD_VIRTUAL_PATH
fi
if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
export PYTHONHOME
unset _OLD_VIRTUAL_PYTHONHOME
fi

# Call hash to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
hash -r 2> /dev/null

if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
PS1="${_OLD_VIRTUAL_PS1:-}"
export PS1
unset _OLD_VIRTUAL_PS1
fi

unset VIRTUAL_ENV
unset VIRTUAL_ENV_PROMPT
if [ ! "${1:-}" = "nondestructive" ] ; then
# Self destruct!
unset -f deactivate
fi
}

# unset irrelevant variables
deactivate nondestructive

# on Windows, a path can contain colons and backslashes and has to be converted:
if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then
# transform D:\path\to\venv to /d/path/to/venv on MSYS
# and to /cygdrive/d/path/to/venv on Cygwin
export VIRTUAL_ENV=$(cygpath "C:\Users\Lénovo P70\Desktop\projet 11\Python_Testing\.venv")
else
# use the path as-is
export VIRTUAL_ENV="C:\Users\Lénovo P70\Desktop\projet 11\Python_Testing\.venv"
fi

_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/Scripts:$PATH"
export PATH

# unset PYTHONHOME if set
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
# could use `if (set -u; : $PYTHONHOME) ;` in bash
if [ -n "${PYTHONHOME:-}" ] ; then
_OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
unset PYTHONHOME
fi

if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
_OLD_VIRTUAL_PS1="${PS1:-}"
PS1="(.venv) ${PS1:-}"
export PS1
VIRTUAL_ENV_PROMPT="(.venv) "
export VIRTUAL_ENV_PROMPT
fi

# Call hash to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
hash -r 2> /dev/null
34 changes: 34 additions & 0 deletions .venv/Scripts/activate.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
@echo off

rem This file is UTF-8 encoded, so we need to update the current code page while executing it
for /f "tokens=2 delims=:." %%a in ('"%SystemRoot%\System32\chcp.com"') do (
set _OLD_CODEPAGE=%%a
)
if defined _OLD_CODEPAGE (
"%SystemRoot%\System32\chcp.com" 65001 > nul
)

set VIRTUAL_ENV=C:\Users\Lénovo P70\Desktop\projet 11\Python_Testing\.venv

if not defined PROMPT set PROMPT=$P$G

if defined _OLD_VIRTUAL_PROMPT set PROMPT=%_OLD_VIRTUAL_PROMPT%
if defined _OLD_VIRTUAL_PYTHONHOME set PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%

set _OLD_VIRTUAL_PROMPT=%PROMPT%
set PROMPT=(.venv) %PROMPT%

if defined PYTHONHOME set _OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME%
set PYTHONHOME=

if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH%
if not defined _OLD_VIRTUAL_PATH set _OLD_VIRTUAL_PATH=%PATH%

set PATH=%VIRTUAL_ENV%\Scripts;%PATH%
set VIRTUAL_ENV_PROMPT=(.venv)

:END
if defined _OLD_CODEPAGE (
"%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul
set _OLD_CODEPAGE=
)
Binary file added .venv/Scripts/coverage-3.12.exe
Binary file not shown.
Binary file added .venv/Scripts/coverage.exe
Binary file not shown.
Binary file added .venv/Scripts/coverage3.exe
Binary file not shown.
22 changes: 22 additions & 0 deletions .venv/Scripts/deactivate.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
@echo off

if defined _OLD_VIRTUAL_PROMPT (
set "PROMPT=%_OLD_VIRTUAL_PROMPT%"
)
set _OLD_VIRTUAL_PROMPT=

if defined _OLD_VIRTUAL_PYTHONHOME (
set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%"
set _OLD_VIRTUAL_PYTHONHOME=
)

if defined _OLD_VIRTUAL_PATH (
set "PATH=%_OLD_VIRTUAL_PATH%"
)

set _OLD_VIRTUAL_PATH=

set VIRTUAL_ENV=
set VIRTUAL_ENV_PROMPT=

:END
Binary file added .venv/Scripts/flask.exe
Binary file not shown.
Binary file added .venv/Scripts/pip.exe
Binary file not shown.
Binary file added .venv/Scripts/pip3.12.exe
Binary file not shown.
Binary file added .venv/Scripts/pip3.exe
Binary file not shown.
Binary file added .venv/Scripts/py.test.exe
Binary file not shown.
Binary file added .venv/Scripts/pygmentize.exe
Binary file not shown.
Binary file added .venv/Scripts/pytest.exe
Binary file not shown.
Binary file added .venv/Scripts/python.exe
Binary file not shown.
Binary file added .venv/Scripts/pythonw.exe
Binary file not shown.
5 changes: 5 additions & 0 deletions .venv/pyvenv.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
home = C:\Users\Lénovo P70\AppData\Local\Programs\Python\Python312
include-system-site-packages = false
version = 3.12.6
executable = C:\Users\Lénovo P70\AppData\Local\Programs\Python\Python312\python.exe
command = C:\Users\Lénovo P70\AppData\Local\Programs\Python\Python312\python.exe -m venv C:\Users\Lénovo P70\Desktop\projet 11\Python_Testing\.venv
31 changes: 27 additions & 4 deletions server.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,15 @@ def index():

@app.route('/showSummary',methods=['POST'])
def showSummary():
club = [club for club in clubs if club['email'] == request.form['email']][0]
return render_template('welcome.html',club=club,competitions=competitions)
# Correction BUG 1 "email"
email = request.form.get('email')
club = next((club for club in clubs if club['email'] == email), None)

if club:
return render_template('welcome.html', club=club, competitions=competitions)
else:
flash("Sorry, that email wasn't found.")
return redirect(url_for('index'))


@app.route('/book/<competition>/<club>')
Expand All @@ -43,15 +50,31 @@ def book(competition,club):

@app.route('/purchasePlaces',methods=['POST'])
def purchasePlaces():
# Trouver la compétition et le club
competition = [c for c in competitions if c['name'] == request.form['competition']][0]
club = [c for c in clubs if c['name'] == request.form['club']][0]
placesRequired = int(request.form['places'])
competition['numberOfPlaces'] = int(competition['numberOfPlaces'])-placesRequired

competition_places = int(competition['numberOfPlaces'])
club_points = int(club['points'])

# Correction BUG 4: Limite de 12 places par club
if placesRequired > 12:
flash("Error: You cannot book more than 12 places per competition.")
return render_template('welcome.html', club=club, competitions=competitions), 400

# Correction BUG 3: Mise à jour des points du club
competition['numberOfPlaces'] = competition_places - placesRequired
club['points'] = club_points - placesRequired

flash('Great-booking complete!')
return render_template('welcome.html', club=club, competitions=competitions)


# TODO: Add route for points display
# FONCTIONNALITÉ BUG 2: Tableau d'affichage des points
@app.route('/pointsDisplay')
def pointsDisplay():
return render_template('points_display.html', clubs=clubs)


@app.route('/logout')
Expand Down
16 changes: 13 additions & 3 deletions templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,19 @@
<body>
<h1>Welcome to the GUDLFT Registration Portal!</h1>
Please enter your secretary email to continue:
<form action="showSummary" method="post">
<label for="email">Email:</label>
<input type="email" name="email" id=""/>

{% with messages = get_flashed_messages() %}
{% if messages %}
<ul>
{% for message in messages %}
<li style="color:red;">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
<form action="{{ url_for('showSummary') }}" method="post">
<label>Email:</label>
<input type="email" name="email" id="email" required />
<button type="submit">Enter</button>
</form>
</body>
Expand Down
27 changes: 27 additions & 0 deletions templates/points_display.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Clubs Points | GUDLFT</title>
</head>
<body>
<h1>Clubs Points</h1>
<a href="{{url_for('index')}}">Back to login</a>
<table>
<thead>
<tr>
<th>Club</th>
<th>Points</th>
</tr>
</thead>
<tbody>
{% for club in clubs %}
<tr>
<td>{{ club['name'] }}</td>
<td>{{ club['points'] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
73 changes: 73 additions & 0 deletions tests/integration/test_max_12_places_flow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import sys
import os
import pytest

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from server import app, clubs, competitions

@pytest.fixture
def client():
app.config['TESTING'] = True
with app.test_client() as client:
yield client


def test_max_12_places_integration_flow(client):
"""
Test d'intégration complet du flux:
Login -> Tentative réservation 15 places -> Vérification erreur
"""

test_club = clubs[0] # "Simply Lift"
test_competition = competitions[0] # "Spring Festival"

initial_places = int(test_competition['numberOfPlaces'])
initial_points = int(test_club['points'])

# LOGIN
login_response = client.post('/showSummary',
data={'email': test_club['email']},
follow_redirects=True)
assert login_response.status_code == 200

# TENTATIVE RÉSERVATION 15 PLACES
booking_data = {
'competition': test_competition['name'],
'club': test_club['name'],
'places': '15'
}

purchase_response = client.post('/purchasePlaces',
data=booking_data,
follow_redirects=True)

# DEBUG
print(f"Status: {purchase_response.status_code}")
print(f"Content contains 'Error': {b'Error' in purchase_response.data}")
print(f"Content contains 'Welcome': {b'Welcome' in purchase_response.data}")

# VÉRIFICATIONS PRINCIPALES
# 1. Le message d'erreur doit apparaître (plusieurs possibilités)
error_patterns = [
b"cannot book more than 12",
b"maximum 12",
b"limit of 12",
b"12 places",
b"Error:",
b"error:"
]

has_error = any(pattern in purchase_response.data for pattern in error_patterns)
assert has_error, "Aucun message d'erreur de limite détecté"

# 2. Les données ne doivent PAS être modifiées
current_points = int(test_club['points'])
current_places = int(test_competition['numberOfPlaces'])

assert current_points == initial_points, f"Points modifiés: {initial_points} -> {current_points}"
assert current_places == initial_places, f"Places modifiées: {initial_places} -> {current_places}"

# 3. Vérification que nous sommes sur la bonne page
# Au lieu de chercher le nom du club, cherchez des éléments de la page welcome
assert b'Welcome,' in purchase_response.data or b'Competitions:' in purchase_response.data
25 changes: 25 additions & 0 deletions tests/unit/test_email_login.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import pytest
from server import app

@pytest.fixture
def client():
app.config['TESTING'] = True
with app.test_client() as client:
yield client

def test_login_with_valid_email(client):
response = client.post('/showSummary',
data={'email': '[email protected]'},
follow_redirects=True)
assert response.status_code == 200
assert b'Welcome' in response.data

def test_login_with_invalid_email(client):
response = client.post('/showSummary',
data={'email': '[email protected]'},
follow_redirects=True)
assert response.status_code == 200
assert b"Sorry, that email wasn&#39;t found." in response.data
43 changes: 43 additions & 0 deletions tests/unit/test_max_12_places.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import sys
import os
import pytest

# Permet d'importer 'server' même si on lance le test depuis /tests
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from server import app, clubs, competitions


@pytest.fixture
def client():
app.config['TESTING'] = True
with app.test_client() as client:
yield client


def test_cannot_book_more_than_12_places(client):
# On prend le premier club et la première compétition
test_club = clubs[0]
test_competition = competitions[0]

# Sauvegarde de l'état initial
initial_places = int(test_competition['numberOfPlaces'])
initial_points = int(test_club['points'])

# Tentative de réservation de 13 places
response = client.post('/purchasePlaces', data={
'competition': test_competition['name'],
'club': test_club['name'],
'places': 13
}, follow_redirects=True)

# Statut HTTP attendu (par exemple 400 si tu l'as défini pour erreur)
assert response.status_code == 400, "Le serveur devrait retourner un code 400 en cas de dépassement de limite"

# Message d'erreur attendu dans la réponse
assert b"Error: You cannot book more than 12 places" in response.data


# Vérifier qu'aucune place n'a été déduite
assert int(test_competition['numberOfPlaces']) == initial_places
assert int(test_club['points']) == initial_points
Loading