diff --git a/app/Http/Controllers/Licenses/LicenseCheckinController.php b/app/Http/Controllers/Licenses/LicenseCheckinController.php index dd83d0154c..373a167642 100644 --- a/app/Http/Controllers/Licenses/LicenseCheckinController.php +++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php @@ -71,7 +71,7 @@ class LicenseCheckinController extends Controller if (! $license->reassignable) { // Not allowed to checkin - Session::flash('error', 'License not reassignable.'); + Session::flash('error', trans('admin/licenses/message.checkin.not_reassignable') . '.'); return redirect()->back()->withInput(); } diff --git a/database/factories/LicenseSeatFactory.php b/database/factories/LicenseSeatFactory.php index f9560af472..aaf75bdc2d 100644 --- a/database/factories/LicenseSeatFactory.php +++ b/database/factories/LicenseSeatFactory.php @@ -4,6 +4,7 @@ namespace Database\Factories; use App\Models\Asset; use App\Models\License; +use App\Models\LicenseSeat; use App\Models\User; use Illuminate\Database\Eloquent\Factories\Factory; @@ -33,4 +34,18 @@ class LicenseSeatFactory extends Factory ]; }); } + + public function reassignable() + { + return $this->afterMaking(function (LicenseSeat $seat) { + $seat->license->update(['reassignable' => true]); + }); + } + + public function notReassignable() + { + return $this->afterMaking(function (LicenseSeat $seat) { + $seat->license->update(['reassignable' => false]); + }); + } } diff --git a/resources/lang/en-US/admin/licenses/message.php b/resources/lang/en-US/admin/licenses/message.php index 7f5981aa05..74e1d7af5a 100644 --- a/resources/lang/en-US/admin/licenses/message.php +++ b/resources/lang/en-US/admin/licenses/message.php @@ -50,6 +50,7 @@ return array( 'checkin' => array( 'error' => 'There was an issue checking in the license. Please try again.', + 'not_reassignable' => 'License not reassignable', 'success' => 'The license was checked in successfully' ), diff --git a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php index f006e41866..7a6553d8ba 100644 --- a/tests/Feature/Checkins/Ui/LicenseCheckinTest.php +++ b/tests/Feature/Checkins/Ui/LicenseCheckinTest.php @@ -2,8 +2,11 @@ namespace Tests\Feature\Checkins\Ui; +use App\Events\CheckoutableCheckedIn; +use App\Models\Asset; use App\Models\LicenseSeat; use App\Models\User; +use Illuminate\Support\Facades\Event; use Tests\TestCase; class LicenseCheckinTest extends TestCase @@ -17,10 +20,112 @@ class LicenseCheckinTest extends TestCase ->assertForbidden(); } + public function testCannotCheckinNonReassignableLicense() + { + $licenseSeat = LicenseSeat::factory() + ->notReassignable() + ->assignedToUser() + ->create(); + + $this->actingAs(User::factory()->checkoutLicenses()->create()) + ->post(route('licenses.checkin.save', $licenseSeat), [ + 'notes' => 'my note', + 'redirect_option' => 'index', + ]) + ->assertSessionHas('error', trans('admin/licenses/message.checkin.not_reassignable') . '.'); + + $this->assertNotNull($licenseSeat->fresh()->assigned_to); + } + + public function testCannotCheckinLicenseThatIsNotAssigned() + { + $licenseSeat = LicenseSeat::factory() + ->reassignable() + ->create(); + + $this->assertNull($licenseSeat->assigned_to); + $this->assertNull($licenseSeat->asset_id); + + $this->actingAs(User::factory()->checkoutLicenses()->create()) + ->post(route('licenses.checkin.save', $licenseSeat), [ + 'notes' => 'my note', + 'redirect_option' => 'index', + ]) + ->assertSessionHas('error', trans('admin/licenses/message.checkin.error')); + } + + public function testCanCheckInLicenseAssignedToAsset() + { + Event::fake([CheckoutableCheckedIn::class]); + + $asset = Asset::factory()->create(); + + $licenseSeat = LicenseSeat::factory() + ->reassignable() + ->assignedToAsset($asset) + ->create(); + + $actor = User::factory()->checkoutLicenses()->create(); + + $this->actingAs($actor) + ->post(route('licenses.checkin.save', $licenseSeat), [ + 'notes' => 'my note', + 'redirect_option' => 'index', + ]) + ->assertRedirect(route('licenses.index')); + + $this->assertNull($licenseSeat->fresh()->asset_id); + $this->assertNull($licenseSeat->fresh()->assigned_to); + $this->assertEquals('my note', $licenseSeat->fresh()->notes); + + Event::assertDispatchedTimes(CheckoutableCheckedIn::class, 1); + Event::assertDispatched(CheckoutableCheckedIn::class, function (CheckoutableCheckedIn $event) use ($actor, $asset, $licenseSeat) { + return $event->checkoutable->is($licenseSeat) + && $event->checkedOutTo->is($asset) + && $event->checkedInBy->is($actor) + && $event->note === 'my note'; + }); + } + + public function testCanCheckInLicenseAssignedToUser() + { + Event::fake([CheckoutableCheckedIn::class]); + + $user = User::factory()->create(); + + $licenseSeat = LicenseSeat::factory() + ->reassignable() + ->assignedToUser($user) + ->create(); + + $actor = User::factory()->checkoutLicenses()->create(); + + $this->actingAs($actor) + ->post(route('licenses.checkin.save', $licenseSeat), [ + 'notes' => 'my note', + 'redirect_option' => 'index', + ]) + ->assertRedirect(route('licenses.index')); + + $this->assertNull($licenseSeat->fresh()->asset_id); + $this->assertNull($licenseSeat->fresh()->assigned_to); + $this->assertEquals('my note', $licenseSeat->fresh()->notes); + + Event::assertDispatchedTimes(CheckoutableCheckedIn::class, 1); + Event::assertDispatched(CheckoutableCheckedIn::class, function (CheckoutableCheckedIn $event) use ($actor, $licenseSeat, $user) { + return $event->checkoutable->is($licenseSeat) + && $event->checkedOutTo->is($user) + && $event->checkedInBy->is($actor) + && $event->note === 'my note'; + }); + + } + public function testPageRenders() { $this->actingAs(User::factory()->superuser()->create()) ->get(route('licenses.checkin', LicenseSeat::factory()->assignedToUser()->create()->id)) ->assertOk(); + } }