Skip to content

Commit

Permalink
- Fixed nullable img url in solutions
Browse files Browse the repository at this point in the history
- Added tests for propose solution method
- Fixed some minor bugs
  • Loading branch information
PavlosIsaris committed Dec 11, 2024
1 parent 2f5a4fe commit e438137
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 54 deletions.
7 changes: 2 additions & 5 deletions .github/workflows/laravel-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,8 @@ jobs:
- name: Cache
run: php artisan config:cache --env=testing

- name: Run the migrations in the testing environment
run: php artisan migrate --env=testing --database=sqlite_testing

- name: Run the seeders in the testing environment
run: php artisan db:seed --env=testing --database=sqlite_testing
- name: Run the migrations & seeders in the testing environment
run: php artisan migrate:fresh --seed --env=testing

- name: Execute tests (Unit and Feature tests) via PHPUnit
run: php artisan test --env=testing
10 changes: 2 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -442,16 +442,10 @@ php artisan config:clear

Then, make sure that you have set up the test database:

First you need to run the migrations for the test database:
Run the migrations & seeders for the test database:

```bash
php artisan migrate --env=testing --database=sqlite_testing
```

Then run the seeders for the test database:

```bash
php artisan db:seed --env=testing --database=sqlite_testing
php artisan migrate:fresh --seed --env=testing
```

### PHPUnit with the `php artisan test` command
Expand Down
2 changes: 2 additions & 0 deletions app/BusinessLogicLayer/Solution/SolutionManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ public function storeSolutionFromPublicForm(array $attributes): int {
protected function storeSolutionWithStatus(array $attributes, int $status_id): int {
if (isset($attributes['solution-image']) && $attributes['solution-image']->isValid()) {
$imgPath = FileHandler::uploadAndGetPath($attributes['solution-image'], 'solution_img');
} else {
$imgPath = null;
}
$solution_owner_problem_id = $attributes['solution-owner-problem'];

Expand Down
46 changes: 8 additions & 38 deletions app/Http/Controllers/Solution/SolutionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,16 @@ public function create(Request $request): View|RedirectResponse {
* Store a newly created resource in storage.
*/
public function store(Request $request): RedirectResponse {
$this->validate($request, [
$validated = $this->validate($request, [
'solution-title' => ['required', 'string', 'max:100'],
'solution-description' => ['required', 'string', 'max:400'],
'solution-status' => ['required'],
'solution-image' => 'nullable|image|mimes:jpeg,png,jpg,webp|max:2048',
'solution-owner-problem' => ['required'],
]);

$attributes = $request->validated();

try {
$createdSolutionId = $this->solutionManager->storeSolution($attributes);
$createdSolutionId = $this->solutionManager->storeSolution($validated);
} catch (\Exception $e) {
session()->flash('flash_message_error', 'Error: ' . $e->getCode() . ' ' . $e->getMessage());

Expand All @@ -73,15 +71,15 @@ public function store(Request $request): RedirectResponse {
}

public function userProposalStore(Request $request): RedirectResponse {
$this->validate($request, [
$validated = $this->validate($request, [
'solution-title' => ['required', 'string', 'max:100'],
'solution-description' => ['required', 'string', 'max:400'],
'solution-image' => 'nullable|image|mimes:jpeg,png,jpg,webp|max:2048',
'solution-owner-problem' => ['required'],
]);

try {
$createdSolutionId = $this->solutionManager->storeSolutionFromPublicForm($request->validated());
$this->solutionManager->storeSolutionFromPublicForm($validated);
} catch (\Exception $e) {
session()->flash('flash_message_error', 'Error: ' . $e->getCode() . ' ' . $e->getMessage());

Expand All @@ -90,7 +88,8 @@ public function userProposalStore(Request $request): RedirectResponse {

session()->flash('flash_message_success', 'Solution Created Successfully.');

return redirect()->route('public-solution-thanks', ['solution_id' => $createdSolutionId]);
// redirect to the same route as the current one, with a "/solution-submitted" suffix
return redirect($request->path() . '/solution-submitted');
}

/**
Expand Down Expand Up @@ -120,7 +119,7 @@ public function edit(Request $request, string $locale, int $id) {
* Update the specified resource in storage.
*/
public function update(Request $request, string $locale, int $id) {
$this->validate($request, [
$validated = $this->validate($request, [
'solution-title' => ['required', 'string', 'max:100'],
'solution-description' => ['required', 'string', 'max:400'],
'solution-status' => ['required'],
Expand All @@ -129,10 +128,8 @@ public function update(Request $request, string $locale, int $id) {
'solution-owner-problem' => ['required'],
]);

$attributes = $request->validated();

try {
$this->solutionManager->updateSolution($id, $attributes);
$this->solutionManager->updateSolution($id, $validated);
} catch (\Exception $e) {
session()->flash('flash_message_error', 'Error: ' . $e->getCode() . ' ' . $e->getMessage());

Expand Down Expand Up @@ -201,33 +198,6 @@ public function userProposalCreate(string $locale, string $project_slug, string
}
}

// public function userProposalStore(Request $request): RedirectResponse {
// return 'user ProposalStore';
// $this->validate($request, [
// 'solution-title' => ['required', 'string', 'max:100'],
// 'solution-description' => ['required', 'string', 'max:400'],
// 'solution-status' => ['required'],
// 'solution-image' => 'nullable|image|mimes:jpeg,png,jpg|max:2048',
// 'solution-owner-problem' => ['required'],
// ]);

// $attributes = $request->all();

// try {
// $createdSolutionId = $this->solutionManager->storeSolution($attributes);
// } catch (\Exception $e) {
// session()->flash('flash_message_error', 'Error: ' . $e->getCode() . ' ' . $e->getMessage());

// return back()->withInput();
// }

// session()->flash('flash_message_success', 'Solution Created Successfully.');

// $route = route('solutions.edit', ['solution' => $createdSolutionId]) . '?translations=1';

// return redirect($route);
// }

public function userProposalSubmitted(Request $request) {
return 'userProposalSubmitted';
}
Expand Down
5 changes: 5 additions & 0 deletions app/Models/Problem/Problem.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Models\Problem;

use App\Models\CrowdSourcingProject\CrowdSourcingProject;
use App\Models\Solution\Solution;
use Awobaz\Compoships\Compoships;
use Illuminate\Database\Eloquent\Factories\HasFactory;
Expand Down Expand Up @@ -40,6 +41,10 @@ public function solutions(): HasMany {
return $this->hasMany(Solution::class, 'problem_id', 'id');
}

public function project(): HasOne {
return $this->hasOne(CrowdSourcingProject::class, 'id', 'project_id');
}

//observe this model being deleted and delete the related records
public static function boot() {
parent::boot();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void {
Schema::table('solutions', function (Blueprint $table) {
$table->string('img_url')->nullable()->change();
});
}

/**
* Reverse the migrations.
*/
public function down(): void {
Schema::table('solutions', function (Blueprint $table) {
//
});
}
};
82 changes: 82 additions & 0 deletions tests/Feature/Controllers/Solution/SolutionControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

namespace Feature\Controllers\Solution;

use App\BusinessLogicLayer\lkp\SolutionStatusLkp;
use App\Http\Middleware\VerifyCsrfToken;
use App\Models\Problem\Problem;
use App\Models\Solution\Solution;
use App\Models\Solution\SolutionTranslation;
use App\Models\User\User;
use Faker\Factory as Faker;
use Tests\TestCase;

class SolutionControllerTest extends TestCase {
Expand All @@ -23,4 +30,79 @@ public function test_user_proposal_create_redirects_to_login_page_when_user_is_n

$response->assertRedirectContains(route('login', ['locale' => 'en']));
}

/**
* @test
*
* @group solution-controller-test
*
* Test Scenario 2:
* GIVEN that a user is authenticated,
*
* AND they try to access the solution propose page,
* THEN they should be able to access the page.
*
* @return void
*/
public function test_user_proposal_create_page_is_accessible_when_user_is_authenticated() {
$user = User::factory()->create();

// get the problem with id 1
$problem = Problem::findOrfail(1);
$route = route('solutions.user-proposal-create', ['locale' => 'en', 'project_slug' => $problem->project->slug, 'problem_slug' => $problem->slug]);

$response = $this->actingAs($user)->get($route);

$response->assertOk();
}

/**
* @test
*
* @group solution-controller-test
*
* Test Scenario 3:
* GIVEN that a user is authenticated,
*
* AND they submit a solution proposal,
* AND the data is valid,
* THEN the solution should be stored in the database.
* AND the solution should be associated with the problem.
* AND the solution should have an "UNPUBLISHED" status.
*
* @return void
*/
public function test_user_proposal_store_stores_solution_in_database_when_data_is_valid() {
$user = User::factory()->create();

// get the problem with id 1
$problem = Problem::findOrfail(1);
$route = route('solutions.user-proposal-store', ['locale' => 'en', 'project_slug' => $problem->project->slug, 'problem_slug' => $problem->slug]);

$faker = Faker::create();

$name = $faker->name;
$description = $faker->text;

$response = $this->actingAs($user)->withoutMiddleware(VerifyCsrfToken::class)
->post($route, [
'solution-title' => $name,
'solution-description' => $description,
'solution-owner-problem' => 1,
]);

$response->assertRedirectContains(
route('solutions.user-proposal-submitted',
['locale' => 'en', 'project_slug' => $problem->project->slug, 'problem_slug' => $problem->slug]
)
);

$response->assertStatus(302);

$solution = SolutionTranslation::where('title', $name)->first()->solution;

$this->assertNotNull($solution);
$this->assertEquals(SolutionStatusLkp::UNPUBLISHED, $solution->status_id);
$this->assertEquals($problem->id, $solution->problem_id);
}
}
3 changes: 0 additions & 3 deletions tests/Unit/Controllers/UserControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,10 @@
use App\Models\User\User;
use App\ViewModels\Gamification\GamificationBadgesWithLevels;
use App\ViewModels\User\UserDashboardViewModel;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Auth;
use Tests\TestCase;

class UserControllerTest extends TestCase {
use RefreshDatabase;

private User $user;
private UserDashboardManager $userDashboardManager;
private UserManager $userManager;
Expand Down

0 comments on commit e438137

Please sign in to comment.