Skip to content
Permalink
Browse files

Episode 14 Complete

  • Loading branch information...
JeffreyWay committed Jan 14, 2019
1 parent 0533ad7 commit 10c753148feec2430ecd2d2177c64d361cc3d343
@@ -3,21 +3,49 @@
namespace App\Http\Controllers;
use App\Project;
use App\Task;
class ProjectTasksController extends Controller
{
/**
* Add a task to the given project.
*
* @param \App\Project $project
* @param Project $project
* @return \Illuminate\Http\RedirectResponse
*/
public function store(Project $project)
{
if (auth()->user()->isNot($project->owner)) {
abort(403);
}
request()->validate(['body' => 'required']);
$project->addTask(request('body'));
return redirect($project->path());
}
/**
* Update the project.
*
* @param Project $project
* @param Task $task
* @return \Illuminate\Http\RedirectResponse
*/
public function update(Project $project, Task $task)
{
if (auth()->user()->isNot($project->owner)) {
abort(403);
}
request()->validate(['body' => 'required']);
$task->update([
'body' => request('body'),
'completed' => request()->has('completed')
]);
return redirect($project->path());
}
}
@@ -56,8 +56,8 @@ public function store()
'description' => 'required'
]);
auth()->user()->projects()->create($attributes);
$project = auth()->user()->projects()->create($attributes);
return redirect('/projects');
return redirect($project->path());
}
}
@@ -12,4 +12,24 @@ class Task extends Model
* @var array
*/
protected $guarded = [];
/**
* Get the owning project.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function project()
{
return $this->belongsTo(Project::class);
}
/**
* Get the path to the task.
*
* @return string
*/
public function path()
{
return "/projects/{$this->project->id}/tasks/{$this->id}";
}
}
@@ -6,8 +6,6 @@
return [
'title' => $faker->sentence(4),
'description' => $faker->sentence(4),
'owner_id' => function () {
return factory(App\User::class)->create()->id;
}
'owner_id' => factory(App\User::class)
];
});
@@ -4,6 +4,7 @@
$factory->define(App\Task::class, function (Faker $faker) {
return [
'body' => $faker->sentence
'body' => $faker->sentence,
'project_id' => factory(\App\Project::class)
];
});
@@ -17,6 +17,7 @@ public function up()
$table->increments('id');
$table->unsignedInteger('project_id');
$table->text('body');
$table->boolean('completed')->default(false);
$table->timestamps();
});
}
@@ -4,7 +4,8 @@
<header class="flex items-center mb-3 py-4">
<div class="flex justify-between items-end w-full">
<p class="text-grey text-sm font-normal">
<a href="/projects" class="text-grey text-sm font-normal no-underline hover:underline">My Projects</a> / {{ $project->title }}
<a href="/projects" class="text-grey text-sm font-normal no-underline hover:underline">My Projects</a>
/ {{ $project->title }}
</p>

<a href="/projects/create" class="button">New Project</a>
@@ -19,8 +20,26 @@

{{-- tasks --}}
@foreach ($project->tasks as $task)
<div class="card mb-3">{{ $task->body }}</div>
<div class="card mb-3">
<form method="POST" action="{{ $task->path() }}">
@method('PATCH')
@csrf

<div class="flex">
<input name="body" value="{{ $task->body }}" class="w-full {{ $task->completed ? 'text-grey' : '' }}">
<input name="completed" type="checkbox" onChange="this.form.submit()" {{ $task->completed ? 'checked' : '' }}>
</div>
</form>
</div>
@endforeach

<div class="card mb-3">
<form action="{{ $project->path() . '/tasks' }}" method="POST">
@csrf

<input placeholder="Add a new task..." class="w-full" name="body">
</form>
</div>
</div>

<div>
@@ -22,6 +22,7 @@
Route::post('/projects', 'ProjectsController@store');
Route::post('/projects/{project}/tasks', 'ProjectTasksController@store');
Route::patch('/projects/{project}/tasks/{task}', 'ProjectTasksController@update');
Route::get('/home', 'HomeController@index')->name('home');
});
@@ -2,6 +2,7 @@
namespace Tests\Feature;
use App\Project;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
@@ -35,7 +36,9 @@ public function a_user_can_create_a_project()
'description' => $this->faker->paragraph
];
$this->post('/projects', $attributes)->assertRedirect('/projects');
$response = $this->post('/projects', $attributes);
$response->assertRedirect(Project::where($attributes)->first()->path());
$this->assertDatabaseHas('projects', $attributes);
@@ -18,6 +18,33 @@ public function guests_cannot_add_tasks_to_projects()
$this->post($project->path() . '/tasks')->assertRedirect('login');
}
/** @test */
function only_the_owner_of_a_project_may_add_tasks()
{
$this->signIn();
$project = factory('App\Project')->create();
$this->post($project->path() . '/tasks', ['body' => 'Test task'])
->assertStatus(403);
$this->assertDatabaseMissing('tasks', ['body' => 'Test task']);
}
/** @test */
function only_the_owner_of_a_project_may_update_a_task()
{
$this->signIn();
$project = factory('App\Project')->create();
$task = $project->addTask('test task');
$this->patch($task->path(), ['body' => 'changed'])
->assertStatus(403);
$this->assertDatabaseMissing('tasks', ['body' => 'changed']);
}
/** @test */
public function a_project_can_have_tasks()
{
@@ -33,6 +60,30 @@ public function a_project_can_have_tasks()
->assertSee('Test task');
}
/** @test */
function a_task_can_be_updated()
{
$this->withoutExceptionHandling();
$this->signIn();
$project = auth()->user()->projects()->create(
factory(Project::class)->raw()
);
$task = $project->addTask('test task');
$this->patch($project->path() . '/tasks/' . $task->id, [
'body' => 'changed',
'completed' => true
]);
$this->assertDatabaseHas('tasks', [
'body' => 'changed',
'completed' => true
]);
}
/** @test */
public function a_task_requires_a_body()
{
@@ -0,0 +1,29 @@
<?php
namespace Tests\Unit;
use App\Project;
use App\Task;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class TaskTest extends TestCase
{
use RefreshDatabase;
/** @test */
function it_belongs_to_a_project()
{
$task = factory(Task::class)->create();
$this->assertInstanceOf(Project::class, $task->project);
}
/** @test */
function it_has_a_path()
{
$task = factory(Task::class)->create();
$this->assertEquals("/projects/{$task->project->id}/tasks/{$task->id}", $task->path());
}
}

0 comments on commit 10c7531

Please sign in to comment.
You can’t perform that action at this time.