mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
Compare commits
2 Commits
A64_TestsA
...
0.0.2
| Author | SHA1 | Date | |
|---|---|---|---|
| 616eaccd0e | |||
| b780e8b4ff |
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,5 +1,4 @@
|
||||
.venv/
|
||||
.env
|
||||
node_modules/
|
||||
hardcoded-strings-report.md
|
||||
backend.env
|
||||
hardcoded-strings-report.md
|
||||
@ -1 +1 @@
|
||||
#node scripts/prepare-commit-msg.js "$1" "$2"
|
||||
node scripts/prepare-commit-msg.js "$1" "$2"
|
||||
4
Back-End/.gitignore
vendored
4
Back-End/.gitignore
vendored
@ -4,6 +4,4 @@ documents
|
||||
data
|
||||
*.dmp
|
||||
staticfiles
|
||||
/*/Configuration/application*.json
|
||||
rapport_tests_back.json
|
||||
tests_automatiques.json
|
||||
/*/Configuration/application*.json
|
||||
@ -37,7 +37,7 @@
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<img src="{{URL_DJANGO}}/static/img/logo_min.svg" alt="Logo N3wt School" class="logo" />
|
||||
<img src="{{URL_DJANGO}}static/img/logo_min.svg" alt="Logo N3wt School" class="logo" />
|
||||
<h1>Confirmation de souscription</h1>
|
||||
</div>
|
||||
<div class="content">
|
||||
|
||||
@ -1 +1 @@
|
||||
__version__ = "0.0.3"
|
||||
__version__ = "0.0.2"
|
||||
|
||||
@ -70,7 +70,3 @@ xhtml2pdf==0.2.16
|
||||
channels==4.0.0
|
||||
channels-redis==4.1.0
|
||||
daphne==4.1.0
|
||||
pytest
|
||||
djangorestframework
|
||||
pytest-django
|
||||
pytest-json-report
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
"""
|
||||
Starter de tests automatiques pour valider tous les endpoints définis dans les fichiers urls.py du projet Django N3WT-SCHOOL.
|
||||
Chaque endpoint est testé pour la réponse HTTP attendue (200, 401, 403, 404, etc.).
|
||||
"""
|
||||
import pytest
|
||||
from django.urls import reverse, resolve
|
||||
from rest_framework.test import APIClient
|
||||
from django.conf import settings
|
||||
from django.urls import get_resolver
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestAllEndpoints:
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup(self):
|
||||
self.client = APIClient()
|
||||
|
||||
def get_all_url_patterns(self):
|
||||
resolver = get_resolver()
|
||||
patterns = resolver.url_patterns
|
||||
urls = []
|
||||
def extract(patterns, prefix=""):
|
||||
for p in patterns:
|
||||
if hasattr(p, 'url_patterns'):
|
||||
extract(p.url_patterns, prefix + str(p.pattern))
|
||||
else:
|
||||
urls.append(prefix + str(p.pattern))
|
||||
extract(patterns)
|
||||
return urls
|
||||
|
||||
def test_all_endpoints_anonymous(self):
|
||||
urls = self.get_all_url_patterns()
|
||||
for url in urls:
|
||||
if '<' in url: # skip dynamic urls for starter
|
||||
continue
|
||||
try:
|
||||
response = self.client.get(url)
|
||||
assert response.status_code in [200, 401, 403, 404]
|
||||
except Exception as e:
|
||||
print(f"Erreur sur {url}: {e}")
|
||||
@ -1,124 +0,0 @@
|
||||
"""
|
||||
Tests automatiques pour les endpoints Auth de l'API N3WT-SCHOOL.
|
||||
- Teste les endpoints GET, y compris dynamiques.
|
||||
- Teste l'authentification (login JWT) et l'accès aux endpoints protégés.
|
||||
- Vérifie la structure JSON des réponses principales.
|
||||
"""
|
||||
import pytest
|
||||
from django.urls import reverse
|
||||
from rest_framework.test import APIClient
|
||||
from Auth.models import Profile, ProfileRole
|
||||
from Establishment.models import Establishment
|
||||
from django.contrib.auth.hashers import make_password
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestAuthEndpoints:
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup(self, db):
|
||||
self.client = APIClient()
|
||||
# Création d'un établissement de test
|
||||
self.establishment = Establishment.objects.create(
|
||||
name="Etablissement Test",
|
||||
address="1 rue du test",
|
||||
total_capacity=100,
|
||||
establishment_type=[1],
|
||||
evaluation_frequency=1,
|
||||
licence_code="LIC123",
|
||||
is_active=True
|
||||
)
|
||||
# Création d'un utilisateur de test
|
||||
self.test_email = 'testuser@example.com'
|
||||
self.test_password = 'testpass123'
|
||||
self.profile = Profile.objects.create(
|
||||
email=self.test_email,
|
||||
username=self.test_email,
|
||||
password=make_password(self.test_password)
|
||||
)
|
||||
self.profile_role = ProfileRole.objects.create(
|
||||
profile=self.profile,
|
||||
role_type=1, # ADMIN
|
||||
establishment=self.establishment,
|
||||
is_active=True
|
||||
)
|
||||
|
||||
def test_csrf(self):
|
||||
response = self.client.get('/Auth/csrf')
|
||||
assert response.status_code == 200
|
||||
assert 'csrfToken' in response.json()
|
||||
|
||||
def test_login(self):
|
||||
response = self.client.post('/Auth/login', {
|
||||
'email': self.test_email,
|
||||
'password': self.test_password
|
||||
}, format='json')
|
||||
assert response.status_code in [200, 401]
|
||||
if response.status_code == 200:
|
||||
assert 'access' in response.json() or 'token' in response.json()
|
||||
|
||||
def test_profiles(self):
|
||||
# GET /Auth/profiles
|
||||
response = self.client.get(f'/Auth/profiles')
|
||||
assert response.status_code in [200, 401, 403]
|
||||
if response.status_code == 200:
|
||||
# Vérifie que le profil de test existe dans la liste
|
||||
emails = [p.get('email') for p in response.json() if isinstance(p, dict)]
|
||||
assert self.test_email in emails
|
||||
|
||||
def test_profiles_id(self):
|
||||
# GET /Auth/profiles/<id>
|
||||
response = self.client.get(f'/Auth/profiles/{self.profile.id}')
|
||||
assert response.status_code in [200, 401, 403, 404]
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
assert data.get('email') == self.test_email
|
||||
|
||||
def test_profile_roles(self):
|
||||
# GET /Auth/profileRoles avec paramètres requis
|
||||
params = {
|
||||
'establishment_id': self.establishment.id,
|
||||
'filter': 'school'
|
||||
}
|
||||
response = self.client.get('/Auth/profileRoles', params)
|
||||
assert response.status_code in [200, 401, 403, 400]
|
||||
if response.status_code == 200:
|
||||
results = response.json()
|
||||
# Adapter à la structure réelle de la réponse : clé 'profilesRoles'
|
||||
if isinstance(results, dict) and 'profilesRoles' in results:
|
||||
results = results['profilesRoles']
|
||||
found = any(
|
||||
r.get('profile') == self.profile.id and r.get('role_type') == 1
|
||||
for r in results if isinstance(r, dict)
|
||||
)
|
||||
assert found
|
||||
|
||||
def test_profile_roles_id(self):
|
||||
# GET /Auth/profileRoles/<id>
|
||||
response = self.client.get(f'/Auth/profileRoles/{self.profile_role.id}')
|
||||
assert response.status_code in [200, 401, 403, 404]
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
assert data.get('profile') == self.profile.id
|
||||
assert data.get('role_type') == 1
|
||||
|
||||
def test_reset_password(self):
|
||||
# POST /Auth/resetPassword/<code> (méthode attendue)
|
||||
response = self.client.post('/Auth/resetPassword/ABCDEF', {
|
||||
'password1': 'newpass123',
|
||||
'password2': 'newpass123'
|
||||
}, format='json')
|
||||
assert response.status_code in [200, 400, 404]
|
||||
# 400 attendu si le code est invalide ou expiré
|
||||
|
||||
def test_info_session(self):
|
||||
# GET /Auth/infoSession (protégé)
|
||||
login = self.client.post('/Auth/login', {
|
||||
'email': self.test_email,
|
||||
'password': self.test_password
|
||||
}, format='json')
|
||||
if login.status_code == 200 and ('access' in login.json() or 'token' in login.json()):
|
||||
token = login.json().get('access') or login.json().get('token')
|
||||
self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {token}')
|
||||
response = self.client.get('/Auth/infoSession')
|
||||
assert response.status_code in [200, 401, 403]
|
||||
else:
|
||||
pytest.skip('Impossible de s’authentifier pour tester infoSession')
|
||||
@ -2,13 +2,6 @@
|
||||
|
||||
Toutes les modifications notables apportées à ce projet seront documentées dans ce fichier.
|
||||
|
||||
### [0.0.3](https://git.v0id.ovh:5022/n3wt-innov/n3wt-school/compare/0.0.2...0.0.3) (2025-06-01)
|
||||
|
||||
|
||||
### Corrections de bugs
|
||||
|
||||
* Ajout d'un '/' en fin d'URL ([67cea2f](https://git.v0id.ovh:5022/n3wt-innov/n3wt-school/commit/67cea2f1c6edae8eed5e024c79b1e19d08788d4c))
|
||||
|
||||
### 0.0.2 (2025-06-01)
|
||||
|
||||
|
||||
@ -168,7 +161,7 @@ Toutes les modifications notables apportées à ce projet seront documentées da
|
||||
* ajout de credential include dans get CSRF ([c161fa7](https://git.v0id.ovh:5022/n3wt-innov/n3wt-school/commit/c161fa7e7568437ba501a565ad53192b9cb3b6f3))
|
||||
* Ajout de l'établissement dans la requête KPI récupérant les ([ada2a44](https://git.v0id.ovh:5022/n3wt-innov/n3wt-school/commit/ada2a44c3ec9ba45462bd7e78984dfa38008e231))
|
||||
* Ajout des niveaux scolaires dans le back [[#27](https://git.v0id.ovh:5022/n3wt-innov/n3wt-school/issues/27)] ([05542df](https://git.v0id.ovh:5022/n3wt-innov/n3wt-school/commit/05542dfc40649fd194ee551f0298f1535753f219))
|
||||
* ajout des urls prod et demo ([043d93d](https://git.v0id.ovh:5022/n3wt-innov/n3wt-school/commit/043d93dcc476e5eb3962fdbe0f6a81b937122647))
|
||||
* ajout des urls prod et demo ([b780e8b](https://git.v0id.ovh:5022/n3wt-innov/n3wt-school/commit/b780e8b4ff4b5e6bbbccf1c77a56136c0c4affcb)), closes [#1](https://git.v0id.ovh:5022/n3wt-innov/n3wt-school/issues/1) [#123](https://git.v0id.ovh:5022/n3wt-innov/n3wt-school/issues/123)
|
||||
* Ajout du % ou € en mode édition de réduction ([f2628bb](https://git.v0id.ovh:5022/n3wt-innov/n3wt-school/commit/f2628bb45a14da42d014e42b1521820ffeedfb33))
|
||||
* Ajout du controle sur le format des dates ([e538ac3](https://git.v0id.ovh:5022/n3wt-innov/n3wt-school/commit/e538ac3d56294d4e647a38d730168ea567c76f04))
|
||||
* Ajout du mode Visu ([e1c6073](https://git.v0id.ovh:5022/n3wt-innov/n3wt-school/commit/e1c607308c12cf75695e9d4593dc27ebe74e6a4f))
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "n3wt-school-front-end",
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.2",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
|
||||
TZ="Europe/Paris"
|
||||
TEST_MODE=true
|
||||
CSRF_COOKIE_SECURE=true
|
||||
CSRF_COOKIE_DOMAIN=".localhost"
|
||||
CORS_ALLOWED_ORIGINS=http://localhost:3000,http://127.0.0.1:3000,http://localhost:8080,http://127.0.0.1:8080
|
||||
CSRF_TRUSTED_ORIGINS=http://localhost:3000,http://127.0.0.1:3000,http://localhost:8080,http://127.0.0.1:8080
|
||||
BASE_URL=http://localhost:3000
|
||||
DEBUG=false
|
||||
EMAIL_HOST="smtp.hostinger.com"
|
||||
EMAIL_PORT="587"
|
||||
EMAIL_HOST_USER=""
|
||||
EMAIL_HOST_PASSWORD=''
|
||||
EMAIL_USE_TLS=true
|
||||
EMAIL_USE_SSL=false
|
||||
DB_NAME="school"
|
||||
DB_USER="postgres"
|
||||
DB_PASSWORD="postgres"
|
||||
DB_HOST="database"
|
||||
DB_PORT="5432"
|
||||
URL_DJANGO="http://localhost:8080"
|
||||
SECRET_KEY="<SIGNINGKEY>"
|
||||
@ -1,19 +1,15 @@
|
||||
services:
|
||||
redis:
|
||||
image: "redis:latest"
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
image: 'redis:latest'
|
||||
expose:
|
||||
- 6379
|
||||
environment:
|
||||
- TZ=Europe/Paris
|
||||
|
||||
database:
|
||||
image: "postgres:latest"
|
||||
image: 'postgres:latest'
|
||||
expose:
|
||||
- 5432
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
@ -24,13 +20,17 @@ services:
|
||||
image: git.v0id.ovh/n3wt-innov/n3wt-school/backend:latest
|
||||
ports:
|
||||
- 8080:8080
|
||||
env_file: "./conf/backend.env"
|
||||
environment:
|
||||
- TZ=Europe/Paris
|
||||
- TEST_MODE=True
|
||||
links:
|
||||
- "database:database"
|
||||
- "redis:redis"
|
||||
depends_on:
|
||||
- redis
|
||||
- database
|
||||
volumes:
|
||||
- ./conf/application.json:/Back-End/Subscriptions/Configuration/application.json
|
||||
command: python start.py
|
||||
|
||||
frontend:
|
||||
@ -40,8 +40,6 @@ services:
|
||||
environment:
|
||||
- TZ=Europe/Paris
|
||||
- NODE_ENV=production
|
||||
volumes:
|
||||
- ./conf/env:/app/.env
|
||||
volumes:
|
||||
postgres-data:
|
||||
redis-data:
|
||||
- NEXT_PUBLIC_API_URL=http://toto:8080
|
||||
depends_on:
|
||||
- backend
|
||||
@ -1,24 +1,55 @@
|
||||
services:
|
||||
redis:
|
||||
image: "redis:latest"
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
expose:
|
||||
- 6379
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
environment:
|
||||
- TZ=Europe/Paris
|
||||
|
||||
database:
|
||||
image: "postgres:latest"
|
||||
expose:
|
||||
- 5432
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
ports:
|
||||
- 5432:5432
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_DB: school
|
||||
TZ: Europe/Paris
|
||||
# docuseal_db:
|
||||
# image: postgres:latest
|
||||
# environment:
|
||||
# POSTGRES_USER: postgres
|
||||
# POSTGRES_PASSWORD: postgres
|
||||
# DOCUSEAL_DB_HOST: docuseal_db
|
||||
# POSTGRES_DB: docuseal
|
||||
# ports:
|
||||
# - 5433:5432 # port différent si besoin d'accès direct depuis l'hôte
|
||||
|
||||
# docuseal:
|
||||
# image: docuseal/docuseal:latest
|
||||
# container_name: docuseal_app
|
||||
# depends_on:
|
||||
# - docuseal_db
|
||||
# ports:
|
||||
# - "3001:3000"
|
||||
# environment:
|
||||
# DATABASE_URL: postgresql://postgres:postgres@docuseal_db:5432/docuseal
|
||||
# volumes:
|
||||
# - ./docuseal:/data/docuseal
|
||||
|
||||
# caddy:
|
||||
# image: caddy:2
|
||||
# container_name: caddy
|
||||
# restart: unless-stopped
|
||||
# ports:
|
||||
# - "4000:4443"
|
||||
# volumes:
|
||||
# - ./Caddyfile:/etc/caddy/Caddyfile
|
||||
# - caddy_data:/data
|
||||
# - caddy_config:/config
|
||||
# depends_on:
|
||||
# - docuseal
|
||||
|
||||
backend:
|
||||
build:
|
||||
@ -27,15 +58,54 @@ services:
|
||||
- 8080:8080
|
||||
volumes:
|
||||
- ./Back-End:/Back-End
|
||||
env_file: "./conf/backend.env"
|
||||
environment:
|
||||
- TZ=Europe/Paris
|
||||
- TEST_MODE=True
|
||||
- CORS_ALLOWED_ORIGINS=http://localhost:3000,http://127.0.0.1:3000,http://localhost:8080,http://127.0.0.1:8080
|
||||
- CSRF_TRUSTED_ORIGINS=http://localhost:3000,http://127.0.0.1:3000,http://localhost:8080,http://127.0.0.1:8080
|
||||
- BASE_URL=http://localhost:3000
|
||||
links:
|
||||
- "database:database"
|
||||
- "redis:redis"
|
||||
depends_on:
|
||||
- redis
|
||||
- database
|
||||
#- docuseal
|
||||
command: python start.py
|
||||
|
||||
# init_docuseal_users:
|
||||
# build:
|
||||
# context: .
|
||||
# dockerfile: Dockerfile
|
||||
# depends_on:
|
||||
# - docuseal
|
||||
# environment:
|
||||
# DOCUSEAL_DB_HOST: docuseal_db
|
||||
# POSTGRES_USER: postgres
|
||||
# POSTGRES_PASSWORD: postgres
|
||||
# USER_FIRST_NAME: n3wt
|
||||
# USER_LAST_NAME: school
|
||||
# USER_COMPANY: n3wt.innov
|
||||
# USER_EMAIL: n3wt.school@gmail.com
|
||||
# USER_PASSWORD: n3wt1234
|
||||
# volumes:
|
||||
# - ./initDocusealUsers.sh:/docker-entrypoint-initdb.d/initDocusealUsers.sh
|
||||
|
||||
# frontend:
|
||||
# build:
|
||||
# context: ./Front-End
|
||||
# args:
|
||||
# - BUILD_MODE=development
|
||||
# ports:
|
||||
# - 3000:3000
|
||||
# volumes:
|
||||
# - ./Front-End:/app
|
||||
# env_file:
|
||||
# - .env
|
||||
# environment:
|
||||
# - TZ=Europe/Paris
|
||||
# depends_on:
|
||||
# - backend
|
||||
volumes:
|
||||
postgres-data:
|
||||
redis-data:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
|
||||
@ -1,59 +0,0 @@
|
||||
# Documentation des tests automatiques
|
||||
|
||||
Ce document décrit la structure et l’utilisation du starter de tests automatiques pour valider tous les endpoints exposés par les fichiers `urls.py` des applications Django du Back-End.
|
||||
|
||||
## Objectif
|
||||
|
||||
- Vérifier automatiquement que chaque route définie dans le projet répond bien à une requête HTTP (statut attendu : 200, 401, 403, 404).
|
||||
- Permettre une validation rapide de la couverture des endpoints lors de chaque pipeline CI.
|
||||
|
||||
## Structure
|
||||
|
||||
- Le fichier principal est `Back-End/test_all_endpoints.py`.
|
||||
- Ce test utilise `pytest` et `pytest-django` pour parcourir toutes les routes du projet et effectuer une requête GET anonyme.
|
||||
- Les routes dynamiques (avec paramètres) sont ignorées dans ce starter.
|
||||
|
||||
## Exécution
|
||||
|
||||
1. Installer les dépendances si besoin :
|
||||
```sh
|
||||
pip install pytest pytest-django djangorestframework
|
||||
```
|
||||
2. Lancer les tests :
|
||||
```sh
|
||||
pytest Back-End/test_all_endpoints.py
|
||||
```
|
||||
|
||||
## Intégration CI
|
||||
|
||||
- Ajouter la commande de test dans votre pipeline CI (GitHub Actions, GitLab CI, Jenkins, etc.) :
|
||||
```sh
|
||||
pytest Back-End/test_all_endpoints.py
|
||||
```
|
||||
|
||||
## Personnalisation
|
||||
|
||||
- Pour tester les routes nécessitant une authentification ou des paramètres, compléter le test avec des cas spécifiques.
|
||||
- Pour chaque nouvelle route, le test s’exécutera automatiquement.
|
||||
|
||||
## Ajout
|
||||
|
||||
- Ajout d'un fichier de tests automatiques dédié à Auth (`test_auth_endpoints.py`) pour tester tous les endpoints Auth (GET, dynamiques, login JWT, accès protégé, structure JSON).
|
||||
- Les tests créent un utilisateur et un profilRole de test, réalisent un login, et vérifient les accès aux endpoints principaux, y compris les routes dynamiques et protégées.
|
||||
|
||||
## Utilisation
|
||||
|
||||
- Lancer les tests avec :
|
||||
```bash
|
||||
pytest --json-report --json-report-file=tests_automatiques.json
|
||||
```
|
||||
- Le rapport inclura les résultats détaillés pour chaque endpoint Auth.
|
||||
|
||||
## Extension
|
||||
|
||||
- Étendre sur le même modèle pour les autres applications (School, Subscriptions, etc.)
|
||||
- Ajouter des tests POST/PUT/DELETE et des cas d’erreur/permissions.
|
||||
|
||||
---
|
||||
|
||||
Pour toute question ou évolution, se référer au ticket associé.
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "n3wt-school",
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.2",
|
||||
"scripts": {
|
||||
"prepare": "husky",
|
||||
"release": "standard-version",
|
||||
|
||||
Reference in New Issue
Block a user