From 9ff5b93157814ca994d89e2e80f936c87072dc1c Mon Sep 17 00:00:00 2001 From: parsa aghaei Date: Tue, 23 Jun 2026 18:37:14 +0330 Subject: [PATCH] 4.1-4.3: add PHPUnit feature tests for all endpoints + factories --- database/factories/Website/AboutMeFactory.php | 17 ++++ .../Website/ProjectCategoryFactory.php | 17 ++++ database/factories/Website/ProjectFactory.php | 19 +++++ database/factories/Website/ServiceFactory.php | 17 ++++ database/factories/Website/SkillFactory.php | 20 +++++ phpunit.xml | 4 +- tests/Feature/Blog/CategoryTest.php | 61 ++++++++++++++ tests/Feature/Blog/HomeTest.php | 29 +++++++ tests/Feature/Blog/PostTest.php | 81 +++++++++++++++++++ tests/Feature/Blog/TagTest.php | 51 ++++++++++++ tests/Feature/ExampleTest.php | 19 ----- tests/Feature/Website/AboutMeTest.php | 75 +++++++++++++++++ tests/Feature/Website/ProjectTest.php | 40 +++++++++ tests/Feature/Website/ServiceTest.php | 35 ++++++++ tests/Unit/ExampleTest.php | 16 ---- tests/Unit/ModelsTest.php | 40 +++++++++ 16 files changed, 504 insertions(+), 37 deletions(-) create mode 100644 database/factories/Website/AboutMeFactory.php create mode 100644 database/factories/Website/ProjectCategoryFactory.php create mode 100644 database/factories/Website/ProjectFactory.php create mode 100644 database/factories/Website/ServiceFactory.php create mode 100644 database/factories/Website/SkillFactory.php create mode 100644 tests/Feature/Blog/CategoryTest.php create mode 100644 tests/Feature/Blog/HomeTest.php create mode 100644 tests/Feature/Blog/PostTest.php create mode 100644 tests/Feature/Blog/TagTest.php delete mode 100644 tests/Feature/ExampleTest.php create mode 100644 tests/Feature/Website/AboutMeTest.php create mode 100644 tests/Feature/Website/ProjectTest.php create mode 100644 tests/Feature/Website/ServiceTest.php delete mode 100644 tests/Unit/ExampleTest.php create mode 100644 tests/Unit/ModelsTest.php diff --git a/database/factories/Website/AboutMeFactory.php b/database/factories/Website/AboutMeFactory.php new file mode 100644 index 0000000..5800ab0 --- /dev/null +++ b/database/factories/Website/AboutMeFactory.php @@ -0,0 +1,17 @@ + $this->faker->imageUrl(), + ]; + } +} diff --git a/database/factories/Website/ProjectCategoryFactory.php b/database/factories/Website/ProjectCategoryFactory.php new file mode 100644 index 0000000..9e7327c --- /dev/null +++ b/database/factories/Website/ProjectCategoryFactory.php @@ -0,0 +1,17 @@ + $this->faker->imageUrl(), + ]; + } +} diff --git a/database/factories/Website/ProjectFactory.php b/database/factories/Website/ProjectFactory.php new file mode 100644 index 0000000..ab001cf --- /dev/null +++ b/database/factories/Website/ProjectFactory.php @@ -0,0 +1,19 @@ + \App\Models\Website\ProjectCategory::factory(), + 'image1' => $this->faker->imageUrl(), + 'image2' => $this->faker->imageUrl(), + ]; + } +} diff --git a/database/factories/Website/ServiceFactory.php b/database/factories/Website/ServiceFactory.php new file mode 100644 index 0000000..931c6a2 --- /dev/null +++ b/database/factories/Website/ServiceFactory.php @@ -0,0 +1,17 @@ + $this->faker->imageUrl(), + ]; + } +} diff --git a/database/factories/Website/SkillFactory.php b/database/factories/Website/SkillFactory.php new file mode 100644 index 0000000..ee48921 --- /dev/null +++ b/database/factories/Website/SkillFactory.php @@ -0,0 +1,20 @@ + $this->faker->imageUrl(), + 'link' => $this->faker->url(), + 'percentage' => $this->faker->numberBetween(10, 100), + 'about_me_id' => \App\Models\Website\AboutMe::factory(), + ]; + } +} diff --git a/phpunit.xml b/phpunit.xml index 506b9a3..61c031c 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -22,8 +22,8 @@ - - + + diff --git a/tests/Feature/Blog/CategoryTest.php b/tests/Feature/Blog/CategoryTest.php new file mode 100644 index 0000000..507ff0d --- /dev/null +++ b/tests/Feature/Blog/CategoryTest.php @@ -0,0 +1,61 @@ +count(3)->create(); + + $response = $this->getJson('/api/blog/categories'); + + $response->assertStatus(200); + } + + public function test_can_get_single_category() + { + $category = Category::factory()->create(); + + $response = $this->getJson("/api/blog/categories/{$category->id}"); + + $response->assertStatus(200); + } + + public function test_can_get_category_posts() + { + $category = Category::factory()->create(); + + $response = $this->getJson("/api/blog/categories/{$category->slug}/posts"); + + $response->assertStatus(200) + ->assertJsonStructure(['category', 'posts', 'meta', 'links']); + } + + public function test_can_create_category() + { + $response = $this->postJson('/api/blog/categories', [ + 'name' => 'Tech', + 'slug' => 'tech', + ]); + + $response->assertStatus(201); + $this->assertDatabaseHas('categories', ['slug' => 'tech']); + } + + public function test_can_delete_category() + { + $category = Category::factory()->create(); + + $response = $this->deleteJson("/api/blog/categories/{$category->id}"); + + $response->assertStatus(200); + $this->assertDatabaseMissing('categories', ['id' => $category->id]); + } +} diff --git a/tests/Feature/Blog/HomeTest.php b/tests/Feature/Blog/HomeTest.php new file mode 100644 index 0000000..701773e --- /dev/null +++ b/tests/Feature/Blog/HomeTest.php @@ -0,0 +1,29 @@ +count(5)->create(); + Category::factory()->count(3)->create(); + + $response = $this->getJson('/api/blog/homepage'); + + $response->assertStatus(200) + ->assertJsonStructure([ + 'latest_posts', + 'latest_categories', + 'most_viewed_posts', + 'random_posts', + ]); + } +} diff --git a/tests/Feature/Blog/PostTest.php b/tests/Feature/Blog/PostTest.php new file mode 100644 index 0000000..9845078 --- /dev/null +++ b/tests/Feature/Blog/PostTest.php @@ -0,0 +1,81 @@ +count(3)->create(); + + $response = $this->getJson('/api/blog/posts'); + + $response->assertStatus(200); + } + + public function test_can_get_single_post() + { + $post = Post::factory()->create(); + + $response = $this->getJson("/api/blog/posts/{$post->slug}"); + + $response->assertStatus(200) + ->assertJsonStructure(['post', 'related_posts']); + } + + public function test_can_create_post() + { + $category = Category::factory()->create(); + $user = User::factory()->create(); + + $response = $this->postJson('/api/blog/posts', [ + 'title' => 'Test Post', + 'body' => 'Content', + 'slug' => 'test-post', + 'category_id' => $category->id, + 'author_id' => $user->id, + ]); + + $response->assertStatus(201); + $this->assertDatabaseHas('posts', ['slug' => 'test-post']); + } + + public function test_can_update_post() + { + $post = Post::factory()->create(); + + $response = $this->putJson("/api/blog/posts/{$post->id}", [ + 'title' => 'Updated', + ]); + + $response->assertStatus(200); + } + + public function test_can_delete_post() + { + $post = Post::factory()->create(); + + $response = $this->deleteJson("/api/blog/posts/{$post->id}"); + + $response->assertStatus(200); + $this->assertDatabaseMissing('posts', ['id' => $post->id]); + } + + public function test_can_filter_posts() + { + Post::factory()->count(3)->create(); + + $response = $this->getJson('/api/blog/posts?per_page=2'); + + $response->assertStatus(200); + } +} diff --git a/tests/Feature/Blog/TagTest.php b/tests/Feature/Blog/TagTest.php new file mode 100644 index 0000000..be2aa6c --- /dev/null +++ b/tests/Feature/Blog/TagTest.php @@ -0,0 +1,51 @@ +count(3)->create(); + + $response = $this->getJson('/api/blog/tags'); + + $response->assertStatus(200); + } + + public function test_can_get_single_tag() + { + $tag = Tag::factory()->create(); + + $response = $this->getJson("/api/blog/tags/{$tag->id}"); + + $response->assertStatus(200); + } + + public function test_can_create_tag() + { + $response = $this->postJson('/api/blog/tags', [ + 'name' => 'Laravel', + 'slug' => 'laravel', + ]); + + $response->assertStatus(201); + $this->assertDatabaseHas('tags', ['slug' => 'laravel']); + } + + public function test_can_delete_tag() + { + $tag = Tag::factory()->create(); + + $response = $this->deleteJson("/api/blog/tags/{$tag->id}"); + + $response->assertStatus(200); + $this->assertDatabaseMissing('tags', ['id' => $tag->id]); + } +} diff --git a/tests/Feature/ExampleTest.php b/tests/Feature/ExampleTest.php deleted file mode 100644 index 8364a84..0000000 --- a/tests/Feature/ExampleTest.php +++ /dev/null @@ -1,19 +0,0 @@ -get('/'); - - $response->assertStatus(200); - } -} diff --git a/tests/Feature/Website/AboutMeTest.php b/tests/Feature/Website/AboutMeTest.php new file mode 100644 index 0000000..a6aedb6 --- /dev/null +++ b/tests/Feature/Website/AboutMeTest.php @@ -0,0 +1,75 @@ +create(); + + $response = $this->getJson('/api/website/about-me'); + + $response->assertStatus(200); + } + + public function test_can_get_about_me_translation() + { + $aboutMe = AboutMe::factory()->create(); + $aboutMe->setTranslation('title', 'en', 'Hello'); + $aboutMe->setTranslation('description', 'en', 'Description'); + $aboutMe->save(); + + $response = $this->getJson("/api/website/about-me/{$aboutMe->id}/translation/en"); + + $response->assertStatus(200) + ->assertJson(['title' => 'Hello']); + } + + public function test_returns_404_for_missing_translation() + { + $aboutMe = AboutMe::factory()->create(); + + $response = $this->getJson("/api/website/about-me/{$aboutMe->id}/translation/de"); + + $response->assertStatus(404); + } + + public function test_can_create_about_me() + { + $response = $this->postJson('/api/website/about-me', [ + 'image' => 'test.jpg', + ]); + + $response->assertStatus(201); + $this->assertDatabaseHas('website_about_me', ['image' => 'test.jpg']); + } + + public function test_can_update_about_me() + { + $aboutMe = AboutMe::factory()->create(); + + $response = $this->putJson("/api/website/about-me/{$aboutMe->id}", [ + 'image' => 'updated.jpg', + ]); + + $response->assertStatus(200); + $this->assertDatabaseHas('website_about_me', ['image' => 'updated.jpg']); + } + + public function test_can_delete_about_me() + { + $aboutMe = AboutMe::factory()->create(); + + $response = $this->deleteJson("/api/website/about-me/{$aboutMe->id}"); + + $response->assertStatus(204); + $this->assertDatabaseMissing('website_about_me', ['id' => $aboutMe->id]); + } +} diff --git a/tests/Feature/Website/ProjectTest.php b/tests/Feature/Website/ProjectTest.php new file mode 100644 index 0000000..2d080ef --- /dev/null +++ b/tests/Feature/Website/ProjectTest.php @@ -0,0 +1,40 @@ +create(); + $category->setTranslation('title', 'fa', 'دسته'); + $category->save(); + + $project = Project::factory()->create(['category_id' => $category->id]); + $project->setTranslation('title', 'fa', 'پروژه'); + $project->setTranslation('description', 'fa', 'توضیحات'); + $project->save(); + + $response = $this->getJson('/api/website/projects/translation/fa'); + + $response->assertStatus(200); + $response->assertJsonStructure(['projects', 'categories']); + } + + public function test_can_get_single_project() + { + $category = ProjectCategory::factory()->create(); + $project = Project::factory()->create(['category_id' => $category->id]); + + $response = $this->getJson("/api/website/projects/{$project->id}/translation/en"); + + $response->assertStatus(200); + } +} diff --git a/tests/Feature/Website/ServiceTest.php b/tests/Feature/Website/ServiceTest.php new file mode 100644 index 0000000..ea26923 --- /dev/null +++ b/tests/Feature/Website/ServiceTest.php @@ -0,0 +1,35 @@ +count(3)->create(); + + $response = $this->getJson('/api/website/services/en'); + + $response->assertStatus(200); + $this->assertCount(3, $response->json()); + } + + public function test_can_get_service_translation() + { + $service = Service::factory()->create(); + $service->setTranslation('title', 'fa', 'عنوان'); + $service->setTranslation('description', 'fa', 'توضیحات'); + $service->save(); + + $response = $this->getJson("/api/website/services/{$service->id}/translation/fa"); + + $response->assertStatus(200) + ->assertJson(['title' => 'عنوان']); + } +} diff --git a/tests/Unit/ExampleTest.php b/tests/Unit/ExampleTest.php deleted file mode 100644 index 5773b0c..0000000 --- a/tests/Unit/ExampleTest.php +++ /dev/null @@ -1,16 +0,0 @@ -assertTrue(true); - } -} diff --git a/tests/Unit/ModelsTest.php b/tests/Unit/ModelsTest.php new file mode 100644 index 0000000..16de18d --- /dev/null +++ b/tests/Unit/ModelsTest.php @@ -0,0 +1,40 @@ +create(); + + $aboutMe->setTranslation('title', 'en', 'Hello'); + $aboutMe->setTranslation('title', 'fa', 'سلام'); + $aboutMe->save(); + + $this->assertEquals('Hello', $aboutMe->getTranslation('title', 'en')); + $this->assertEquals('سلام', $aboutMe->getTranslation('title', 'fa')); + } + + public function test_about_me_has_skills_relation() + { + $aboutMe = AboutMe::factory()->create(); + Skill::factory()->count(2)->create(['about_me_id' => $aboutMe->id]); + + $this->assertCount(2, $aboutMe->skills); + } + + public function test_about_me_fillable_fields() + { + $aboutMe = AboutMe::factory()->create(['image' => 'photo.jpg']); + + $this->assertEquals('photo.jpg', $aboutMe->image); + } +}