enabled())->toBeFalse(); enableSnipeit(); expect(app(SnipeItClient::class)->enabled())->toBeTrue(); }); test('assetsForEmail looks up the Snipe-IT user by e-mail, then lists what is checked out to them', function () { enableSnipeit(); Http::fake([ 'assets.test/api/v1/users?*' => Http::response(['rows' => [ ['id' => 7, 'email' => 'jan@example.com', 'name' => 'Jan Kowalski'], ]]), 'assets.test/api/v1/users/7/assets*' => Http::response(['rows' => [ [ 'id' => 100, 'asset_tag' => 'SI-001', 'name' => 'Laptop Jana', 'serial' => 'SN12345', 'manufacturer' => ['name' => 'Dell'], 'model' => ['name' => 'Latitude 5420'], 'category' => ['name' => 'Laptopy'], 'status_label' => ['name' => 'Deployed'], ], ]]), ]); $assets = app(SnipeItClient::class)->assetsForEmail('jan@example.com'); expect($assets)->toHaveCount(1); expect($assets[0]['id'])->toBe(100); expect($assets[0]['label'])->toBe('SI-001 - SN12345 - Dell Latitude 5420'); expect($assets[0]['category'])->toBe('Laptopy'); expect($assets[0]['status'])->toBe('Deployed'); expect($assets[0]['url'])->toBe('https://assets.test/hardware/100'); }); test('normalizeAsset joins only whichever of asset tag / serial / manufacturer+model are present, falling back to the asset id', function () { enableSnipeit(); Http::fake(['assets.test/api/v1/hardware/1' => Http::response([ 'id' => 1, 'asset_tag' => 'SI-100', 'serial' => null, 'manufacturer' => null, 'model' => null, ])]); expect(app(SnipeItClient::class)->asset(1)['label'])->toBe('SI-100'); Http::fake(['assets.test/api/v1/hardware/2' => Http::response([ 'id' => 2, 'asset_tag' => null, 'serial' => null, 'manufacturer' => null, 'model' => null, ])]); expect(app(SnipeItClient::class)->asset(2)['label'])->toBe('Zasób #2'); }); test('assetsForEmail returns nothing when no Snipe-IT user matches the e-mail', function () { enableSnipeit(); Http::fake(['assets.test/api/v1/users?*' => Http::response(['rows' => []])]); expect(app(SnipeItClient::class)->assetsForEmail('nobody@example.com'))->toBe([]); }); test('assetsForEmail returns an empty list without an HTTP call when the integration is disabled', function () { Http::fake(); expect(app(SnipeItClient::class)->assetsForEmail('jan@example.com'))->toBe([]); Http::assertNothingSent(); }); test('searchAssets hits the hardware list endpoint with the search query', function () { enableSnipeit(); Http::fake(['assets.test/api/v1/hardware?*' => Http::response(['rows' => [ [ 'id' => 55, 'asset_tag' => 'SI-055', 'name' => null, 'serial' => null, 'manufacturer' => ['name' => 'HP'], 'model' => ['name' => 'LaserJet Pro'], 'category' => ['name' => 'Drukarki'], 'status_label' => ['name' => 'Ready to Deploy'], ], ]])]); $results = app(SnipeItClient::class)->searchAssets('drukarka'); expect($results)->toHaveCount(1); expect($results[0]['label'])->toBe('SI-055 - HP LaserJet Pro'); expect($results[0]['category'])->toBe('Drukarki'); Http::assertSent(fn ($request) => str_contains((string) $request->url(), 'search=drukarka')); }); test('searchAssets returns nothing for a blank query without calling out', function () { enableSnipeit(); Http::fake(); expect(app(SnipeItClient::class)->searchAssets(' '))->toBe([]); Http::assertNothingSent(); }); test('asset fetches live detail including serial, category and current assignment', function () { enableSnipeit(); Http::fake(['assets.test/api/v1/hardware/100' => Http::response([ 'id' => 100, 'asset_tag' => 'SI-001', 'name' => 'Laptop Jana', 'serial' => 'ABC123', 'manufacturer' => ['name' => 'Dell'], 'model' => ['name' => 'Latitude 5420'], 'category' => ['name' => 'Laptopy'], 'status_label' => ['name' => 'Deployed'], 'assigned_to' => ['name' => 'Jan Kowalski'], ])]); $asset = app(SnipeItClient::class)->asset(100); expect($asset['label'])->toBe('SI-001 - ABC123 - Dell Latitude 5420'); expect($asset['serial'])->toBe('ABC123'); expect($asset['category'])->toBe('Laptopy'); expect($asset['assignedTo'])->toBe('Jan Kowalski'); }); test('asset returns null when the asset no longer exists in Snipe-IT', function () { enableSnipeit(); Http::fake(['assets.test/api/v1/hardware/999' => Http::response(['status' => 'error'], 404)]); expect(app(SnipeItClient::class)->asset(999))->toBeNull(); }); test('testConnection reports ok on a successful response', function () { Http::fake(['assets.test/api/v1/hardware?*' => Http::response(['rows' => []])]); $result = app(SnipeItClient::class)->testConnection('https://assets.test', 'tok', true); expect($result)->toBe(['ok' => true, 'message' => null]); }); test('testConnection reports the API error message on failure', function () { Http::fake(['assets.test/api/v1/hardware?*' => Http::response(['status' => 'error', 'messages' => 'Unauthenticated.'], 401)]); $result = app(SnipeItClient::class)->testConnection('https://assets.test', 'bad-tok', true); expect($result['ok'])->toBeFalse(); expect($result['message'])->toBe('Unauthenticated.'); });