adminUser = User::factory()->create(['role' => Role::ADMIN]); $this->managerUser = User::factory()->create(['role' => Role::MANAGER]); $this->brigadierUser = User::factory()->create(['role' => Role::BRIGADIER]); } // ==================== Authentication ==================== public function test_guest_cannot_access_inventory(): void { $response = $this->get(route('spare_part_inventory.index')); $response->assertRedirect(route('login')); } // ==================== Authorization ==================== public function test_brigadier_cannot_access_inventory(): void { $response = $this->actingAs($this->brigadierUser) ->get(route('spare_part_inventory.index')); $response->assertStatus(403); } // ==================== Index ==================== public function test_admin_can_access_inventory_index(): void { $response = $this->actingAs($this->adminUser) ->get(route('spare_part_inventory.index')); $response->assertStatus(200); $response->assertViewIs('spare_parts.index'); } public function test_manager_can_access_inventory_index(): void { $response = $this->actingAs($this->managerUser) ->get(route('spare_part_inventory.index')); $response->assertStatus(200); $response->assertViewIs('spare_parts.index'); } public function test_inventory_view_has_required_data(): void { $response = $this->actingAs($this->adminUser) ->get(route('spare_part_inventory.index')); $response->assertStatus(200); $response->assertViewHas('critical_shortages'); $response->assertViewHas('below_min_stock'); $response->assertViewHas('open_shortages'); $response->assertViewHas('tab'); } public function test_inventory_shows_open_shortages(): void { $sparePart = SparePart::factory()->create([ 'min_stock' => 5, ]); $reclamation = Reclamation::factory()->create(); $shortage = Shortage::factory()->create([ 'spare_part_id' => $sparePart->id, 'reclamation_id' => $reclamation->id, 'status' => Shortage::STATUS_OPEN, 'required_qty' => 3, 'reserved_qty' => 0, 'missing_qty' => 3, ]); $response = $this->actingAs($this->adminUser) ->get(route('spare_part_inventory.index')); $response->assertStatus(200); $openShortages = $response->viewData('open_shortages'); $this->assertTrue($openShortages->contains('id', $shortage->id)); } public function test_inventory_does_not_show_closed_shortages(): void { $sparePart = SparePart::factory()->create(); $reclamation = Reclamation::factory()->create(); $closedShortage = Shortage::factory()->create([ 'spare_part_id' => $sparePart->id, 'reclamation_id' => $reclamation->id, 'status' => Shortage::STATUS_CLOSED, 'required_qty' => 2, 'reserved_qty' => 2, 'missing_qty' => 0, ]); $response = $this->actingAs($this->adminUser) ->get(route('spare_part_inventory.index')); $response->assertStatus(200); $openShortages = $response->viewData('open_shortages'); $this->assertFalse($openShortages->contains('id', $closedShortage->id)); } public function test_inventory_shows_below_min_stock_parts(): void { // SparePart без SparePartOrders в STATUS_IN_STOCK => total_free_stock = 0 // При min_stock > 0 isBelowMinStock() вернёт true $belowMinSparePart = SparePart::factory()->create([ 'min_stock' => 10, ]); $response = $this->actingAs($this->adminUser) ->get(route('spare_part_inventory.index')); $response->assertStatus(200); $belowMinStock = $response->viewData('below_min_stock'); $this->assertTrue($belowMinStock->contains('id', $belowMinSparePart->id)); } public function test_inventory_tab_is_set_correctly(): void { $response = $this->actingAs($this->adminUser) ->get(route('spare_part_inventory.index')); $response->assertStatus(200); $response->assertViewHas('tab', 'inventory'); } }