134 lines
3.9 KiB
PHP
134 lines
3.9 KiB
PHP
<?php
|
|
|
|
use App\Enums\PostStatus;
|
|
use App\Models\Post;
|
|
use App\Models\User;
|
|
|
|
it('redirects guests to login', function () {
|
|
$this->get(route('post.index'))->assertRedirect(route('login'));
|
|
$this->get(route('post.create'))->assertRedirect(route('login'));
|
|
});
|
|
|
|
it('shows only the authenticated users own posts', function () {
|
|
$user = User::factory()->create();
|
|
$otherUser = User::factory()->create();
|
|
|
|
$ownPost = Post::factory()->for($user)->create();
|
|
$otherPost = Post::factory()->for($otherUser)->create();
|
|
|
|
$this->actingAs($user)
|
|
->get(route('post.index'))
|
|
->assertOk()
|
|
->assertSee($ownPost->title)
|
|
->assertDontSee($otherPost->title);
|
|
});
|
|
|
|
it('can create a post', function () {
|
|
$user = User::factory()->create();
|
|
|
|
$this->actingAs($user)
|
|
->post(route('post.store'), [
|
|
'title' => 'Hello World',
|
|
'content' => 'Some content here.',
|
|
'slug' => 'hello-world',
|
|
'status' => PostStatus::Published->value,
|
|
])
|
|
->assertRedirect(route('post.index'));
|
|
|
|
expect(Post::where('slug', 'hello-world')->where('user_id', $user->id)->exists())->toBeTrue();
|
|
});
|
|
|
|
it('validates required fields on create', function () {
|
|
$user = User::factory()->create();
|
|
|
|
$this->actingAs($user)
|
|
->post(route('post.store'), [])
|
|
->assertSessionHasErrors(['title', 'content', 'slug', 'status']);
|
|
});
|
|
|
|
it('enforces unique slug on create', function () {
|
|
$user = User::factory()->create();
|
|
Post::factory()->for($user)->create(['slug' => 'taken-slug']);
|
|
|
|
$this->actingAs($user)
|
|
->post(route('post.store'), [
|
|
'title' => 'Another Post',
|
|
'content' => 'Content.',
|
|
'slug' => 'taken-slug',
|
|
'status' => PostStatus::Draft->value,
|
|
])
|
|
->assertSessionHasErrors('slug');
|
|
});
|
|
|
|
it('can edit own post', function () {
|
|
$user = User::factory()->create();
|
|
$post = Post::factory()->for($user)->published()->create();
|
|
|
|
$this->actingAs($user)
|
|
->get(route('post.edit', $post))
|
|
->assertOk()
|
|
->assertSee($post->title);
|
|
});
|
|
|
|
it('cannot edit another users post', function () {
|
|
$user = User::factory()->create();
|
|
$otherPost = Post::factory()->create();
|
|
|
|
$this->actingAs($user)
|
|
->get(route('post.edit', $otherPost))
|
|
->assertForbidden();
|
|
});
|
|
|
|
it('can update own post', function () {
|
|
$user = User::factory()->create();
|
|
$post = Post::factory()->for($user)->draft()->create();
|
|
|
|
$this->actingAs($user)
|
|
->patch(route('post.update', $post), [
|
|
'title' => 'Updated Title',
|
|
'content' => 'Updated content.',
|
|
'slug' => 'updated-slug',
|
|
'status' => PostStatus::Published->value,
|
|
])
|
|
->assertRedirect(route('post.edit', $post));
|
|
|
|
expect($post->fresh()->title)->toBe('Updated Title')
|
|
->and($post->fresh()->status)->toBe(PostStatus::Published);
|
|
});
|
|
|
|
it('cannot update another users post', function () {
|
|
$user = User::factory()->create();
|
|
$otherPost = Post::factory()->create(['slug' => 'original-slug']);
|
|
|
|
$this->actingAs($user)
|
|
->patch(route('post.update', $otherPost), [
|
|
'title' => 'Hacked',
|
|
'content' => 'Hacked content.',
|
|
'slug' => 'hacked-slug',
|
|
'status' => PostStatus::Published->value,
|
|
])
|
|
->assertForbidden();
|
|
});
|
|
|
|
it('can delete own post', function () {
|
|
$user = User::factory()->create();
|
|
$post = Post::factory()->for($user)->create();
|
|
|
|
$this->actingAs($user)
|
|
->delete(route('post.destroy', $post))
|
|
->assertRedirect(route('post.index'));
|
|
|
|
$this->assertModelMissing($post);
|
|
});
|
|
|
|
it('cannot delete another users post', function () {
|
|
$user = User::factory()->create();
|
|
$otherPost = Post::factory()->create();
|
|
|
|
$this->actingAs($user)
|
|
->delete(route('post.destroy', $otherPost))
|
|
->assertForbidden();
|
|
|
|
$this->assertModelExists($otherPost);
|
|
});
|