user = User::factory()->create(['role' => 'apoteker']); $this->actingAs($this->user); } private function createKategori(): Kategori { return Kategori::create(['nama' => 'Antibiotik']); } private function createSatuan(): Satuan { return Satuan::create(['nama' => 'Tablet']); } private function validData(array $overrides = []): array { $kategori = Kategori::firstOrCreate(['nama' => 'Antibiotik']); $satuan = Satuan::firstOrCreate(['nama' => 'Tablet']); return array_merge([ '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(), ], $overrides); } // ───────────────────────────────────────── // index // ───────────────────────────────────────── public function test_index_returns_200(): void { $response = $this->get(route('obat-masuk.index')); $response->assertStatus(200); } public function test_index_guest_redirects_to_login(): void { auth()->logout(); $response = $this->get(route('obat-masuk.index')); $response->assertRedirect(route('login')); } public function test_index_search_by_nama_obat(): void { $kategori = $this->createKategori(); $satuan = $this->createSatuan(); 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, ]); ObatMasuk::create([ 'nama_obat' => 'Paracetamol', 'kategori_id' => $kategori->id, 'satuan_id' => $satuan->id, 'kode_batch' => 'BTH-002', 'stok' => 50, 'tanggal_penerimaan' => now()->toDateString(), 'tanggal_kadaluarsa' => now()->addYear()->toDateString(), 'user_id' => $this->user->id, ]); $response = $this->get(route('obat-masuk.index', ['search' => 'Amoxicillin'])); $data = $response->viewData('obatMasuks'); $names = $data->pluck('nama_obat')->toArray(); $this->assertContains('Amoxicillin', $names); $this->assertNotContains('Paracetamol', $names); } public function test_index_filter_by_status_tersedia(): void { $kategori = $this->createKategori(); $satuan = $this->createSatuan(); ObatMasuk::create([ 'nama_obat' => 'ObatA', 'kategori_id' => $kategori->id, 'satuan_id' => $satuan->id, 'kode_batch' => 'B1', 'stok' => 10, 'tanggal_penerimaan' => now()->toDateString(), 'tanggal_kadaluarsa' => now()->addYear()->toDateString(), 'user_id' => $this->user->id, ]); ObatMasuk::create([ 'nama_obat' => 'ObatB', 'kategori_id' => $kategori->id, 'satuan_id' => $satuan->id, 'kode_batch' => 'B2', 'stok' => 0, 'tanggal_penerimaan' => now()->toDateString(), 'tanggal_kadaluarsa' => now()->addYear()->toDateString(), 'user_id' => $this->user->id, ]); $response = $this->get(route('obat-masuk.index', ['status' => 'tersedia'])); $data = $response->viewData('obatMasuks'); $names = $data->pluck('nama_obat')->toArray(); $this->assertContains('ObatA', $names); $this->assertNotContains('ObatB', $names); } public function test_index_filter_by_status_habis(): void { $kategori = $this->createKategori(); $satuan = $this->createSatuan(); ObatMasuk::create([ 'nama_obat' => 'ObatA', 'kategori_id' => $kategori->id, 'satuan_id' => $satuan->id, 'kode_batch' => 'B1', 'stok' => 10, 'tanggal_penerimaan' => now()->toDateString(), 'tanggal_kadaluarsa' => now()->addYear()->toDateString(), 'user_id' => $this->user->id, ]); ObatMasuk::create([ 'nama_obat' => 'ObatHabis', 'kategori_id' => $kategori->id, 'satuan_id' => $satuan->id, 'kode_batch' => 'B2', 'stok' => 0, 'tanggal_penerimaan' => now()->toDateString(), 'tanggal_kadaluarsa' => now()->addYear()->toDateString(), 'user_id' => $this->user->id, ]); $response = $this->get(route('obat-masuk.index', ['status' => 'habis'])); $data = $response->viewData('obatMasuks'); $names = $data->pluck('nama_obat')->toArray(); $this->assertContains('ObatHabis', $names); $this->assertNotContains('ObatA', $names); } // ───────────────────────────────────────── // store // ───────────────────────────────────────── public function test_store_creates_obat_masuk_with_valid_data(): void { $response = $this->post(route('obat-masuk.store'), $this->validData()); $response->assertRedirect(route('obat-masuk.index')); $response->assertSessionHas('success'); $this->assertDatabaseHas('obat_masuks', ['nama_obat' => 'Amoxicillin', 'stok' => 100]); } public function test_store_fails_without_required_fields(): void { $response = $this->post(route('obat-masuk.store'), []); $response->assertSessionHasErrors(['nama_obat', 'kode_batch', 'stok', 'tanggal_penerimaan', 'tanggal_kadaluarsa']); } public function test_store_fails_when_kadaluarsa_before_penerimaan(): void { $response = $this->post(route('obat-masuk.store'), $this->validData([ 'tanggal_penerimaan' => now()->toDateString(), 'tanggal_kadaluarsa' => now()->subDay()->toDateString(), // sebelum penerimaan ])); $response->assertSessionHasErrors('tanggal_kadaluarsa'); } public function test_store_fails_with_zero_stok(): void { $response = $this->post(route('obat-masuk.store'), $this->validData(['stok' => 0])); $response->assertSessionHasErrors('stok'); } public function test_store_sets_user_id_from_authenticated_user(): void { $this->post(route('obat-masuk.store'), $this->validData()); $this->assertDatabaseHas('obat_masuks', ['user_id' => $this->user->id]); } // ───────────────────────────────────────── // show // ───────────────────────────────────────── public function test_show_returns_200(): void { $obat = ObatMasuk::create(array_merge($this->validData(), ['user_id' => $this->user->id])); $response = $this->get(route('obat-masuk.show', $obat)); $response->assertStatus(200); } // ───────────────────────────────────────── // update // ───────────────────────────────────────── public function test_update_modifies_obat_masuk(): void { $obat = ObatMasuk::create(array_merge($this->validData(), ['user_id' => $this->user->id])); $response = $this->put(route('obat-masuk.update', $obat), $this->validData(['nama_obat' => 'Paracetamol', 'stok' => 50])); $response->assertRedirect(route('obat-masuk.index')); $this->assertDatabaseHas('obat_masuks', ['id' => $obat->id, 'nama_obat' => 'Paracetamol', 'stok' => 50]); } public function test_update_fails_without_required_fields(): void { $obat = ObatMasuk::create(array_merge($this->validData(), ['user_id' => $this->user->id])); $response = $this->put(route('obat-masuk.update', $obat), []); $response->assertSessionHasErrors(['nama_obat', 'kode_batch']); } // ───────────────────────────────────────── // destroy // ───────────────────────────────────────── public function test_destroy_deletes_obat_masuk(): void { $obat = ObatMasuk::create(array_merge($this->validData(), ['user_id' => $this->user->id])); $response = $this->delete(route('obat-masuk.destroy', $obat)); $response->assertRedirect(route('obat-masuk.index')); $this->assertDatabaseMissing('obat_masuks', ['id' => $obat->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-masuk.index')); $response->assertStatus(200); } public function test_superadmin_can_access_show(): void { $superadmin = User::factory()->create(['role' => 'superadmin']); $this->actingAs($superadmin); $obat = ObatMasuk::create(array_merge($this->validData(), ['user_id' => $this->user->id])); $response = $this->get(route('obat-masuk.show', $obat)); $response->assertStatus(200); } public function test_superadmin_can_access_create_store_edit_update_destroy(): void { $superadmin = User::factory()->create(['role' => 'superadmin']); $this->actingAs($superadmin); $obat = ObatMasuk::create(array_merge($this->validData(), ['user_id' => $this->user->id])); $this->get(route('obat-masuk.create'))->assertStatus(200); $storePayload = $this->validData([ 'nama_obat' => 'Cefixime', 'kode_batch' => 'BTH-003', ]); $this->post(route('obat-masuk.store'), $storePayload)->assertRedirect(route('obat-masuk.index')); $this->assertDatabaseHas('obat_masuks', ['nama_obat' => 'Cefixime']); $this->get(route('obat-masuk.edit', $obat))->assertStatus(200); $updatePayload = $this->validData(['nama_obat' => 'Paracetamol Superadmin']); $this->put(route('obat-masuk.update', $obat), $updatePayload)->assertRedirect(route('obat-masuk.index')); $this->assertDatabaseHas('obat_masuks', ['id' => $obat->id, 'nama_obat' => 'Paracetamol Superadmin']); $this->delete(route('obat-masuk.destroy', $obat))->assertRedirect(route('obat-masuk.index')); $this->assertDatabaseMissing('obat_masuks', ['id' => $obat->id]); } }