create(); $model = AssetModel::factory()->create(['requestable' => 0]); $response = $this->actingAs($user) ->post(route('account/request-item', ['itemType' => 'asset_model', 'itemId' => $model->id])); $response->assertStatus(302); $response->assertSessionHas('error'); // No request record should have been created. $this->assertDatabaseMissing('action_logs', [ 'item_id' => $model->id, 'item_type' => AssetModel::class, 'action_type' => 'requested', ]); } public function test_requestable_asset_model_can_still_be_requested(): void { // Non-regression: flipping the requestable flag ON must still // let the request go through. $user = User::factory()->create(); $model = AssetModel::factory()->create(['requestable' => 1]); $response = $this->actingAs($user) ->post(route('account/request-item', ['itemType' => 'asset_model', 'itemId' => $model->id])); $response->assertStatus(302); $response->assertSessionHas('success'); } public function test_arbitrary_item_type_is_rejected_by_route_constraint(): void { // Route now constrains {itemType} to asset|asset_model|accessory, // so arbitrary values like `user` no longer resolve to // App\Models\User via the studly_case concatenation inside // the controller. Anything else 404s at the router. $user = User::factory()->create(); $victim = User::factory()->create(); $response = $this->actingAs($user) ->post('/account/request/user/'.$victim->id); $response->assertNotFound(); } public function test_ignored_item_types_do_not_reach_the_controller(): void { // Belt-and-suspenders check for a couple more shapes. $user = User::factory()->create(); foreach (['location', 'component', 'consumable', 'license'] as $itemType) { $response = $this->actingAs($user) ->post('/account/request/'.$itemType.'/1'); $response->assertNotFound(); } // Make sure no stray Actionlog rows landed from the loop. $this->assertSame(0, Actionlog::where('action_type', 'requested')->count()); } }