148 lines
7.3 KiB
PHP
148 lines
7.3 KiB
PHP
|
|
<?php
|
|||
|
|
|
|||
|
|
use App\Models\Classe;
|
|||
|
|
use App\Models\Devoir;
|
|||
|
|
use App\Models\Eleve;
|
|||
|
|
use App\Models\RenduDevoir;
|
|||
|
|
use Illuminate\Http\UploadedFile;
|
|||
|
|
use Illuminate\Support\Facades\Storage;
|
|||
|
|
|
|||
|
|
/** Active le disque s3 factice et le fait passer pour configuré. */
|
|||
|
|
function avecDisqueS3Factice(): void
|
|||
|
|
{
|
|||
|
|
config(['filesystems.disks.s3.bucket' => 'bucket-de-test']);
|
|||
|
|
Storage::fake('s3');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
test('tant que le bucket s3 n’est pas configuré, le dépôt de fichier est masqué et refusé', function () {
|
|||
|
|
$classe = Classe::factory()->create();
|
|||
|
|
$eleve = Eleve::factory()->create(['classe_id' => $classe->id]);
|
|||
|
|
$devoir = Devoir::create(['classe_id' => $classe->id, 'titre' => 'Test', 'consigne' => 'Test', 'echeance' => now()->addDay()]);
|
|||
|
|
|
|||
|
|
eleve($this, $eleve)->get(route('devoirs.eleve.show', $devoir))->assertOk()->assertDontSee('Joindre un fichier');
|
|||
|
|
|
|||
|
|
eleve($this, $eleve)->post(route('devoirs.eleve.rendre', $devoir), [
|
|||
|
|
'fichier' => UploadedFile::fake()->create('devoir.pdf', 100, 'application/pdf'),
|
|||
|
|
])->assertStatus(503);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test('un élève peut rendre un devoir avec un fichier seul, sans texte', function () {
|
|||
|
|
avecDisqueS3Factice();
|
|||
|
|
$classe = Classe::factory()->create();
|
|||
|
|
$eleve = Eleve::factory()->create(['classe_id' => $classe->id]);
|
|||
|
|
$devoir = Devoir::create(['classe_id' => $classe->id, 'titre' => 'Test', 'consigne' => 'Test', 'echeance' => now()->addDay()]);
|
|||
|
|
|
|||
|
|
eleve($this, $eleve)->get(route('devoirs.eleve.show', $devoir))->assertOk()->assertSee('Joindre un fichier');
|
|||
|
|
|
|||
|
|
eleve($this, $eleve)->post(route('devoirs.eleve.rendre', $devoir), [
|
|||
|
|
'fichier' => UploadedFile::fake()->create('devoir.pdf', 100, 'application/pdf'),
|
|||
|
|
])->assertRedirect();
|
|||
|
|
|
|||
|
|
$rendu = RenduDevoir::where('devoir_id', $devoir->id)->where('eleve_id', $eleve->id)->first();
|
|||
|
|
expect($rendu)->not->toBeNull();
|
|||
|
|
expect($rendu->reponse)->toBeNull();
|
|||
|
|
expect($rendu->aUnFichier())->toBeTrue();
|
|||
|
|
expect($rendu->fichier_nom_original)->toBe('devoir.pdf');
|
|||
|
|
Storage::disk('s3')->assertExists($rendu->fichier_chemin);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test('un rendu sans réponse ni fichier est refusé', function () {
|
|||
|
|
avecDisqueS3Factice();
|
|||
|
|
$classe = Classe::factory()->create();
|
|||
|
|
$eleve = Eleve::factory()->create(['classe_id' => $classe->id]);
|
|||
|
|
$devoir = Devoir::create(['classe_id' => $classe->id, 'titre' => 'Test', 'consigne' => 'Test', 'echeance' => now()->addDay()]);
|
|||
|
|
|
|||
|
|
eleve($this, $eleve)->post(route('devoirs.eleve.rendre', $devoir), [])->assertSessionHasErrors(['reponse', 'fichier']);
|
|||
|
|
expect(RenduDevoir::count())->toBe(0);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test('un fichier trop lourd ou d’une extension refusée est rejeté', function () {
|
|||
|
|
avecDisqueS3Factice();
|
|||
|
|
$classe = Classe::factory()->create();
|
|||
|
|
$eleve = Eleve::factory()->create(['classe_id' => $classe->id]);
|
|||
|
|
$devoir = Devoir::create(['classe_id' => $classe->id, 'titre' => 'Test', 'consigne' => 'Test', 'echeance' => now()->addDay()]);
|
|||
|
|
|
|||
|
|
eleve($this, $eleve)->post(route('devoirs.eleve.rendre', $devoir), [
|
|||
|
|
'fichier' => UploadedFile::fake()->create('trop-gros.pdf', 11 * 1024, 'application/pdf'),
|
|||
|
|
])->assertSessionHasErrors('fichier');
|
|||
|
|
|
|||
|
|
eleve($this, $eleve)->post(route('devoirs.eleve.rendre', $devoir), [
|
|||
|
|
'fichier' => UploadedFile::fake()->create('script.exe', 10, 'application/x-msdownload'),
|
|||
|
|
])->assertSessionHasErrors('fichier');
|
|||
|
|
|
|||
|
|
expect(RenduDevoir::count())->toBe(0);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test('remplacer son fichier supprime l’ancien de l’object storage, un nouvel envoi en texte seul le conserve', function () {
|
|||
|
|
avecDisqueS3Factice();
|
|||
|
|
$classe = Classe::factory()->create();
|
|||
|
|
$eleve = Eleve::factory()->create(['classe_id' => $classe->id]);
|
|||
|
|
$devoir = Devoir::create(['classe_id' => $classe->id, 'titre' => 'Test', 'consigne' => 'Test', 'echeance' => now()->addDay()]);
|
|||
|
|
|
|||
|
|
eleve($this, $eleve)->post(route('devoirs.eleve.rendre', $devoir), [
|
|||
|
|
'fichier' => UploadedFile::fake()->create('premier.pdf', 100, 'application/pdf'),
|
|||
|
|
])->assertRedirect();
|
|||
|
|
$cheminPremier = RenduDevoir::first()->fichier_chemin;
|
|||
|
|
Storage::disk('s3')->assertExists($cheminPremier);
|
|||
|
|
|
|||
|
|
// Un nouvel envoi en texte seul (pas de nouveau fichier) garde l'ancien fichier.
|
|||
|
|
eleve($this, $eleve)->post(route('devoirs.eleve.rendre', $devoir), ['reponse' => 'Je précise ma réponse'])->assertRedirect();
|
|||
|
|
$rendu = RenduDevoir::first();
|
|||
|
|
expect($rendu->fichier_chemin)->toBe($cheminPremier)->and($rendu->reponse)->toBe('Je précise ma réponse');
|
|||
|
|
Storage::disk('s3')->assertExists($cheminPremier);
|
|||
|
|
|
|||
|
|
// Un nouveau fichier remplace l'ancien, qui est supprimé de l'object storage.
|
|||
|
|
eleve($this, $eleve)->post(route('devoirs.eleve.rendre', $devoir), [
|
|||
|
|
'fichier' => UploadedFile::fake()->create('second.pdf', 100, 'application/pdf'),
|
|||
|
|
])->assertRedirect();
|
|||
|
|
Storage::disk('s3')->assertMissing($cheminPremier);
|
|||
|
|
expect(RenduDevoir::count())->toBe(1);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test('seul le prof propriétaire peut télécharger le fichier rendu par un élève', function () {
|
|||
|
|
avecDisqueS3Factice();
|
|||
|
|
$classe = Classe::factory()->create();
|
|||
|
|
$eleve = Eleve::factory()->create(['classe_id' => $classe->id]);
|
|||
|
|
$devoir = Devoir::create(['classe_id' => $classe->id, 'titre' => 'Test', 'consigne' => 'Test', 'echeance' => now()->addDay()]);
|
|||
|
|
eleve($this, $eleve)->post(route('devoirs.eleve.rendre', $devoir), [
|
|||
|
|
'fichier' => UploadedFile::fake()->create('devoir.pdf', 100, 'application/pdf'),
|
|||
|
|
])->assertRedirect();
|
|||
|
|
$rendu = RenduDevoir::first();
|
|||
|
|
|
|||
|
|
commeProf($this, $classe->prof)->get(route('mes-classes.devoirs.telecharger', [$classe, $devoir, $rendu]))->assertRedirect();
|
|||
|
|
|
|||
|
|
$autreClasse = Classe::factory()->create();
|
|||
|
|
commeProf($this, $autreClasse->prof)->get(route('mes-classes.devoirs.telecharger', [$classe, $devoir, $rendu]))->assertForbidden();
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test('le prof voit le fichier déposé par un élève dans la page du devoir', function () {
|
|||
|
|
avecDisqueS3Factice();
|
|||
|
|
$classe = Classe::factory()->create();
|
|||
|
|
$eleve = Eleve::factory()->create(['classe_id' => $classe->id]);
|
|||
|
|
$devoir = Devoir::create(['classe_id' => $classe->id, 'titre' => 'Test', 'consigne' => 'Test', 'echeance' => now()->addDay()]);
|
|||
|
|
eleve($this, $eleve)->post(route('devoirs.eleve.rendre', $devoir), [
|
|||
|
|
'fichier' => UploadedFile::fake()->create('rapport-reseau.pdf', 100, 'application/pdf'),
|
|||
|
|
])->assertRedirect();
|
|||
|
|
|
|||
|
|
commeProf($this, $classe->prof)->get(route('mes-classes.devoirs.show', [$classe, $devoir]))
|
|||
|
|
->assertSee('rapport-reseau.pdf');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test('purger une classe archivée supprime aussi les fichiers de ses rendus sur l’object storage', function () {
|
|||
|
|
avecDisqueS3Factice();
|
|||
|
|
$classe = Classe::factory()->create();
|
|||
|
|
$eleve = Eleve::factory()->create(['classe_id' => $classe->id]);
|
|||
|
|
$devoir = Devoir::create(['classe_id' => $classe->id, 'titre' => 'Test', 'consigne' => 'Test', 'echeance' => now()->addDay()]);
|
|||
|
|
eleve($this, $eleve)->post(route('devoirs.eleve.rendre', $devoir), [
|
|||
|
|
'fichier' => UploadedFile::fake()->create('devoir.pdf', 100, 'application/pdf'),
|
|||
|
|
])->assertRedirect();
|
|||
|
|
$chemin = RenduDevoir::first()->fichier_chemin;
|
|||
|
|
Storage::disk('s3')->assertExists($chemin);
|
|||
|
|
|
|||
|
|
$classe->forceFill(['archivee_a' => now()->subDays(91)])->save();
|
|||
|
|
$this->artisan('classes:purger-archivees');
|
|||
|
|
|
|||
|
|
Storage::disk('s3')->assertMissing($chemin);
|
|||
|
|
expect(RenduDevoir::count())->toBe(0);
|
|||
|
|
});
|