L'élève saisit le code de classe et son prénom, le prof accepte, l'élève voit une seule fois son identifiant et son code. Aucun e-mail. Le prof peut aussi régénérer les fiches de plusieurs élèves d'un coup. Procédure pour prouver la copie de la clé des sauvegardes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
98 lines
5 KiB
PHP
98 lines
5 KiB
PHP
<?php
|
||
|
||
use App\Models\Classe;
|
||
use App\Models\DemandeInscription;
|
||
use App\Models\Eleve;
|
||
use App\Models\User;
|
||
use Illuminate\Support\Facades\Auth;
|
||
|
||
function commeProf($test, User $prof)
|
||
{
|
||
return $test->withSession(['jeton_session_web' => $prof->demarreNouvelleSession()])->actingAs($prof, 'web');
|
||
}
|
||
|
||
test('un élève rejoint la classe avec son code ; le prof accepte ; l’élève voit son code une seule fois et peut se reconnecter', function () {
|
||
$classe = Classe::factory()->create();
|
||
|
||
$this->post(route('rejoindre.demander'), ['code' => strtolower($classe->code_classe), 'prenom' => 'Inès', 'nom' => 'Martin'])
|
||
->assertRedirect(route('rejoindre.attente'));
|
||
$this->get(route('rejoindre.attente'))->assertOk()->assertSee('Demande envoyée, Inès');
|
||
$this->getJson(route('rejoindre.etat'))->assertJson(['statut' => 'en_attente']);
|
||
|
||
$demande = DemandeInscription::sole();
|
||
commeProf($this, $classe->prof)->get(route('mes-classes.show', $classe))->assertSee('Inès Martin')->assertSee($classe->code_classe);
|
||
commeProf($this, $classe->prof)->post(route('mes-classes.demandes.accepter', [$classe, $demande]))->assertRedirect();
|
||
Auth::guard('web')->logout();
|
||
|
||
$this->getJson(route('rejoindre.etat'))->assertJson(['statut' => 'acceptee']);
|
||
$page = $this->get(route('rejoindre.bienvenue'))->assertOk()->assertSee('ines.m');
|
||
preg_match('#Code secret<br><span[^>]*>([A-Z0-9]{6})</span>#', $page->getContent(), $m);
|
||
$code = $m[1];
|
||
|
||
expect(DemandeInscription::count())->toBe(0)
|
||
->and(Auth::guard('eleve')->user()?->identifiant)->toBe('ines.m');
|
||
|
||
// Une seule fois : un second affichage renvoie vers l'espace élève.
|
||
$this->get(route('rejoindre.bienvenue'))->assertRedirect(route('eleve'));
|
||
|
||
Auth::guard('eleve')->logout();
|
||
expect(Auth::guard('eleve')->attempt(['identifiant' => 'ines.m', 'password' => $code]))->toBeTrue();
|
||
});
|
||
|
||
test('un code faux ou une classe archivée sont refusés', function () {
|
||
$this->post(route('rejoindre.demander'), ['code' => 'ZZZZZZ', 'prenom' => 'Léo'])->assertSessionHasErrors('code');
|
||
|
||
$archivee = Classe::factory()->create();
|
||
$archivee->forceFill(['archivee_a' => now()])->save();
|
||
$this->post(route('rejoindre.demander'), ['code' => $archivee->code_classe, 'prenom' => 'Léo'])->assertSessionHasErrors('code');
|
||
|
||
expect(DemandeInscription::count())->toBe(0);
|
||
});
|
||
|
||
test('une demande refusée l’annonce à l’élève et disparaît', function () {
|
||
$classe = Classe::factory()->create();
|
||
$this->post(route('rejoindre.demander'), ['code' => $classe->code_classe, 'prenom' => 'Léo']);
|
||
|
||
commeProf($this, $classe->prof)->post(route('mes-classes.demandes.refuser', [$classe, DemandeInscription::sole()]));
|
||
Auth::guard('web')->logout();
|
||
|
||
$this->get(route('rejoindre.attente'))->assertOk()->assertSee('pas accepté');
|
||
expect(DemandeInscription::count())->toBe(0)->and(Eleve::count())->toBe(0);
|
||
});
|
||
|
||
test('seul le navigateur de l’élève voit son code, et seul le prof de la classe peut accepter', function () {
|
||
$classe = Classe::factory()->create();
|
||
$this->post(route('rejoindre.demander'), ['code' => $classe->code_classe, 'prenom' => 'Léo']);
|
||
$demande = DemandeInscription::sole();
|
||
|
||
commeProf($this, User::factory()->create())->post(route('mes-classes.demandes.accepter', [$classe, $demande]))->assertForbidden();
|
||
commeProf($this, $classe->prof)->post(route('mes-classes.demandes.accepter', [$classe, $demande]));
|
||
Auth::guard('web')->logout();
|
||
|
||
$this->flushSession();
|
||
$this->get(route('rejoindre.bienvenue'))->assertRedirect(route('rejoindre'));
|
||
expect(DemandeInscription::sole()->statut)->toBe(DemandeInscription::ACCEPTEE);
|
||
});
|
||
|
||
test('une demande non traitée depuis une heure est supprimée', function () {
|
||
$classe = Classe::factory()->create();
|
||
$ancienne = DemandeInscription::create(['classe_id' => $classe->id, 'prenom' => 'A', 'jeton_empreinte' => DemandeInscription::empreinte('a'), 'statut' => 'en_attente']);
|
||
$ancienne->forceFill(['created_at' => now()->subMinutes(61)])->save();
|
||
DemandeInscription::create(['classe_id' => $classe->id, 'prenom' => 'B', 'jeton_empreinte' => DemandeInscription::empreinte('b'), 'statut' => 'en_attente']);
|
||
|
||
$this->artisan('model:prune', ['--model' => [DemandeInscription::class]]);
|
||
|
||
expect(DemandeInscription::pluck('prenom')->all())->toBe(['B']);
|
||
});
|
||
|
||
test('le prof génère de nouvelles fiches pour les élèves cochés, et seulement eux', function () {
|
||
$classe = Classe::factory()->create();
|
||
[$a, $b] = Eleve::factory()->count(2)->create(['classe_id' => $classe->id]);
|
||
$ancienB = $b->code_secret;
|
||
|
||
commeProf($this, $classe->prof)->post(route('mes-classes.fiches', $classe), ['eleves' => [$a->id]])
|
||
->assertSessionHas('fiches', fn ($fiches) => count($fiches) === 1 && $fiches[0]['identifiant'] === $a->identifiant);
|
||
|
||
expect(Auth::guard('eleve')->attempt(['identifiant' => $a->identifiant, 'password' => '123456']))->toBeFalse()
|
||
->and($b->refresh()->code_secret)->toBe($ancienB);
|
||
});
|