3
0
mirror of https://github.com/snipe/snipe-it.git synced 2026-08-18 11:15:42 +00:00
Files
snipe-it/tests/Feature/Livewire/CheckoutTargetPanelTest.php
2026-07-15 11:31:29 +01:00

268 lines
11 KiB
PHP

<?php
namespace Tests\Feature\Livewire;
use App\Livewire\CheckoutTargetPanel;
use App\Models\Accessory;
use App\Models\Asset;
use App\Models\Component;
use App\Models\LicenseSeat;
use App\Models\Location;
use App\Models\User;
use Livewire\Livewire;
use Tests\TestCase;
class CheckoutTargetPanelTest extends TestCase
{
public function test_mount_rejects_unknown_type(): void
{
$this->actingAs(User::factory()->superuser()->create());
// Laravel wraps our InvalidArgumentException in ViewException at the
// point mount() is invoked during blade rendering — match the raw
// message rather than the outer wrapper class so the assertion stays
// valid if the wrapping ever changes.
$this->expectExceptionMessage('Unknown checkout-target-panel type: widgets');
Livewire::test(CheckoutTargetPanel::class, ['type' => 'widgets']);
}
public function test_mount_rejects_unknown_target_type_dispatch(): void
{
$this->actingAs(User::factory()->superuser()->create());
Livewire::test(CheckoutTargetPanel::class, ['type' => 'assets'])
->dispatch('checkout-target-selected', targetType: 'sinister', targetId: '1')
->assertSet('targetType', null)
->assertSet('targetId', 1);
}
public function test_type_prop_is_locked_against_client_mutation(): void
{
$this->actingAs(User::factory()->superuser()->create());
// Livewire's #[Locked] attribute throws CannotUpdateLockedPropertyException
// from the test client itself when the caller tries to mutate the
// property — the exception surfaces directly in the test process,
// not as a rendered 500 response.
$this->expectException(\Livewire\Features\SupportLockedProperties\CannotUpdateLockedPropertyException::class);
Livewire::test(CheckoutTargetPanel::class, ['type' => 'assets'])
->set('type', 'licenses');
}
public function test_initial_render_shows_empty_message_with_no_target(): void
{
$this->actingAs(User::factory()->superuser()->create());
Livewire::test(CheckoutTargetPanel::class, ['type' => 'assets'])
->assertSet('targetType', null)
->assertSet('targetId', null)
->assertSee(trans('admin/users/message.nothing_currently_assigned'));
}
public function test_user_target_lists_user_assets(): void
{
$admin = User::factory()->superuser()->create();
$target = User::factory()->create();
$asset = Asset::factory()->create([
'assigned_to' => $target->id,
'assigned_type' => User::class,
'asset_tag' => 'PANEL-TEST-USER-ASSETS',
]);
Livewire::actingAs($admin)
->test(CheckoutTargetPanel::class, ['type' => 'assets'])
->dispatch('checkout-target-selected', targetType: 'user', targetId: (string) $target->id)
->assertSet('targetType', 'user')
->assertSet('targetId', $target->id)
->assertSee($asset->asset_tag);
}
public function test_asset_target_lists_child_assets(): void
{
$admin = User::factory()->superuser()->create();
$parent = Asset::factory()->create();
$child = Asset::factory()->create([
'assigned_to' => $parent->id,
'assigned_type' => Asset::class,
'asset_tag' => 'PANEL-TEST-CHILD-ASSET',
]);
Livewire::actingAs($admin)
->test(CheckoutTargetPanel::class, ['type' => 'assets'])
->dispatch('checkout-target-selected', targetType: 'asset', targetId: (string) $parent->id)
->assertSee($child->asset_tag);
}
public function test_location_target_lists_assets_checked_out_to_that_location(): void
{
$admin = User::factory()->superuser()->create();
$location = Location::factory()->create();
// "Checked out to a location" = polymorphic assigned_to / assigned_type
// pair. We deliberately do NOT set location_id here so this asserts
// the panel is using Location::assignedAssets (checkout target),
// not Location::assets (physical/default location).
$asset = Asset::factory()->create([
'assigned_to' => $location->id,
'assigned_type' => Location::class,
'asset_tag' => 'PANEL-TEST-LOCATION-ASSET',
]);
Livewire::actingAs($admin)
->test(CheckoutTargetPanel::class, ['type' => 'assets'])
->dispatch('checkout-target-selected', targetType: 'location', targetId: (string) $location->id)
->assertSee($asset->asset_tag);
}
public function test_location_target_does_not_list_assets_merely_assigned_to_that_location_id(): void
{
// Regression: earlier version used Location::assets() (location_id-
// based) which pulls in assets that just happen to have this as their
// physical/default location but were never CHECKED OUT to it. That's
// wrong for a "current checkouts" sidebar.
$admin = User::factory()->superuser()->create();
$location = Location::factory()->create();
Asset::factory()->create([
'location_id' => $location->id,
// no assigned_to / assigned_type — asset is at this location
// physically but not checked out to it.
'asset_tag' => 'PANEL-TEST-PHYSICAL-ONLY',
]);
Livewire::actingAs($admin)
->test(CheckoutTargetPanel::class, ['type' => 'assets'])
->dispatch('checkout-target-selected', targetType: 'location', targetId: (string) $location->id)
->assertDontSee('PANEL-TEST-PHYSICAL-ONLY');
}
public function test_impossible_combo_consumables_to_asset_returns_empty(): void
{
// Consumables can only be checked out to users; picking an asset target
// on the consumables panel must not accidentally return the asset's
// accessories or something equally wrong.
$admin = User::factory()->superuser()->create();
$asset = Asset::factory()->create();
Livewire::actingAs($admin)
->test(CheckoutTargetPanel::class, ['type' => 'consumables'])
->dispatch('checkout-target-selected', targetType: 'asset', targetId: (string) $asset->id)
->assertSee(trans('admin/users/message.nothing_currently_assigned'));
}
public function test_impossible_combo_licenses_to_location_returns_empty(): void
{
$admin = User::factory()->superuser()->create();
$location = Location::factory()->create();
Livewire::actingAs($admin)
->test(CheckoutTargetPanel::class, ['type' => 'licenses'])
->dispatch('checkout-target-selected', targetType: 'location', targetId: (string) $location->id)
->assertSee(trans('admin/users/message.nothing_currently_assigned'));
}
public function test_authorization_gate_hides_target_items_from_unauthorized_viewer(): void
{
// Someone who can reach a checkout page for an item they're permitted
// to see, but a target user they aren't (FMCS cross-company etc.),
// must not have that target's other checkouts leaked through the
// sidebar. Simulate by acting as a plain user without view-users.
$viewer = User::factory()->create();
$target = User::factory()->create();
Asset::factory()->create([
'assigned_to' => $target->id,
'assigned_type' => User::class,
'asset_tag' => 'PANEL-TEST-SHOULD-NOT-SHOW',
]);
Livewire::actingAs($viewer)
->test(CheckoutTargetPanel::class, ['type' => 'assets'])
->dispatch('checkout-target-selected', targetType: 'user', targetId: (string) $target->id)
->assertDontSee('PANEL-TEST-SHOULD-NOT-SHOW')
->assertSee(trans('admin/users/message.nothing_currently_assigned'));
}
public function test_user_target_lists_user_accessories(): void
{
$admin = User::factory()->superuser()->create();
$target = User::factory()->create();
$accessory = Accessory::factory()->create(['name' => 'PANEL_ACCESSORY_TEST']);
$target->accessories()->attach($accessory->id, [
'assigned_type' => User::class,
'created_at' => now(),
]);
Livewire::actingAs($admin)
->test(CheckoutTargetPanel::class, ['type' => 'accessories'])
->dispatch('checkout-target-selected', targetType: 'user', targetId: (string) $target->id)
->assertSee('PANEL_ACCESSORY_TEST');
}
public function test_user_target_lists_user_licenses(): void
{
$admin = User::factory()->superuser()->create();
$target = User::factory()->create();
$seat = LicenseSeat::factory()->create(['assigned_to' => $target->id]);
Livewire::actingAs($admin)
->test(CheckoutTargetPanel::class, ['type' => 'licenses'])
->dispatch('checkout-target-selected', targetType: 'user', targetId: (string) $target->id)
->assertSee($seat->license->name);
}
public function test_asset_target_lists_target_components(): void
{
$admin = User::factory()->superuser()->create();
$target = Asset::factory()->create();
$component = Component::factory()->create(['name' => 'PANEL_COMPONENT_TEST']);
$target->components()->attach($component->id, [
'assigned_qty' => 2,
'created_by' => $admin->id,
'created_at' => now(),
]);
Livewire::actingAs($admin)
->test(CheckoutTargetPanel::class, ['type' => 'components'])
->dispatch('checkout-target-selected', targetType: 'asset', targetId: (string) $target->id)
->assertSee('PANEL_COMPONENT_TEST');
}
public function test_impossible_combo_components_to_user_returns_empty(): void
{
// Components can only be checked out to assets; picking a user target
// on the components panel must fall through to the empty state rather
// than surfacing anything the user happens to have.
$admin = User::factory()->superuser()->create();
$target = User::factory()->create();
Livewire::actingAs($admin)
->test(CheckoutTargetPanel::class, ['type' => 'components'])
->dispatch('checkout-target-selected', targetType: 'user', targetId: (string) $target->id)
->assertSee(trans('admin/users/message.nothing_currently_assigned'));
}
public function test_mount_rejects_unknown_default_target_type(): void
{
$this->actingAs(User::factory()->superuser()->create());
$this->expectExceptionMessage('Unknown checkout-target-panel defaultTargetType: martian');
Livewire::test(CheckoutTargetPanel::class, [
'type' => 'components',
'defaultTargetType' => 'martian',
]);
}
public function test_default_target_type_prop_is_locked_against_client_mutation(): void
{
$this->actingAs(User::factory()->superuser()->create());
$this->expectException(\Livewire\Features\SupportLockedProperties\CannotUpdateLockedPropertyException::class);
Livewire::test(CheckoutTargetPanel::class, [
'type' => 'components',
'defaultTargetType' => 'asset',
])->set('defaultTargetType', 'user');
}
}