feat: complete Smartgift AI Laravel unit testing toolkit
- Add 10 core testing guides (setup, AAA principles, PHPUnit/Pest, mocking, anti-patterns, PHP 8.4+, debugging, data factories, advanced edge cases) - Add 13 component testing guides covering all Laravel layers - Add standard templates for PHPUnit 10/11 and Pest v2/v3 including ArchitectureTest - Add Docker smart test runner, dependency installer, and CI/CD templates (GitHub Actions, GitLab CI) - Add 4 Claude Code skills (laravel-test-setup, laravel-unit-test with --all mode, laravel-test-review, laravel-mock-helper) - Add single unified installer script (sg-install-unit-testing.sh) with global support, CLI runners, and 1-click updater (sg-test-update) - Add comprehensive documentation (README.md, USAGE-GUIDE.md) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
# Component Guide: Policies & Authorization Gates
|
||||
|
||||
Policies kiểm soát quyền hạn truy cập của người dùng đối với từng hành động trên Model (view, create, update, delete).
|
||||
|
||||
---
|
||||
|
||||
## 1. Bản Chất Kiểm Thử Policy
|
||||
|
||||
- Policy methods là các hàm thuần túy nhận `User` và `Model` (hoặc chỉ `User`) và trả về `bool` (hoặc `Response::allow()` / `Response::deny()`).
|
||||
- **Ưu điểm lớn**: Policy có thể được kiểm thử đơn vị **hoàn toàn 100% trong bộ nhớ (In-Memory)** mà không cần kết nối database hay framework gate pipeline.
|
||||
|
||||
---
|
||||
|
||||
## 2. Mã Mẫu Chuẩn: Policy Unit Test
|
||||
|
||||
### Policy Nguồn: `App\Policies\ArticlePolicy`
|
||||
```php
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\Article;
|
||||
use App\Models\User;
|
||||
|
||||
class ArticlePolicy
|
||||
{
|
||||
public function update(User $user, Article $article): bool
|
||||
{
|
||||
// Admin được sửa tất cả bài viết
|
||||
if ($user->is_admin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Tác giả chỉ được sửa bài của mình khi bài chưa publish
|
||||
return $user->id === $article->user_id && !$article->is_published;
|
||||
}
|
||||
|
||||
public function delete(User $user, Article $article): bool
|
||||
{
|
||||
// Chỉ admin hoặc tác giả mới được xóa
|
||||
return $user->is_admin || $user->id === $article->user_id;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Test Chuẩn: PHPUnit 10+
|
||||
```php
|
||||
namespace Tests\Unit\Policies;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use App\Policies\ArticlePolicy;
|
||||
use App\Models\Article;
|
||||
use App\Models\User;
|
||||
|
||||
class ArticlePolicyTest extends TestCase
|
||||
{
|
||||
private ArticlePolicy $policy;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->policy = new ArticlePolicy();
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function admin_can_update_any_article_even_if_published(): void
|
||||
{
|
||||
$admin = new User(['id' => 99, 'is_admin' => true]);
|
||||
$article = new Article(['user_id' => 1, 'is_published' => true]);
|
||||
|
||||
$this->assertTrue($this->policy->update($admin, $article));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function author_can_update_own_article_if_not_published(): void
|
||||
{
|
||||
$author = new User(['id' => 10, 'is_admin' => false]);
|
||||
$article = new Article(['user_id' => 10, 'is_published' => false]);
|
||||
|
||||
$this->assertTrue($this->policy->update($author, $article));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function author_cannot_update_own_article_once_published(): void
|
||||
{
|
||||
$author = new User(['id' => 10, 'is_admin' => false]);
|
||||
$article = new Article(['user_id' => 10, 'is_published' => true]);
|
||||
|
||||
$this->assertFalse($this->policy->update($author, $article));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function non_author_cannot_update_others_article(): void
|
||||
{
|
||||
$otherUser = new User(['id' => 20, 'is_admin' => false]);
|
||||
$article = new Article(['user_id' => 10, 'is_published' => false]);
|
||||
|
||||
$this->assertFalse($this->policy->update($otherUser, $article));
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user