TIF_Nganjuk_E41220879/tests/Feature/ObatKeluarTest.php

364 lines
14 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Tests\Feature;
use App\Models\Kategori;
use App\Models\ObatKeluar;
use App\Models\ObatMasuk;
use App\Models\Satuan;
use App\Models\User;
use Tests\DatabaseTestCase;
class ObatKeluarTest extends DatabaseTestCase
{
private User $user;
private ObatMasuk $obatMasuk;
protected function setUp(): void
{
parent::setUp();
$this->user = User::factory()->create(['role' => 'apoteker']);
$this->actingAs($this->user);
$kategori = Kategori::create(['nama' => 'Antibiotik']);
$satuan = Satuan::create(['nama' => 'Tablet']);
$this->obatMasuk = ObatMasuk::create([
'nama_obat' => 'Amoxicillin',
'kategori_id' => $kategori->id,
'satuan_id' => $satuan->id,
'kode_batch' => 'BTH-001',
'stok' => 100,
'tanggal_penerimaan' => now()->toDateString(),
'tanggal_kadaluarsa' => now()->addYear()->toDateString(),
'user_id' => $this->user->id,
]);
}
private function validData(array $overrides = []): array
{
return array_merge([
'obat_masuk_id' => $this->obatMasuk->id,
'kode_batch' => 'BTH-001',
'jumlah' => 10,
'tujuan_pemakaian' => 'Penggunaan internal',
'tanggal_kadaluarsa' => now()->addYear()->toDateString(),
'tanggal_pengeluaran' => now()->toDateString(),
'nama_petugas' => 'Petugas A',
'nama_penerima' => 'Penerima B',
], $overrides);
}
// ─────────────────────────────────────────
// index
// ─────────────────────────────────────────
public function test_index_returns_200(): void
{
$response = $this->get(route('obat-keluar.index'));
$response->assertStatus(200);
}
public function test_index_guest_redirects_to_login(): void
{
auth()->logout();
$response = $this->get(route('obat-keluar.index'));
$response->assertRedirect(route('login'));
}
public function test_index_filter_by_status(): void
{
ObatKeluar::create(array_merge($this->validData(['jumlah' => 5]), [
'nama_obat' => 'Amoxicillin',
'status' => 'proses',
'user_id' => $this->user->id,
]));
$response = $this->get(route('obat-keluar.index', ['status' => 'proses']));
$response->assertStatus(200);
}
public function test_index_search(): void
{
ObatKeluar::create(array_merge($this->validData(), [
'nama_obat' => 'Amoxicillin',
'kode_batch' => 'BTH-001',
'user_id' => $this->user->id,
]));
ObatKeluar::create(array_merge($this->validData(), [
'nama_obat' => 'Paracetamol',
'kode_batch' => 'BTH-002',
'user_id' => $this->user->id,
]));
$response = $this->get(route('obat-keluar.index', ['search' => 'Paracetamol']));
$data = $response->viewData('obatKeluars');
$names = $data->pluck('nama_obat')->toArray();
$this->assertContains('Paracetamol', $names);
$this->assertNotContains('Amoxicillin', $names);
}
// ─────────────────────────────────────────
// create, show, edit
// ─────────────────────────────────────────
public function test_create_returns_200(): void
{
$response = $this->get(route('obat-keluar.create'));
$response->assertStatus(200);
}
public function test_show_returns_200(): void
{
$keluar = ObatKeluar::create(array_merge($this->validData(), [
'nama_obat' => 'Amoxicillin',
'status' => 'proses',
'user_id' => $this->user->id,
]));
$response = $this->get(route('obat-keluar.show', $keluar));
$response->assertStatus(200);
}
public function test_edit_returns_200(): void
{
$keluar = ObatKeluar::create(array_merge($this->validData(), [
'nama_obat' => 'Amoxicillin',
'status' => 'proses',
'user_id' => $this->user->id,
]));
$response = $this->get(route('obat-keluar.edit', $keluar));
$response->assertStatus(200);
}
// ─────────────────────────────────────────
// store — berhasil
// ─────────────────────────────────────────
public function test_store_creates_obat_keluar_and_decrements_stok(): void
{
$initialStok = $this->obatMasuk->stok; // 100
$response = $this->post(route('obat-keluar.store'), $this->validData(['jumlah' => 10]));
$response->assertRedirect(route('obat-keluar.index'));
$response->assertSessionHas('success');
$this->assertDatabaseHas('obat_keluars', [
'obat_masuk_id' => $this->obatMasuk->id,
'jumlah' => 10,
'nama_obat' => 'Amoxicillin',
]);
// Stok berkurang dari 100 menjadi 90
$this->assertEquals($initialStok - 10, $this->obatMasuk->fresh()->stok);
}
public function test_store_sets_user_id_and_nama_obat_automatically(): void
{
$this->post(route('obat-keluar.store'), $this->validData(['jumlah' => 5]));
$this->assertDatabaseHas('obat_keluars', [
'user_id' => $this->user->id,
'nama_obat' => 'Amoxicillin',
]);
}
// ─────────────────────────────────────────
// store — gagal karena stok
// ─────────────────────────────────────────
public function test_store_fails_when_jumlah_exceeds_stok(): void
{
$response = $this->post(route('obat-keluar.store'), $this->validData(['jumlah' => 200])); // stok cuma 100
// Harus kembali ke form dengan error jumlah
$response->assertSessionHasErrors('jumlah');
}
public function test_store_stok_unchanged_when_validation_fails(): void
{
$this->post(route('obat-keluar.store'), $this->validData(['jumlah' => 200]));
$this->assertEquals(100, $this->obatMasuk->fresh()->stok);
}
// ─────────────────────────────────────────
// store — validasi field wajib
// ─────────────────────────────────────────
public function test_store_fails_without_required_fields(): void
{
$response = $this->post(route('obat-keluar.store'), []);
$response->assertSessionHasErrors([
'obat_masuk_id',
'kode_batch',
'jumlah',
'tujuan_pemakaian',
'tanggal_kadaluarsa',
'tanggal_pengeluaran',
'nama_petugas',
'nama_penerima',
]);
}
// ─────────────────────────────────────────
// update — perubahan jumlah
// ─────────────────────────────────────────
public function test_update_adjusts_stok_when_jumlah_increases(): void
{
// Buat obat keluar awal dengan jumlah 10 → stok jadi 90
$keluar = ObatKeluar::create(array_merge($this->validData(['jumlah' => 10]), [
'nama_obat' => 'Amoxicillin',
'status' => 'proses',
'user_id' => $this->user->id,
]));
$this->obatMasuk->decrement('stok', 10); // stok = 90
// Update jumlah menjadi 30 (selisih +20, stok dari 90 → 70)
$response = $this->put(
route('obat-keluar.update', $keluar),
$this->validData(['jumlah' => 30])
);
$response->assertRedirect(route('obat-keluar.index'));
$this->assertEquals(70, $this->obatMasuk->fresh()->stok);
}
public function test_update_adjusts_stok_when_jumlah_decreases(): void
{
// Buat obat keluar awal dengan jumlah 20 → stok jadi 80
$keluar = ObatKeluar::create(array_merge($this->validData(['jumlah' => 20]), [
'nama_obat' => 'Amoxicillin',
'status' => 'proses',
'user_id' => $this->user->id,
]));
$this->obatMasuk->decrement('stok', 20); // stok = 80
// Update jumlah menjadi 10 (selisih 10, stok dari 80 → 90)
$response = $this->put(
route('obat-keluar.update', $keluar),
$this->validData(['jumlah' => 10])
);
$response->assertRedirect(route('obat-keluar.index'));
$this->assertEquals(90, $this->obatMasuk->fresh()->stok);
}
public function test_update_fails_when_increased_jumlah_exceeds_available_stok(): void
{
// Stok awal 100, keluar 10 → stok = 90
$keluar = ObatKeluar::create(array_merge($this->validData(['jumlah' => 10]), [
'nama_obat' => 'Amoxicillin',
'status' => 'proses',
'user_id' => $this->user->id,
]));
$this->obatMasuk->decrement('stok', 10);
// Coba update ke 200 (selisih = +190, stok hanya 90)
$response = $this->put(
route('obat-keluar.update', $keluar),
$this->validData(['jumlah' => 200])
);
$response->assertSessionHasErrors('jumlah');
}
public function test_update_fails_without_required_fields(): void
{
$keluar = ObatKeluar::create(array_merge($this->validData(['jumlah' => 10]), [
'nama_obat' => 'Amoxicillin',
'user_id' => $this->user->id,
]));
$response = $this->put(route('obat-keluar.update', $keluar), []);
$response->assertSessionHasErrors([
'obat_masuk_id',
'kode_batch',
'jumlah',
'tujuan_pemakaian',
'tanggal_kadaluarsa',
'tanggal_pengeluaran',
'nama_petugas',
'nama_penerima',
]);
}
// ─────────────────────────────────────────
// destroy — stok dikembalikan
// ─────────────────────────────────────────
public function test_destroy_deletes_obat_keluar_and_restores_stok(): void
{
// Buat keluar jumlah 15 → stok jadi 85
$keluar = ObatKeluar::create(array_merge($this->validData(['jumlah' => 15]), [
'nama_obat' => 'Amoxicillin',
'status' => 'proses',
'user_id' => $this->user->id,
]));
$this->obatMasuk->decrement('stok', 15);
$response = $this->delete(route('obat-keluar.destroy', $keluar));
$response->assertRedirect(route('obat-keluar.index'));
$response->assertSessionHas('success');
// Stok dikembalikan → 100
$this->assertEquals(100, $this->obatMasuk->fresh()->stok);
$this->assertDatabaseMissing('obat_keluars', ['id' => $keluar->id]);
}
// ─────────────────────────────────────────
// superadmin access
// ─────────────────────────────────────────
public function test_superadmin_can_access_index(): void
{
$superadmin = User::factory()->create(['role' => 'superadmin']);
$this->actingAs($superadmin);
$response = $this->get(route('obat-keluar.index'));
$response->assertStatus(200);
}
public function test_superadmin_can_access_show(): void
{
$superadmin = User::factory()->create(['role' => 'superadmin']);
$this->actingAs($superadmin);
$keluar = ObatKeluar::create(array_merge($this->validData(), [
'nama_obat' => 'Amoxicillin',
'status' => 'proses',
'user_id' => $this->user->id,
]));
$response = $this->get(route('obat-keluar.show', $keluar));
$response->assertStatus(200);
}
public function test_superadmin_can_access_create_store_edit_update_destroy(): void
{
$superadmin = User::factory()->create(['role' => 'superadmin']);
$this->actingAs($superadmin);
$keluar = ObatKeluar::create(array_merge($this->validData(), [
'nama_obat' => 'Amoxicillin',
'status' => 'proses',
'user_id' => $this->user->id,
]));
$this->get(route('obat-keluar.create'))->assertStatus(200);
$this->post(route('obat-keluar.store'), $this->validData(['jumlah' => 10]))
->assertRedirect(route('obat-keluar.index'));
$this->assertDatabaseHas('obat_keluars', ['user_id' => $superadmin->id, 'jumlah' => 10]);
$this->get(route('obat-keluar.edit', $keluar))->assertStatus(200);
$this->put(route('obat-keluar.update', $keluar), $this->validData(['jumlah' => 8]))
->assertRedirect(route('obat-keluar.index'));
$this->assertDatabaseHas('obat_keluars', ['id' => $keluar->id, 'jumlah' => 8]);
$this->delete(route('obat-keluar.destroy', $keluar))->assertRedirect(route('obat-keluar.index'));
$this->assertDatabaseMissing('obat_keluars', ['id' => $keluar->id]);
}
}