334 lines
11 KiB
PHP
334 lines
11 KiB
PHP
<?php
|
|
|
|
use App\Enums\Permission as PermissionEnum;
|
|
use App\Models\Category;
|
|
use App\Models\User;
|
|
use Database\Seeders\RolePermissionSeeder;
|
|
use Illuminate\Database\Eloquent\Collection;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
beforeEach(function () {
|
|
$this->seed(RolePermissionSeeder::class);
|
|
});
|
|
|
|
// ─── Helper ───────────────────────────────────────────────
|
|
|
|
function createUserWithPermission(PermissionEnum ...$permissions): User
|
|
{
|
|
$user = User::factory()->create();
|
|
|
|
$user->givePermissionTo(
|
|
array_merge(
|
|
[PermissionEnum::DASHBOARD_VIEW->value],
|
|
array_map(fn (PermissionEnum $p) => $p->value, $permissions)
|
|
)
|
|
);
|
|
|
|
$user->forgetCachedPermissions();
|
|
|
|
return $user;
|
|
}
|
|
|
|
// ─── Index ────────────────────────────────────────────────
|
|
|
|
describe('Category Index', function () {
|
|
test('authenticated user with permission can view category index', function () {
|
|
$user = createUserWithPermission(PermissionEnum::CATEGORIES_VIEW);
|
|
|
|
Category::factory()->count(3)->create();
|
|
|
|
$this->actingAs($user)
|
|
->get(route('admin.master.categories.index'))
|
|
->assertOk();
|
|
});
|
|
|
|
test('guest is redirected to login', function () {
|
|
$this->get(route('admin.master.categories.index'))
|
|
->assertRedirect(route('login'));
|
|
});
|
|
|
|
test('user without permission is forbidden', function () {
|
|
$user = User::factory()->create();
|
|
|
|
$this->actingAs($user)
|
|
->get(route('admin.master.categories.index'))
|
|
->assertForbidden();
|
|
});
|
|
|
|
test('index returns categories with pagination', function () {
|
|
$user = createUserWithPermission(PermissionEnum::CATEGORIES_VIEW);
|
|
|
|
Category::factory()->count(15)->create();
|
|
|
|
$response = $this->actingAs($user)
|
|
->get(route('admin.master.categories.index'));
|
|
|
|
$response->assertOk();
|
|
});
|
|
|
|
test('index can search categories by name', function () {
|
|
$user = createUserWithPermission(PermissionEnum::CATEGORIES_VIEW);
|
|
|
|
Category::factory()->create(['name' => 'Kaos Polos']);
|
|
Category::factory()->create(['name' => 'Kemeja Formal']);
|
|
|
|
$this->actingAs($user)
|
|
->get(route('admin.master.categories.index', ['search' => 'Kaos']))
|
|
->assertOk();
|
|
});
|
|
});
|
|
|
|
// ─── Store ────────────────────────────────────────────────
|
|
|
|
describe('Category Store', function () {
|
|
test('authenticated user with permission can create a category', function () {
|
|
$user = createUserWithPermission(PermissionEnum::CATEGORIES_VIEW, PermissionEnum::CATEGORIES_CREATE);
|
|
|
|
$this->actingAs($user)
|
|
->post(route('admin.master.categories.store'), [
|
|
'name' => 'Kategori Baru',
|
|
])
|
|
->assertRedirect(route('admin.master.categories.index'));
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Kategori Baru',
|
|
'slug' => 'kategori-baru',
|
|
]);
|
|
});
|
|
|
|
test('guest cannot create a category', function () {
|
|
$this->post(route('admin.master.categories.store'), [
|
|
'name' => 'Kategori Baru',
|
|
])->assertRedirect(route('login'));
|
|
});
|
|
|
|
test('user without create permission is forbidden', function () {
|
|
$user = createUserWithPermission(PermissionEnum::CATEGORIES_VIEW);
|
|
|
|
$this->actingAs($user)
|
|
->post(route('admin.master.categories.store'), [
|
|
'name' => 'Kategori Baru',
|
|
])
|
|
->assertForbidden();
|
|
|
|
$this->assertDatabaseCount('categories', 0);
|
|
});
|
|
|
|
test('name is required', function () {
|
|
$user = createUserWithPermission(PermissionEnum::CATEGORIES_VIEW, PermissionEnum::CATEGORIES_CREATE);
|
|
|
|
$this->actingAs($user)
|
|
->post(route('admin.master.categories.store'), [
|
|
'name' => '',
|
|
])
|
|
->assertSessionHasErrors('name');
|
|
|
|
$this->assertDatabaseCount('categories', 0);
|
|
});
|
|
|
|
test('name must not exceed 50 characters', function () {
|
|
$user = createUserWithPermission(PermissionEnum::CATEGORIES_VIEW, PermissionEnum::CATEGORIES_CREATE);
|
|
|
|
$this->actingAs($user)
|
|
->post(route('admin.master.categories.store'), [
|
|
'name' => str_repeat('a', 51),
|
|
])
|
|
->assertSessionHasErrors('name');
|
|
|
|
$this->assertDatabaseCount('categories', 0);
|
|
});
|
|
|
|
test('name must be a string', function () {
|
|
$user = createUserWithPermission(PermissionEnum::CATEGORIES_VIEW, PermissionEnum::CATEGORIES_CREATE);
|
|
|
|
$this->actingAs($user)
|
|
->post(route('admin.master.categories.store'), [
|
|
'name' => ['bukan string'],
|
|
])
|
|
->assertSessionHasErrors('name');
|
|
|
|
$this->assertDatabaseCount('categories', 0);
|
|
});
|
|
|
|
test('slug is auto-generated from name', function () {
|
|
$user = createUserWithPermission(PermissionEnum::CATEGORIES_VIEW, PermissionEnum::CATEGORIES_CREATE);
|
|
|
|
$this->actingAs($user)
|
|
->post(route('admin.master.categories.store'), [
|
|
'name' => 'Bahan Katun',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'name' => 'Bahan Katun',
|
|
'slug' => 'bahan-katun',
|
|
]);
|
|
});
|
|
});
|
|
|
|
// ─── Update ───────────────────────────────────────────────
|
|
|
|
describe('Category Update', function () {
|
|
test('authenticated user with permission can update a category', function () {
|
|
$user = createUserWithPermission(PermissionEnum::CATEGORIES_VIEW, PermissionEnum::CATEGORIES_UPDATE);
|
|
|
|
$category = Category::factory()->create(['name' => 'Nama Lama']);
|
|
|
|
$this->actingAs($user)
|
|
->put(route('admin.master.categories.update', $category), [
|
|
'name' => 'Nama Baru',
|
|
])
|
|
->assertRedirect(route('admin.master.categories.index'));
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'id' => $category->id,
|
|
'name' => 'Nama Baru',
|
|
]);
|
|
});
|
|
|
|
test('guest cannot update a category', function () {
|
|
$category = Category::factory()->create();
|
|
|
|
$this->put(route('admin.master.categories.update', $category), [
|
|
'name' => 'Nama Baru',
|
|
])->assertRedirect(route('login'));
|
|
});
|
|
|
|
test('user without update permission is forbidden', function () {
|
|
$user = createUserWithPermission(PermissionEnum::CATEGORIES_VIEW);
|
|
|
|
$category = Category::factory()->create(['name' => 'Nama Lama']);
|
|
|
|
$this->actingAs($user)
|
|
->put(route('admin.master.categories.update', $category), [
|
|
'name' => 'Nama Baru',
|
|
])
|
|
->assertForbidden();
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'id' => $category->id,
|
|
'name' => 'Nama Lama',
|
|
]);
|
|
});
|
|
|
|
test('name is required on update', function () {
|
|
$user = createUserWithPermission(PermissionEnum::CATEGORIES_VIEW, PermissionEnum::CATEGORIES_UPDATE);
|
|
|
|
$category = Category::factory()->create();
|
|
|
|
$this->actingAs($user)
|
|
->put(route('admin.master.categories.update', $category), [
|
|
'name' => '',
|
|
])
|
|
->assertSessionHasErrors('name');
|
|
});
|
|
|
|
test('name must not exceed 50 characters on update', function () {
|
|
$user = createUserWithPermission(PermissionEnum::CATEGORIES_VIEW, PermissionEnum::CATEGORIES_UPDATE);
|
|
|
|
$category = Category::factory()->create();
|
|
|
|
$this->actingAs($user)
|
|
->put(route('admin.master.categories.update', $category), [
|
|
'name' => str_repeat('a', 51),
|
|
])
|
|
->assertSessionHasErrors('name');
|
|
});
|
|
|
|
test('slug is updated when name changes', function () {
|
|
$user = createUserWithPermission(PermissionEnum::CATEGORIES_VIEW, PermissionEnum::CATEGORIES_UPDATE);
|
|
|
|
$category = Category::factory()->create(['name' => 'Nama Lama']);
|
|
|
|
$this->actingAs($user)
|
|
->put(route('admin.master.categories.update', $category), [
|
|
'name' => 'Nama Terbaru',
|
|
]);
|
|
|
|
$this->assertDatabaseHas('categories', [
|
|
'id' => $category->id,
|
|
'slug' => 'nama-terbaru',
|
|
]);
|
|
});
|
|
});
|
|
|
|
// ─── Destroy ──────────────────────────────────────────────
|
|
|
|
describe('Category Destroy', function () {
|
|
test('authenticated user with permission can delete a category', function () {
|
|
$user = createUserWithPermission(PermissionEnum::CATEGORIES_VIEW, PermissionEnum::CATEGORIES_DELETE);
|
|
|
|
$category = Category::factory()->create();
|
|
|
|
$this->actingAs($user)
|
|
->delete(route('admin.master.categories.destroy', $category))
|
|
->assertRedirect(route('admin.master.categories.index'));
|
|
|
|
$this->assertSoftDeleted('categories', [
|
|
'id' => $category->id,
|
|
]);
|
|
});
|
|
|
|
test('guest cannot delete a category', function () {
|
|
$category = Category::factory()->create();
|
|
|
|
$this->delete(route('admin.master.categories.destroy', $category))
|
|
->assertRedirect(route('login'));
|
|
|
|
$this->assertNotSoftDeleted('categories', [
|
|
'id' => $category->id,
|
|
]);
|
|
});
|
|
|
|
test('user without delete permission is forbidden', function () {
|
|
$user = createUserWithPermission(PermissionEnum::CATEGORIES_VIEW);
|
|
|
|
$category = Category::factory()->create();
|
|
|
|
$this->actingAs($user)
|
|
->delete(route('admin.master.categories.destroy', $category))
|
|
->assertForbidden();
|
|
|
|
$this->assertNotSoftDeleted('categories', [
|
|
'id' => $category->id,
|
|
]);
|
|
});
|
|
|
|
test('deleted category is soft deleted', function () {
|
|
$user = createUserWithPermission(PermissionEnum::CATEGORIES_VIEW, PermissionEnum::CATEGORIES_DELETE);
|
|
|
|
$category = Category::factory()->create();
|
|
|
|
$this->actingAs($user)
|
|
->delete(route('admin.master.categories.destroy', $category));
|
|
|
|
$this->assertSoftDeleted('categories', ['id' => $category->id]);
|
|
$this->assertDatabaseHas('categories', ['id' => $category->id]);
|
|
});
|
|
});
|
|
|
|
// ─── Category Model ───────────────────────────────────────
|
|
|
|
describe('Category Model', function () {
|
|
test('category has slug auto-generated via attribute', function () {
|
|
$category = Category::factory()->create(['name' => 'Test Kategori', 'slug' => null]);
|
|
|
|
expect($category->fresh()->slug)->toBe('test-kategori');
|
|
});
|
|
|
|
test('category uses soft deletes', function () {
|
|
$category = Category::factory()->create();
|
|
|
|
$category->delete();
|
|
|
|
expect($category->trashed())->toBeTrue();
|
|
});
|
|
|
|
test('category can have products', function () {
|
|
$category = Category::factory()->create();
|
|
|
|
expect($category->products)->toBeInstanceOf(Collection::class);
|
|
});
|
|
});
|