store/tests/Feature/Admin/Master/SupplierTest.php

350 lines
12 KiB
PHP

<?php
use App\Enums\Permission as PermissionEnum;
use App\Models\Supplier;
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 createSupplierUserWithPermission(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('Supplier Index', function () {
test('authenticated user with permission can view supplier index', function () {
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW);
Supplier::factory()->count(3)->create();
$this->actingAs($user)
->get(route('admin.master.suppliers.index'))
->assertOk();
});
test('guest is redirected to login', function () {
$this->get(route('admin.master.suppliers.index'))
->assertRedirect(route('login'));
});
test('user without permission is forbidden', function () {
$user = User::factory()->create();
$this->actingAs($user)
->get(route('admin.master.suppliers.index'))
->assertForbidden();
});
test('index returns suppliers with pagination', function () {
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW);
Supplier::factory()->count(15)->create();
$this->actingAs($user)
->get(route('admin.master.suppliers.index'))
->assertOk();
});
test('index can search suppliers by name', function () {
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW);
Supplier::factory()->create(['name' => 'PT Maju Jaya']);
Supplier::factory()->create(['name' => 'CV Berkah Tekstil']);
$this->actingAs($user)
->get(route('admin.master.suppliers.index', ['search' => 'Maju']))
->assertOk();
});
});
// ─── Store ────────────────────────────────────────────────
describe('Supplier Store', function () {
test('authenticated user with permission can create a supplier', function () {
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_CREATE);
$this->actingAs($user)
->post(route('admin.master.suppliers.store'), [
'name' => 'PT Supplier Baru',
'phone_number' => '081234567890',
'address' => 'Jl. Merdeka No. 1',
])
->assertRedirect(route('admin.master.suppliers.index'));
$this->assertDatabaseHas('suppliers', [
'name' => 'PT Supplier Baru',
'phone_number' => '081234567890',
'address' => 'Jl. Merdeka No. 1',
]);
});
test('guest cannot create a supplier', function () {
$this->post(route('admin.master.suppliers.store'), [
'name' => 'PT Supplier Baru',
])->assertRedirect(route('login'));
});
test('user without create permission is forbidden', function () {
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW);
$this->actingAs($user)
->post(route('admin.master.suppliers.store'), [
'name' => 'PT Supplier Baru',
])
->assertForbidden();
$this->assertDatabaseCount('suppliers', 0);
});
test('name is required', function () {
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_CREATE);
$this->actingAs($user)
->post(route('admin.master.suppliers.store'), [
'name' => '',
])
->assertSessionHasErrors('name');
$this->assertDatabaseCount('suppliers', 0);
});
test('name must not exceed 200 characters', function () {
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_CREATE);
$this->actingAs($user)
->post(route('admin.master.suppliers.store'), [
'name' => str_repeat('a', 201),
])
->assertSessionHasErrors('name');
$this->assertDatabaseCount('suppliers', 0);
});
test('phone number must start with 08', function () {
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_CREATE);
$this->actingAs($user)
->post(route('admin.master.suppliers.store'), [
'name' => 'PT Supplier Baru',
'phone_number' => '0211234567',
])
->assertSessionHasErrors('phone_number');
$this->assertDatabaseCount('suppliers', 0);
});
test('phone number can be null', function () {
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_CREATE);
$this->actingAs($user)
->post(route('admin.master.suppliers.store'), [
'name' => 'PT Supplier Baru',
'phone_number' => null,
])
->assertRedirect(route('admin.master.suppliers.index'));
$this->assertDatabaseHas('suppliers', [
'name' => 'PT Supplier Baru',
'phone_number' => null,
]);
});
test('address can be null', function () {
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_CREATE);
$this->actingAs($user)
->post(route('admin.master.suppliers.store'), [
'name' => 'PT Supplier Baru',
'address' => null,
])
->assertRedirect(route('admin.master.suppliers.index'));
$this->assertDatabaseHas('suppliers', [
'name' => 'PT Supplier Baru',
'address' => null,
]);
});
});
// ─── Update ───────────────────────────────────────────────
describe('Supplier Update', function () {
test('authenticated user with permission can update a supplier', function () {
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_UPDATE);
$supplier = Supplier::factory()->create(['name' => 'Nama Lama']);
$this->actingAs($user)
->put(route('admin.master.suppliers.update', $supplier), [
'name' => 'Nama Baru',
'phone_number' => '089876543210',
'address' => 'Jl. Baru No. 2',
])
->assertRedirect(route('admin.master.suppliers.index'));
$this->assertDatabaseHas('suppliers', [
'id' => $supplier->id,
'name' => 'Nama Baru',
'phone_number' => '089876543210',
'address' => 'Jl. Baru No. 2',
]);
});
test('guest cannot update a supplier', function () {
$supplier = Supplier::factory()->create();
$this->put(route('admin.master.suppliers.update', $supplier), [
'name' => 'Nama Baru',
])->assertRedirect(route('login'));
});
test('user without update permission is forbidden', function () {
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW);
$supplier = Supplier::factory()->create(['name' => 'Nama Lama']);
$this->actingAs($user)
->put(route('admin.master.suppliers.update', $supplier), [
'name' => 'Nama Baru',
])
->assertForbidden();
$this->assertDatabaseHas('suppliers', [
'id' => $supplier->id,
'name' => 'Nama Lama',
]);
});
test('name is required on update', function () {
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_UPDATE);
$supplier = Supplier::factory()->create();
$this->actingAs($user)
->put(route('admin.master.suppliers.update', $supplier), [
'name' => '',
])
->assertSessionHasErrors('name');
});
test('name must not exceed 200 characters on update', function () {
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_UPDATE);
$supplier = Supplier::factory()->create();
$this->actingAs($user)
->put(route('admin.master.suppliers.update', $supplier), [
'name' => str_repeat('a', 201),
])
->assertSessionHasErrors('name');
});
test('phone number validation on update', function () {
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_UPDATE);
$supplier = Supplier::factory()->create();
$this->actingAs($user)
->put(route('admin.master.suppliers.update', $supplier), [
'name' => 'Nama Valid',
'phone_number' => '123invalid',
])
->assertSessionHasErrors('phone_number');
});
});
// ─── Destroy ──────────────────────────────────────────────
describe('Supplier Destroy', function () {
test('authenticated user with permission can delete a supplier', function () {
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_DELETE);
$supplier = Supplier::factory()->create();
$this->actingAs($user)
->delete(route('admin.master.suppliers.destroy', $supplier))
->assertRedirect(route('admin.master.suppliers.index'));
$this->assertSoftDeleted('suppliers', [
'id' => $supplier->id,
]);
});
test('guest cannot delete a supplier', function () {
$supplier = Supplier::factory()->create();
$this->delete(route('admin.master.suppliers.destroy', $supplier))
->assertRedirect(route('login'));
$this->assertNotSoftDeleted('suppliers', [
'id' => $supplier->id,
]);
});
test('user without delete permission is forbidden', function () {
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW);
$supplier = Supplier::factory()->create();
$this->actingAs($user)
->delete(route('admin.master.suppliers.destroy', $supplier))
->assertForbidden();
$this->assertNotSoftDeleted('suppliers', [
'id' => $supplier->id,
]);
});
test('deleted supplier is soft deleted', function () {
$user = createSupplierUserWithPermission(PermissionEnum::SUPPLIERS_VIEW, PermissionEnum::SUPPLIERS_DELETE);
$supplier = Supplier::factory()->create();
$this->actingAs($user)
->delete(route('admin.master.suppliers.destroy', $supplier));
$this->assertSoftDeleted('suppliers', ['id' => $supplier->id]);
$this->assertDatabaseHas('suppliers', ['id' => $supplier->id]);
});
});
// ─── Supplier Model ───────────────────────────────────────
describe('Supplier Model', function () {
test('supplier uses soft deletes', function () {
$supplier = Supplier::factory()->create();
$supplier->delete();
expect($supplier->trashed())->toBeTrue();
});
test('supplier can have purchases', function () {
$supplier = Supplier::factory()->create();
expect($supplier->purchases)->toBeInstanceOf(Collection::class);
});
});