mirror of https://github.com/Devoalda/LaDo.git
test(Project and Todo Tests):
Created test cases for project and todo functionality + validations
This commit is contained in:
parent
6dbeb8e992
commit
6e4c8f68e0
|
@ -20,14 +20,16 @@ class ProjectTodoController extends Controller
|
||||||
/**
|
/**
|
||||||
* Display a listing of all Todos for a Project.
|
* Display a listing of all Todos for a Project.
|
||||||
*/
|
*/
|
||||||
public function index($project_id)
|
public function index($project_id): Factory|Application|View|\Illuminate\Contracts\Foundation\Application|RedirectResponse
|
||||||
{
|
{
|
||||||
$user = User::find(auth()->user()->id);
|
$user = User::find(auth()->user()->id);
|
||||||
$projects = $user->projects;
|
$projects = $user->projects;
|
||||||
$project = $projects->find($project_id);
|
$project = $projects->find($project_id);
|
||||||
|
|
||||||
if (!$project || $project->user->id !== auth()->user()->id)
|
if (!$project || $project->user->id !== auth()->user()->id)
|
||||||
return back()->with('error', 'Project not found');
|
return back()
|
||||||
|
->with('error', 'Project not found')
|
||||||
|
->setStatusCode(404);
|
||||||
|
|
||||||
$todos = $project->todos;
|
$todos = $project->todos;
|
||||||
|
|
||||||
|
@ -56,24 +58,14 @@ class ProjectTodoController extends Controller
|
||||||
{
|
{
|
||||||
$validatedData = $request->validated();
|
$validatedData = $request->validated();
|
||||||
|
|
||||||
$due_end = match (true) {
|
|
||||||
isset($validatedData['due_end']) => strtotime($validatedData['due_end']),
|
|
||||||
isset($validatedData['due_start']) => strtotime($validatedData['due_start']),
|
|
||||||
default => null,
|
|
||||||
};
|
|
||||||
|
|
||||||
$validatedData = array_merge($validatedData, [
|
|
||||||
// due_end = due_start if due_end is not provided and due_start is provided or null
|
|
||||||
'due_end' => $due_end,
|
|
||||||
'user_id' => auth()->user()->id,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Modify all dates to unix timestamp
|
|
||||||
if(isset($validatedData['due_start']))
|
if(isset($validatedData['due_start']))
|
||||||
$validatedData['due_start'] = strtotime($validatedData['due_start']);
|
$validatedData['due_start'] = strtotime($validatedData['due_start']);
|
||||||
|
|
||||||
if (isset($validatedData['due_end']))
|
if (isset($validatedData['due_end']))
|
||||||
$validatedData['due_end'] = strtotime($validatedData['due_end']);
|
$validatedData['due_end'] = strtotime($validatedData['due_end']);
|
||||||
|
elseif (isset($validatedData['due_start']))
|
||||||
|
$validatedData['due_end'] = $validatedData['due_start'];
|
||||||
|
//
|
||||||
$todo = new Todo($validatedData);
|
$todo = new Todo($validatedData);
|
||||||
|
|
||||||
$user = User::find(auth()->user()->id);
|
$user = User::find(auth()->user()->id);
|
||||||
|
@ -82,7 +74,8 @@ class ProjectTodoController extends Controller
|
||||||
$project->todos()->save($todo);
|
$project->todos()->save($todo);
|
||||||
|
|
||||||
return redirect()->route('project.todo.index', $project_id)
|
return redirect()->route('project.todo.index', $project_id)
|
||||||
->with('success', 'Todo created successfully.');
|
->with('success', 'Todo created successfully.')
|
||||||
|
->setStatusCode(201);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -156,7 +149,8 @@ class ProjectTodoController extends Controller
|
||||||
|
|
||||||
$todo->update($data);
|
$todo->update($data);
|
||||||
|
|
||||||
return back()->with('success', 'Todo updated successfully');
|
return back()
|
||||||
|
->with('success', 'Todo updated successfully');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -26,7 +26,7 @@ class StoreTodoRequest extends FormRequest
|
||||||
'title' => 'required|string|max:255',
|
'title' => 'required|string|max:255',
|
||||||
'description' => 'nullable|string|max:255',
|
'description' => 'nullable|string|max:255',
|
||||||
'due_start' => 'nullable|date',
|
'due_start' => 'nullable|date',
|
||||||
'due_end' => 'nullable|date',
|
'due_end' => 'nullable|date|after_or_equal:due_start',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,4 +127,21 @@ class ProjectCRUDTest extends TestCase
|
||||||
$response->assertNotFound();
|
$response->assertNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_other_user_cannot_see_user_projects(): void
|
||||||
|
{
|
||||||
|
$this->test_user_can_create_project();
|
||||||
|
// Test if the current user can see the project
|
||||||
|
$this->actingAs($this->user);
|
||||||
|
$response = $this->get(route('project.index'));
|
||||||
|
$response->assertSee('Test Project');
|
||||||
|
$response->assertSee('Test Description');
|
||||||
|
|
||||||
|
// Test if another user can see the project
|
||||||
|
$this->actingAs(User::factory()->create());
|
||||||
|
$response = $this->get(route('project.index'));
|
||||||
|
$response->assertDontSee('Test Project');
|
||||||
|
$response->assertDontSee('Test Description');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,210 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature\Project;
|
||||||
|
|
||||||
|
use App\Models\Project;
|
||||||
|
use App\Models\Todo;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class TodoCRUDTest extends TestCase
|
||||||
|
{
|
||||||
|
use RefreshDatabase;
|
||||||
|
|
||||||
|
private User $user;
|
||||||
|
|
||||||
|
private Project $project;
|
||||||
|
private Todo $todo;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
$this->actingAs($user = User::factory()->create());
|
||||||
|
$this->user = $user;
|
||||||
|
$this->assertAuthenticated();
|
||||||
|
// Create a project through POST and store it in the project property
|
||||||
|
$response = $this->post(route('project.store'), [
|
||||||
|
'name' => 'Test Project',
|
||||||
|
'description' => 'Test Description',
|
||||||
|
]);
|
||||||
|
$response->assertRedirect(route('project.index'));
|
||||||
|
$this->assertDatabaseHas('projects', [
|
||||||
|
'name' => 'Test Project',
|
||||||
|
'description' => 'Test Description',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertDatabaseHas('project_user', [
|
||||||
|
'project_id' => Project::where('name', 'Test Project')->first()->id,
|
||||||
|
'user_id' => $this->user->id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->project = Project::where('name', 'Test Project')->first();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_user_can_create_todo(): void
|
||||||
|
{
|
||||||
|
$response = $this->post(route('project.todo.store', $this->project->id), [
|
||||||
|
'title' => 'Test Todo',
|
||||||
|
'description' => 'Test Description',
|
||||||
|
]);
|
||||||
|
$response->assertRedirect(route('project.todo.index', $this->project->id));
|
||||||
|
|
||||||
|
$this->todo = Todo::where('title', 'Test Todo')->first();
|
||||||
|
|
||||||
|
$this->assertDatabaseHas('todos', [
|
||||||
|
'title' => 'Test Todo',
|
||||||
|
'description' => 'Test Description',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertDatabaseHas('project_todo', [
|
||||||
|
'project_id' => $this->project->id,
|
||||||
|
'todo_id' => Todo::where('title', 'Test Todo')->first()->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_user_can_view_todo(): void
|
||||||
|
{
|
||||||
|
$this->test_user_can_create_todo();
|
||||||
|
$this->assertAuthenticated();
|
||||||
|
$response = $this->get(route('project.index'));
|
||||||
|
$response->assertSee('Test Todo');
|
||||||
|
$response->assertSee('Test Description');
|
||||||
|
|
||||||
|
$response = $this->get(route('project.todo.index', $this->project->id));
|
||||||
|
$response->assertSee('Test Todo');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_user_can_update_todo(): void
|
||||||
|
{
|
||||||
|
$this->test_user_can_create_todo();
|
||||||
|
$this->assertAuthenticated();
|
||||||
|
$response = $this->put(route('project.todo.update', [$this->project->id, $this->todo->id]), [
|
||||||
|
'title' => 'Updated Todo',
|
||||||
|
'description' => 'Updated Description',
|
||||||
|
]);
|
||||||
|
$response->assertRedirect(back()->getTargetUrl());
|
||||||
|
|
||||||
|
$this->assertDatabaseHas('todos', [
|
||||||
|
'title' => 'Updated Todo',
|
||||||
|
'description' => 'Updated Description',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertDatabaseMissing('todos', [
|
||||||
|
'title' => 'Test Todo',
|
||||||
|
'description' => 'Test Description',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response = $this->get(route('project.todo.index', $this->project->id));
|
||||||
|
$response->assertSee('Updated Todo');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_user_can_delete_todo(): void
|
||||||
|
{
|
||||||
|
$this->test_user_can_create_todo();
|
||||||
|
$this->assertAuthenticated();
|
||||||
|
$response = $this->delete(route('project.todo.destroy', [$this->project->id, $this->todo->id]));
|
||||||
|
$response->assertRedirect(route('project.todo.index', $this->project->id));
|
||||||
|
|
||||||
|
$this->assertDatabaseMissing('todos', [
|
||||||
|
'title' => 'Test Todo',
|
||||||
|
'description' => 'Test Description',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response = $this->get(route('project.todo.index', $this->project->id));
|
||||||
|
$response->assertDontSee('Test Todo');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional Create Tests
|
||||||
|
public function test_user_can_create_todo_with_due_start_only(): void
|
||||||
|
{
|
||||||
|
$this->assertAuthenticated();
|
||||||
|
$response = $this->post(route('project.todo.store', $this->project->id), [
|
||||||
|
'title' => 'Test Todo',
|
||||||
|
'description' => 'Test Description',
|
||||||
|
'due_start' => '2020-01-01',
|
||||||
|
]);
|
||||||
|
$response->assertRedirect(route('project.todo.index', $this->project->id));
|
||||||
|
|
||||||
|
$this->assertDatabaseHas('todos', [
|
||||||
|
'title' => 'Test Todo',
|
||||||
|
'description' => 'Test Description',
|
||||||
|
'due_start' => '1577836800',
|
||||||
|
'due_end' => '1577836800',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertDatabaseHas('project_todo', [
|
||||||
|
'project_id' => $this->project->id,
|
||||||
|
'todo_id' => Todo::where('title', 'Test Todo')->first()->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_user_can_create_todo_with_due_end_only(): void
|
||||||
|
{
|
||||||
|
$this->assertAuthenticated();
|
||||||
|
$response = $this->post(route('project.todo.store', $this->project->id), [
|
||||||
|
'title' => 'Test Todo',
|
||||||
|
'description' => 'Test Description',
|
||||||
|
'due_end' => '2020-01-01',
|
||||||
|
]);
|
||||||
|
$response->assertRedirect(route('project.todo.index', $this->project->id));
|
||||||
|
|
||||||
|
$this->assertDatabaseHas('todos', [
|
||||||
|
'title' => 'Test Todo',
|
||||||
|
'description' => 'Test Description',
|
||||||
|
'due_start' => null,
|
||||||
|
'due_end' => '1577836800',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertDatabaseHas('project_todo', [
|
||||||
|
'project_id' => $this->project->id,
|
||||||
|
'todo_id' => Todo::where('title', 'Test Todo')->first()->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional Update Tests
|
||||||
|
public function test_user_can_complete_todo_only(): void
|
||||||
|
{
|
||||||
|
$this->test_user_can_create_todo();
|
||||||
|
$this->assertAuthenticated();
|
||||||
|
// Send a PUT request to update route, with "completed_at" set to on
|
||||||
|
$response = $this->put(route('project.todo.update', [$this->project->id, $this->todo->id]), [
|
||||||
|
'title' => 'Updated Todo',
|
||||||
|
'completed_at' => 'on',
|
||||||
|
]);
|
||||||
|
$response->assertRedirect(back()->getTargetUrl());
|
||||||
|
|
||||||
|
// Check that the todo is completed in database completed_at value is not null
|
||||||
|
$completedTodo = $this->user->projects()->first()->todos()->first();
|
||||||
|
$this->assertNotNull($completedTodo->completed_at);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_user_can_uncomplete_todo(): void
|
||||||
|
{
|
||||||
|
$this->test_user_can_complete_todo_only();
|
||||||
|
$this->assertAuthenticated();
|
||||||
|
// Send a PUT request to update route with empty data
|
||||||
|
$response = $this->put(route('project.todo.update', [$this->project->id, $this->todo->id]), []);
|
||||||
|
$response->assertRedirect(back()->getTargetUrl());
|
||||||
|
|
||||||
|
// Check that the todo is completed in database completed_at value is not null
|
||||||
|
$uncompletedTodo = $this->user->projects()->first()->todos()->first();
|
||||||
|
$this->assertNull($uncompletedTodo->completed_at);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional Retrieve Tests (Validation for unauthorized users)
|
||||||
|
public function test_other_user_cannot_see_user_todo(): void
|
||||||
|
{
|
||||||
|
$this->test_user_can_create_todo();
|
||||||
|
$this->assertAuthenticated();
|
||||||
|
$otherUser = User::factory()->create();
|
||||||
|
$this->actingAs($otherUser);
|
||||||
|
$response = $this->get(route('project.todo.index', $this->project->id));
|
||||||
|
$response->assertStatus(404);
|
||||||
|
$response->assertDontSee('Test Todo');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue