ajoute le portail Laravel : connexion prof/élève, session unique, gestion de classe, salle d'attente
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
aa31b6112f
commit
30e14b1c54
191 changed files with 25324 additions and 0 deletions
42
portail/tests/Feature/ConnexionEleveTest.php
Normal file
42
portail/tests/Feature/ConnexionEleveTest.php
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Eleve;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
test("un élève se connecte avec son identifiant et son code secret, et voit son tableau de bord", function () {
|
||||
$eleve = Eleve::factory()->create([
|
||||
'prenom' => 'Léa',
|
||||
'identifiant' => 'lea.m',
|
||||
'code_secret' => Hash::make('ABC123'),
|
||||
]);
|
||||
|
||||
$this->post(route('connexion.eleve'), [
|
||||
'identifiant' => 'lea.m',
|
||||
'code' => 'ABC123',
|
||||
])->assertRedirect(route('eleve'));
|
||||
|
||||
$this->assertAuthenticatedAs($eleve, 'eleve');
|
||||
|
||||
$this->get(route('eleve'))
|
||||
->assertOk()
|
||||
->assertSee('Salut Léa')
|
||||
->assertSee($eleve->classe->nom);
|
||||
});
|
||||
|
||||
test('un mauvais code secret refuse la connexion élève', function () {
|
||||
$eleve = Eleve::factory()->create([
|
||||
'identifiant' => 'lea.m',
|
||||
'code_secret' => Hash::make('ABC123'),
|
||||
]);
|
||||
|
||||
$this->post(route('connexion.eleve'), [
|
||||
'identifiant' => 'lea.m',
|
||||
'code' => 'FAUXCODE',
|
||||
])->assertSessionHasErrors('identifiant');
|
||||
|
||||
$this->assertGuest('eleve');
|
||||
});
|
||||
|
||||
test('un élève non connecté est renvoyé vers la connexion', function () {
|
||||
$this->get(route('eleve'))->assertRedirect(route('login'));
|
||||
});
|
||||
33
portail/tests/Feature/ConnexionProfTest.php
Normal file
33
portail/tests/Feature/ConnexionProfTest.php
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
test('un prof se connecte avec son e-mail et son mot de passe', function () {
|
||||
$prof = User::factory()->create(['password' => Hash::make('mot-de-passe-prof')]);
|
||||
|
||||
$this->post(route('connexion.prof'), [
|
||||
'email' => $prof->email,
|
||||
'password' => 'mot-de-passe-prof',
|
||||
])->assertRedirect(route('mes-classes.index'));
|
||||
|
||||
$this->assertAuthenticatedAs($prof, 'web');
|
||||
});
|
||||
|
||||
test('un mauvais mot de passe refuse la connexion', function () {
|
||||
$prof = User::factory()->create(['password' => Hash::make('mot-de-passe-prof')]);
|
||||
|
||||
$this->post(route('connexion.prof'), [
|
||||
'email' => $prof->email,
|
||||
'password' => 'mauvais-mot-de-passe',
|
||||
])->assertSessionHasErrors('email');
|
||||
|
||||
$this->assertGuest('web');
|
||||
});
|
||||
|
||||
test('la page de connexion affiche le formulaire prof et élève', function () {
|
||||
$this->get(route('login'))
|
||||
->assertOk()
|
||||
->assertSee('Je suis élève')
|
||||
->assertSee('Je suis enseignant');
|
||||
});
|
||||
67
portail/tests/Feature/CreationClasseTest.php
Normal file
67
portail/tests/Feature/CreationClasseTest.php
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Classe;
|
||||
use App\Models\Etablissement;
|
||||
use App\Models\User;
|
||||
|
||||
test('un prof crée son compte, son établissement et sa première classe en une fois', function () {
|
||||
$reponse = $this->post(route('inscription.store'), [
|
||||
'prenom' => 'Chloé',
|
||||
'nom' => 'Roux',
|
||||
'email' => 'chloe.roux@exemple.test',
|
||||
'password' => 'mot-de-passe-sur',
|
||||
'password_confirmation' => 'mot-de-passe-sur',
|
||||
'etablissement_nom_liste' => 'autre',
|
||||
'etablissement_nom' => 'Lycée Marie-Curie',
|
||||
'etablissement_ville' => 'Nancy',
|
||||
'etablissement_uai' => '',
|
||||
'formation' => 'BTS SIO SISR',
|
||||
'classe' => '2nde NSI · Groupe B',
|
||||
]);
|
||||
|
||||
$etablissement = Etablissement::where('nom', 'Lycée Marie-Curie')->first();
|
||||
expect($etablissement)->not->toBeNull();
|
||||
|
||||
$prof = User::where('email', 'chloe.roux@exemple.test')->first();
|
||||
expect($prof)->not->toBeNull();
|
||||
expect($prof->etablissement_id)->toBe($etablissement->id);
|
||||
|
||||
$classe = Classe::where('nom', '2nde NSI · Groupe B')->first();
|
||||
expect($classe)->not->toBeNull();
|
||||
expect($classe->user_id)->toBe($prof->id);
|
||||
expect($classe->code_classe)->toHaveLength(6);
|
||||
|
||||
$reponse->assertRedirect(route('mes-classes.show', $classe));
|
||||
$this->assertAuthenticatedAs($prof, 'web');
|
||||
});
|
||||
|
||||
test('une classe existante peut réutiliser le même établissement', function () {
|
||||
$this->post(route('inscription.store'), [
|
||||
'prenom' => 'A', 'nom' => 'B', 'email' => 'a@exemple.test',
|
||||
'password' => 'mot-de-passe-sur', 'password_confirmation' => 'mot-de-passe-sur',
|
||||
'etablissement_nom_liste' => 'Lycée Jean-Jaurès · Montreuil',
|
||||
'formation' => 'BTS SIO SISR', 'classe' => 'Classe 1',
|
||||
]);
|
||||
|
||||
$this->post(route('inscription.store'), [
|
||||
'prenom' => 'C', 'nom' => 'D', 'email' => 'c@exemple.test',
|
||||
'password' => 'mot-de-passe-sur', 'password_confirmation' => 'mot-de-passe-sur',
|
||||
'etablissement_nom_liste' => 'Lycée Jean-Jaurès · Montreuil',
|
||||
'formation' => 'BTS SIO SISR', 'classe' => 'Classe 2',
|
||||
]);
|
||||
|
||||
expect(Etablissement::where('nom', 'Lycée Jean-Jaurès · Montreuil')->count())->toBe(1);
|
||||
expect(Classe::count())->toBe(2);
|
||||
});
|
||||
|
||||
test("l'inscription échoue si les mots de passe ne correspondent pas", function () {
|
||||
$this->post(route('inscription.store'), [
|
||||
'prenom' => 'Chloé', 'nom' => 'Roux', 'email' => 'chloe@exemple.test',
|
||||
'password' => 'mot-de-passe-sur', 'password_confirmation' => 'autre-chose',
|
||||
'etablissement_nom_liste' => 'autre',
|
||||
'etablissement_nom' => 'Lycée Marie-Curie', 'etablissement_ville' => 'Nancy',
|
||||
'formation' => 'BTS SIO SISR', 'classe' => '2nde NSI',
|
||||
])->assertSessionHasErrors('password');
|
||||
|
||||
expect(User::count())->toBe(0);
|
||||
});
|
||||
60
portail/tests/Feature/SessionUniqueTest.php
Normal file
60
portail/tests/Feature/SessionUniqueTest.php
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Eleve;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
test('une nouvelle connexion prof coupe la précédente', function () {
|
||||
$prof = User::factory()->create(['password' => Hash::make('mot-de-passe-prof')]);
|
||||
|
||||
// "Navigateur A" se connecte.
|
||||
$this->post(route('connexion.prof'), [
|
||||
'email' => $prof->email,
|
||||
'password' => 'mot-de-passe-prof',
|
||||
]);
|
||||
$jetonA = $prof->refresh()->jeton_session_actif;
|
||||
expect($jetonA)->not->toBeNull();
|
||||
|
||||
// "Navigateur B" se connecte avec le même compte.
|
||||
$this->post(route('connexion.prof'), [
|
||||
'email' => $prof->email,
|
||||
'password' => 'mot-de-passe-prof',
|
||||
])->assertSessionHas('session_precedente_fermee', true);
|
||||
$jetonB = $prof->refresh()->jeton_session_actif;
|
||||
expect($jetonB)->not->toBe($jetonA);
|
||||
|
||||
// "Navigateur A", qui ne sait pas qu'il a été coupé, retente une page protégée.
|
||||
$this->withSession(['jeton_session_web' => $jetonA])
|
||||
->actingAs($prof, 'web')
|
||||
->get(route('mes-classes.index'))
|
||||
->assertRedirect(route('login'))
|
||||
->assertSessionHas('session_coupee');
|
||||
|
||||
$this->assertGuest('web');
|
||||
|
||||
// "Navigateur B" continue de fonctionner normalement.
|
||||
$this->withSession(['jeton_session_web' => $jetonB])
|
||||
->actingAs($prof, 'web')
|
||||
->get(route('mes-classes.index'))
|
||||
->assertOk();
|
||||
});
|
||||
|
||||
test('une nouvelle connexion élève coupe la précédente', function () {
|
||||
$eleve = Eleve::factory()->create([
|
||||
'identifiant' => 'lea.m',
|
||||
'code_secret' => Hash::make('ABC123'),
|
||||
]);
|
||||
|
||||
$this->post(route('connexion.eleve'), ['identifiant' => 'lea.m', 'code' => 'ABC123']);
|
||||
$jetonA = $eleve->refresh()->jeton_session_actif;
|
||||
|
||||
$this->post(route('connexion.eleve'), ['identifiant' => 'lea.m', 'code' => 'ABC123']);
|
||||
$jetonB = $eleve->refresh()->jeton_session_actif;
|
||||
expect($jetonB)->not->toBe($jetonA);
|
||||
|
||||
$this->withSession(['jeton_session_eleve' => $jetonA])
|
||||
->actingAs($eleve, 'eleve')
|
||||
->get(route('eleve'))
|
||||
->assertRedirect(route('login'))
|
||||
->assertSessionHas('session_coupee');
|
||||
});
|
||||
50
portail/tests/Pest.php
Normal file
50
portail/tests/Pest.php
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Test Case
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The closure you provide to your test functions is always bound to a specific PHPUnit test
|
||||
| case class. By default, that class is "PHPUnit\Framework\TestCase". Of course, you may
|
||||
| need to change it using the "pest()" function to bind different classes or traits.
|
||||
|
|
||||
*/
|
||||
|
||||
pest()->extend(TestCase::class)
|
||||
->use(RefreshDatabase::class)
|
||||
->in('Feature');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Expectations
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When you're writing tests, you often need to check that values meet certain conditions. The
|
||||
| "expect()" function gives you access to a set of "expectations" methods that you can use
|
||||
| to assert different things. Of course, you may extend the Expectation API at any time.
|
||||
|
|
||||
*/
|
||||
|
||||
expect()->extend('toBeOne', function () {
|
||||
return $this->toBe(1);
|
||||
});
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Functions
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| While Pest is very powerful out-of-the-box, you may have some testing code specific to your
|
||||
| project that you don't want to repeat in every file. Here you can also expose helpers as
|
||||
| global functions to help you to reduce the number of lines of code in your test files.
|
||||
|
|
||||
*/
|
||||
|
||||
function something()
|
||||
{
|
||||
// ..
|
||||
}
|
||||
10
portail/tests/TestCase.php
Normal file
10
portail/tests/TestCase.php
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace Tests;
|
||||
|
||||
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
|
||||
|
||||
abstract class TestCase extends BaseTestCase
|
||||
{
|
||||
//
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue