'Utilisateur']); return Utilisateur::create([ 'Pseudo' => $pseudo, 'Email' => $email, 'MotDePasse' => Hash::make('motdepasse123'), 'ID_Role' => $role->ID_Role, 'Statut' => 'Actif', ]); } private function suggestion(Utilisateur $utilisateur, ?int $numero = 42): Suggestion { return Suggestion::create([ 'ID_Utilisateur' => $utilisateur->ID_Utilisateur, 'Type' => 'Correction', 'Titre' => 'Faute dans une ressource', 'Description' => 'Il y a une faute à corriger sur la page des ressources.', 'GiteaIssueNumber' => $numero, ]); } private function configurerGitea(): void { config([ 'services.gitea.url' => 'https://gitea.test', 'services.gitea.token' => 'fake-token', 'services.gitea.repo' => 'Groupe1/Ressources-relationnel', ]); } public function test_le_formulaire_de_suggestion_exige_une_authentification(): void { $this->get('/suggestions/nouveau')->assertRedirect('/login'); $this->get('/suggestions')->assertRedirect('/login'); } public function test_une_suggestion_valide_cree_un_ticket_gitea_et_est_conservee(): void { $this->configurerGitea(); Http::fake([ '*/api/v1/repos/*/issues' => Http::response(['number' => 42], 201), ]); $utilisateur = $this->utilisateur(); $response = $this->actingAs($utilisateur)->post('/suggestions', [ 'type' => 'Correction', 'titre' => 'Faute dans une ressource', 'description' => 'Il y a une faute à corriger sur la page des ressources.', ]); // L'utilisateur arrive sur la page de suivi de ses suggestions $response->assertRedirect(route('suggestions.index')); $response->assertSessionHas('success'); Http::assertSent(function ($request) { return str_contains($request->url(), '/api/v1/repos/Groupe1/Ressources-relationnel/issues') && $request['title'] === '[Correction] Faute dans une ressource' && str_contains($request['body'], 'JeanTest'); }); // La suggestion est liée au ticket pour permettre le suivi $this->assertDatabaseHas('suggestions', [ 'ID_Utilisateur' => $utilisateur->ID_Utilisateur, 'Titre' => 'Faute dans une ressource', 'GiteaIssueNumber' => 42, ]); } public function test_la_liste_affiche_l_etat_du_ticket_et_les_nouvelles_reponses(): void { $this->configurerGitea(); Http::fake([ 'gitea.test/api/v1/repos/*/issues/42' => Http::response([ 'number' => 42, 'state' => 'open', 'comments' => 2, 'title' => '[Correction] Faute', ]), ]); $utilisateur = $this->utilisateur(); $this->suggestion($utilisateur); $response = $this->actingAs($utilisateur)->get('/suggestions'); $response->assertOk() ->assertSee('Faute dans une ressource') ->assertSee('En cours') ->assertSee('2 nouvelles réponses'); } public function test_la_liste_ne_montre_pas_les_suggestions_des_autres(): void { $this->configurerGitea(); Http::fake(); $autre = $this->utilisateur('AutreUser', 'autre@example.com'); $this->suggestion($autre); $moi = $this->utilisateur('Moi', 'moi@example.com'); $this->actingAs($moi)->get('/suggestions') ->assertOk() ->assertDontSee('Faute dans une ressource'); } public function test_le_detail_affiche_les_reponses_du_ticket_et_les_marque_comme_vues(): void { $this->configurerGitea(); Http::fake([ 'gitea.test/api/v1/repos/*/issues/42/comments' => Http::response([ [ 'user' => ['username' => 'sam-depardieu'], 'body' => 'Merci, correction prévue dans la v1.1 !', 'created_at' => '2026-07-08T10:00:00Z', ], ]), 'gitea.test/api/v1/repos/*/issues/42' => Http::response([ 'number' => 42, 'state' => 'open', 'comments' => 1, 'title' => '[Correction] Faute', ]), ]); $utilisateur = $this->utilisateur(); $suggestion = $this->suggestion($utilisateur); $response = $this->actingAs($utilisateur)->get('/suggestions/'.$suggestion->ID_Suggestion); $response->assertOk() ->assertSee('sam-depardieu') ->assertSee('Merci, correction prévue dans la v1.1 !'); // Les réponses consultées ne comptent plus comme « nouvelles » $this->assertSame(1, $suggestion->fresh()->CommentairesVus); } public function test_le_detail_d_une_suggestion_d_un_autre_est_interdit(): void { $this->configurerGitea(); Http::fake(); $autre = $this->utilisateur('AutreUser', 'autre@example.com'); $suggestion = $this->suggestion($autre); $moi = $this->utilisateur('Moi', 'moi@example.com'); $this->actingAs($moi)->get('/suggestions/'.$suggestion->ID_Suggestion) ->assertForbidden(); } public function test_l_utilisateur_peut_repondre_sur_le_ticket(): void { $this->configurerGitea(); Http::fake([ 'gitea.test/api/v1/repos/*/issues/42/comments' => Http::response(['id' => 7], 201), ]); $utilisateur = $this->utilisateur(); $suggestion = $this->suggestion($utilisateur); $response = $this->actingAs($utilisateur) ->post('/suggestions/'.$suggestion->ID_Suggestion.'/repondre', [ 'message' => 'Précision : la faute est dans le deuxième paragraphe.', ]); $response->assertRedirect(route('suggestions.show', $suggestion)); $response->assertSessionHas('success'); // Le commentaire est publié sur le ticket Gitea, signé du pseudo Http::assertSent(function ($request) { return $request->method() === 'POST' && str_contains($request->url(), '/issues/42/comments') && str_contains($request['body'], 'JeanTest') && str_contains($request['body'], 'deuxième paragraphe'); }); } public function test_une_suggestion_invalide_est_rejetee(): void { Http::fake(); $response = $this->actingAs($this->utilisateur())->post('/suggestions', [ 'type' => 'Inconnu', 'titre' => 'x', 'description' => 'court', ]); $response->assertSessionHasErrors(['type', 'titre', 'description']); Http::assertNothingSent(); } public function test_un_echec_gitea_affiche_une_erreur(): void { $this->configurerGitea(); Http::fake([ '*/api/v1/repos/*/issues' => Http::response(['message' => 'nope'], 500), ]); $response = $this->actingAs($this->utilisateur())->post('/suggestions', [ 'type' => 'Ajout', 'titre' => 'Nouvelle fonctionnalité utile', 'description' => 'Ce serait bien d\'ajouter un filtre par thème.', ]); $response->assertSessionHasErrors('gitea'); // Rien n'est conservé si le ticket n'a pas pu être créé $this->assertDatabaseCount('suggestions', 0); } }