summaryrefslogtreecommitdiff
path: root/tests/Feature/WritingTest.php
diff options
context:
space:
mode:
Diffstat (limited to 'tests/Feature/WritingTest.php')
-rw-r--r--tests/Feature/WritingTest.php279
1 files changed, 279 insertions, 0 deletions
diff --git a/tests/Feature/WritingTest.php b/tests/Feature/WritingTest.php
new file mode 100644
index 0000000..5a88b17
--- /dev/null
+++ b/tests/Feature/WritingTest.php
@@ -0,0 +1,279 @@
+<?php
+
+namespace Tests\Feature;
+
+use App\Models\User;
+use App\Models\Writing;
+use Illuminate\Foundation\Testing\RefreshDatabase;
+use Tests\TestCase;
+
+class WritingTest extends TestCase
+{
+ use RefreshDatabase;
+
+ // ─── Index ───────────────────────────────────────────────────────────────
+
+ public function test_guests_can_view_index(): void
+ {
+ $response = $this->get(route('w.index'));
+ $response->assertOk();
+ }
+
+ public function test_index_lists_writings(): void
+ {
+ $writing = Writing::factory()->create();
+
+ $response = $this->get(route('w.index'));
+ $response->assertSee($writing->title);
+ }
+
+ // ─── Show ─────────────────────────────────────────────────────────────────
+
+ public function test_guests_can_view_a_writing(): void
+ {
+ $writing = Writing::factory()->create();
+
+ $response = $this->get(route('w.show', $writing));
+ $response->assertOk()->assertSee($writing->title);
+ }
+
+ public function test_show_404s_for_missing_writing(): void
+ {
+ $response = $this->get(route('w.show', 99999));
+ $response->assertNotFound();
+ }
+
+ // ─── Create ───────────────────────────────────────────────────────────────
+
+ public function test_guest_is_redirected_from_create(): void
+ {
+ $response = $this->get(route('w.create'));
+ $response->assertRedirect(route('login'));
+ }
+
+ public function test_authenticated_user_can_see_create_form(): void
+ {
+ $user = User::factory()->create();
+
+ $response = $this->actingAs($user)->get(route('w.create'));
+ $response->assertOk();
+ }
+
+ // ─── Store ────────────────────────────────────────────────────────────────
+
+ public function test_guest_cannot_store_writing(): void
+ {
+ $response = $this->post(route('w.store'), [
+ 'title' => 'Guest Writing',
+ 'content' => 'Should not be stored at all.',
+ ]);
+ $response->assertRedirect(route('login'));
+ $this->assertDatabaseMissing('writings', ['title' => 'Guest Writing']);
+ }
+
+ public function test_user_can_store_writing(): void
+ {
+ $user = User::factory()->create();
+
+ $response = $this->actingAs($user)->post(route('w.store'), [
+ 'title' => 'My New Writing',
+ 'content' => 'This is content that is long enough to pass validation.',
+ ]);
+
+ $response->assertRedirect();
+ $this->assertDatabaseHas('writings', [
+ 'title' => 'My New Writing',
+ 'user_id' => $user->id,
+ ]);
+ }
+
+ public function test_store_requires_title(): void
+ {
+ $user = User::factory()->create();
+
+ $response = $this->actingAs($user)->post(route('w.store'), [
+ 'title' => '',
+ 'content' => 'Content long enough to pass.',
+ ]);
+ $response->assertSessionHasErrors('title');
+ }
+
+ public function test_store_requires_title_min_3_chars(): void
+ {
+ $user = User::factory()->create();
+
+ $response = $this->actingAs($user)->post(route('w.store'), [
+ 'title' => 'AB',
+ 'content' => 'Content long enough to pass.',
+ ]);
+ $response->assertSessionHasErrors('title');
+ }
+
+ public function test_store_requires_content(): void
+ {
+ $user = User::factory()->create();
+
+ $response = $this->actingAs($user)->post(route('w.store'), [
+ 'title' => 'Valid Title',
+ 'content' => '',
+ ]);
+ $response->assertSessionHasErrors('content');
+ }
+
+ public function test_store_requires_content_min_10_chars(): void
+ {
+ $user = User::factory()->create();
+
+ $response = $this->actingAs($user)->post(route('w.store'), [
+ 'title' => 'Valid Title',
+ 'content' => 'Too short',
+ ]);
+ $response->assertSessionHasErrors('content');
+ }
+
+ // ─── Edit ─────────────────────────────────────────────────────────────────
+
+ public function test_guest_is_redirected_from_edit(): void
+ {
+ $writing = Writing::factory()->create();
+
+ $response = $this->get(route('w.edit', $writing));
+ $response->assertRedirect(route('login'));
+ }
+
+ public function test_owner_can_access_edit_form(): void
+ {
+ $user = User::factory()->create();
+ $writing = Writing::factory()->create(['user_id' => $user->id]);
+
+ $response = $this->actingAs($user)->get(route('w.edit', $writing));
+ $response->assertOk();
+ }
+
+ public function test_non_owner_cannot_access_edit_form(): void
+ {
+ $owner = User::factory()->create();
+ $other = User::factory()->create();
+ $writing = Writing::factory()->create(['user_id' => $owner->id]);
+
+ $response = $this->actingAs($other)->get(route('w.edit', $writing));
+ $response->assertForbidden();
+ }
+
+ public function test_admin_can_access_any_edit_form(): void
+ {
+ $owner = User::factory()->create();
+ $admin = User::factory()->create(['role' => 0]);
+ $writing = Writing::factory()->create(['user_id' => $owner->id]);
+
+ $response = $this->actingAs($admin)->get(route('w.edit', $writing));
+ $response->assertOk();
+ }
+
+ // ─── Update ───────────────────────────────────────────────────────────────
+
+ public function test_owner_can_update_writing(): void
+ {
+ $user = User::factory()->create();
+ $writing = Writing::factory()->create(['user_id' => $user->id]);
+
+ $response = $this->actingAs($user)->put(route('w.update', $writing), [
+ 'title' => 'Updated Title',
+ 'content' => 'Updated content that is long enough to pass validation.',
+ ]);
+
+ $response->assertRedirect(route('w.show', $writing));
+ $this->assertDatabaseHas('writings', [
+ 'id' => $writing->id,
+ 'title' => 'Updated Title',
+ ]);
+ }
+
+ public function test_non_owner_cannot_update_writing(): void
+ {
+ $owner = User::factory()->create();
+ $other = User::factory()->create();
+ $writing = Writing::factory()->create(['user_id' => $owner->id, 'title' => 'Original Title']);
+
+ $response = $this->actingAs($other)->put(route('w.update', $writing), [
+ 'title' => 'Hijacked Title',
+ 'content' => 'Hijacked content that is long enough.',
+ ]);
+
+ $response->assertForbidden();
+ $this->assertDatabaseHas('writings', ['id' => $writing->id, 'title' => 'Original Title']);
+ }
+
+ public function test_admin_can_update_any_writing(): void
+ {
+ $owner = User::factory()->create();
+ $admin = User::factory()->create(['role' => 0]);
+ $writing = Writing::factory()->create(['user_id' => $owner->id]);
+
+ $response = $this->actingAs($admin)->put(route('w.update', $writing), [
+ 'title' => 'Admin Updated Title',
+ 'content' => 'Admin updated content that is long enough.',
+ ]);
+
+ $response->assertRedirect(route('w.show', $writing));
+ $this->assertDatabaseHas('writings', ['id' => $writing->id, 'title' => 'Admin Updated Title']);
+ }
+
+ public function test_update_validates_title(): void
+ {
+ $user = User::factory()->create();
+ $writing = Writing::factory()->create(['user_id' => $user->id]);
+
+ $response = $this->actingAs($user)->put(route('w.update', $writing), [
+ 'title' => 'AB',
+ 'content' => 'Content long enough to pass.',
+ ]);
+ $response->assertSessionHasErrors('title');
+ }
+
+ // ─── Destroy ─────────────────────────────────────────────────────────────
+
+ public function test_guest_cannot_delete_writing(): void
+ {
+ $writing = Writing::factory()->create();
+
+ $response = $this->delete(route('w.destroy', $writing));
+ $response->assertRedirect(route('login'));
+ $this->assertDatabaseHas('writings', ['id' => $writing->id]);
+ }
+
+ public function test_owner_can_delete_writing(): void
+ {
+ $user = User::factory()->create();
+ $writing = Writing::factory()->create(['user_id' => $user->id]);
+
+ $response = $this->actingAs($user)->delete(route('w.destroy', $writing));
+
+ $response->assertRedirect(route('w.index'));
+ $this->assertDatabaseMissing('writings', ['id' => $writing->id]);
+ }
+
+ public function test_non_owner_cannot_delete_writing(): void
+ {
+ $owner = User::factory()->create();
+ $other = User::factory()->create();
+ $writing = Writing::factory()->create(['user_id' => $owner->id]);
+
+ $response = $this->actingAs($other)->delete(route('w.destroy', $writing));
+
+ $response->assertForbidden();
+ $this->assertDatabaseHas('writings', ['id' => $writing->id]);
+ }
+
+ public function test_admin_can_delete_any_writing(): void
+ {
+ $owner = User::factory()->create();
+ $admin = User::factory()->create(['role' => 0]);
+ $writing = Writing::factory()->create(['user_id' => $owner->id]);
+
+ $response = $this->actingAs($admin)->delete(route('w.destroy', $writing));
+
+ $response->assertRedirect(route('w.index'));
+ $this->assertDatabaseMissing('writings', ['id' => $writing->id]);
+ }
+}