create(); if ($archiveeIlYaJours !== null) { $classe->forceFill(['archivee_a' => now()->subDays($archiveeIlYaJours)])->save(); } $eleves = Eleve::factory()->count(2)->create(['classe_id' => $classe->id]); $lab = Lab::factory()->create(); $seance = Seance::create(['classe_id' => $classe->id, 'lab_id' => $lab->id, 'statut' => Seance::TERMINEE]); $session = LabSession::create(['seance_id' => $seance->id, 'eleve_id' => $eleves[0]->id, 'lab_id' => $lab->id, 'etat' => LabSession::EXPIRE]); $session->machines()->create(['nom' => 'pc-a', 'instance_id' => 'uuid-a']); $session->corrections()->create(['reussi' => true, 'note' => 10, 'note_max' => 10, 'details' => []]); return $classe; } test('la purge supprime une classe archivée depuis plus de 90 jours et toutes les données de ses élèves', function () { $classe = classeComplete(91); $prof = $classe->prof; $this->artisan('classes:purger-archivees')->expectsOutput('1 classe(s) purgée(s).')->assertSuccessful(); expect(Classe::find($classe->id))->toBeNull() ->and(Eleve::where('classe_id', $classe->id)->count())->toBe(0) ->and(Seance::where('classe_id', $classe->id)->count())->toBe(0) ->and(LabSession::count())->toBe(0) ->and(LabSessionMachine::count())->toBe(0) ->and(Correction::count())->toBe(0) // Le compte du prof n'est pas une donnée d'élève : il reste. ->and(User::find($prof->id))->not->toBeNull(); }); test('la purge épargne les classes archivées depuis moins de 90 jours et les classes en cours', function () { $recente = classeComplete(89); $enCours = classeComplete(null); $this->artisan('classes:purger-archivees')->expectsOutput('0 classe(s) purgée(s).'); expect(Classe::find($recente->id))->not->toBeNull() ->and(Classe::find($enCours->id))->not->toBeNull() ->and(Eleve::count())->toBe(4) ->and(Correction::count())->toBe(2); }); test('la purge ne touche qu’aux classes concernées', function () { $aPurger = classeComplete(120); $aGarder = classeComplete(null); $this->artisan('classes:purger-archivees'); expect(Classe::pluck('id')->all())->toBe([$aGarder->id]) ->and(Eleve::pluck('classe_id')->unique()->all())->toBe([$aGarder->id]); }); test('un prof archive sa classe : plus de séance possible, date de suppression annoncée', function () { $classe = classeComplete(null); $prof = $classe->prof; $jeton = $prof->demarreNouvelleSession(); $connecte = fn () => $this->withSession(['jeton_session_web' => $jeton])->actingAs($prof, 'web'); $connecte()->post(route('mes-classes.archiver', $classe))->assertRedirect(route('mes-classes.show', $classe)); $classe->refresh(); expect($classe->estArchivee())->toBeTrue() ->and($classe->supprimeeLe()->toDateString())->toBe(now()->addDays(90)->toDateString()); $connecte()->get(route('mes-classes.show', $classe)) ->assertSee('Classe archivée') ->assertSee($classe->supprimeeLe()->timezone(config('app.fuseau_utilisateurs'))->format('d/m/Y')); $connecte()->post(route('mes-classes.seances.store', $classe), ['lab_id' => Lab::first()->id])->assertSessionHasErrors('prevue_a'); expect(Seance::where('classe_id', $classe->id)->where('statut', '!=', Seance::TERMINEE)->count())->toBe(0); }); test('un autre prof ne peut pas archiver la classe', function () { $classe = classeComplete(null); $intrus = User::factory()->create(); $jeton = $intrus->demarreNouvelleSession(); $this->withSession(['jeton_session_web' => $jeton])->actingAs($intrus, 'web') ->post(route('mes-classes.archiver', $classe))->assertForbidden(); expect($classe->refresh()->estArchivee())->toBeFalse(); });