diff --git a/src/Api.php b/src/Api.php index 8a2c923..7b51ab8 100644 --- a/src/Api.php +++ b/src/Api.php @@ -13,7 +13,6 @@ use Illuminate\Support\LazyCollection; use Illuminate\Support\Str; use Log; use Zoomyboy\LaravelNami\Authentication\Authenticator; -use Zoomyboy\LaravelNami\Backend\Backend; use Zoomyboy\LaravelNami\Concerns\IsNamiMember; use Zoomyboy\LaravelNami\Exceptions\NotAuthenticatedException; use Zoomyboy\LaravelNami\Exceptions\RightException; @@ -169,11 +168,19 @@ class Api { return collect($r->json()['data']); } - public function subactivitiesOf($activityId) { + public function subactivitiesOf(int $activityId): Collection + { $this->assertLoggedIn(); - return collect($this->http()->get($this->url.'/ica/rest/nami/untergliederungauftaetigkeit/filtered/untergliederung/taetigkeit/'.$activityId)->json()['data'])->map(function($subactivity) { + $url = $this->url.'/ica/rest/nami/untergliederungauftaetigkeit/filtered/untergliederung/taetigkeit/'.$activityId; + $response = $this->http()->get($url); + + if ($response['success'] === false) { + $this->exception('Getting subactivities failed', $url, $response->json()); + } + + return collect($response['data'])->map(function($subactivity) { return Subactivity::fromNami($subactivity); - });; + }); } public function membership($memberId, $membershipId) { @@ -232,15 +239,17 @@ class Api { public function createCourse(int $memberId, array $payload): int { $this->assertLoggedIn(); - $response = $this->http()->post($this->url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}", [ + $url = $this->url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}"; + $payload = [ 'bausteinId' => $payload['course_id'], 'vstgName' => $payload['event_name'], 'vstgTag' => Carbon::parse($payload['completed_at'])->format('Y-m-d').'T00:00:00', 'veranstalter' => $payload['organizer'], - ]); + ]; + $response = $this->http()->post($url, $payload); if (data_get($response->json(), 'success') !== true) { - $this->exception('Course creation failed', $payload, $response->json()); + $this->exception('Course creation failed', $url, $response->json(), $payload); } return $response['data']; @@ -255,25 +264,28 @@ class Api { public function updateCourse(int $memberId, int $courseId, array $payload): void { $this->assertLoggedIn(); - $response = $this->http()->put($this->url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/{$courseId}", [ + $url = $this->url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/{$courseId}"; + $payload = [ 'bausteinId' => $payload['course_id'], 'vstgName' => $payload['event_name'], 'vstgTag' => Carbon::parse($payload['completed_at'])->format('Y-m-d').'T00:00:00', 'veranstalter' => $payload['organizer'], - ]); + ]; + $response = $this->http()->put($url, $payload); if (data_get($response->json(), 'success') !== true) { - $this->exception('Course update failed', $payload, $response->json()); + $this->exception('Course update failed', $url, $response->json(), $payload); } } public function deleteCourse(int $memberId, int $courseId): void { $this->assertLoggedIn(); - $response = $this->http()->delete($this->url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/{$courseId}"); + $url = $this->url."/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}/{$courseId}"; + $response = $this->http()->delete($url); if ($response->json() !== null && data_get($response->json(), 'success') !== true) { - $this->exception('Course deletion failed', [], $response->json()); + $this->exception('Course deletion failed', $url, $response->json()); } } @@ -292,16 +304,11 @@ class Api { return $this->singleMemberFallback($groupId, $memberId); } - if ($response->json()['success'] === true) { - return $response->json()['data']; - } else { - $e = new NamiException('Fetch von Mitglied fehlgeschlagen'); - $e->setData([ - 'response' => $response->body(), - 'url' => $url - ]); - throw $e; + if ($response->json()['success'] !== true) { + $this->exception('Fetching member failed', $url, $response->json()); } + + return $response->json()['data']; } public function hasGroup($groupId): bool { @@ -342,18 +349,13 @@ class Api { $url = $this->url."/ica/rest/baseadmin/staatsangehoerigkeit"; $response = $this->http()->get($url); - if ($response->json()['success'] === true) { - return collect($response['data'])->map(function($nationality) { - return Nationality::fromNami($nationality); - }); - } else { - $e = new NamiException('Fetch von Nationalität fehlgeschlagen'); - $e->setData([ - 'response' => $response->body(), - 'url' => $url - ]); - throw $e; + if ($response->json()['success'] !== true) { + $this->exception("Fetch von Nationalität fehlgeschlagen", $url, $response->json()); } + + return collect($response['data'])->map(function($nationality) { + return Nationality::fromNami($nationality); + }); } public function countries() { @@ -416,7 +418,7 @@ class Api { $member = collect($response['data'])->first(function($member) use ($memberId) { return $member['id'] == $memberId; }); - + $member = collect($member)->mapWithKeys(function($value, $key) { return [ str_replace('entries_', '', $key) => $value ]; }); @@ -425,8 +427,9 @@ class Api { return $member->toArray(); } - private function exception($message, $request, $response) { - throw (new NamiException($message))->response($response)->request($request); + private function exception(string $message, string $url, array $response, array $requestData = []): void + { + throw (new NamiException($message))->response($response)->request($url, $requestData); } private function assertLoggedIn(): void diff --git a/src/Fakes/CourseFake.php b/src/Fakes/CourseFake.php index e695f50..1e4b210 100644 --- a/src/Fakes/CourseFake.php +++ b/src/Fakes/CourseFake.php @@ -81,11 +81,14 @@ class CourseFake extends Fake { }); } - public function doesntCreateWithError(int $memberId): void + /** + * @todo migrate this to parent errorResponse + */ + public function createFailed(int $memberId): void { Http::fake(function($request) use ($memberId) { if ($request->url() === "https://nami.dpsg.de/ica/rest/nami/mitglied-ausbildung/filtered-for-navigation/mitglied/mitglied/{$memberId}") { - return Http::response('{"success":false,"data":null,"responseType":"EXCEPTION","message":"Unexpected Error javax.ejb.EJBException","title":null}', 200); + return $this->errorResponse("Unexpected Error javaEx"); } }); } diff --git a/src/Fakes/Fake.php b/src/Fakes/Fake.php index 7d09111..f59b3ed 100644 --- a/src/Fakes/Fake.php +++ b/src/Fakes/Fake.php @@ -2,6 +2,17 @@ namespace Zoomyboy\LaravelNami\Fakes; +use GuzzleHttp\Promise\PromiseInterface; +use Illuminate\Support\Facades\Http; + abstract class Fake { + public function errorResponse(string $error): PromiseInterface + { + return Http::response(json_encode([ + 'success' => false, + 'message' => $error, + ])); + } + } diff --git a/src/Fakes/SubactivityFake.php b/src/Fakes/SubactivityFake.php new file mode 100644 index 0000000..59abd57 --- /dev/null +++ b/src/Fakes/SubactivityFake.php @@ -0,0 +1,19 @@ +url() === 'https://nami.dpsg.de/ica/rest/nami/untergliederungauftaetigkeit/filtered/untergliederung/taetigkeit/'.$activityId) { + return $this->errorResponse($error); + } + }); + } + +} diff --git a/src/NamiException.php b/src/NamiException.php index e249ab3..30b44a2 100644 --- a/src/NamiException.php +++ b/src/NamiException.php @@ -7,25 +7,32 @@ use Illuminate\Validation\ValidationException; class NamiException extends \Exception { - private $data; - public $response; - public $request; + private array $data; + private array $response; + private string $requestUrl; - public function setData($data) { + public function setData(array $data): self + { $this->data = $data; - } - - public function getData() { - return $this->data; - } - - public function request($request) { - $this->request = $request; return $this; } - public function response($response) { + public function getData(): array + { + return $this->data; + } + + public function request(string $url, ?array $data = []): self + { + $this->requestUrl = $url; + $this->data = $data; + + return $this; + } + + public function response(array $response): self + { $this->response = $response; return $this; @@ -34,8 +41,9 @@ class NamiException extends \Exception { public function report(): void { \Log::error($this->getMessage(), [ - 'request' => $this->request, - 'response' => $this->response + 'requestUrl' => $this->requestUrl, + 'data' => $this->data, + 'response' => json_encode($this->response), ]); throw ValidationException::withMessages(['id' => 'Unbekannter Fehler']); diff --git a/tests/Unit/CourseTest.php b/tests/Unit/CourseTest.php index 71f413d..e21634c 100644 --- a/tests/Unit/CourseTest.php +++ b/tests/Unit/CourseTest.php @@ -8,6 +8,7 @@ use Zoomyboy\LaravelNami\Exceptions\NotAuthenticatedException; use Zoomyboy\LaravelNami\Fakes\CourseFake; use Zoomyboy\LaravelNami\LoginException; use Zoomyboy\LaravelNami\Nami; +use Zoomyboy\LaravelNami\NamiException; use Zoomyboy\LaravelNami\Tests\TestCase; class CourseTest extends TestCase @@ -101,4 +102,19 @@ class CourseTest extends TestCase Nami::login(12345, 'secret')->coursesFor(11111); } + public function test_throw_exception_when_storing_failed(): void + { + $this->expectException(NamiException::class); + Auth::success(12345, 'secret'); + app(CourseFake::class)->createFailed(123); + Nami::login(12345, 'secret'); + + Nami::createCourse(123, [ + 'event_name' => '::event::', + 'completed_at' => '2021-01-02 00:00:00', + 'organizer' => '::org::', + 'course_id' => 456 + ]); + } + } diff --git a/tests/Unit/PullActivitiesTest.php b/tests/Unit/PullActivitiesTest.php index b1d4481..e483132 100644 --- a/tests/Unit/PullActivitiesTest.php +++ b/tests/Unit/PullActivitiesTest.php @@ -4,9 +4,11 @@ namespace Zoomyboy\LaravelNami\Tests\Unit; use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Http; +use Zoomyboy\LaravelNami\Fakes\SubactivityFake; use Zoomyboy\LaravelNami\Group; use Zoomyboy\LaravelNami\LoginException; use Zoomyboy\LaravelNami\Nami; +use Zoomyboy\LaravelNami\NamiException; use Zoomyboy\LaravelNami\NamiServiceProvider; use Zoomyboy\LaravelNami\Tests\TestCase; @@ -48,4 +50,21 @@ class PullActivitiesTest extends TestCase Http::assertSentCount(3); } + public function test_throw_error_when_subactivities_request_fails(): void + { + $this->expectException(NamiException::class); + app(SubactivityFake::class)->fetchFailed(4, 'sorry dude'); + Http::fake([ + 'https://nami.dpsg.de/ica/rest/nami/untergliederungauftaetigkeit/filtered/untergliederung/taetigkeit/4' => Http::response($this->fakeJson('subactivities-4.json'), 200) + ]); + + $subactivities = $this->login()->subactivitiesOf(4); + + $this->assertSame([ + [ 'name' => 'Biber', 'id' => 40 ], + [ 'name' => 'Wölfling', 'id' => 30 ] + ], $subactivities->toArray()); + Http::assertSentCount(3); + } + }