Added delete cli prompt tool
This commit is contained in:
@@ -0,0 +1,619 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Console;
|
||||
|
||||
use App\Events\CheckoutableCheckedIn;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Asset;
|
||||
use App\Models\CheckoutAcceptance;
|
||||
use App\Models\Company;
|
||||
use App\Models\Component;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\License;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Models\Maintenance;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Testing\PendingCommand;
|
||||
use Tests\TestCase;
|
||||
|
||||
class BulkDeleteTest extends TestCase
|
||||
{
|
||||
// ---------------------------------------------------------------------------
|
||||
// Prompt sequence helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Builds a PendingCommand with the full prompt sequence pre-answered.
|
||||
*
|
||||
* Search() falls back as two steps: ask() for the search term, then
|
||||
* choice() to select from matching results. Multiselect() and select()
|
||||
* each fall back as a single choice() call.
|
||||
*/
|
||||
private function runCommand(
|
||||
User $admin,
|
||||
array $companyIds,
|
||||
array $types,
|
||||
string $deleteType = 'soft',
|
||||
bool $dryRun = false,
|
||||
bool $sendNotifications = false,
|
||||
bool $clearLogs = false,
|
||||
bool $deleteFiles = false,
|
||||
bool $doBackup = false,
|
||||
bool $confirm = true,
|
||||
): PendingCommand {
|
||||
$hasNotifiableTypes = ! empty(array_intersect($types, ['assets', 'licenses', 'accessories', 'components']));
|
||||
|
||||
$searchLabel = 'Who are you? Search by username, first or last name.';
|
||||
$companiesLabel = 'Which companies would you like to check in and delete items for?';
|
||||
$typesLabel = 'What item types would you like to check in and delete?';
|
||||
$deleteLabel = 'How should items be deleted?';
|
||||
|
||||
$cmd = $this->artisan('snipeit:checkin-delete-items')
|
||||
// Step 1: dry run confirm
|
||||
->expectsConfirmation('Is this a dry run?', $dryRun ? 'yes' : 'no')
|
||||
// Step 2: search() — ask() for the search term, then choice() to pick from results
|
||||
// Using expectsQuestion for both to avoid triggering choices validation
|
||||
->expectsQuestion($searchLabel, $admin->username)
|
||||
->expectsQuestion($searchLabel, (string) $admin->id)
|
||||
// Step 3: multiselect for companies
|
||||
->expectsQuestion($companiesLabel, $companyIds)
|
||||
// Step 4: multiselect for item types
|
||||
->expectsQuestion($typesLabel, $types)
|
||||
// Step 5: select for delete mode
|
||||
->expectsQuestion($deleteLabel, $deleteType);
|
||||
|
||||
// Step 6: notification confirm only shown for checkiable types
|
||||
if ($hasNotifiableTypes) {
|
||||
$cmd->expectsConfirmation('Should we send checkin notifications?', $sendNotifications ? 'yes' : 'no');
|
||||
}
|
||||
|
||||
// Steps 7–10 and final confirm
|
||||
$cmd->expectsConfirmation('Should we clear related action logs?', $clearLogs ? 'yes' : 'no');
|
||||
|
||||
// Step 8: file deletion prompt — only shown when deleteType !== 'none'
|
||||
if ($deleteType !== 'none') {
|
||||
$cmd->expectsConfirmation('Should we also delete associated image and upload files?', $deleteFiles ? 'yes' : 'no');
|
||||
}
|
||||
|
||||
$cmd->expectsConfirmation('Should we run a backup before proceeding?', $doBackup ? 'yes' : 'no')
|
||||
->expectsConfirmation(
|
||||
$dryRun ? 'Proceed with dry run?' : 'Are you sure you want to proceed? This cannot be undone.',
|
||||
$confirm ? 'yes' : 'no',
|
||||
);
|
||||
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Assets
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
public function test_assigned_asset_is_checked_in_and_soft_deleted(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$user = User::factory()->create(['company_id' => $company->id]);
|
||||
$asset = Asset::factory()->for($company)->assignedToUser($user)->create();
|
||||
|
||||
$this->assertNotNull($asset->assigned_to);
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['assets'])
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertSoftDeleted($asset);
|
||||
$this->assertNull($asset->fresh()->assigned_to);
|
||||
}
|
||||
|
||||
public function test_unassigned_asset_is_soft_deleted(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$asset = Asset::factory()->for($company)->create();
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['assets'])
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertSoftDeleted($asset);
|
||||
}
|
||||
|
||||
public function test_asset_is_hard_deleted(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$asset = Asset::factory()->for($company)->assignedToUser()->create();
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['assets'], deleteType: 'hard')
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertDatabaseMissing('assets', ['id' => $asset->id]);
|
||||
}
|
||||
|
||||
public function test_asset_checkin_event_fired_when_notifications_enabled(): void
|
||||
{
|
||||
Event::fake([CheckoutableCheckedIn::class]);
|
||||
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$asset = Asset::factory()->for($company)->assignedToUser()->create();
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['assets'], sendNotifications: true)
|
||||
->assertExitCode(0);
|
||||
|
||||
Event::assertDispatched(CheckoutableCheckedIn::class, fn ($e) => $e->checkoutable->is($asset));
|
||||
}
|
||||
|
||||
public function test_asset_checkin_event_not_fired_when_notifications_suppressed(): void
|
||||
{
|
||||
Event::fake([CheckoutableCheckedIn::class]);
|
||||
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
Asset::factory()->for($company)->assignedToUser()->create();
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['assets'], sendNotifications: false)
|
||||
->assertExitCode(0);
|
||||
|
||||
Event::assertNotDispatched(CheckoutableCheckedIn::class);
|
||||
}
|
||||
|
||||
public function test_asset_scoped_to_correct_company(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
[$companyA, $companyB] = Company::factory()->count(2)->create();
|
||||
|
||||
$assetA = Asset::factory()->for($companyA)->create();
|
||||
$assetB = Asset::factory()->for($companyB)->create();
|
||||
|
||||
$this->runCommand($admin, [$companyA->id], ['assets'])
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertSoftDeleted($assetA);
|
||||
$this->assertNotSoftDeleted($assetB);
|
||||
}
|
||||
|
||||
public function test_asset_delete_clears_all_checkout_acceptances(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$asset = Asset::factory()->for($company)->create();
|
||||
|
||||
CheckoutAcceptance::factory()->create([
|
||||
'checkoutable_type' => Asset::class,
|
||||
'checkoutable_id' => $asset->id,
|
||||
]);
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['assets'])
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertDatabaseMissing('checkout_acceptances', [
|
||||
'checkoutable_type' => Asset::class,
|
||||
'checkoutable_id' => $asset->id,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_asset_checkin_clears_linked_license_seats(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$user = User::factory()->create(['company_id' => $company->id]);
|
||||
$asset = Asset::factory()->for($company)->assignedToUser($user)->create();
|
||||
$seat = LicenseSeat::factory()->create(['asset_id' => $asset->id, 'assigned_to' => $user->id]);
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['assets'])
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertNull($seat->fresh()->assigned_to);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Licenses
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
public function test_assigned_license_seat_is_checked_in_and_license_soft_deleted(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$license = License::factory()->for($company)->create();
|
||||
$seat = LicenseSeat::factory()->for($license)->assignedToUser()->create();
|
||||
|
||||
$this->assertNotNull($seat->assigned_to);
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['licenses'])
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertSoftDeleted($license);
|
||||
$this->assertNull($seat->fresh()->assigned_to);
|
||||
$this->assertNull($seat->fresh()->asset_id);
|
||||
}
|
||||
|
||||
public function test_license_hard_delete_removes_seats_and_their_checkout_acceptances(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$license = License::factory()->for($company)->create();
|
||||
$seat = LicenseSeat::factory()->for($license)->assignedToUser()->create();
|
||||
|
||||
CheckoutAcceptance::factory()->create([
|
||||
'checkoutable_type' => LicenseSeat::class,
|
||||
'checkoutable_id' => $seat->id,
|
||||
]);
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['licenses'], deleteType: 'hard')
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertDatabaseMissing('licenses', ['id' => $license->id]);
|
||||
$this->assertDatabaseMissing('license_seats', ['id' => $seat->id]);
|
||||
$this->assertDatabaseMissing('checkout_acceptances', [
|
||||
'checkoutable_type' => LicenseSeat::class,
|
||||
'checkoutable_id' => $seat->id,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_license_scoped_to_correct_company(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
[$companyA, $companyB] = Company::factory()->count(2)->create();
|
||||
|
||||
$licenseA = License::factory()->for($companyA)->create();
|
||||
$licenseB = License::factory()->for($companyB)->create();
|
||||
|
||||
$this->runCommand($admin, [$companyA->id], ['licenses'])
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertSoftDeleted($licenseA);
|
||||
$this->assertNotSoftDeleted($licenseB);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Accessories
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
public function test_checked_out_accessory_is_checked_in_and_soft_deleted(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$accessory = Accessory::factory()->for($company)->checkedOutToUser()->create();
|
||||
|
||||
$this->assertEquals(1, $accessory->checkouts->count());
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['accessories'])
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertSoftDeleted($accessory);
|
||||
$this->assertEquals(0, $accessory->fresh()->checkouts->count());
|
||||
}
|
||||
|
||||
public function test_accessory_scoped_to_correct_company(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
[$companyA, $companyB] = Company::factory()->count(2)->create();
|
||||
|
||||
$accessoryA = Accessory::factory()->for($companyA)->checkedOutToUser()->create();
|
||||
$accessoryB = Accessory::factory()->for($companyB)->checkedOutToUser()->create();
|
||||
|
||||
$this->runCommand($admin, [$companyA->id], ['accessories'])
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertSoftDeleted($accessoryA);
|
||||
$this->assertNotSoftDeleted($accessoryB);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Components
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
public function test_checked_out_component_is_checked_in_and_soft_deleted(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$component = Component::factory()->for($company)->checkedOutToAsset()->create();
|
||||
|
||||
$this->assertDatabaseHas('components_assets', ['component_id' => $component->id]);
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['components'])
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertSoftDeleted($component);
|
||||
$this->assertDatabaseMissing('components_assets', ['component_id' => $component->id]);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Consumables
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
public function test_consumable_is_soft_deleted(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$consumable = Consumable::factory()->for($company)->create();
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['consumables'])
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertSoftDeleted($consumable);
|
||||
}
|
||||
|
||||
public function test_consumable_is_hard_deleted(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$consumable = Consumable::factory()->for($company)->create();
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['consumables'], deleteType: 'hard')
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertDatabaseMissing('consumables', ['id' => $consumable->id]);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Users
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
public function test_user_is_soft_deleted(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$user = User::factory()->create(['company_id' => $company->id, 'activated' => 1]);
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['users'])
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertSoftDeleted($user);
|
||||
}
|
||||
|
||||
public function test_user_delete_nulls_license_seat_assignments(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$user = User::factory()->create(['company_id' => $company->id, 'activated' => 1]);
|
||||
$seat = LicenseSeat::factory()->create(['assigned_to' => $user->id]);
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['users'])
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertNull($seat->fresh()->assigned_to);
|
||||
}
|
||||
|
||||
public function test_user_delete_removes_accessory_checkout_records(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$user = User::factory()->create(['company_id' => $company->id, 'activated' => 1]);
|
||||
Accessory::factory()->for($company)->checkedOutToUser($user)->create();
|
||||
|
||||
$this->assertDatabaseHas('accessories_checkout', ['assigned_to' => $user->id]);
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['users'])
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertDatabaseMissing('accessories_checkout', ['assigned_to' => $user->id]);
|
||||
}
|
||||
|
||||
public function test_user_delete_removes_consumable_assignments(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$user = User::factory()->create(['company_id' => $company->id, 'activated' => 1]);
|
||||
Consumable::factory()->for($company)->checkedOutToUser($user)->create();
|
||||
|
||||
$this->assertDatabaseHas('consumables_users', ['assigned_to' => $user->id]);
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['users'])
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertDatabaseMissing('consumables_users', ['assigned_to' => $user->id]);
|
||||
}
|
||||
|
||||
public function test_user_delete_removes_checkout_acceptances(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$user = User::factory()->create(['company_id' => $company->id, 'activated' => 1]);
|
||||
|
||||
CheckoutAcceptance::factory()->create(['assigned_to_id' => $user->id]);
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['users'])
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertDatabaseMissing('checkout_acceptances', ['assigned_to_id' => $user->id]);
|
||||
}
|
||||
|
||||
public function test_admin_user_is_skipped_during_user_deletion(): void
|
||||
{
|
||||
$company = Company::factory()->create();
|
||||
$admin = User::factory()->superuser()->create(['company_id' => $company->id, 'activated' => 1]);
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['users'])
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertDatabaseHas('users', ['id' => $admin->id, 'deleted_at' => null]);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Action log clearing
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
public function test_clear_logs_removes_asset_action_logs(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$user = User::factory()->create();
|
||||
$asset = Asset::factory()->for($company)->assignedToUser($user)->create();
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['assets'], clearLogs: true)
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertDatabaseMissing('action_logs', [
|
||||
'item_type' => Asset::class,
|
||||
'item_id' => $asset->id,
|
||||
]);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Maintenance / related table cleanup
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
public function test_asset_hard_delete_removes_maintenance_records(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$asset = Asset::factory()->for($company)->create();
|
||||
$maintenance = Maintenance::factory()->create(['asset_id' => $asset->id]);
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['assets'], deleteType: 'hard')
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertDatabaseMissing('maintenances', ['id' => $maintenance->id]);
|
||||
}
|
||||
|
||||
public function test_asset_hard_delete_removes_accessory_checkouts_to_asset(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$asset = Asset::factory()->for($company)->create();
|
||||
$accessory = Accessory::factory()->for($company)->create();
|
||||
$accessory->checkouts()->create([
|
||||
'accessory_id' => $accessory->id,
|
||||
'assigned_to' => $asset->id,
|
||||
'assigned_type' => Asset::class,
|
||||
'created_by' => $admin->id,
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('accessories_checkout', [
|
||||
'assigned_to' => $asset->id,
|
||||
'assigned_type' => Asset::class,
|
||||
]);
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['assets'], deleteType: 'hard')
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertDatabaseMissing('accessories_checkout', [
|
||||
'assigned_to' => $asset->id,
|
||||
'assigned_type' => Asset::class,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_asset_hard_delete_nulls_child_asset_assignments(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$target = Asset::factory()->for($company)->create();
|
||||
$child = Asset::factory()->create(['assigned_to' => $target->id, 'assigned_type' => Asset::class]);
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['assets'], deleteType: 'hard')
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertNull($child->fresh()->assigned_to);
|
||||
$this->assertNull($child->fresh()->assigned_type);
|
||||
}
|
||||
|
||||
public function test_license_hard_delete_removes_kit_entries(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$license = License::factory()->for($company)->create();
|
||||
DB::table('kits_licenses')->insert(['kit_id' => 1, 'license_id' => $license->id, 'quantity' => 1]);
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['licenses'], deleteType: 'hard')
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertDatabaseMissing('kits_licenses', ['license_id' => $license->id]);
|
||||
}
|
||||
|
||||
public function test_accessory_hard_delete_removes_kit_entries(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$accessory = Accessory::factory()->for($company)->create();
|
||||
DB::table('kits_accessories')->insert(['kit_id' => 1, 'accessory_id' => $accessory->id, 'quantity' => 1]);
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['accessories'], deleteType: 'hard')
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertDatabaseMissing('kits_accessories', ['accessory_id' => $accessory->id]);
|
||||
}
|
||||
|
||||
public function test_consumable_hard_delete_removes_kit_entries(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$consumable = Consumable::factory()->for($company)->create();
|
||||
DB::table('kits_consumables')->insert(['kit_id' => 1, 'consumable_id' => $consumable->id, 'quantity' => 1]);
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['consumables'], deleteType: 'hard')
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertDatabaseMissing('kits_consumables', ['consumable_id' => $consumable->id]);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Dry run
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
public function test_dry_run_does_not_delete_or_checkin_assets(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$user = User::factory()->create(['company_id' => $company->id]);
|
||||
$asset = Asset::factory()->for($company)->assignedToUser($user)->create();
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['assets'], dryRun: true)
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertNotSoftDeleted($asset);
|
||||
$this->assertNotNull($asset->fresh()->assigned_to);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Final confirm / abort
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
public function test_declining_final_confirm_makes_no_changes(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$asset = Asset::factory()->for($company)->create();
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['assets'], confirm: false)
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertNotSoftDeleted($asset);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Multi-company / checkin-only mode
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
public function test_multiple_companies_are_all_processed(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
[$companyA, $companyB] = Company::factory()->count(2)->create();
|
||||
|
||||
$assetA = Asset::factory()->for($companyA)->create();
|
||||
$assetB = Asset::factory()->for($companyB)->create();
|
||||
$assetC = Asset::factory()->create(); // no company — should be untouched
|
||||
|
||||
$this->runCommand($admin, [$companyA->id, $companyB->id], ['assets'])
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertSoftDeleted($assetA);
|
||||
$this->assertSoftDeleted($assetB);
|
||||
$this->assertNotSoftDeleted($assetC);
|
||||
}
|
||||
|
||||
public function test_checkin_only_mode_checks_in_without_deleting(): void
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$company = Company::factory()->create();
|
||||
$user = User::factory()->create(['company_id' => $company->id]);
|
||||
$asset = Asset::factory()->for($company)->assignedToUser($user)->create();
|
||||
|
||||
$this->runCommand($admin, [$company->id], ['assets'], deleteType: 'none')
|
||||
->assertExitCode(0);
|
||||
|
||||
$this->assertNotSoftDeleted($asset);
|
||||
$this->assertNull($asset->fresh()->assigned_to);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user