From 00e0025a7346028eeea8f750c633fe722893a2f6 Mon Sep 17 00:00:00 2001 From: Paul Isaris Date: Fri, 4 Oct 2024 16:45:37 +0300 Subject: [PATCH 1/2] Aligned tests --- .../CrowdSourcingProjectControllerTest.php | 72 ++--- .../Controllers/FileControllerTest.php | 52 ++-- .../QuestionnaireControllerTest.php | 275 +++++++++--------- .../QuestionnaireResponseControllerTest.php | 55 ++-- .../QuestionnaireStatisticsControllerTest.php | 49 ++-- .../Controllers/UserControllerTest.php | 54 ++-- 6 files changed, 298 insertions(+), 259 deletions(-) diff --git a/tests/Feature/Controllers/CrowdSourcingProjectControllerTest.php b/tests/Feature/Controllers/CrowdSourcingProjectControllerTest.php index e466a4b0..bdfc1a02 100644 --- a/tests/Feature/Controllers/CrowdSourcingProjectControllerTest.php +++ b/tests/Feature/Controllers/CrowdSourcingProjectControllerTest.php @@ -5,6 +5,7 @@ use App\BusinessLogicLayer\CrowdSourcingProject\CrowdSourcingProjectManager; use App\BusinessLogicLayer\lkp\CrowdSourcingProjectStatusLkp; use App\BusinessLogicLayer\lkp\UserRolesLkp; +use App\Http\Middleware\VerifyCsrfToken; use App\Models\CrowdSourcingProject\CrowdSourcingProject; use App\Models\User; use App\Models\UserRole; @@ -282,13 +283,14 @@ public function adminCanAccessEditPage() { * @test */ public function guestCannotStoreProject() { - $response = $this->post(route('projects.store'), [ - 'name' => 'Test Project', - 'description' => 'Test Description', - 'status_id' => 1, - 'slug' => 'test-project', - 'language_id' => 1, - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('projects.store'), [ + 'name' => 'Test Project', + 'description' => 'Test Description', + 'status_id' => 1, + 'slug' => 'test-project', + 'language_id' => 1, + ]); $response->assertStatus(302); $response->assertRedirect(route('login', ['locale' => 'en'])); @@ -298,16 +300,17 @@ public function guestCannotStoreProject() { * @test */ public function authenticatedUserCannotStoreProject() { - $user = User::factory()->make(); - $this->be($user); - - $response = $this->post(route('projects.store'), [ - 'name' => 'Test Project', - 'description' => 'Test Description', - 'status_id' => 1, - 'slug' => 'test-project', - 'language_id' => 1, - ]); + $user = User::factory()->create(); + $this->actingAs($user); + + $response = $this->withoutMiddleware(VerifyCsrfToken::class) // Disable CSRF only + ->post(route('projects.store'), [ + 'name' => 'Test Project', + 'description' => 'Test Description', + 'status_id' => 1, + 'slug' => 'test-project', + 'language_id' => 1, + ]); $response->assertStatus(403); } @@ -323,17 +326,18 @@ public function adminCanStoreProjectWithValidData() { $faker = Faker::create(); - $response = $this->post(route('projects.store'), [ - 'name' => 'Valid Project', - 'description' => 'Valid Description', - 'status_id' => 1, - 'slug' => 'valid-project', - 'language_id' => 1, - 'color_ids' => [1], - 'color_names' => [$faker->name], - 'color_codes' => [$faker->hexColor], - 'motto_subtitle' => $faker->text, - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('projects.store'), [ + 'name' => 'Valid Project', + 'description' => 'Valid Description', + 'status_id' => 1, + 'slug' => 'valid-project', + 'language_id' => 1, + 'color_ids' => [1], + 'color_names' => [$faker->name], + 'color_codes' => [$faker->hexColor], + 'motto_subtitle' => $faker->text, + ]); $response->assertStatus(302); $response->assertSessionHas('flash_message_success', 'The project has been successfully created'); @@ -357,7 +361,7 @@ public function adminCannotStoreProjectWithExistingData() { $project = CrowdSourcingProject::factory()->create(); - $response = $this->post(route('projects.store'), [ + $response = $this->withoutMiddleware(VerifyCsrfToken::class)->post(route('projects.store'), [ 'name' => $project->defaultTranslation->name, 'description' => $project->defaultTranslation->description, 'status_id' => $project->status_id, @@ -378,7 +382,7 @@ public function storeProjectWithInvalidData() { ->create(); $this->be($user); - $response = $this->post(route('projects.store'), [ + $response = $this->withoutMiddleware(VerifyCsrfToken::class)->post(route('projects.store'), [ 'name' => '', 'description' => '', 'status_id' => 'invalid', @@ -396,7 +400,7 @@ public function storeProjectWithInvalidData() { public function guestCannotUpdateProject() { $project = CrowdSourcingProject::factory()->create(); - $response = $this->put(route('projects.update', ['project' => $project->id]), [ + $response = $this->withoutMiddleware(VerifyCsrfToken::class)->put(route('projects.update', ['project' => $project->id]), [ 'name' => 'Updated Project', 'description' => 'Updated Description', 'status_id' => 1, @@ -417,7 +421,7 @@ public function authenticatedUserCannotUpdateProject() { $project = CrowdSourcingProject::factory()->create(); - $response = $this->put(route('projects.update', ['project' => $project->id]), [ + $response = $this->withoutMiddleware(VerifyCsrfToken::class)->put(route('projects.update', ['project' => $project->id]), [ 'name' => 'Updated Project', 'description' => 'Updated Description', 'status_id' => 1, @@ -439,7 +443,7 @@ public function adminCanUpdateProjectWithValidData() { $project = CrowdSourcingProject::factory()->create(); $faker = Faker::create(); - $response = $this->put(route('projects.update', ['project' => $project->id]), [ + $response = $this->withoutMiddleware(VerifyCsrfToken::class)->put(route('projects.update', ['project' => $project->id]), [ 'name' => 'Updated Project', 'description' => 'Updated Description', 'status_id' => 1, @@ -475,7 +479,7 @@ public function adminCannotUpdateProjectWithInvalidData() { $project = CrowdSourcingProject::factory()->create(); - $response = $this->put(route('projects.update', ['project' => $project->id]), [ + $response = $this->withoutMiddleware(VerifyCsrfToken::class)->put(route('projects.update', ['project' => $project->id]), [ 'name' => '', 'description' => '', 'status_id' => 'invalid', diff --git a/tests/Feature/Controllers/FileControllerTest.php b/tests/Feature/Controllers/FileControllerTest.php index b70f5edf..a01d8b86 100644 --- a/tests/Feature/Controllers/FileControllerTest.php +++ b/tests/Feature/Controllers/FileControllerTest.php @@ -2,6 +2,7 @@ namespace Tests\Feature\Controllers; +use App\Http\Middleware\VerifyCsrfToken; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Http\UploadedFile; use Illuminate\Support\Facades\Storage; @@ -20,11 +21,12 @@ public function uploadFilesSuccessfullyUploadsFiles() { UploadedFile::fake()->image('photo2.jpg'), ]; - $response = $this->postJson('/files/upload', [ - 'files' => $files, - 'project_id' => 1, - 'questionnaire_id' => 1, - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->postJson('/files/upload', [ + 'files' => $files, + 'project_id' => 1, + 'questionnaire_id' => 1, + ]); $response->assertStatus(200); $response->assertJsonCount(2); @@ -42,11 +44,12 @@ public function uploadFilesFailsWithInvalidFileType() { UploadedFile::fake()->create('document.txt', 100), ]; - $response = $this->postJson('/files/upload', [ - 'files' => $files, - 'project_id' => 1, - 'questionnaire_id' => 1, - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->postJson('/files/upload', [ + 'files' => $files, + 'project_id' => 1, + 'questionnaire_id' => 1, + ]); $response->assertStatus(422); $response->assertJsonValidationErrors(['files.0']); @@ -57,11 +60,12 @@ public function uploadFilesFailsWithTooManyFiles() { Storage::fake('s3'); $files = array_fill(0, 9, UploadedFile::fake()->image('photo.jpg')); - $response = $this->postJson('/files/upload', [ - 'files' => $files, - 'project_id' => 1, - 'questionnaire_id' => 1, - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->postJson('/files/upload', [ + 'files' => $files, + 'project_id' => 1, + 'questionnaire_id' => 1, + ]); $response->assertStatus(422); $response->assertJsonValidationErrors(['files']); @@ -74,10 +78,11 @@ public function uploadFilesFailsWithoutProjectId() { UploadedFile::fake()->image('photo.jpg'), ]; - $response = $this->postJson('/files/upload', [ - 'files' => $files, - 'questionnaire_id' => 1, - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->postJson('/files/upload', [ + 'files' => $files, + 'questionnaire_id' => 1, + ]); $response->assertStatus(422); $response->assertJsonValidationErrors(['project_id']); @@ -90,10 +95,11 @@ public function uploadFilesFailsWithoutQuestionnaireId() { UploadedFile::fake()->image('photo.jpg'), ]; - $response = $this->postJson('/files/upload', [ - 'files' => $files, - 'project_id' => 1, - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->postJson('/files/upload', [ + 'files' => $files, + 'project_id' => 1, + ]); $response->assertStatus(422); $response->assertJsonValidationErrors(['questionnaire_id']); diff --git a/tests/Feature/Controllers/Questionnaire/QuestionnaireControllerTest.php b/tests/Feature/Controllers/Questionnaire/QuestionnaireControllerTest.php index 1da12dc0..bfac7df0 100644 --- a/tests/Feature/Controllers/Questionnaire/QuestionnaireControllerTest.php +++ b/tests/Feature/Controllers/Questionnaire/QuestionnaireControllerTest.php @@ -5,30 +5,27 @@ use App\BusinessLogicLayer\lkp\CrowdSourcingProjectStatusLkp; use App\BusinessLogicLayer\lkp\QuestionnaireStatusLkp; use App\BusinessLogicLayer\lkp\UserRolesLkp; +use App\Http\Middleware\VerifyCsrfToken; use App\Models\CrowdSourcingProject\CrowdSourcingProject; use App\Models\Questionnaire\Questionnaire; use App\Models\Questionnaire\QuestionnaireLanguage; use App\Models\User; use App\Models\UserRole; use App\Utils\Translator; -use Illuminate\Foundation\Testing\RefreshDatabase; use Mockery; use Tests\TestCase; class QuestionnaireControllerTest extends TestCase { - use RefreshDatabase; - - protected $seed = true; - /** * @test */ public function guestCannotSaveQuestionnaireStatus() { - $response = $this->post(route('update-questionnaire-status'), [ - 'questionnaire_id' => 1, - 'status_id' => 1, - 'comments' => 'Test comment', - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('update-questionnaire-status'), [ + 'questionnaire_id' => 1, + 'status_id' => 1, + 'comments' => 'Test comment', + ]); $response->assertStatus(302); $response->assertRedirect(route('login', ['locale' => 'en'])); @@ -45,11 +42,12 @@ public function adminCanSaveQuestionnaireStatus() { $questionnaire = Questionnaire::factory()->create(); - $response = $this->post(route('update-questionnaire-status'), [ - 'questionnaire_id' => $questionnaire->id, - 'status_id' => QuestionnaireStatusLkp::PUBLISHED, - 'comments' => 'Test comment', - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('update-questionnaire-status'), [ + 'questionnaire_id' => $questionnaire->id, + 'status_id' => QuestionnaireStatusLkp::PUBLISHED, + 'comments' => 'Test comment', + ]); $response->assertStatus(302); $response->assertSessionHas('flash_message_success', 'The questionnaire status has been updated.'); @@ -68,11 +66,12 @@ public function adminCannotSaveQuestionnaireStatusWithInvalidQuestionnaireId() { ->create(); $this->be($user); - $response = $this->post(route('update-questionnaire-status'), [ - 'questionnaire_id' => 'invalid', - 'status_id' => 'invalid', - 'comments' => '', - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('update-questionnaire-status'), [ + 'questionnaire_id' => 'invalid', + 'status_id' => 'invalid', + 'comments' => '', + ]); $response->assertStatus(302); $response->assertSessionHasErrors(['status_id']); @@ -87,11 +86,12 @@ public function adminCannotSaveQuestionnaireStatusWithInvalidData() { ->create(); $this->be($user); - $response = $this->post(route('update-questionnaire-status'), [ - 'questionnaire_id' => 1, - 'status_id' => 'invalid', - 'comments' => '', - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('update-questionnaire-status'), [ + 'questionnaire_id' => 1, + 'status_id' => 'invalid', + 'comments' => '', + ]); $response->assertStatus(302); $response->assertSessionHasErrors(['status_id']); @@ -130,28 +130,29 @@ public function adminCanStoreQuestionnaireWithValidData() { ->has(UserRole::factory()->state(['role_id' => UserRolesLkp::ADMIN])) ->create(); $this->be($user); - $response = $this->post(route('store-questionnaire'), [ - 'title' => 'Test Questionnaire', - 'description' => 'Test Description', - 'project_id' => 1, - 'prerequisite_order' => 1, - 'status_id' => 1, - 'type_id' => 1, - 'language' => 1, - 'goal' => 123, - 'questionnaire_json' => json_encode([ - 'question1' => 'What is your name?', - 'question2' => 'What is your age?', - 'question3' => 'What?']), - 'statistics_page_visibility_lkp_id' => 1, - 'max_votes_num' => 5, - 'show_general_statistics' => true, - 'respondent_auth_required' => false, - 'show_file_type_questions_to_statistics_page_audience' => false, - 'lang_codes' => ['en', 'fr'], - 'content' => 'Test content', - 'project_ids' => [1], - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('store-questionnaire'), [ + 'title' => 'Test Questionnaire', + 'description' => 'Test Description', + 'project_id' => 1, + 'prerequisite_order' => 1, + 'status_id' => 1, + 'type_id' => 1, + 'language' => 1, + 'goal' => 123, + 'questionnaire_json' => json_encode([ + 'question1' => 'What is your name?', + 'question2' => 'What is your age?', + 'question3' => 'What?']), + 'statistics_page_visibility_lkp_id' => 1, + 'max_votes_num' => 5, + 'show_general_statistics' => true, + 'respondent_auth_required' => false, + 'show_file_type_questions_to_statistics_page_audience' => false, + 'lang_codes' => ['en', 'fr'], + 'content' => 'Test content', + 'project_ids' => [1], + ]); $response->assertStatus(201); $questionnaire = Questionnaire::latest()->first(); @@ -172,19 +173,20 @@ public function adminCannotStoreQuestionnaireWithInvalidData() { ->create(); $this->be($user); - $response = $this->post(route('store-questionnaire'), [ - 'title' => 'Test Questionnaire', - 'description' => 'Test Description', - 'project_id' => 'invalid', - 'prerequisite_order' => 1, - 'status_id' => 1, - 'type_id' => 1, - 'language' => 1, - 'goal' => 123, - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('store-questionnaire'), [ + 'title' => 'Test Questionnaire', + 'description' => 'Test Description', + 'project_id' => 'invalid', + 'prerequisite_order' => 1, + 'status_id' => 1, + 'type_id' => 1, + 'language' => 1, + 'goal' => 123, + ]); $response->assertStatus(302); - $response->assertSessionHasErrors(['statistics_page_visibility_lkp_id', 'lang_codes', 'content', 'project_ids']); + $response->assertSessionHasErrors(['statistics_page_visibility_lkp_id', 'content', 'project_ids']); } /** @@ -196,28 +198,29 @@ public function adminCannotStoreQuestionnaireWithInvalidData() { public function guestCannotUpdateQuestionnaire() { $questionnaire = Questionnaire::factory()->create(); - $response = $this->post(route('update-questionnaire', ['id' => $questionnaire->id]), [ - 'title' => 'Test Questionnaire', - 'description' => 'Test Description', - 'project_id' => 1, - 'prerequisite_order' => 1, - 'status_id' => 1, - 'type_id' => 1, - 'language' => 1, - 'goal' => 123, - 'questionnaire_json' => json_encode([ - 'question1' => 'What is your name?', - 'question2' => 'What is your age?', - 'question3' => 'What?']), - 'statistics_page_visibility_lkp_id' => 1, - 'max_votes_num' => 5, - 'show_general_statistics' => true, - 'respondent_auth_required' => false, - 'show_file_type_questions_to_statistics_page_audience' => false, - 'lang_codes' => ['en', 'fr'], - 'content' => 'Test content', - 'project_ids' => [1], - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('update-questionnaire', ['id' => $questionnaire->id]), [ + 'title' => 'Test Questionnaire', + 'description' => 'Test Description', + 'project_id' => 1, + 'prerequisite_order' => 1, + 'status_id' => 1, + 'type_id' => 1, + 'language' => 1, + 'goal' => 123, + 'questionnaire_json' => json_encode([ + 'question1' => 'What is your name?', + 'question2' => 'What is your age?', + 'question3' => 'What?']), + 'statistics_page_visibility_lkp_id' => 1, + 'max_votes_num' => 5, + 'show_general_statistics' => true, + 'respondent_auth_required' => false, + 'show_file_type_questions_to_statistics_page_audience' => false, + 'lang_codes' => ['en', 'fr'], + 'content' => 'Test content', + 'project_ids' => [1], + ]); $response->assertStatus(302); $response->assertRedirect(route('login', ['locale' => 'en'])); @@ -235,28 +238,29 @@ public function adminCanUpdateQuestionnaireWithValidData() { ->has(UserRole::factory()->state(['role_id' => UserRolesLkp::ADMIN])) ->create(); $this->be($user); - $response = $this->post(route('update-questionnaire', ['id' => $questionnaire->id]), [ - 'title' => 'Test Questionnaire new', - 'description' => 'Test Description new', - 'project_id' => 1, - 'prerequisite_order' => 1, - 'status_id' => 1, - 'type_id' => 1, - 'language' => 1, - 'goal' => 10, - 'questionnaire_json' => json_encode([ - 'question1' => 'What is your name?', - 'question2' => 'What is your age?', - 'question3' => 'What?']), - 'statistics_page_visibility_lkp_id' => 1, - 'max_votes_num' => 5, - 'show_general_statistics' => 1, - 'respondent_auth_required' => false, - 'show_file_type_questions_to_statistics_page_audience' => false, - 'lang_codes' => ['en', 'fr'], - 'content' => 'Test content', - 'project_ids' => [1], - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('update-questionnaire', ['id' => $questionnaire->id]), [ + 'title' => 'Test Questionnaire new', + 'description' => 'Test Description new', + 'project_id' => 1, + 'prerequisite_order' => 1, + 'status_id' => 1, + 'type_id' => 1, + 'language' => 1, + 'goal' => 10, + 'questionnaire_json' => json_encode([ + 'question1' => 'What is your name?', + 'question2' => 'What is your age?', + 'question3' => 'What?']), + 'statistics_page_visibility_lkp_id' => 1, + 'max_votes_num' => 5, + 'show_general_statistics' => 1, + 'respondent_auth_required' => false, + 'show_file_type_questions_to_statistics_page_audience' => false, + 'lang_codes' => ['en', 'fr'], + 'content' => 'Test content', + 'project_ids' => [1], + ]); $response->assertStatus(200); $this->assertDatabaseHas('questionnaires', [ @@ -284,31 +288,33 @@ public function adminCannotUpdateQuestionnaireWithInvalidData() { $questionnaire = Questionnaire::factory()->create(); - $response = $this->post(route('update-questionnaire', ['id' => $questionnaire->id]), [ - 'title' => 'Test Questionnaire', - 'description' => 'Test Description', - 'project_id' => 'invalid', - 'prerequisite_order' => 1, - 'status_id' => 1, - 'type_id' => 1, - 'language' => 1, - 'goal' => 123, - 'content' => 'Test content', - 'project_ids' => [1], - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('update-questionnaire', ['id' => $questionnaire->id]), [ + 'title' => 'Test Questionnaire', + 'description' => 'Test Description', + 'project_id' => 'invalid', + 'prerequisite_order' => 1, + 'status_id' => 1, + 'type_id' => 1, + 'language' => 1, + 'goal' => 123, + 'content' => 'Test content', + 'project_ids' => [1], + ]); $response->assertStatus(302); - $response->assertSessionHasErrors(['statistics_page_visibility_lkp_id', 'lang_codes']); + $response->assertSessionHasErrors(['statistics_page_visibility_lkp_id']); } /** * @test */ public function guestCannotTranslateQuestionnaire() { - $response = $this->post(route('questionnaire.translate'), [ - 'questionnaire_json' => '{}', - 'locales' => ['en', 'fr'], - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('questionnaire.translate'), [ + 'questionnaire_json' => '{}', + 'locales' => ['en', 'fr'], + ]); $response->assertStatus(302); $response->assertRedirect(route('login', ['locale' => 'en'])); @@ -339,10 +345,11 @@ public function adminCanTranslateQuestionnaireWithValidData() { // Inject the mock into the service container $this->app->instance(Translator::class, $translatorMock); - $response = $this->post(route('questionnaire.translate'), [ - 'questionnaire_json' => '{ "title": { "default": "What is your opinion on Democracy in EU?", "gr": "Ποιά είναι η άποψή σας για τις Εκλογές στην ΕΕ;" }, "description": { "default": "Please share your opinion with us!", "gr": "Μοιραστείτε μαζί μας τη γνώμη σας!" }, "logoPosition": "right", "pages": [ { "name": "page1", "elements": [ { "type": "radiogroup", "name": "question2", "title": { "default": "Have you ever participated in Democratic processes about the EU?", "gr": "Έχετε συμμετάσχει ποτέ σε δημοκρατικές διαδικασίες που αφορούν την ΕΕ;" }, "choices": [ { "value": "item1", "text": { "default": "Yes, more than once", "gr": "Ναι, περισσότερες από μια φορές" } }, { "value": "item2", "text": { "default": "I am not sure", "gr": "Δεν είμαι σίγουρος/η" } }, { "value": "item3", "text": { "default": "Never", "gr": "Ποτέ" } } ] }, { "type": "comment", "name": "question3", "title": { "default": "How could Democracy in EU improve?", "gr": "Πώς θα μπορούσε να βελτιωθεί η Δημοκρατία στην ΕΕ;" } } ] } ] }', - 'locales' => ['en', 'fr'], - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('questionnaire.translate'), [ + 'questionnaire_json' => '{ "title": { "default": "What is your opinion on Democracy in EU?", "gr": "Ποιά είναι η άποψή σας για τις Εκλογές στην ΕΕ;" }, "description": { "default": "Please share your opinion with us!", "gr": "Μοιραστείτε μαζί μας τη γνώμη σας!" }, "logoPosition": "right", "pages": [ { "name": "page1", "elements": [ { "type": "radiogroup", "name": "question2", "title": { "default": "Have you ever participated in Democratic processes about the EU?", "gr": "Έχετε συμμετάσχει ποτέ σε δημοκρατικές διαδικασίες που αφορούν την ΕΕ;" }, "choices": [ { "value": "item1", "text": { "default": "Yes, more than once", "gr": "Ναι, περισσότερες από μια φορές" } }, { "value": "item2", "text": { "default": "I am not sure", "gr": "Δεν είμαι σίγουρος/η" } }, { "value": "item3", "text": { "default": "Never", "gr": "Ποτέ" } } ] }, { "type": "comment", "name": "question3", "title": { "default": "How could Democracy in EU improve?", "gr": "Πώς θα μπορούσε να βελτιωθεί η Δημοκρατία στην ΕΕ;" } } ] } ] }', + 'locales' => ['en', 'fr'], + ]); $response->assertStatus(200); $response->assertJsonStructure(['translation']); @@ -357,10 +364,11 @@ public function adminCannotTranslateQuestionnaireWithInvalidData() { ->create(); $this->be($user); - $response = $this->post(route('questionnaire.translate'), [ - 'questionnaire_json' => '', - 'locales' => 'invalid', - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('questionnaire.translate'), [ + 'questionnaire_json' => '', + 'locales' => 'invalid', + ]); $response->assertStatus(302); $response->assertSessionHasErrors(['questionnaire_json', 'locales']); @@ -401,12 +409,13 @@ public function adminCanMarkQuestionnaireTranslations() { ]); - $response = $this->post(route('questionnaire.mark-translations'), [ - 'questionnaire_id' => $questionnaire->id, - 'lang_ids_to_status' => [ - ['id' => 1, 'status' => true], - ], - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('questionnaire.mark-translations'), [ + 'questionnaire_id' => $questionnaire->id, + 'lang_ids_to_status' => [ + ['id' => 1, 'status' => true], + ], + ]); $response->assertStatus(200); $response->assertJson(['success' => true]); diff --git a/tests/Feature/Controllers/Questionnaire/QuestionnaireResponseControllerTest.php b/tests/Feature/Controllers/Questionnaire/QuestionnaireResponseControllerTest.php index d0723174..1a4e270a 100644 --- a/tests/Feature/Controllers/Questionnaire/QuestionnaireResponseControllerTest.php +++ b/tests/Feature/Controllers/Questionnaire/QuestionnaireResponseControllerTest.php @@ -3,6 +3,7 @@ namespace Tests\Feature\Controllers\Questionnaire; use App\BusinessLogicLayer\UserManager; +use App\Http\Middleware\VerifyCsrfToken; use App\Models\CrowdSourcingProject\CrowdSourcingProject; use App\Models\Questionnaire\Questionnaire; use App\Models\Questionnaire\QuestionnaireResponse; @@ -20,11 +21,12 @@ public function testStoreInvalidData() { $user = User::factory()->create(); $this->be($user); - $response = $this->postJson(route('questionnaire-responses.store'), [ - 'browser_fingerprint_id' => '', - 'questionnaire_id' => 'invalid', - 'project_id' => 'invalid', - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->postJson(route('questionnaire-responses.store'), [ + 'browser_fingerprint_id' => '', + 'questionnaire_id' => 'invalid', + 'project_id' => 'invalid', + ]); $response->assertStatus(422); $response->assertJsonValidationErrors(['browser_fingerprint_id', 'questionnaire_id', 'project_id']); @@ -34,21 +36,22 @@ public function testStoreInvalidData() { public function testStoreWithoutAuthenticationForNonModerator() { $questionnaire = Questionnaire::factory()->create(); - $response = $this->postJson(route('questionnaire-responses.store'), [ - 'browser_fingerprint_id' => 'test_fingerprint', - 'questionnaire_id' => $questionnaire->id, - 'project_id' => 1, - 'lang' => 'en', - 'moderator' => false, - 'response' => json_encode([ - 'question1' => 5, - 'question5' => 'item1', - 'question4' => [ - 'item1' => 'answer1', - 'item2' => 'answer2', - ], - ]), - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->postJson(route('questionnaire-responses.store'), [ + 'browser_fingerprint_id' => 'test_fingerprint', + 'questionnaire_id' => $questionnaire->id, + 'project_id' => 1, + 'lang' => 'en', + 'moderator' => false, + 'response' => json_encode([ + 'question1' => 5, + 'question5' => 'item1', + 'question4' => [ + 'item1' => 'answer1', + 'item2' => 'answer2', + ], + ]), + ]); // since in case of non-logged in user we create an anonymous user, the user that responded is the // latest user inserted in the Database. @@ -90,7 +93,8 @@ public function testStoreOfModerator() { ]; // Send POST request to store endpoint - $response = $this->post(route('questionnaire-responses.store'), $requestData); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('questionnaire-responses.store'), $requestData); // Assert response status $response->assertStatus(200); @@ -130,7 +134,8 @@ public function testStoreWithoutAuthenticationForNonModeratorWithStoredCookie() ]; // Send POST request to store endpoint - $response = $this->post(route('questionnaire-responses.store'), $requestData); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('questionnaire-responses.store'), $requestData); // Assert response status $response->assertStatus(200); @@ -193,7 +198,8 @@ public function testVoteAnswerUpvote() { ]; // Send POST request to voteAnswer endpoint - $response = $this->post(route('questionnaire.answer-votes.store'), $requestData); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('questionnaire.answer-votes.store'), $requestData); // Assert response status $response->assertStatus(200); @@ -227,7 +233,8 @@ public function testVoteAnswerDownvote() { ]; // Send POST request to voteAnswer endpoint - $response = $this->post(route('questionnaire.answer-votes.store'), $requestData); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('questionnaire.answer-votes.store'), $requestData); // Assert response status $response->assertStatus(200); diff --git a/tests/Feature/Controllers/Questionnaire/QuestionnaireStatisticsControllerTest.php b/tests/Feature/Controllers/Questionnaire/QuestionnaireStatisticsControllerTest.php index 23949ae3..d27252f4 100644 --- a/tests/Feature/Controllers/Questionnaire/QuestionnaireStatisticsControllerTest.php +++ b/tests/Feature/Controllers/Questionnaire/QuestionnaireStatisticsControllerTest.php @@ -6,6 +6,7 @@ use App\BusinessLogicLayer\lkp\QuestionnaireStatusLkp; use App\BusinessLogicLayer\lkp\UserRolesLkp; use App\BusinessLogicLayer\questionnaire\QuestionnaireStatisticsManager; +use App\Http\Middleware\VerifyCsrfToken; use App\Models\CrowdSourcingProject\CrowdSourcingProject; use App\Models\Questionnaire\Questionnaire; use App\Models\User; @@ -63,11 +64,12 @@ public function saveStatisticsColorsSavesColorsAndRedirectsBackWithSuccessMessag $this->be($user); $questionnaire = Questionnaire::factory()->create(); - $response = $this->post(route('questionnaire.statistics-colors.store', ['questionnaire' => $questionnaire->id]), [ - 'goal_responses_color' => '#FFFFFF', - 'actual_responses_color' => '#000000', - 'total_responses_color' => '#111111', - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('questionnaire.statistics-colors.store', ['questionnaire' => $questionnaire->id]), [ + 'goal_responses_color' => '#FFFFFF', + 'actual_responses_color' => '#000000', + 'total_responses_color' => '#111111', + ]); $response->assertStatus(302); $response->assertSessionHas('flash_message_success', 'Colors saved!'); @@ -81,15 +83,16 @@ public function saveAllStatisticsColorsSavesColorsAndRedirectsBackWithSuccessMes $this->be($user); $questionnaire = Questionnaire::factory()->create(); - $response = $this->post(route('questionnaire.statistics-colors.store', ['questionnaire' => $questionnaire->id]), [ - 'goal_responses_color' => '#FFFFFF', - 'actual_responses_color' => '#000000', - 'total_responses_color' => '#111111', - 'lang_colors' => [ - '1' => '#000000', - '2' => '#111111', - ], - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('questionnaire.statistics-colors.store', ['questionnaire' => $questionnaire->id]), [ + 'goal_responses_color' => '#FFFFFF', + 'actual_responses_color' => '#000000', + 'total_responses_color' => '#111111', + 'lang_colors' => [ + '1' => '#000000', + '2' => '#111111', + ], + ]); $response->assertStatus(302); $response->assertSessionHas('flash_message_success', 'Colors saved!'); @@ -103,10 +106,11 @@ public function saveStatisticsColorsSavesColorsWithWrongInputAndRedirectsBackWit $this->be($user); $questionnaire = Questionnaire::factory()->create(); - $response = $this->post(route('questionnaire.statistics-colors.store', ['questionnaire' => $questionnaire->id]), [ - 'color1' => '#FFFFFF', - 'color2' => '#000000', - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('questionnaire.statistics-colors.store', ['questionnaire' => $questionnaire->id]), [ + 'color1' => '#FFFFFF', + 'color2' => '#000000', + ]); $response->assertStatus(302); $response->assertSessionHas('flash_message_failure', 'Error: 0 Undefined array key "goal_responses_color"'); @@ -124,10 +128,11 @@ public function saveStatisticsColorsHandlesExceptionAndRedirectsBackWithFailureM $mock->shouldReceive('saveStatisticsColors')->andThrow(new \Exception('Test Exception', 123)); }); - $response = $this->post(route('questionnaire.statistics-colors.store', ['questionnaire' => $questionnaire->id]), [ - 'color1' => '#FFFFFF', - 'color2' => '#000000', - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('questionnaire.statistics-colors.store', ['questionnaire' => $questionnaire->id]), [ + 'color1' => '#FFFFFF', + 'color2' => '#000000', + ]); $response->assertStatus(302); $response->assertSessionHas('flash_message_failure', 'Error: 123 Test Exception'); diff --git a/tests/Feature/Controllers/UserControllerTest.php b/tests/Feature/Controllers/UserControllerTest.php index 1c466c21..580d0f95 100644 --- a/tests/Feature/Controllers/UserControllerTest.php +++ b/tests/Feature/Controllers/UserControllerTest.php @@ -3,6 +3,7 @@ namespace Tests\Feature\Controllers; use App\BusinessLogicLayer\lkp\UserRolesLkp; +use App\Http\Middleware\VerifyCsrfToken; use App\Models\User; use App\Models\UserRole; use Tests\TestCase; @@ -51,12 +52,13 @@ public function patchUpdatesUserProfileWithValidData() { $user = User::factory()->create(); $this->be($user); - $response = $this->post(route('updateUser'), [ - 'nickname' => 'updated-nickname', - 'password' => '12345678', - 'password_confirmation' => '12345678', - 'current_password' => 'password', - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('updateUser'), [ + 'nickname' => 'updated-nickname', + 'password' => '12345678', + 'password_confirmation' => '12345678', + 'current_password' => 'password', + ]); $response->assertStatus(302); $response->assertSessionHas('flash_message_success', 'Profile updated.'); @@ -68,12 +70,13 @@ public function patchUpdatesUserProfileWithValidData() { /** @test */ public function patchRedirectsToLoginForUnauthenticatedUser() { - $response = $this->post(route('updateUser'), [ - 'nickname' => 'updated-nickname', - 'password' => '12345678', - 'password_confirmation' => '12345678', - 'current_password' => 'password', - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('updateUser'), [ + 'nickname' => 'updated-nickname', + 'password' => '12345678', + 'password_confirmation' => '12345678', + 'current_password' => 'password', + ]); $response->assertStatus(302); $response->assertRedirect(route('login', ['locale' => 'en'])); @@ -84,10 +87,11 @@ public function patchHandlesInvalidDataCorrectly() { $user = User::factory()->create(); $this->be($user); - $response = $this->post(route('updateUser'), [ - 'nickname' => 'updated-nickname', - 'password' => '1234', - ]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('updateUser'), [ + 'nickname' => 'updated-nickname', + 'password' => '1234', + ]); $response->assertStatus(302); $response->assertSessionHasErrors(['password']); @@ -98,7 +102,8 @@ public function cannotDeleteDeactivatesUserForNonAdminUser() { $user = User::factory()->create(); $this->be($user); - $response = $this->post(route('deleteUser'), ['id' => $user->id]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('deleteUser'), ['id' => $user->id]); $response->assertStatus(403); $this->assertDatabaseHas('users', [ @@ -113,14 +118,14 @@ public function deleteDeactivatesUserForAdminUser() { ->has(UserRole::factory()->state(['role_id' => UserRolesLkp::ADMIN])) ->create(); $this->be($user); - $now = now()->toDateTimeString(); - $response = $this->post(route('deleteUser'), ['id' => $user->id]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('deleteUser'), ['id' => $user->id]); $response->assertStatus(302); $response->assertSessionHas('flash_message_success', 'User deleted.'); $this->assertDatabaseHas('users', [ 'id' => $user->id, - 'deleted_at' => $now, + 'deleted_at' => \DB::raw('deleted_at IS NOT NULL'), ]); } @@ -128,7 +133,8 @@ public function deleteDeactivatesUserForAdminUser() { public function deleteRedirectsToLoginForUnauthenticatedUser() { $user = User::factory()->create(); - $response = $this->post(route('deleteUser'), ['id' => $user->id]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('deleteUser'), ['id' => $user->id]); $response->assertStatus(302); $response->assertRedirect(route('login', ['locale' => 'en'])); @@ -141,7 +147,8 @@ public function deleteHandlesInvalidUserIdCorrectly() { ->create(); $this->be($user); - $response = $this->post(route('deleteUser'), ['id' => 999]); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->post(route('deleteUser'), ['id' => 999]); $response->assertStatus(404); } @@ -173,7 +180,8 @@ public function nonAdminUserCannotGetUsersByCriteria() { $user = User::factory()->create(); $this->be($user); - $response = $this->get(route('filterUsers')); + $response = $this->withoutMiddleware(VerifyCsrfToken::class) + ->get(route('filterUsers')); $response->assertStatus(403); } From b221acf2225db5324b17142072f453e422baa45a Mon Sep 17 00:00:00 2001 From: Paul Isaris Date: Fri, 4 Oct 2024 16:46:07 +0300 Subject: [PATCH 2/2] Refactored projects that are shown in the home page --- .../CrowdSourcingProjectManager.php | 23 +++---------------- app/Http/Controllers/HomeController.php | 3 +-- .../Questionnaire/QuestionnaireController.php | 16 +++++++------ .../CrowdSourcingProjectRepository.php | 10 +------- .../partials/projects-list-home.blade.php | 2 +- .../home/partials/together/projects.blade.php | 15 +----------- 6 files changed, 16 insertions(+), 53 deletions(-) diff --git a/app/BusinessLogicLayer/CrowdSourcingProject/CrowdSourcingProjectManager.php b/app/BusinessLogicLayer/CrowdSourcingProject/CrowdSourcingProjectManager.php index a172eb46..eeaee7ed 100644 --- a/app/BusinessLogicLayer/CrowdSourcingProject/CrowdSourcingProjectManager.php +++ b/app/BusinessLogicLayer/CrowdSourcingProject/CrowdSourcingProjectManager.php @@ -4,7 +4,6 @@ use App\BusinessLogicLayer\gamification\ContributorBadge; use App\BusinessLogicLayer\lkp\CrowdSourcingProjectStatusLkp; -use App\BusinessLogicLayer\lkp\QuestionnaireStatusLkp; use App\BusinessLogicLayer\questionnaire\QuestionnaireGoalManager; use App\BusinessLogicLayer\UserManager; use App\Models\CrowdSourcingProject\CrowdSourcingProject; @@ -67,28 +66,12 @@ public function __construct(CrowdSourcingProjectRepository $crowdSourcingProject public function getCrowdSourcingProjectsForHomePage(): Collection { $projects = $this->crowdSourcingProjectRepository->getActiveProjectsWithAtLeastOneQuestionnaireWithStatus(); - $projectsWithFinalizedQuestionnaires = $this->crowdSourcingProjectRepository->getActiveProjectsWithAtLeastOneQuestionnaireWithStatus([], QuestionnaireStatusLkp::FINALIZED); - // for each project in the finalized ones, - // if it does not exist in the collection of the projects with active questionnaires, - // add it there. - foreach ($projectsWithFinalizedQuestionnaires as $project) { - if (!$projects->contains('id', $project->id)) { - $projects->push($project); - } - } - - foreach ($projects as $project) { - $project->currentTranslation = $this->crowdSourcingProjectTranslationManager->getFieldsTranslationForProject($project); - $project->latestQuestionnaire = $project->questionnaires->last(); - } - return $projects; - } - - public function getPastCrowdSourcingProjectsForHomePage(): Collection { - $projects = $this->crowdSourcingProjectRepository->getPastProjects(); foreach ($projects as $project) { $project->currentTranslation = $this->crowdSourcingProjectTranslationManager->getFieldsTranslationForProject($project); + if ($project->questionnaires->count() > 0) { + $project->latestQuestionnaire = $project->questionnaires->last(); + } } return $projects; diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index d84d0c62..844c87f7 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -15,9 +15,8 @@ public function __construct(CrowdSourcingProjectManager $crowdSourcingProjectMan public function showHomePage() { $projects = $this->crowdSourcingProjectManager->getCrowdSourcingProjectsForHomePage(); - $pastProjects = $this->crowdSourcingProjectManager->getPastCrowdSourcingProjectsForHomePage(); - return view('home.home')->with(['projects' => $projects, 'pastProjects' => $pastProjects]); + return view('home.home')->with(['projects' => $projects]); } public function showTermsAndPrivacyPage() { diff --git a/app/Http/Controllers/Questionnaire/QuestionnaireController.php b/app/Http/Controllers/Questionnaire/QuestionnaireController.php index a0a6fbc6..4f47c665 100644 --- a/app/Http/Controllers/Questionnaire/QuestionnaireController.php +++ b/app/Http/Controllers/Questionnaire/QuestionnaireController.php @@ -25,11 +25,11 @@ class QuestionnaireController extends Controller { protected QuestionnaireTranslator $questionnaireTranslator; protected QuestionnaireLanguageManager $questionnaireLanguageManager; - public function __construct(QuestionnaireManager $questionnaireManager, - UserQuestionnaireShareManager $questionnaireShareManager, - QuestionnaireVMProvider $questionnaireVMProvider, - QuestionnaireTranslator $questionnaireTranslator, - QuestionnaireLanguageManager $questionnaireLanguageManager) { + public function __construct(QuestionnaireManager $questionnaireManager, + UserQuestionnaireShareManager $questionnaireShareManager, + QuestionnaireVMProvider $questionnaireVMProvider, + QuestionnaireTranslator $questionnaireTranslator, + QuestionnaireLanguageManager $questionnaireLanguageManager) { $this->questionnaireManager = $questionnaireManager; $this->questionnaireShareManager = $questionnaireShareManager; $this->questionnaireVMProvider = $questionnaireVMProvider; @@ -60,8 +60,9 @@ public function createQuestionnaire() { public function store(Request $request) { $data = $request->all(); - if (!isset($data['status_id'])) + if (!isset($data['status_id'])) { $data['status_id'] = QuestionnaireStatusLkp::DRAFT; + } $this->validate($request, [ 'type_id' => 'required|integer', @@ -74,8 +75,9 @@ public function store(Request $request) { 'project_ids' => 'required|array', ]); $questionnaire = $this->questionnaireManager->storeOrUpdateQuestionnaire($data); - if (isset($data['lang_codes']) && count($data['lang_codes']) > 0) + if (isset($data['lang_codes']) && count($data['lang_codes']) > 0) { $this->questionnaireLanguageManager->saveLanguagesForQuestionnaire($data['lang_codes'], $questionnaire->id); + } return $questionnaire; } diff --git a/app/Repository/CrowdSourcingProject/CrowdSourcingProjectRepository.php b/app/Repository/CrowdSourcingProject/CrowdSourcingProjectRepository.php index a06775da..7980bc69 100644 --- a/app/Repository/CrowdSourcingProject/CrowdSourcingProjectRepository.php +++ b/app/Repository/CrowdSourcingProject/CrowdSourcingProjectRepository.php @@ -6,7 +6,6 @@ use App\BusinessLogicLayer\lkp\QuestionnaireStatusLkp; use App\Models\CrowdSourcingProject\CrowdSourcingProject; use App\Repository\Repository; -use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Collection; class CrowdSourcingProjectRepository extends Repository { @@ -23,9 +22,6 @@ public function getActiveProjectsWithAtLeastOneQuestionnaireWithStatus( $additionalRelationships = [], $questionnaireStatusId = QuestionnaireStatusLkp::PUBLISHED ): Collection { $builder = CrowdSourcingProject::where(['status_id' => CrowdSourcingProjectStatusLkp::PUBLISHED]) - ->whereHas('questionnaires', function (Builder $query) use ($questionnaireStatusId) { - $query->where(['status_id' => $questionnaireStatusId]); - }) ->with('questionnaires', function ($query) use ($questionnaireStatusId) { $query->select(['id', 'prerequisite_order', 'status_id', 'default_language_id', 'goal', 'statistics_page_visibility_lkp_id', 'questionnaires.created_at as questionnaire_created', ]) @@ -33,7 +29,7 @@ public function getActiveProjectsWithAtLeastOneQuestionnaireWithStatus( ->withCount('responses') ->orderBy('prerequisite_order') ->orderBy('questionnaire_created', 'desc'); - }); + })->with('problems'); if (count($additionalRelationships)) { $builder = $builder->with($additionalRelationships); @@ -41,8 +37,4 @@ public function getActiveProjectsWithAtLeastOneQuestionnaireWithStatus( return $builder->get(); } - - public function getPastProjects(): Collection { - return CrowdSourcingProject::where(['status_id' => CrowdSourcingProjectStatusLkp::FINALIZED])->get(); - } } diff --git a/resources/views/home/partials/projects-list-home.blade.php b/resources/views/home/partials/projects-list-home.blade.php index dc08e516..80f8eadb 100644 --- a/resources/views/home/partials/projects-list-home.blade.php +++ b/resources/views/home/partials/projects-list-home.blade.php @@ -11,7 +11,7 @@ {!! $project->currentTranslation->motto_title !!} -@if(isset($pastProjects)) -
-
-
-
-

Check out our past projects:

-
-
-
- @include('home.partials.projects-list-home', ['projects' => $pastProjects, 'projectBtnText' => 'See more']) -
-
-
-@endif