From f28a82de71873e054c9e40410afbab5b83ac28af Mon Sep 17 00:00:00 2001 From: Marcus Moore Date: Wed, 10 Apr 2024 17:27:07 -0700 Subject: [PATCH] Implement some tests, scaffold others --- app/Http/Controllers/Api/AssetsController.php | 14 +-- .../Feature/Api/Assets/AssetCheckoutTest.php | 108 +++++++++++++++++- tests/Feature/Checkouts/AssetCheckoutTest.php | 7 +- 3 files changed, 116 insertions(+), 13 deletions(-) diff --git a/app/Http/Controllers/Api/AssetsController.php b/app/Http/Controllers/Api/AssetsController.php index f436990e7b..f1f0018a89 100644 --- a/app/Http/Controllers/Api/AssetsController.php +++ b/app/Http/Controllers/Api/AssetsController.php @@ -823,15 +823,14 @@ class AssetsController extends Controller // This item is checked out to a location if (request('checkout_to_type') == 'location') { - // @todo: test this - dd('asdfasdf'); $target = Location::find(request('assigned_location')); + // @todo: test the setting of '' $asset->location_id = ($target) ? $target->id : ''; $error_payload['target_id'] = $request->input('assigned_location'); $error_payload['target_type'] = 'location'; } elseif (request('checkout_to_type') == 'asset') { - // @todo: test this + // @todo: test this code path $target = Asset::where('id', '!=', $asset_id)->find(request('assigned_asset')); // Override with the asset's location_id if it has one $asset->location_id = (($target) && (isset($target->location_id))) ? $target->location_id : ''; @@ -839,28 +838,25 @@ class AssetsController extends Controller $error_payload['target_type'] = 'asset'; } elseif (request('checkout_to_type') == 'user') { - // @todo: test this + // @todo: test this code path // Fetch the target and set the asset's new location_id $target = User::find(request('assigned_user')); + // @todo: test if this is needed or already handled in checkOut method $asset->location_id = (($target) && (isset($target->location_id))) ? $target->location_id : ''; $error_payload['target_id'] = $request->input('assigned_user'); $error_payload['target_type'] = 'user'; } if ($request->filled('status_id')) { - // @todo: test this $asset->status_id = $request->get('status_id'); } if (! isset($target)) { - // @todo: test this + // @todo: test this code path return response()->json(Helper::formatStandardApiResponse('error', $error_payload, 'Checkout target for asset '.e($asset->asset_tag).' is invalid - '.$error_payload['target_type'].' does not exist.')); } - - - // @todo: test this $checkout_at = request('checkout_at', date('Y-m-d H:i:s')); // @todo: test this $expected_checkin = request('expected_checkin', null); diff --git a/tests/Feature/Api/Assets/AssetCheckoutTest.php b/tests/Feature/Api/Assets/AssetCheckoutTest.php index 6fa578a714..b902ba4189 100644 --- a/tests/Feature/Api/Assets/AssetCheckoutTest.php +++ b/tests/Feature/Api/Assets/AssetCheckoutTest.php @@ -4,7 +4,10 @@ namespace Tests\Feature\Api\Assets; use App\Events\CheckoutableCheckedOut; use App\Models\Asset; +use App\Models\Location; +use App\Models\Statuslabel; use App\Models\User; +use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Event; use Tests\TestCase; @@ -50,6 +53,11 @@ class AssetCheckoutTest extends TestCase ->assertStatusMessageIs('error'); } + public function testAssetCannotBeCheckedOutToItself() + { + $this->markTestIncomplete(); + } + public function testValidationWhenCheckingOutAsset() { $this->actingAsForApi(User::factory()->checkoutAssets()->create()) @@ -64,9 +72,93 @@ class AssetCheckoutTest extends TestCase $this->markTestIncomplete('This is not implemented'); } - public function testAssetCanBeCheckedOut() + /** + * This data provider contains checkout targets along with the + * asset's expected location after the checkout process. + */ + public function checkoutTargets(): array { - $this->markTestIncomplete(); + return [ + 'User' => [function () { + $userLocation = Location::factory()->create(); + $user = User::factory()->for($userLocation)->create(); + + return [ + 'checkout_type' => 'user', + 'target' => $user, + 'expected_location' => $userLocation, + ]; + }], + 'Asset without location set' => [function () { + $rtdLocation = Location::factory()->create(); + $asset = Asset::factory()->for($rtdLocation, 'defaultLoc')->create(['location_id' => null]); + + return [ + 'checkout_type' => 'asset', + 'target' => $asset, + 'expected_location' => $rtdLocation, + ]; + }], + 'Asset with location set' => [function () { + $rtdLocation = Location::factory()->create(); + $location = Location::factory()->create(); + $asset = Asset::factory()->for($location)->for($rtdLocation, 'defaultLoc')->create(); + + return [ + 'checkout_type' => 'asset', + 'target' => $asset, + 'expected_location' => $location, + ]; + }], + 'Location' => [function () { + $location = Location::factory()->create(); + + return [ + 'checkout_type' => 'location', + 'target' => $location, + 'expected_location' => $location, + ]; + }], + ]; + } + + /** @dataProvider checkoutTargets */ + public function testAssetCanBeCheckedOut($data) + { + // $this->markTestIncomplete(); + + ['checkout_type' => $type, 'target' => $target, 'expected_location' => $expectedLocation] = $data(); + + $newStatus = Statuslabel::factory()->readyToDeploy()->create(); + $asset = Asset::factory()->create(); + $admin = User::factory()->checkoutAssets()->create(); + + $this->actingAsForApi($admin) + ->postJson(route('api.asset.checkout', $asset), [ + 'checkout_to_type' => $type, + 'assigned_' . $type => $target->id, + 'status_id' => $newStatus->id, + 'checkout_at' => '2024-04-01', + 'expected_checkin' => '2024-04-08', + 'name' => 'Changed Name', + 'note' => 'Here is a cool note!', + ]); + + $asset->refresh(); + $this->assertTrue($asset->assignedTo()->is($target)); + $this->assertTrue($asset->location->is($expectedLocation)); + $this->assertEquals('Changed Name', $asset->name); + $this->assertTrue($asset->assetstatus->is($newStatus)); + $this->assertEquals('2024-04-01 00:00:00', $asset->last_checkout); + $this->assertEquals('2024-04-08 00:00:00', (string)$asset->expected_checkin); + + Event::assertDispatched(CheckoutableCheckedOut::class, 1); + Event::assertDispatched(function (CheckoutableCheckedOut $event) use ($admin, $asset, $target) { + return $event->checkoutable->is($asset) + && $event->checkedOutTo->is($target) + && $event->checkedOutBy->is($admin) + && $event->note === 'Here is a cool note!'; + }); } public function testLicenseSeatsAreAssignedToUserUponCheckout() @@ -76,6 +168,16 @@ class AssetCheckoutTest extends TestCase public function testLastCheckoutUsesCurrentDateIfNotProvided() { - $this->markTestIncomplete(); + $asset = Asset::factory()->create(['last_checkout' => now()->subMonth()]); + + $this->actingAsForApi(User::factory()->checkoutAssets()->create()) + ->postJson(route('api.asset.checkout', $asset), [ + 'checkout_to_type' => 'user', + 'assigned_user' => User::factory()->create()->id, + ]); + + $asset->refresh(); + + $this->assertTrue(Carbon::parse($asset->last_checkout)->diffInSeconds(now()) < 2); } } diff --git a/tests/Feature/Checkouts/AssetCheckoutTest.php b/tests/Feature/Checkouts/AssetCheckoutTest.php index 25ff69fa90..b3f8daab94 100644 --- a/tests/Feature/Checkouts/AssetCheckoutTest.php +++ b/tests/Feature/Checkouts/AssetCheckoutTest.php @@ -61,6 +61,11 @@ class AssetCheckoutTest extends TestCase Event::assertNotDispatched(CheckoutableCheckedOut::class); } + public function testAssetCannotBeCheckedOutToItself() + { + $this->markTestIncomplete(); + } + public function testValidationWhenCheckingOutAsset() { $this->actingAs(User::factory()->create()) @@ -208,7 +213,7 @@ class AssetCheckoutTest extends TestCase public function testLastCheckoutUsesCurrentDateIfNotProvided() { - $asset = Asset::factory()->create(); + $asset = Asset::factory()->create(['last_checkout' => now()->subMonth()]); $this->actingAs(User::factory()->checkoutAssets()->create()) ->post(route('hardware.checkout.store', $asset), [