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'); });