ajout app
This commit is contained in:
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Accessories;
|
||||
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CheckoutAccessoryNotification;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AccessoryCheckoutTest extends TestCase
|
||||
{
|
||||
public function testCheckingOutAccessoryRequiresCorrectPermission()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->create())
|
||||
->postJson(route('api.accessories.checkout', Accessory::factory()->create()))
|
||||
->assertForbidden();
|
||||
}
|
||||
|
||||
public function testValidationWhenCheckingOutAccessory()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->checkoutAccessories()->create())
|
||||
->postJson(route('api.accessories.checkout', Accessory::factory()->create()), [
|
||||
// missing assigned_to
|
||||
])
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testAccessoryMustBeAvailableWhenCheckingOut()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->checkoutAccessories()->create())
|
||||
->postJson(route('api.accessories.checkout', Accessory::factory()->withoutItemsRemaining()->create()), [
|
||||
'assigned_to' => User::factory()->create()->id,
|
||||
])
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testAccessoryCanBeCheckedOut()
|
||||
{
|
||||
$accessory = Accessory::factory()->create();
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAsForApi(User::factory()->checkoutAccessories()->create())
|
||||
->postJson(route('api.accessories.checkout', $accessory), [
|
||||
'assigned_to' => $user->id,
|
||||
]);
|
||||
|
||||
$this->assertTrue($accessory->users->contains($user));
|
||||
}
|
||||
|
||||
public function testUserSentNotificationUponCheckout()
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$accessory = Accessory::factory()->requiringAcceptance()->create();
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAsForApi(User::factory()->checkoutAccessories()->create())
|
||||
->postJson(route('api.accessories.checkout', $accessory), [
|
||||
'assigned_to' => $user->id,
|
||||
]);
|
||||
|
||||
Notification::assertSentTo($user, CheckoutAccessoryNotification::class);
|
||||
}
|
||||
|
||||
public function testActionLogCreatedUponCheckout()
|
||||
{
|
||||
$accessory = Accessory::factory()->create();
|
||||
$actor = User::factory()->checkoutAccessories()->create();
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAsForApi($actor)
|
||||
->postJson(route('api.accessories.checkout', $accessory), [
|
||||
'assigned_to' => $user->id,
|
||||
'note' => 'oh hi there',
|
||||
]);
|
||||
|
||||
$this->assertEquals(
|
||||
1,
|
||||
Actionlog::where([
|
||||
'action_type' => 'checkout',
|
||||
'target_id' => $user->id,
|
||||
'target_type' => User::class,
|
||||
'item_id' => $accessory->id,
|
||||
'item_type' => Accessory::class,
|
||||
'user_id' => $actor->id,
|
||||
'note' => 'oh hi there',
|
||||
])->count(),
|
||||
'Log entry either does not exist or there are more than expected'
|
||||
);
|
||||
}
|
||||
}
|
162
SNIPE-IT/tests/Feature/Api/Assets/AssetCheckinTest.php
Normal file
162
SNIPE-IT/tests/Feature/Api/Assets/AssetCheckinTest.php
Normal file
@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Assets;
|
||||
|
||||
use App\Events\CheckoutableCheckedIn;
|
||||
use App\Models\Asset;
|
||||
use App\Models\CheckoutAcceptance;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Models\Location;
|
||||
use App\Models\Statuslabel;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AssetCheckinTest extends TestCase
|
||||
{
|
||||
public function testCheckingInAssetRequiresCorrectPermission()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->create())
|
||||
->postJson(route('api.asset.checkin', Asset::factory()->assignedToUser()->create()))
|
||||
->assertForbidden();
|
||||
}
|
||||
|
||||
public function testCannotCheckInNonExistentAsset()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->checkinAssets()->create())
|
||||
->postJson(route('api.asset.checkin', ['id' => 'does-not-exist']))
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testCannotCheckInAssetThatIsNotCheckedOut()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->checkinAssets()->create())
|
||||
->postJson(route('api.asset.checkin', Asset::factory()->create()->id))
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testAssetCanBeCheckedIn()
|
||||
{
|
||||
Event::fake([CheckoutableCheckedIn::class]);
|
||||
|
||||
$user = User::factory()->create();
|
||||
$location = Location::factory()->create();
|
||||
$status = Statuslabel::factory()->create();
|
||||
$asset = Asset::factory()->assignedToUser($user)->create([
|
||||
'expected_checkin' => now()->addDay(),
|
||||
'last_checkin' => null,
|
||||
'accepted' => 'accepted',
|
||||
]);
|
||||
|
||||
$this->assertTrue($asset->assignedTo->is($user));
|
||||
|
||||
$currentTimestamp = now();
|
||||
|
||||
$this->actingAsForApi(User::factory()->checkinAssets()->create())
|
||||
->postJson(route('api.asset.checkin', $asset), [
|
||||
'name' => 'Changed Name',
|
||||
'status_id' => $status->id,
|
||||
'location_id' => $location->id,
|
||||
])
|
||||
->assertOk();
|
||||
|
||||
$this->assertNull($asset->refresh()->assignedTo);
|
||||
$this->assertNull($asset->expected_checkin);
|
||||
$this->assertNull($asset->assignedTo);
|
||||
$this->assertNull($asset->assigned_type);
|
||||
$this->assertNull($asset->accepted);
|
||||
$this->assertEquals('Changed Name', $asset->name);
|
||||
$this->assertEquals($status->id, $asset->status_id);
|
||||
$this->assertTrue($asset->location()->is($location));
|
||||
|
||||
Event::assertDispatched(function (CheckoutableCheckedIn $event) use ($currentTimestamp) {
|
||||
// this could be better mocked but is ok for now.
|
||||
return Carbon::parse($event->action_date)->diffInSeconds($currentTimestamp) < 2;
|
||||
}, 1);
|
||||
}
|
||||
|
||||
public function testLocationIsSetToRTDLocationByDefaultUponCheckin()
|
||||
{
|
||||
$rtdLocation = Location::factory()->create();
|
||||
$asset = Asset::factory()->assignedToUser()->create([
|
||||
'location_id' => Location::factory()->create()->id,
|
||||
'rtd_location_id' => $rtdLocation->id,
|
||||
]);
|
||||
|
||||
$this->actingAsForApi(User::factory()->checkinAssets()->create())
|
||||
->postJson(route('api.asset.checkin', $asset->id));
|
||||
|
||||
$this->assertTrue($asset->refresh()->location()->is($rtdLocation));
|
||||
}
|
||||
|
||||
public function testDefaultLocationCanBeUpdatedUponCheckin()
|
||||
{
|
||||
$location = Location::factory()->create();
|
||||
$asset = Asset::factory()->assignedToUser()->create();
|
||||
|
||||
$this->actingAsForApi(User::factory()->checkinAssets()->create())
|
||||
->postJson(route('api.asset.checkin', $asset), [
|
||||
'location_id' => $location->id,
|
||||
'update_default_location' => true,
|
||||
]);
|
||||
|
||||
$this->assertTrue($asset->refresh()->defaultLoc()->is($location));
|
||||
}
|
||||
|
||||
public function testAssetsLicenseSeatsAreClearedUponCheckin()
|
||||
{
|
||||
$asset = Asset::factory()->assignedToUser()->create();
|
||||
LicenseSeat::factory()->assignedToUser()->for($asset)->create();
|
||||
|
||||
$this->assertNotNull($asset->licenseseats->first()->assigned_to);
|
||||
|
||||
$this->actingAsForApi(User::factory()->checkinAssets()->create())
|
||||
->postJson(route('api.asset.checkin', $asset));
|
||||
|
||||
$this->assertNull($asset->refresh()->licenseseats->first()->assigned_to);
|
||||
}
|
||||
|
||||
public function testLegacyLocationValuesSetToZeroAreUpdated()
|
||||
{
|
||||
$asset = Asset::factory()->canBeInvalidUponCreation()->assignedToUser()->create([
|
||||
'rtd_location_id' => 0,
|
||||
'location_id' => 0,
|
||||
]);
|
||||
|
||||
$this->actingAsForApi(User::factory()->checkinAssets()->create())
|
||||
->postJson(route('api.asset.checkin', $asset));
|
||||
|
||||
$this->assertNull($asset->refresh()->rtd_location_id);
|
||||
$this->assertEquals($asset->location_id, $asset->rtd_location_id);
|
||||
}
|
||||
|
||||
public function testPendingCheckoutAcceptancesAreClearedUponCheckin()
|
||||
{
|
||||
$asset = Asset::factory()->assignedToUser()->create();
|
||||
|
||||
$acceptance = CheckoutAcceptance::factory()->for($asset, 'checkoutable')->pending()->create();
|
||||
|
||||
$this->actingAsForApi(User::factory()->checkinAssets()->create())
|
||||
->postJson(route('api.asset.checkin', $asset));
|
||||
|
||||
$this->assertFalse($acceptance->exists(), 'Acceptance was not deleted');
|
||||
}
|
||||
|
||||
public function testCheckinTimeAndActionLogNoteCanBeSet()
|
||||
{
|
||||
Event::fake();
|
||||
|
||||
$this->actingAsForApi(User::factory()->checkinAssets()->create())
|
||||
->postJson(route('api.asset.checkin', Asset::factory()->assignedToUser()->create()), [
|
||||
// time is appended to the provided date in controller
|
||||
'checkin_at' => '2023-01-02',
|
||||
'note' => 'hi there',
|
||||
]);
|
||||
|
||||
Event::assertDispatched(function (CheckoutableCheckedIn $event) {
|
||||
return Carbon::parse('2023-01-02')->isSameDay(Carbon::parse($event->action_date))
|
||||
&& $event->note === 'hi there';
|
||||
}, 1);
|
||||
}
|
||||
}
|
78
SNIPE-IT/tests/Feature/Api/Assets/AssetIndexTest.php
Normal file
78
SNIPE-IT/tests/Feature/Api/Assets/AssetIndexTest.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Assets;
|
||||
|
||||
use App\Models\Asset;
|
||||
use App\Models\Company;
|
||||
use App\Models\User;
|
||||
use Illuminate\Testing\Fluent\AssertableJson;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AssetIndexTest extends TestCase
|
||||
{
|
||||
public function testAssetIndexReturnsExpectedAssets()
|
||||
{
|
||||
Asset::factory()->count(3)->create();
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->getJson(
|
||||
route('api.assets.index', [
|
||||
'sort' => 'name',
|
||||
'order' => 'asc',
|
||||
'offset' => '0',
|
||||
'limit' => '20',
|
||||
]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'total',
|
||||
'rows',
|
||||
])
|
||||
->assertJson(fn(AssertableJson $json) => $json->has('rows', 3)->etc());
|
||||
}
|
||||
|
||||
public function testAssetIndexAdheresToCompanyScoping()
|
||||
{
|
||||
[$companyA, $companyB] = Company::factory()->count(2)->create();
|
||||
|
||||
$assetA = Asset::factory()->for($companyA)->create();
|
||||
$assetB = Asset::factory()->for($companyB)->create();
|
||||
|
||||
$superUser = $companyA->users()->save(User::factory()->superuser()->make());
|
||||
$userInCompanyA = $companyA->users()->save(User::factory()->viewAssets()->make());
|
||||
$userInCompanyB = $companyB->users()->save(User::factory()->viewAssets()->make());
|
||||
|
||||
$this->settings->disableMultipleFullCompanySupport();
|
||||
|
||||
$this->actingAsForApi($superUser)
|
||||
->getJson(route('api.assets.index'))
|
||||
->assertResponseContainsInRows($assetA, 'asset_tag')
|
||||
->assertResponseContainsInRows($assetB, 'asset_tag');
|
||||
|
||||
$this->actingAsForApi($userInCompanyA)
|
||||
->getJson(route('api.assets.index'))
|
||||
->assertResponseContainsInRows($assetA, 'asset_tag')
|
||||
->assertResponseContainsInRows($assetB, 'asset_tag');
|
||||
|
||||
$this->actingAsForApi($userInCompanyB)
|
||||
->getJson(route('api.assets.index'))
|
||||
->assertResponseContainsInRows($assetA, 'asset_tag')
|
||||
->assertResponseContainsInRows($assetB, 'asset_tag');
|
||||
|
||||
$this->settings->enableMultipleFullCompanySupport();
|
||||
|
||||
$this->actingAsForApi($superUser)
|
||||
->getJson(route('api.assets.index'))
|
||||
->assertResponseContainsInRows($assetA, 'asset_tag')
|
||||
->assertResponseContainsInRows($assetB, 'asset_tag');
|
||||
|
||||
$this->actingAsForApi($userInCompanyA)
|
||||
->getJson(route('api.assets.index'))
|
||||
->assertResponseContainsInRows($assetA, 'asset_tag')
|
||||
->assertResponseDoesNotContainInRows($assetB, 'asset_tag');
|
||||
|
||||
$this->actingAsForApi($userInCompanyB)
|
||||
->getJson(route('api.assets.index'))
|
||||
->assertResponseDoesNotContainInRows($assetA, 'asset_tag')
|
||||
->assertResponseContainsInRows($assetB, 'asset_tag');
|
||||
}
|
||||
}
|
482
SNIPE-IT/tests/Feature/Api/Assets/AssetStoreTest.php
Normal file
482
SNIPE-IT/tests/Feature/Api/Assets/AssetStoreTest.php
Normal file
@ -0,0 +1,482 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Assets;
|
||||
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Company;
|
||||
use App\Models\Location;
|
||||
use App\Models\Statuslabel;
|
||||
use App\Models\Supplier;
|
||||
use App\Models\User;
|
||||
use Illuminate\Testing\Fluent\AssertableJson;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AssetStoreTest extends TestCase
|
||||
{
|
||||
public function testRequiresPermissionToCreateAsset()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->create())
|
||||
->postJson(route('api.assets.store'))
|
||||
->assertForbidden();
|
||||
}
|
||||
|
||||
public function testAllAssetAttributesAreStored()
|
||||
{
|
||||
$company = Company::factory()->create();
|
||||
$location = Location::factory()->create();
|
||||
$model = AssetModel::factory()->create();
|
||||
$rtdLocation = Location::factory()->create();
|
||||
$status = Statuslabel::factory()->create();
|
||||
$supplier = Supplier::factory()->create();
|
||||
$user = User::factory()->createAssets()->create();
|
||||
$userAssigned = User::factory()->create();
|
||||
|
||||
$response = $this->actingAsForApi($user)
|
||||
->postJson(route('api.assets.store'), [
|
||||
'asset_eol_date' => '2024-06-02',
|
||||
'asset_tag' => 'random_string',
|
||||
'assigned_user' => $userAssigned->id,
|
||||
'company_id' => $company->id,
|
||||
'last_audit_date' => '2023-09-03',
|
||||
'location_id' => $location->id,
|
||||
'model_id' => $model->id,
|
||||
'name' => 'A New Asset',
|
||||
'notes' => 'Some notes',
|
||||
'order_number' => '5678',
|
||||
'purchase_cost' => '123.45',
|
||||
'purchase_date' => '2023-09-02',
|
||||
'requestable' => true,
|
||||
'rtd_location_id' => $rtdLocation->id,
|
||||
'serial' => '1234567890',
|
||||
'status_id' => $status->id,
|
||||
'supplier_id' => $supplier->id,
|
||||
'warranty_months' => 10,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success')
|
||||
->json();
|
||||
|
||||
$asset = Asset::find($response['payload']['id']);
|
||||
|
||||
$this->assertTrue($asset->adminuser->is($user));
|
||||
|
||||
$this->assertEquals('2024-06-02', $asset->asset_eol_date);
|
||||
$this->assertEquals('random_string', $asset->asset_tag);
|
||||
$this->assertEquals($userAssigned->id, $asset->assigned_to);
|
||||
$this->assertTrue($asset->company->is($company));
|
||||
$this->assertEquals('2023-09-03 00:00:00', $asset->last_audit_date->format('Y-m-d H:i:s'));
|
||||
$this->assertTrue($asset->location->is($location));
|
||||
$this->assertTrue($asset->model->is($model));
|
||||
$this->assertEquals('A New Asset', $asset->name);
|
||||
$this->assertEquals('Some notes', $asset->notes);
|
||||
$this->assertEquals('5678', $asset->order_number);
|
||||
$this->assertEquals('123.45', $asset->purchase_cost);
|
||||
$this->assertTrue($asset->purchase_date->is('2023-09-02'));
|
||||
$this->assertEquals('1', $asset->requestable);
|
||||
$this->assertTrue($asset->defaultLoc->is($rtdLocation));
|
||||
$this->assertEquals('1234567890', $asset->serial);
|
||||
$this->assertTrue($asset->assetstatus->is($status));
|
||||
$this->assertTrue($asset->supplier->is($supplier));
|
||||
$this->assertEquals(10, $asset->warranty_months);
|
||||
}
|
||||
|
||||
public function testSetsLastAuditDateToMidnightOfProvidedDate()
|
||||
{
|
||||
$response = $this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'last_audit_date' => '2023-09-03 12:23:45',
|
||||
'asset_tag' => '1234',
|
||||
'model_id' => AssetModel::factory()->create()->id,
|
||||
'status_id' => Statuslabel::factory()->create()->id,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success');
|
||||
|
||||
$asset = Asset::find($response['payload']['id']);
|
||||
$this->assertEquals('00:00:00', $asset->last_audit_date->format('H:i:s'));
|
||||
}
|
||||
|
||||
public function testLastAuditDateCanBeNull()
|
||||
{
|
||||
$response = $this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
// 'last_audit_date' => '2023-09-03 12:23:45',
|
||||
'asset_tag' => '1234',
|
||||
'model_id' => AssetModel::factory()->create()->id,
|
||||
'status_id' => Statuslabel::factory()->create()->id,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success');
|
||||
|
||||
$asset = Asset::find($response['payload']['id']);
|
||||
$this->assertNull($asset->last_audit_date);
|
||||
}
|
||||
|
||||
public function testNonDateUsedForLastAuditDateReturnsValidationError()
|
||||
{
|
||||
$response = $this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'last_audit_date' => 'this-is-not-valid',
|
||||
'asset_tag' => '1234',
|
||||
'model_id' => AssetModel::factory()->create()->id,
|
||||
'status_id' => Statuslabel::factory()->create()->id,
|
||||
])
|
||||
->assertStatusMessageIs('error');
|
||||
|
||||
$this->assertNotNull($response->json('messages.last_audit_date'));
|
||||
}
|
||||
|
||||
public function testArchivedDepreciateAndPhysicalCanBeNull()
|
||||
{
|
||||
$model = AssetModel::factory()->ipadModel()->create();
|
||||
$status = Statuslabel::factory()->create();
|
||||
|
||||
$this->settings->enableAutoIncrement();
|
||||
|
||||
$response = $this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'model_id' => $model->id,
|
||||
'status_id' => $status->id,
|
||||
'archive' => null,
|
||||
'depreciate' => null,
|
||||
'physical' => null
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success')
|
||||
->json();
|
||||
|
||||
$asset = Asset::find($response['payload']['id']);
|
||||
$this->assertEquals(0, $asset->archived);
|
||||
$this->assertEquals(1, $asset->physical);
|
||||
$this->assertEquals(0, $asset->depreciate);
|
||||
}
|
||||
|
||||
public function testArchivedDepreciateAndPhysicalCanBeEmpty()
|
||||
{
|
||||
$model = AssetModel::factory()->ipadModel()->create();
|
||||
$status = Statuslabel::factory()->create();
|
||||
|
||||
$this->settings->enableAutoIncrement();
|
||||
|
||||
$response = $this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'model_id' => $model->id,
|
||||
'status_id' => $status->id,
|
||||
'archive' => '',
|
||||
'depreciate' => '',
|
||||
'physical' => ''
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success')
|
||||
->json();
|
||||
|
||||
$asset = Asset::find($response['payload']['id']);
|
||||
$this->assertEquals(0, $asset->archived);
|
||||
$this->assertEquals(1, $asset->physical);
|
||||
$this->assertEquals(0, $asset->depreciate);
|
||||
}
|
||||
|
||||
public function testAssetEolDateIsCalculatedIfPurchaseDateSet()
|
||||
{
|
||||
$model = AssetModel::factory()->mbp13Model()->create();
|
||||
$status = Statuslabel::factory()->create();
|
||||
|
||||
$this->settings->enableAutoIncrement();
|
||||
|
||||
$response = $this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'model_id' => $model->id,
|
||||
'purchase_date' => '2021-01-01',
|
||||
'status_id' => $status->id,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success')
|
||||
->json();
|
||||
|
||||
$asset = Asset::find($response['payload']['id']);
|
||||
$this->assertEquals('2024-01-01', $asset->asset_eol_date);
|
||||
}
|
||||
|
||||
public function testAssetEolDateIsNotCalculatedIfPurchaseDateNotSet()
|
||||
{
|
||||
$model = AssetModel::factory()->mbp13Model()->create();
|
||||
$status = Statuslabel::factory()->create();
|
||||
|
||||
$this->settings->enableAutoIncrement();
|
||||
|
||||
$response = $this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'model_id' => $model->id,
|
||||
'status_id' => $status->id,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success')
|
||||
->json();
|
||||
|
||||
$asset = Asset::find($response['payload']['id']);
|
||||
$this->assertNull($asset->asset_eol_date);
|
||||
}
|
||||
|
||||
public function testAssetEolExplicitIsSetIfAssetEolDateIsExplicitlySet()
|
||||
{
|
||||
$model = AssetModel::factory()->mbp13Model()->create();
|
||||
$status = Statuslabel::factory()->create();
|
||||
|
||||
$this->settings->enableAutoIncrement();
|
||||
|
||||
$response = $this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'model_id' => $model->id,
|
||||
'asset_eol_date' => '2025-01-01',
|
||||
'status_id' => $status->id,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success')
|
||||
->json();
|
||||
|
||||
$asset = Asset::find($response['payload']['id']);
|
||||
$this->assertEquals('2025-01-01', $asset->asset_eol_date);
|
||||
$this->assertTrue($asset->eol_explicit);
|
||||
}
|
||||
|
||||
public function testAssetGetsAssetTagWithAutoIncrement()
|
||||
{
|
||||
$model = AssetModel::factory()->create();
|
||||
$status = Statuslabel::factory()->create();
|
||||
|
||||
$this->settings->enableAutoIncrement();
|
||||
|
||||
$response = $this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'model_id' => $model->id,
|
||||
'status_id' => $status->id,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success')
|
||||
->json();
|
||||
|
||||
$asset = Asset::find($response['payload']['id']);
|
||||
$this->assertNotNull($asset->asset_tag);
|
||||
}
|
||||
|
||||
public function testAssetCreationFailsWithNoAssetTagOrAutoIncrement()
|
||||
{
|
||||
$model = AssetModel::factory()->create();
|
||||
$status = Statuslabel::factory()->create();
|
||||
|
||||
$this->settings->disableAutoIncrement();
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'model_id' => $model->id,
|
||||
'status_id' => $status->id,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testUniqueSerialNumbersIsEnforcedWhenEnabled()
|
||||
{
|
||||
$model = AssetModel::factory()->create();
|
||||
$status = Statuslabel::factory()->create();
|
||||
$serial = '1234567890';
|
||||
|
||||
$this->settings->enableAutoIncrement();
|
||||
$this->settings->enableUniqueSerialNumbers();
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'model_id' => $model->id,
|
||||
'status_id' => $status->id,
|
||||
'serial' => $serial,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success');
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'model_id' => $model->id,
|
||||
'status_id' => $status->id,
|
||||
'serial' => $serial,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testUniqueSerialNumbersIsNotEnforcedWhenDisabled()
|
||||
{
|
||||
$model = AssetModel::factory()->create();
|
||||
$status = Statuslabel::factory()->create();
|
||||
$serial = '1234567890';
|
||||
|
||||
$this->settings->enableAutoIncrement();
|
||||
$this->settings->disableUniqueSerialNumbers();
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'model_id' => $model->id,
|
||||
'status_id' => $status->id,
|
||||
'serial' => $serial,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success');
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'model_id' => $model->id,
|
||||
'status_id' => $status->id,
|
||||
'serial' => $serial,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success');
|
||||
}
|
||||
|
||||
public function testAssetTagsMustBeUniqueWhenUndeleted()
|
||||
{
|
||||
$model = AssetModel::factory()->create();
|
||||
$status = Statuslabel::factory()->create();
|
||||
$asset_tag = '1234567890';
|
||||
|
||||
$this->settings->disableAutoIncrement();
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'asset_tag' => $asset_tag,
|
||||
'model_id' => $model->id,
|
||||
'status_id' => $status->id,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success');
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'asset_tag' => $asset_tag,
|
||||
'model_id' => $model->id,
|
||||
'status_id' => $status->id,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testAssetTagsCanBeDuplicatedIfDeleted()
|
||||
{
|
||||
$model = AssetModel::factory()->create();
|
||||
$status = Statuslabel::factory()->create();
|
||||
$asset_tag = '1234567890';
|
||||
|
||||
$this->settings->disableAutoIncrement();
|
||||
|
||||
$response = $this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'asset_tag' => $asset_tag,
|
||||
'model_id' => $model->id,
|
||||
'status_id' => $status->id,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success')
|
||||
->json();
|
||||
|
||||
Asset::find($response['payload']['id'])->delete();
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'asset_tag' => $asset_tag,
|
||||
'model_id' => $model->id,
|
||||
'status_id' => $status->id,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success');
|
||||
}
|
||||
|
||||
public function testAnAssetCanBeCheckedOutToUserOnStore()
|
||||
{
|
||||
$model = AssetModel::factory()->create();
|
||||
$status = Statuslabel::factory()->create();
|
||||
$user = User::factory()->createAssets()->create();
|
||||
$userAssigned = User::factory()->create();
|
||||
|
||||
$this->settings->enableAutoIncrement();
|
||||
|
||||
$response = $this->actingAsForApi($user)
|
||||
->postJson(route('api.assets.store'), [
|
||||
'assigned_user' => $userAssigned->id,
|
||||
'model_id' => $model->id,
|
||||
'status_id' => $status->id,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success')
|
||||
->json();
|
||||
|
||||
$asset = Asset::find($response['payload']['id']);
|
||||
|
||||
$this->assertTrue($asset->adminuser->is($user));
|
||||
$this->assertTrue($asset->checkedOutToUser());
|
||||
$this->assertTrue($asset->assignedTo->is($userAssigned));
|
||||
}
|
||||
|
||||
public function testAnAssetCanBeCheckedOutToLocationOnStore()
|
||||
{
|
||||
$model = AssetModel::factory()->create();
|
||||
$status = Statuslabel::factory()->create();
|
||||
$location = Location::factory()->create();
|
||||
$user = User::factory()->createAssets()->create();
|
||||
|
||||
$this->settings->enableAutoIncrement();
|
||||
|
||||
$response = $this->actingAsForApi($user)
|
||||
->postJson(route('api.assets.store'), [
|
||||
'assigned_location' => $location->id,
|
||||
'model_id' => $model->id,
|
||||
'status_id' => $status->id,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success')
|
||||
->json();
|
||||
|
||||
$asset = Asset::find($response['payload']['id']);
|
||||
|
||||
$this->assertTrue($asset->adminuser->is($user));
|
||||
$this->assertTrue($asset->checkedOutToLocation());
|
||||
$this->assertTrue($asset->location->is($location));
|
||||
}
|
||||
|
||||
public function testAnAssetCanBeCheckedOutToAssetOnStore()
|
||||
{
|
||||
$model = AssetModel::factory()->create();
|
||||
$status = Statuslabel::factory()->create();
|
||||
$asset = Asset::factory()->create();
|
||||
$user = User::factory()->createAssets()->create();
|
||||
|
||||
$this->settings->enableAutoIncrement();
|
||||
|
||||
$response = $this->actingAsForApi($user)
|
||||
->postJson(route('api.assets.store'), [
|
||||
'assigned_asset' => $asset->id,
|
||||
'model_id' => $model->id,
|
||||
'status_id' => $status->id,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success')
|
||||
->json();
|
||||
|
||||
$apiAsset = Asset::find($response['payload']['id']);
|
||||
|
||||
$this->assertTrue($apiAsset->adminuser->is($user));
|
||||
$this->assertTrue($apiAsset->checkedOutToAsset());
|
||||
// I think this makes sense, but open to a sanity check
|
||||
$this->assertTrue($asset->assignedAssets()->find($response['payload']['id'])->is($apiAsset));
|
||||
}
|
||||
|
||||
public function testCompanyIdNeedsToBeInteger()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->createAssets()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'company_id' => [1],
|
||||
])
|
||||
->assertStatusMessageIs('error')
|
||||
->assertJson(function (AssertableJson $json) {
|
||||
$json->has('messages.company_id')->etc();
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Assets;
|
||||
|
||||
use App\Models\Asset;
|
||||
use App\Models\Company;
|
||||
use App\Models\User;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AssetsForSelectListTest extends TestCase
|
||||
{
|
||||
public function testAssetsCanBeSearchedForByAssetTag()
|
||||
{
|
||||
Asset::factory()->create(['asset_tag' => '0001']);
|
||||
Asset::factory()->create(['asset_tag' => '0002']);
|
||||
|
||||
$response = $this->actingAsForApi(User::factory()->create())
|
||||
->getJson(route('assets.selectlist', ['search' => '000']))
|
||||
->assertOk();
|
||||
|
||||
$results = collect($response->json('results'));
|
||||
|
||||
$this->assertEquals(2, $results->count());
|
||||
$this->assertTrue($results->pluck('text')->contains(fn($text) => str_contains($text, '0001')));
|
||||
$this->assertTrue($results->pluck('text')->contains(fn($text) => str_contains($text, '0002')));
|
||||
}
|
||||
|
||||
public function testAssetsAreScopedToCompanyWhenMultipleCompanySupportEnabled()
|
||||
{
|
||||
[$companyA, $companyB] = Company::factory()->count(2)->create();
|
||||
|
||||
$assetA = Asset::factory()->for($companyA)->create(['asset_tag' => '0001']);
|
||||
$assetB = Asset::factory()->for($companyB)->create(['asset_tag' => '0002']);
|
||||
|
||||
$superUser = $companyA->users()->save(User::factory()->superuser()->make());
|
||||
$userInCompanyA = $companyA->users()->save(User::factory()->viewAssets()->make());
|
||||
$userInCompanyB = $companyB->users()->save(User::factory()->viewAssets()->make());
|
||||
|
||||
$this->settings->disableMultipleFullCompanySupport();
|
||||
|
||||
$this->actingAsForApi($superUser)
|
||||
->getJson(route('assets.selectlist', ['search' => '000']))
|
||||
->assertResponseContainsInResults($assetA)
|
||||
->assertResponseContainsInResults($assetB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyA)
|
||||
->getJson(route('assets.selectlist', ['search' => '000']))
|
||||
->assertResponseContainsInResults($assetA)
|
||||
->assertResponseContainsInResults($assetB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyB)
|
||||
->getJson(route('assets.selectlist', ['search' => '000']))
|
||||
->assertResponseContainsInResults($assetA)
|
||||
->assertResponseContainsInResults($assetB);
|
||||
|
||||
$this->settings->enableMultipleFullCompanySupport();
|
||||
|
||||
$this->actingAsForApi($superUser)
|
||||
->getJson(route('assets.selectlist', ['search' => '000']))
|
||||
->assertResponseContainsInResults($assetA)
|
||||
->assertResponseContainsInResults($assetB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyA)
|
||||
->getJson(route('assets.selectlist', ['search' => '000']))
|
||||
->assertResponseContainsInResults($assetA)
|
||||
->assertResponseDoesNotContainInResults($assetB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyB)
|
||||
->getJson(route('assets.selectlist', ['search' => '000']))
|
||||
->assertResponseDoesNotContainInResults($assetA)
|
||||
->assertResponseContainsInResults($assetB);
|
||||
}
|
||||
}
|
76
SNIPE-IT/tests/Feature/Api/Assets/RequestableAssetsTest.php
Normal file
76
SNIPE-IT/tests/Feature/Api/Assets/RequestableAssetsTest.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Assets;
|
||||
|
||||
use App\Models\Asset;
|
||||
use App\Models\Company;
|
||||
use App\Models\User;
|
||||
use Tests\TestCase;
|
||||
|
||||
class RequestableAssetsTest extends TestCase
|
||||
{
|
||||
public function testViewingRequestableAssetsRequiresCorrectPermission()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->create())
|
||||
->getJson(route('api.assets.requestable'))
|
||||
->assertForbidden();
|
||||
}
|
||||
|
||||
public function testReturnsRequestableAssets()
|
||||
{
|
||||
$requestableAsset = Asset::factory()->requestable()->create(['asset_tag' => 'requestable']);
|
||||
$nonRequestableAsset = Asset::factory()->nonrequestable()->create(['asset_tag' => 'non-requestable']);
|
||||
|
||||
$this->actingAsForApi(User::factory()->viewRequestableAssets()->create())
|
||||
->getJson(route('api.assets.requestable'))
|
||||
->assertOk()
|
||||
->assertResponseContainsInRows($requestableAsset, 'asset_tag')
|
||||
->assertResponseDoesNotContainInRows($nonRequestableAsset, 'asset_tag');
|
||||
}
|
||||
|
||||
public function testRequestableAssetsAreScopedToCompanyWhenMultipleCompanySupportEnabled()
|
||||
{
|
||||
[$companyA, $companyB] = Company::factory()->count(2)->create();
|
||||
|
||||
$assetA = Asset::factory()->requestable()->for($companyA)->create(['asset_tag' => '0001']);
|
||||
$assetB = Asset::factory()->requestable()->for($companyB)->create(['asset_tag' => '0002']);
|
||||
|
||||
$superUser = $companyA->users()->save(User::factory()->superuser()->make());
|
||||
$userInCompanyA = $companyA->users()->save(User::factory()->viewRequestableAssets()->make());
|
||||
$userInCompanyB = $companyB->users()->save(User::factory()->viewRequestableAssets()->make());
|
||||
|
||||
$this->settings->disableMultipleFullCompanySupport();
|
||||
|
||||
$this->actingAsForApi($superUser)
|
||||
->getJson(route('api.assets.requestable'))
|
||||
->assertResponseContainsInRows($assetA, 'asset_tag')
|
||||
->assertResponseContainsInRows($assetB, 'asset_tag');
|
||||
|
||||
$this->actingAsForApi($userInCompanyA)
|
||||
->getJson(route('api.assets.requestable'))
|
||||
->assertResponseContainsInRows($assetA, 'asset_tag')
|
||||
->assertResponseContainsInRows($assetB, 'asset_tag');
|
||||
|
||||
$this->actingAsForApi($userInCompanyB)
|
||||
->getJson(route('api.assets.requestable'))
|
||||
->assertResponseContainsInRows($assetA, 'asset_tag')
|
||||
->assertResponseContainsInRows($assetB, 'asset_tag');
|
||||
|
||||
$this->settings->enableMultipleFullCompanySupport();
|
||||
|
||||
$this->actingAsForApi($superUser)
|
||||
->getJson(route('api.assets.requestable'))
|
||||
->assertResponseContainsInRows($assetA, 'asset_tag')
|
||||
->assertResponseContainsInRows($assetB, 'asset_tag');
|
||||
|
||||
$this->actingAsForApi($userInCompanyA)
|
||||
->getJson(route('api.assets.requestable'))
|
||||
->assertResponseContainsInRows($assetA, 'asset_tag')
|
||||
->assertResponseDoesNotContainInRows($assetB, 'asset_tag');
|
||||
|
||||
$this->actingAsForApi($userInCompanyB)
|
||||
->getJson(route('api.assets.requestable'))
|
||||
->assertResponseDoesNotContainInRows($assetA, 'asset_tag')
|
||||
->assertResponseContainsInRows($assetB, 'asset_tag');
|
||||
}
|
||||
}
|
57
SNIPE-IT/tests/Feature/Api/Components/ComponentIndexTest.php
Normal file
57
SNIPE-IT/tests/Feature/Api/Components/ComponentIndexTest.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Components;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\Component;
|
||||
use App\Models\User;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ComponentIndexTest extends TestCase
|
||||
{
|
||||
public function testComponentIndexAdheresToCompanyScoping()
|
||||
{
|
||||
[$companyA, $companyB] = Company::factory()->count(2)->create();
|
||||
|
||||
$componentA = Component::factory()->for($companyA)->create();
|
||||
$componentB = Component::factory()->for($companyB)->create();
|
||||
|
||||
$superUser = $companyA->users()->save(User::factory()->superuser()->make());
|
||||
$userInCompanyA = $companyA->users()->save(User::factory()->viewComponents()->make());
|
||||
$userInCompanyB = $companyB->users()->save(User::factory()->viewComponents()->make());
|
||||
|
||||
$this->settings->disableMultipleFullCompanySupport();
|
||||
|
||||
$this->actingAsForApi($superUser)
|
||||
->getJson(route('api.components.index'))
|
||||
->assertResponseContainsInRows($componentA)
|
||||
->assertResponseContainsInRows($componentB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyA)
|
||||
->getJson(route('api.components.index'))
|
||||
->assertResponseContainsInRows($componentA)
|
||||
->assertResponseContainsInRows($componentB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyB)
|
||||
->getJson(route('api.components.index'))
|
||||
->assertResponseContainsInRows($componentA)
|
||||
->assertResponseContainsInRows($componentB);
|
||||
|
||||
$this->settings->enableMultipleFullCompanySupport();
|
||||
|
||||
$this->actingAsForApi($superUser)
|
||||
->getJson(route('api.components.index'))
|
||||
->assertResponseContainsInRows($componentA)
|
||||
->assertResponseContainsInRows($componentB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyA)
|
||||
->getJson(route('api.components.index'))
|
||||
->assertResponseContainsInRows($componentA)
|
||||
->assertResponseDoesNotContainInRows($componentB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyB)
|
||||
->getJson(route('api.components.index'))
|
||||
->assertResponseDoesNotContainInRows($componentA)
|
||||
->assertResponseContainsInRows($componentB);
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Consumables;
|
||||
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CheckoutConsumableNotification;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ConsumableCheckoutTest extends TestCase
|
||||
{
|
||||
public function testCheckingOutConsumableRequiresCorrectPermission()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->create())
|
||||
->postJson(route('api.consumables.checkout', Consumable::factory()->create()))
|
||||
->assertForbidden();
|
||||
}
|
||||
|
||||
public function testValidationWhenCheckingOutConsumable()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->checkoutConsumables()->create())
|
||||
->postJson(route('api.consumables.checkout', Consumable::factory()->create()), [
|
||||
// missing assigned_to
|
||||
])
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testConsumableMustBeAvailableWhenCheckingOut()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->checkoutConsumables()->create())
|
||||
->postJson(route('api.consumables.checkout', Consumable::factory()->withoutItemsRemaining()->create()), [
|
||||
'assigned_to' => User::factory()->create()->id,
|
||||
])
|
||||
->assertStatusMessageIs('error');
|
||||
}
|
||||
|
||||
public function testConsumableCanBeCheckedOut()
|
||||
{
|
||||
$consumable = Consumable::factory()->create();
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAsForApi(User::factory()->checkoutConsumables()->create())
|
||||
->postJson(route('api.consumables.checkout', $consumable), [
|
||||
'assigned_to' => $user->id,
|
||||
]);
|
||||
|
||||
$this->assertTrue($user->consumables->contains($consumable));
|
||||
}
|
||||
|
||||
public function testUserSentNotificationUponCheckout()
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$consumable = Consumable::factory()->requiringAcceptance()->create();
|
||||
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAsForApi(User::factory()->checkoutConsumables()->create())
|
||||
->postJson(route('api.consumables.checkout', $consumable), [
|
||||
'assigned_to' => $user->id,
|
||||
]);
|
||||
|
||||
Notification::assertSentTo($user, CheckoutConsumableNotification::class);
|
||||
}
|
||||
|
||||
public function testActionLogCreatedUponCheckout()
|
||||
{$consumable = Consumable::factory()->create();
|
||||
$actor = User::factory()->checkoutConsumables()->create();
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAsForApi($actor)
|
||||
->postJson(route('api.consumables.checkout', $consumable), [
|
||||
'assigned_to' => $user->id,
|
||||
'note' => 'oh hi there',
|
||||
]);
|
||||
|
||||
$this->assertEquals(
|
||||
1,
|
||||
Actionlog::where([
|
||||
'action_type' => 'checkout',
|
||||
'target_id' => $user->id,
|
||||
'target_type' => User::class,
|
||||
'item_id' => $consumable->id,
|
||||
'item_type' => Consumable::class,
|
||||
'user_id' => $actor->id,
|
||||
'note' => 'oh hi there',
|
||||
])->count(),
|
||||
'Log entry either does not exist or there are more than expected'
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Consumables;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\User;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ConsumablesIndexTest extends TestCase
|
||||
{
|
||||
public function testConsumableIndexAdheresToCompanyScoping()
|
||||
{
|
||||
[$companyA, $companyB] = Company::factory()->count(2)->create();
|
||||
|
||||
$consumableA = Consumable::factory()->for($companyA)->create();
|
||||
$consumableB = Consumable::factory()->for($companyB)->create();
|
||||
|
||||
$superUser = $companyA->users()->save(User::factory()->superuser()->make());
|
||||
$userInCompanyA = $companyA->users()->save(User::factory()->viewConsumables()->make());
|
||||
$userInCompanyB = $companyB->users()->save(User::factory()->viewConsumables()->make());
|
||||
|
||||
$this->settings->disableMultipleFullCompanySupport();
|
||||
|
||||
$this->actingAsForApi($superUser)
|
||||
->getJson(route('api.consumables.index'))
|
||||
->assertResponseContainsInRows($consumableA)
|
||||
->assertResponseContainsInRows($consumableB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyA)
|
||||
->getJson(route('api.consumables.index'))
|
||||
->assertResponseContainsInRows($consumableA)
|
||||
->assertResponseContainsInRows($consumableB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyB)
|
||||
->getJson(route('api.consumables.index'))
|
||||
->assertResponseContainsInRows($consumableA)
|
||||
->assertResponseContainsInRows($consumableB);
|
||||
|
||||
$this->settings->enableMultipleFullCompanySupport();
|
||||
|
||||
$this->actingAsForApi($superUser)
|
||||
->getJson(route('api.consumables.index'))
|
||||
->assertResponseContainsInRows($consumableA)
|
||||
->assertResponseContainsInRows($consumableB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyA)
|
||||
->getJson(route('api.consumables.index'))
|
||||
->assertResponseContainsInRows($consumableA)
|
||||
->assertResponseDoesNotContainInRows($consumableB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyB)
|
||||
->getJson(route('api.consumables.index'))
|
||||
->assertResponseDoesNotContainInRows($consumableA)
|
||||
->assertResponseContainsInRows($consumableB);
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Departments;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\Department;
|
||||
use App\Models\User;
|
||||
use Illuminate\Testing\Fluent\AssertableJson;
|
||||
use Tests\TestCase;
|
||||
|
||||
class DepartmentIndexTest extends TestCase
|
||||
{
|
||||
public function testViewingDepartmentIndexRequiresAuthentication()
|
||||
{
|
||||
$this->getJson(route('api.departments.index'))->assertRedirect();
|
||||
}
|
||||
|
||||
public function testViewingDepartmentIndexRequiresPermission()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->create())
|
||||
->getJson(route('api.departments.index'))
|
||||
->assertForbidden();
|
||||
}
|
||||
|
||||
public function testDepartmentIndexReturnsExpectedDepartments()
|
||||
{
|
||||
Department::factory()->count(3)->create();
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->getJson(
|
||||
route('api.departments.index', [
|
||||
'sort' => 'name',
|
||||
'order' => 'asc',
|
||||
'offset' => '0',
|
||||
'limit' => '20',
|
||||
]))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'total',
|
||||
'rows',
|
||||
])
|
||||
->assertJson(fn(AssertableJson $json) => $json->has('rows', 3)->etc());
|
||||
}
|
||||
|
||||
public function testDepartmentIndexAdheresToCompanyScoping()
|
||||
{
|
||||
[$companyA, $companyB] = Company::factory()->count(2)->create();
|
||||
|
||||
$departmentA = Department::factory()->for($companyA)->create();
|
||||
$departmentB = Department::factory()->for($companyB)->create();
|
||||
|
||||
$superUser = $companyA->users()->save(User::factory()->superuser()->make());
|
||||
$userInCompanyA = $companyA->users()->save(User::factory()->viewDepartments()->make());
|
||||
$userInCompanyB = $companyB->users()->save(User::factory()->viewDepartments()->make());
|
||||
|
||||
$this->settings->disableMultipleFullCompanySupport();
|
||||
|
||||
$this->actingAsForApi($superUser)
|
||||
->getJson(route('api.departments.index'))
|
||||
->assertResponseContainsInRows($departmentA)
|
||||
->assertResponseContainsInRows($departmentB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyA)
|
||||
->getJson(route('api.departments.index'))
|
||||
->assertResponseContainsInRows($departmentA)
|
||||
->assertResponseContainsInRows($departmentB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyB)
|
||||
->getJson(route('api.departments.index'))
|
||||
->assertResponseContainsInRows($departmentA)
|
||||
->assertResponseContainsInRows($departmentB);
|
||||
|
||||
$this->settings->enableMultipleFullCompanySupport();
|
||||
|
||||
$this->actingAsForApi($superUser)
|
||||
->getJson(route('api.departments.index'))
|
||||
->assertResponseContainsInRows($departmentA)
|
||||
->assertResponseContainsInRows($departmentB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyA)
|
||||
->getJson(route('api.departments.index'))
|
||||
->assertResponseContainsInRows($departmentA)
|
||||
->assertResponseDoesNotContainInRows($departmentB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyB)
|
||||
->getJson(route('api.departments.index'))
|
||||
->assertResponseDoesNotContainInRows($departmentA)
|
||||
->assertResponseContainsInRows($departmentB);
|
||||
}
|
||||
}
|
38
SNIPE-IT/tests/Feature/Api/Groups/GroupStoreTest.php
Normal file
38
SNIPE-IT/tests/Feature/Api/Groups/GroupStoreTest.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Groups;
|
||||
|
||||
use App\Models\Group;
|
||||
use App\Models\User;
|
||||
use Tests\TestCase;
|
||||
|
||||
class GroupStoreTest extends TestCase
|
||||
{
|
||||
public function testStoringGroupRequiresSuperAdminPermission()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->create())
|
||||
->postJson(route('api.groups.store'))
|
||||
->assertForbidden();
|
||||
}
|
||||
|
||||
public function testCanStoreGroup()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.groups.store'), [
|
||||
'name' => 'My Awesome Group',
|
||||
'permissions' => [
|
||||
'admin' => '1',
|
||||
'import' => '1',
|
||||
'reports.view' => '0',
|
||||
],
|
||||
])
|
||||
->assertOk();
|
||||
|
||||
$group = Group::where('name', 'My Awesome Group')->first();
|
||||
|
||||
$this->assertNotNull($group);
|
||||
$this->assertEquals('1', $group->decodePermissions()['admin']);
|
||||
$this->assertEquals('1', $group->decodePermissions()['import']);
|
||||
$this->assertEquals('0', $group->decodePermissions()['reports.view']);
|
||||
}
|
||||
}
|
57
SNIPE-IT/tests/Feature/Api/Licenses/LicensesIndexTest.php
Normal file
57
SNIPE-IT/tests/Feature/Api/Licenses/LicensesIndexTest.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Licenses;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\License;
|
||||
use App\Models\User;
|
||||
use Tests\TestCase;
|
||||
|
||||
class LicensesIndexTest extends TestCase
|
||||
{
|
||||
public function testLicensesIndexAdheresToCompanyScoping()
|
||||
{
|
||||
[$companyA, $companyB] = Company::factory()->count(2)->create();
|
||||
|
||||
$licenseA = License::factory()->for($companyA)->create();
|
||||
$licenseB = License::factory()->for($companyB)->create();
|
||||
|
||||
$superUser = $companyA->users()->save(User::factory()->superuser()->make());
|
||||
$userInCompanyA = $companyA->users()->save(User::factory()->viewLicenses()->make());
|
||||
$userInCompanyB = $companyB->users()->save(User::factory()->viewLicenses()->make());
|
||||
|
||||
$this->settings->disableMultipleFullCompanySupport();
|
||||
|
||||
$this->actingAsForApi($superUser)
|
||||
->getJson(route('api.licenses.index'))
|
||||
->assertResponseContainsInRows($licenseA)
|
||||
->assertResponseContainsInRows($licenseB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyA)
|
||||
->getJson(route('api.licenses.index'))
|
||||
->assertResponseContainsInRows($licenseA)
|
||||
->assertResponseContainsInRows($licenseB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyB)
|
||||
->getJson(route('api.licenses.index'))
|
||||
->assertResponseContainsInRows($licenseA)
|
||||
->assertResponseContainsInRows($licenseB);
|
||||
|
||||
$this->settings->enableMultipleFullCompanySupport();
|
||||
|
||||
$this->actingAsForApi($superUser)
|
||||
->getJson(route('api.licenses.index'))
|
||||
->assertResponseContainsInRows($licenseA)
|
||||
->assertResponseContainsInRows($licenseB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyA)
|
||||
->getJson(route('api.licenses.index'))
|
||||
->assertResponseContainsInRows($licenseA)
|
||||
->assertResponseDoesNotContainInRows($licenseB);
|
||||
|
||||
$this->actingAsForApi($userInCompanyB)
|
||||
->getJson(route('api.licenses.index'))
|
||||
->assertResponseDoesNotContainInRows($licenseA)
|
||||
->assertResponseContainsInRows($licenseB);
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Locations;
|
||||
|
||||
use App\Models\Location;
|
||||
use App\Models\User;
|
||||
use Illuminate\Testing\Fluent\AssertableJson;
|
||||
use Tests\TestCase;
|
||||
|
||||
class LocationsForSelectListTest extends TestCase
|
||||
{
|
||||
public function testGettingLocationListRequiresProperPermission()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->create())
|
||||
->getJson(route('api.locations.selectlist'))
|
||||
->assertForbidden();
|
||||
}
|
||||
|
||||
public function testLocationsReturned()
|
||||
{
|
||||
Location::factory()->create();
|
||||
|
||||
// see the where the "view.selectlists" is defined in the AuthServiceProvider
|
||||
// for info on why "createUsers()" is used here.
|
||||
$this->actingAsForApi(User::factory()->createUsers()->create())
|
||||
->getJson(route('api.locations.selectlist'))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'results',
|
||||
'pagination',
|
||||
'total_count',
|
||||
'page',
|
||||
'page_count',
|
||||
])
|
||||
->assertJson(fn(AssertableJson $json) => $json->has('results', 1)->etc());
|
||||
}
|
||||
|
||||
public function testLocationsAreReturnedWhenUserIsUpdatingTheirProfileAndHasPermissionToUpdateLocation()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->canEditOwnLocation()->create())
|
||||
->withHeader('referer', route('profile'))
|
||||
->getJson(route('api.locations.selectlist'))
|
||||
->assertOk();
|
||||
}
|
||||
}
|
61
SNIPE-IT/tests/Feature/Api/Users/UpdateUserApiTest.php
Normal file
61
SNIPE-IT/tests/Feature/Api/Users/UpdateUserApiTest.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Users;
|
||||
|
||||
use App\Models\User;
|
||||
use Tests\TestCase;
|
||||
|
||||
class UpdateUserApiTest extends TestCase
|
||||
{
|
||||
public function testApiUsersCanBeActivatedWithNumber()
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$user = User::factory()->create(['activated' => 0]);
|
||||
|
||||
$this->actingAsForApi($admin)
|
||||
->patch(route('api.users.update', $user), [
|
||||
'activated' => 1,
|
||||
]);
|
||||
|
||||
$this->assertEquals(1, $user->refresh()->activated);
|
||||
}
|
||||
|
||||
public function testApiUsersCanBeActivatedWithBooleanTrue()
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$user = User::factory()->create(['activated' => false]);
|
||||
|
||||
$this->actingAsForApi($admin)
|
||||
->patch(route('api.users.update', $user), [
|
||||
'activated' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals(1, $user->refresh()->activated);
|
||||
}
|
||||
|
||||
public function testApiUsersCanBeDeactivatedWithNumber()
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$user = User::factory()->create(['activated' => true]);
|
||||
|
||||
$this->actingAsForApi($admin)
|
||||
->patch(route('api.users.update', $user), [
|
||||
'activated' => 0,
|
||||
]);
|
||||
|
||||
$this->assertEquals(0, $user->refresh()->activated);
|
||||
}
|
||||
|
||||
public function testApiUsersCanBeDeactivatedWithBooleanFalse()
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$user = User::factory()->create(['activated' => true]);
|
||||
|
||||
$this->actingAsForApi($admin)
|
||||
->patch(route('api.users.update', $user), [
|
||||
'activated' => false,
|
||||
]);
|
||||
|
||||
$this->assertEquals(0, $user->refresh()->activated);
|
||||
}
|
||||
}
|
97
SNIPE-IT/tests/Feature/Api/Users/UsersForSelectListTest.php
Normal file
97
SNIPE-IT/tests/Feature/Api/Users/UsersForSelectListTest.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Users;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\User;
|
||||
use Illuminate\Testing\Fluent\AssertableJson;
|
||||
use Laravel\Passport\Passport;
|
||||
use Tests\TestCase;
|
||||
|
||||
class UsersForSelectListTest extends TestCase
|
||||
{
|
||||
public function testUsersAreReturned()
|
||||
{
|
||||
$users = User::factory()->superuser()->count(3)->create();
|
||||
|
||||
Passport::actingAs($users->first());
|
||||
$this->getJson(route('api.users.selectlist'))
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'results',
|
||||
'pagination',
|
||||
'total_count',
|
||||
'page',
|
||||
'page_count',
|
||||
])
|
||||
->assertJson(fn(AssertableJson $json) => $json->has('results', 3)->etc());
|
||||
}
|
||||
|
||||
public function testUsersCanBeSearchedByFirstAndLastName()
|
||||
{
|
||||
User::factory()->create(['first_name' => 'Luke', 'last_name' => 'Skywalker']);
|
||||
|
||||
Passport::actingAs(User::factory()->create());
|
||||
$response = $this->getJson(route('api.users.selectlist', ['search' => 'luke sky']))->assertOk();
|
||||
|
||||
$results = collect($response->json('results'));
|
||||
|
||||
$this->assertEquals(1, $results->count());
|
||||
$this->assertTrue($results->pluck('text')->contains(fn($text) => str_contains($text, 'Luke')));
|
||||
}
|
||||
|
||||
public function testUsersScopedToCompanyWhenMultipleFullCompanySupportEnabled()
|
||||
{
|
||||
$this->settings->enableMultipleFullCompanySupport();
|
||||
|
||||
$jedi = Company::factory()->has(User::factory()->count(3)->sequence(
|
||||
['first_name' => 'Luke', 'last_name' => 'Skywalker', 'username' => 'lskywalker'],
|
||||
['first_name' => 'Obi-Wan', 'last_name' => 'Kenobi', 'username' => 'okenobi'],
|
||||
['first_name' => 'Anakin', 'last_name' => 'Skywalker', 'username' => 'askywalker'],
|
||||
))->create();
|
||||
|
||||
$sith = Company::factory()
|
||||
->has(User::factory()->state(['first_name' => 'Darth', 'last_name' => 'Vader', 'username' => 'dvader']))
|
||||
->create();
|
||||
|
||||
Passport::actingAs($jedi->users->first());
|
||||
$response = $this->getJson(route('api.users.selectlist'))->assertOk();
|
||||
|
||||
$results = collect($response->json('results'));
|
||||
|
||||
$this->assertEquals(3, $results->count());
|
||||
$this->assertTrue(
|
||||
$results->pluck('text')->contains(fn($text) => str_contains($text, 'Luke'))
|
||||
);
|
||||
$this->assertFalse(
|
||||
$results->pluck('text')->contains(fn($text) => str_contains($text, 'Darth'))
|
||||
);
|
||||
}
|
||||
|
||||
public function testUsersScopedToCompanyDuringSearchWhenMultipleFullCompanySupportEnabled()
|
||||
{
|
||||
$this->settings->enableMultipleFullCompanySupport();
|
||||
|
||||
$jedi = Company::factory()->has(User::factory()->count(3)->sequence(
|
||||
['first_name' => 'Luke', 'last_name' => 'Skywalker', 'username' => 'lskywalker'],
|
||||
['first_name' => 'Obi-Wan', 'last_name' => 'Kenobi', 'username' => 'okenobi'],
|
||||
['first_name' => 'Anakin', 'last_name' => 'Skywalker', 'username' => 'askywalker'],
|
||||
))->create();
|
||||
|
||||
Company::factory()
|
||||
->has(User::factory()->state(['first_name' => 'Darth', 'last_name' => 'Vader', 'username' => 'dvader']))
|
||||
->create();
|
||||
|
||||
Passport::actingAs($jedi->users->first());
|
||||
$response = $this->getJson(route('api.users.selectlist', ['search' => 'a']))->assertOk();
|
||||
|
||||
$results = collect($response->json('results'));
|
||||
|
||||
$this->assertEquals(3, $results->count());
|
||||
$this->assertTrue($results->pluck('text')->contains(fn($text) => str_contains($text, 'Luke')));
|
||||
$this->assertTrue($results->pluck('text')->contains(fn($text) => str_contains($text, 'Anakin')));
|
||||
|
||||
$response = $this->getJson(route('api.users.selectlist', ['search' => 'v']))->assertOk();
|
||||
$this->assertEquals(0, collect($response->json('results'))->count());
|
||||
}
|
||||
}
|
147
SNIPE-IT/tests/Feature/Api/Users/UsersSearchTest.php
Normal file
147
SNIPE-IT/tests/Feature/Api/Users/UsersSearchTest.php
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Users;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\User;
|
||||
use Laravel\Passport\Passport;
|
||||
use Tests\TestCase;
|
||||
|
||||
class UsersSearchTest extends TestCase
|
||||
{
|
||||
public function testCanSearchByUserFirstAndLastName()
|
||||
{
|
||||
User::factory()->create(['first_name' => 'Luke', 'last_name' => 'Skywalker']);
|
||||
User::factory()->create(['first_name' => 'Darth', 'last_name' => 'Vader']);
|
||||
|
||||
Passport::actingAs(User::factory()->viewUsers()->create());
|
||||
$response = $this->getJson(route('api.users.index', ['search' => 'luke sky']))->assertOk();
|
||||
|
||||
$results = collect($response->json('rows'));
|
||||
|
||||
$this->assertEquals(1, $results->count());
|
||||
$this->assertTrue($results->pluck('name')->contains(fn($text) => str_contains($text, 'Luke')));
|
||||
$this->assertFalse($results->pluck('name')->contains(fn($text) => str_contains($text, 'Darth')));
|
||||
}
|
||||
|
||||
public function testResultsWhenSearchingForActiveUsers()
|
||||
{
|
||||
User::factory()->create(['first_name' => 'Active', 'last_name' => 'User']);
|
||||
User::factory()->create(['first_name' => 'Deleted', 'last_name' => 'User'])->delete();
|
||||
|
||||
$response = $this->actingAsForApi(User::factory()->viewUsers()->create())
|
||||
->getJson(route('api.users.index', [
|
||||
'deleted' => 'false',
|
||||
'company_id' => '',
|
||||
'search' => 'user',
|
||||
'order' => 'asc',
|
||||
'offset' => '0',
|
||||
'limit' => '20',
|
||||
]))
|
||||
->assertOk();
|
||||
|
||||
$firstNames = collect($response->json('rows'))->pluck('first_name');
|
||||
|
||||
$this->assertTrue(
|
||||
$firstNames->contains('Active'),
|
||||
'Expected user does not appear in results'
|
||||
);
|
||||
|
||||
$this->assertFalse(
|
||||
$firstNames->contains('Deleted'),
|
||||
'Unexpected deleted user appears in results'
|
||||
);
|
||||
}
|
||||
|
||||
public function testResultsWhenSearchingForDeletedUsers()
|
||||
{
|
||||
User::factory()->create(['first_name' => 'Active', 'last_name' => 'User']);
|
||||
User::factory()->create(['first_name' => 'Deleted', 'last_name' => 'User'])->delete();
|
||||
|
||||
$response = $this->actingAsForApi(User::factory()->viewUsers()->create())
|
||||
->getJson(route('api.users.index', [
|
||||
'deleted' => 'true',
|
||||
'company_id' => '',
|
||||
'search' => 'user',
|
||||
'order' => 'asc',
|
||||
'offset' => '0',
|
||||
'limit' => '20',
|
||||
]))
|
||||
->assertOk();
|
||||
|
||||
$firstNames = collect($response->json('rows'))->pluck('first_name');
|
||||
|
||||
$this->assertFalse(
|
||||
$firstNames->contains('Active'),
|
||||
'Unexpected active user appears in results'
|
||||
);
|
||||
|
||||
$this->assertTrue(
|
||||
$firstNames->contains('Deleted'),
|
||||
'Expected deleted user does not appear in results'
|
||||
);
|
||||
}
|
||||
|
||||
public function testUsersScopedToCompanyWhenMultipleFullCompanySupportEnabled()
|
||||
{
|
||||
$this->settings->enableMultipleFullCompanySupport();
|
||||
|
||||
$companyA = Company::factory()
|
||||
->has(User::factory(['first_name' => 'Company A', 'last_name' => 'User']))
|
||||
->create();
|
||||
|
||||
Company::factory()
|
||||
->has(User::factory(['first_name' => 'Company B', 'last_name' => 'User']))
|
||||
->create();
|
||||
|
||||
$response = $this->actingAsForApi(User::factory()->for($companyA)->viewUsers()->create())
|
||||
->getJson(route('api.users.index'))
|
||||
->assertOk();
|
||||
|
||||
$results = collect($response->json('rows'));
|
||||
|
||||
$this->assertTrue(
|
||||
$results->pluck('name')->contains(fn($text) => str_contains($text, 'Company A')),
|
||||
'User index does not contain expected user'
|
||||
);
|
||||
$this->assertFalse(
|
||||
$results->pluck('name')->contains(fn($text) => str_contains($text, 'Company B')),
|
||||
'User index contains unexpected user from another company'
|
||||
);
|
||||
}
|
||||
|
||||
public function testUsersScopedToCompanyDuringSearchWhenMultipleFullCompanySupportEnabled()
|
||||
{
|
||||
$this->settings->enableMultipleFullCompanySupport();
|
||||
|
||||
$companyA = Company::factory()
|
||||
->has(User::factory(['first_name' => 'Company A', 'last_name' => 'User']))
|
||||
->create();
|
||||
|
||||
Company::factory()
|
||||
->has(User::factory(['first_name' => 'Company B', 'last_name' => 'User']))
|
||||
->create();
|
||||
|
||||
$response = $this->actingAsForApi(User::factory()->for($companyA)->viewUsers()->create())
|
||||
->getJson(route('api.users.index', [
|
||||
'deleted' => 'false',
|
||||
'company_id' => null,
|
||||
'search' => 'user',
|
||||
'order' => 'asc',
|
||||
'offset' => '0',
|
||||
'limit' => '20',
|
||||
]))
|
||||
->assertOk();
|
||||
|
||||
$results = collect($response->json('rows'));
|
||||
|
||||
$this->assertTrue(
|
||||
$results->pluck('name')->contains(fn($text) => str_contains($text, 'Company A')),
|
||||
'User index does not contain expected user'
|
||||
);
|
||||
$this->assertFalse(
|
||||
$results->pluck('name')->contains(fn($text) => str_contains($text, 'Company B')),
|
||||
'User index contains unexpected user from another company'
|
||||
);
|
||||
}
|
||||
}
|
84
SNIPE-IT/tests/Feature/Api/Users/UsersUpdateTest.php
Normal file
84
SNIPE-IT/tests/Feature/Api/Users/UsersUpdateTest.php
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Users;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\Department;
|
||||
use App\Models\Group;
|
||||
use App\Models\Location;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Tests\TestCase;
|
||||
|
||||
class UsersUpdateTest extends TestCase
|
||||
{
|
||||
public function testCanUpdateUserViaPatch()
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
$manager = User::factory()->create();
|
||||
$company = Company::factory()->create();
|
||||
$department = Department::factory()->create();
|
||||
$location = Location::factory()->create();
|
||||
[$groupA, $groupB] = Group::factory()->count(2)->create();
|
||||
|
||||
$user = User::factory()->create([
|
||||
'activated' => false,
|
||||
'remote' => false,
|
||||
'vip' => false,
|
||||
]);
|
||||
|
||||
$this->actingAsForApi($admin)
|
||||
->patchJson(route('api.users.update', $user), [
|
||||
'first_name' => 'Mabel',
|
||||
'last_name' => 'Mora',
|
||||
'username' => 'mabel',
|
||||
'password' => 'super-secret',
|
||||
'email' => 'mabel@onlymurderspod.com',
|
||||
'permissions' => '{"a.new.permission":"1"}',
|
||||
'activated' => true,
|
||||
'phone' => '619-555-5555',
|
||||
'jobtitle' => 'Host',
|
||||
'manager_id' => $manager->id,
|
||||
'employee_num' => '1111',
|
||||
'notes' => 'Pretty good artist',
|
||||
'company_id' => $company->id,
|
||||
'department_id' => $department->id,
|
||||
'location_id' => $location->id,
|
||||
'remote' => true,
|
||||
'groups' => $groupA->id,
|
||||
'vip' => true,
|
||||
'start_date' => '2021-08-01',
|
||||
'end_date' => '2025-12-31',
|
||||
])
|
||||
->assertOk();
|
||||
|
||||
$user->refresh();
|
||||
$this->assertEquals('Mabel', $user->first_name, 'First name was not updated');
|
||||
$this->assertEquals('Mora', $user->last_name, 'Last name was not updated');
|
||||
$this->assertEquals('mabel', $user->username, 'Username was not updated');
|
||||
$this->assertTrue(Hash::check('super-secret', $user->password), 'Password was not updated');
|
||||
$this->assertEquals('mabel@onlymurderspod.com', $user->email, 'Email was not updated');
|
||||
$this->assertArrayHasKey('a.new.permission', $user->decodePermissions(), 'Permissions were not updated');
|
||||
$this->assertTrue((bool)$user->activated, 'User not marked as activated');
|
||||
$this->assertEquals('619-555-5555', $user->phone, 'Phone was not updated');
|
||||
$this->assertEquals('Host', $user->jobtitle, 'Job title was not updated');
|
||||
$this->assertTrue($user->manager->is($manager), 'Manager was not updated');
|
||||
$this->assertEquals('1111', $user->employee_num, 'Employee number was not updated');
|
||||
$this->assertEquals('Pretty good artist', $user->notes, 'Notes was not updated');
|
||||
$this->assertTrue($user->company->is($company), 'Company was not updated');
|
||||
$this->assertTrue($user->department->is($department), 'Department was not updated');
|
||||
$this->assertTrue($user->location->is($location), 'Location was not updated');
|
||||
$this->assertEquals(1, $user->remote, 'Remote was not updated');
|
||||
$this->assertTrue($user->groups->contains($groupA), 'Groups were not updated');
|
||||
$this->assertEquals(1, $user->vip, 'VIP was not updated');
|
||||
$this->assertEquals('2021-08-01', $user->start_date, 'Start date was not updated');
|
||||
$this->assertEquals('2025-12-31', $user->end_date, 'End date was not updated');
|
||||
|
||||
// `groups` can be an id or array or ids
|
||||
$this->patch(route('api.users.update', $user), ['groups' => [$groupA->id, $groupB->id]]);
|
||||
|
||||
$user->refresh();
|
||||
$this->assertTrue($user->groups->contains($groupA), 'Not part of expected group');
|
||||
$this->assertTrue($user->groups->contains($groupB), 'Not part of expected group');
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user