From c234d3e7577884b8360f618add1181fac964cd09 Mon Sep 17 00:00:00 2001 From: Daniel Siepmann Date: Mon, 21 Sep 2020 15:48:04 +0200 Subject: [PATCH] Add first API implementation Allow to retrieve skill and skill set by ID. Returns PHP classes with proper getter for most important info. All info are available via PHP array from those classes. --- src/Api/Skill.php | 71 ++++++++++++++ src/Api/SkillSet.php | 71 ++++++++++++++ src/Entity/Skill.php | 65 +++++++++++++ src/Entity/SkillSet.php | 78 +++++++++++++++ tests/Unit/Api/SkillSetTest.php | 146 +++++++++++++++++++++++++++++ tests/Unit/Api/SkillTest.php | 146 +++++++++++++++++++++++++++++ tests/Unit/Entity/SkillSetTest.php | 113 ++++++++++++++++++++++ tests/Unit/Entity/SkillTest.php | 98 +++++++++++++++++++ 8 files changed, 788 insertions(+) create mode 100644 src/Api/Skill.php create mode 100644 src/Api/SkillSet.php create mode 100644 src/Entity/Skill.php create mode 100644 src/Entity/SkillSet.php create mode 100644 tests/Unit/Api/SkillSetTest.php create mode 100644 tests/Unit/Api/SkillTest.php create mode 100644 tests/Unit/Entity/SkillSetTest.php create mode 100644 tests/Unit/Entity/SkillTest.php diff --git a/src/Api/Skill.php b/src/Api/Skill.php new file mode 100644 index 0000000..b952759 --- /dev/null +++ b/src/Api/Skill.php @@ -0,0 +1,71 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +use GuzzleHttp\Client; +use GuzzleHttp\Psr7\Request; +use SkillDisplay\PHPToolKit\Configuration\Settings; +use SkillDisplay\PHPToolKit\Entity\Skill as Entity; + +class Skill +{ + /** + * @var Settings + */ + protected $settings; + + /** + * @var Client + */ + protected $client; + + public function __construct( + Settings $settings, + Client $client + ) { + $this->settings = $settings; + $this->client = $client; + } + + public function getById(int $id): Entity + { + if ($id <= 0) { + throw new \Exception('ID of Skill has to be a positive integer.', 1600764849); + } + + $url = $this->settings->getAPIUrl() . '/api/v1/skill/' . $id; + $result = $this->client->send(new Request( + 'GET', + $url, + [ + 'Content-Type' => 'application/json', + 'x-api-key' => $this->settings->getApiKey() + ] + )); + + if ($result->getStatusCode() !== 200) { + throw new \Exception('Did not get proper response for skill.', 1600694312); + } + + return Entity::createFromJson((string) $result->getBody()); + } +} diff --git a/src/Api/SkillSet.php b/src/Api/SkillSet.php new file mode 100644 index 0000000..dfded92 --- /dev/null +++ b/src/Api/SkillSet.php @@ -0,0 +1,71 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +use GuzzleHttp\Client; +use GuzzleHttp\Psr7\Request; +use SkillDisplay\PHPToolKit\Configuration\Settings; +use SkillDisplay\PHPToolKit\Entity\SkillSet as Entity; + +class SkillSet +{ + /** + * @var Settings + */ + protected $settings; + + /** + * @var Client + */ + protected $client; + + public function __construct( + Settings $settings, + Client $client + ) { + $this->settings = $settings; + $this->client = $client; + } + + public function getById(int $id): Entity + { + if ($id <= 0) { + throw new \Exception('ID of SkillSet has to be a positive integer.', 1600764811); + } + + $url = $this->settings->getAPIUrl() . '/api/v1/skillset/' . $id; + $result = $this->client->send(new Request( + 'GET', + $url, + [ + 'Content-Type' => 'application/json', + 'x-api-key' => $this->settings->getApiKey() + ] + )); + + if ($result->getStatusCode() !== 200) { + throw new \Exception('Did not get proper response for skill.', 1600694312); + } + + return Entity::createFromJson((string) $result->getBody()); + } +} diff --git a/src/Entity/Skill.php b/src/Entity/Skill.php new file mode 100644 index 0000000..145e70d --- /dev/null +++ b/src/Entity/Skill.php @@ -0,0 +1,65 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +class Skill +{ + /** + * @var array + */ + private $data; + + private function __construct(array $data) + { + $this->data = $data; + } + + public function getId(): int + { + return $this->data['uid']; + } + + public function getTitle(): string + { + return $this->data['title'] ?? ''; + } + + public function getDescription(): string + { + return $this->data['description'] ?? ''; + } + + public function getGoals(): string + { + return $this->data['goals'] ?? ''; + } + + public function toArray(): array + { + return $this->data; + } + + public static function createFromJson(string $json): Skill + { + return new Skill(json_decode($json, true)); + } +} diff --git a/src/Entity/SkillSet.php b/src/Entity/SkillSet.php new file mode 100644 index 0000000..35bfc69 --- /dev/null +++ b/src/Entity/SkillSet.php @@ -0,0 +1,78 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +class SkillSet +{ + /** + * @var array + */ + private $data; + + private function __construct(array $data) + { + $this->data = $data; + } + + public function getId(): int + { + return $this->data['uid']; + } + + public function getName(): string + { + return $this->data['name'] ?? ''; + } + + public function getDescription(): string + { + return $this->data['description'] ?? ''; + } + + /** + * @return Skill[] + */ + public function getSkills(): array + { + static $skills = []; + + if ($skills !== []) { + return $skills; + } + + foreach ($this->data['skills'] as $skill) { + $skills[] = Skill::createFromJson(json_encode($skill)); + } + + return $skills; + } + + public function toArray(): array + { + return $this->data; + } + + public static function createFromJson(string $json): SkillSet + { + return new SkillSet(json_decode($json, true)); + } +} diff --git a/tests/Unit/Api/SkillSetTest.php b/tests/Unit/Api/SkillSetTest.php new file mode 100644 index 0000000..c04259e --- /dev/null +++ b/tests/Unit/Api/SkillSetTest.php @@ -0,0 +1,146 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +use GuzzleHttp\Client; +use GuzzleHttp\Psr7\Request; +use GuzzleHttp\Psr7\Response; +use Prophecy\Argument; +use Prophecy\PhpUnit\ProphecyTrait; +use SkillDisplay\PHPToolKit\Api\SkillSet; +use PHPUnit\Framework\TestCase; +use SkillDisplay\PHPToolKit\Configuration\Settings; +use SkillDisplay\PHPToolKit\Entity\SkillSet as Entity; + +/** + * @covers SkillDisplay\PHPToolKit\Api\SkillSet + */ +class SkillSetTest extends TestCase +{ + use ProphecyTrait; + + /** + * @test + */ + public function instanceCanBeCreated() + { + $settings = $this->prophesize(Settings::class); + $client = $this->prophesize(Client::class); + + $subject = new SkillSet( + $settings->reveal(), + $client->reveal() + ); + + static::assertInstanceOf(SkillSet::class, $subject); + } + + /** + * @test + */ + public function fetchedEntityFromApi() + { + $settings = $this->prophesize(Settings::class); + $client = $this->prophesize(Client::class); + $response = $this->prophesize(Response::class); + + $settings->getAPIUrl()->willReturn('https://example.com'); + $settings->getApiKey()->willReturn('none'); + + $client->send(Argument::that(function (Request $request) { + return (string) $request->getUri() === 'https://example.com/api/v1/skillset/10' + && $request->getHeader('x-api-key') === ['none'] + && $request->getHeader('Content-Type') === ['application/json'] + && $request->getMethod() === 'GET' + ; + }))->willReturn($response->reveal()); + + $response->getStatusCode()->willReturn(200); + $response->getBody()->willReturn('{"uid":10}'); + + $subject = new SkillSet( + $settings->reveal(), + $client->reveal() + ); + $result = $subject->getById(10); + static::assertInstanceOf(Entity::class, $result); + } + + /** + * @test + */ + public function throwsExceptionIfStatusCodeIsNot200() + { + $settings = $this->prophesize(Settings::class); + $client = $this->prophesize(Client::class); + $response = $this->prophesize(Response::class); + + $settings->getAPIUrl()->willReturn('https://example.com'); + $settings->getApiKey()->willReturn('none'); + + $client->send(Argument::any())->willReturn($response->reveal()); + + $response->getStatusCode()->willReturn(500); + + $subject = new SkillSet( + $settings->reveal(), + $client->reveal() + ); + + $this->expectExceptionMessage('Did not get proper response for skill.'); + $this->expectExceptionCode(1600694312); + + $result = $subject->getById(10); + } + + /** + * @test + * @dataProvider nonePositiveIds + */ + public function throwsExceptionIfSkillSetIdIsNotPositive(int $skillId) + { + $settings = $this->prophesize(Settings::class); + $client = $this->prophesize(Client::class); + + $subject = new SkillSet( + $settings->reveal(), + $client->reveal() + ); + + $this->expectExceptionMessage('ID of SkillSet has to be a positive integer.'); + $this->expectExceptionCode(1600764811); + + $subject->getById($skillId); + } + + public function nonePositiveIds(): array + { + return [ + 'zero' => [ + 'skillId' => 0, + ], + 'negative' => [ + 'skillId' => -1, + ], + ]; + } +} diff --git a/tests/Unit/Api/SkillTest.php b/tests/Unit/Api/SkillTest.php new file mode 100644 index 0000000..536a1cf --- /dev/null +++ b/tests/Unit/Api/SkillTest.php @@ -0,0 +1,146 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +use GuzzleHttp\Client; +use GuzzleHttp\Psr7\Request; +use GuzzleHttp\Psr7\Response; +use Prophecy\Argument; +use Prophecy\PhpUnit\ProphecyTrait; +use SkillDisplay\PHPToolKit\Api\Skill; +use PHPUnit\Framework\TestCase; +use SkillDisplay\PHPToolKit\Configuration\Settings; +use SkillDisplay\PHPToolKit\Entity\Skill as Entity; + +/** + * @covers SkillDisplay\PHPToolKit\Api\Skill + */ +class SkillTest extends TestCase +{ + use ProphecyTrait; + + /** + * @test + */ + public function instanceCanBeCreated() + { + $settings = $this->prophesize(Settings::class); + $client = $this->prophesize(Client::class); + + $subject = new Skill( + $settings->reveal(), + $client->reveal() + ); + + static::assertInstanceOf(Skill::class, $subject); + } + + /** + * @test + */ + public function fetchedEntityFromApi() + { + $settings = $this->prophesize(Settings::class); + $client = $this->prophesize(Client::class); + $response = $this->prophesize(Response::class); + + $settings->getAPIUrl()->willReturn('https://example.com'); + $settings->getApiKey()->willReturn('none'); + + $client->send(Argument::that(function (Request $request) { + return (string) $request->getUri() === 'https://example.com/api/v1/skill/10' + && $request->getHeader('x-api-key') === ['none'] + && $request->getHeader('Content-Type') === ['application/json'] + && $request->getMethod() === 'GET' + ; + }))->willReturn($response->reveal()); + + $response->getStatusCode()->willReturn(200); + $response->getBody()->willReturn('{"uid":10}'); + + $subject = new Skill( + $settings->reveal(), + $client->reveal() + ); + $result = $subject->getById(10); + static::assertInstanceOf(Entity::class, $result); + } + + /** + * @test + */ + public function throwsExceptionIfStatusCodeIsNot200() + { + $settings = $this->prophesize(Settings::class); + $client = $this->prophesize(Client::class); + $response = $this->prophesize(Response::class); + + $settings->getAPIUrl()->willReturn('https://example.com'); + $settings->getApiKey()->willReturn('none'); + + $client->send(Argument::any())->willReturn($response->reveal()); + + $response->getStatusCode()->willReturn(500); + + $subject = new Skill( + $settings->reveal(), + $client->reveal() + ); + + $this->expectExceptionMessage('Did not get proper response for skill.'); + $this->expectExceptionCode(1600694312); + + $result = $subject->getById(10); + } + + /** + * @test + * @dataProvider nonePositiveIds + */ + public function throwsExceptionIfSkillIdIsNotPositive(int $skillId) + { + $settings = $this->prophesize(Settings::class); + $client = $this->prophesize(Client::class); + + $subject = new Skill( + $settings->reveal(), + $client->reveal() + ); + + $this->expectExceptionMessage('ID of Skill has to be a positive integer.'); + $this->expectExceptionCode(1600764849); + + $subject->getById($skillId); + } + + public function nonePositiveIds(): array + { + return [ + 'zero' => [ + 'skillId' => 0, + ], + 'negative' => [ + 'skillId' => -1, + ], + ]; + } +} diff --git a/tests/Unit/Entity/SkillSetTest.php b/tests/Unit/Entity/SkillSetTest.php new file mode 100644 index 0000000..b3af901 --- /dev/null +++ b/tests/Unit/Entity/SkillSetTest.php @@ -0,0 +1,113 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +use PHPUnit\Framework\TestCase; +use SkillDisplay\PHPToolKit\Entity\SkillSet; + +/** + * @covers SkillDisplay\PHPToolKit\Entity\SkillSet + */ +class SkillSetTest extends TestCase +{ + /** + * @test + */ + public function instanceCanNotBeCreatedViaConstructor() + { + $this->expectErrorMessage('Call to private SkillDisplay\PHPToolKit\Entity\SkillSet::__construct() from context \'SkillDisplay\PHPToolKit\Tests\Unit\Entity\SkillSetTest\''); + new SkillSet(); + } + + /** + * @test + */ + public function instanceCanBeCreatedFromJson() + { + $subject = SkillSet::createFromJson('{}'); + static::assertInstanceOf(SkillSet::class, $subject); + } + + /** + * @test + */ + public function instanceReturnsId() + { + $subject = SkillSet::createFromJson('{"uid":90}'); + static::assertSame(90, $subject->getId()); + } + + /** + * @test + */ + public function instanceReturnsName() + { + $subject = SkillSet::createFromJson('{"name":"Example name"}'); + static::assertSame('Example name', $subject->getName()); + } + + /** + * @test + */ + public function instanceReturnsDescription() + { + $subject = SkillSet::createFromJson('{"description":"

Example description

"}'); + static::assertSame('

Example description

', $subject->getDescription()); + } + + /** + * @test + */ + public function instanceReturnsSkills() + { + $subject = SkillSet::createFromJson('{"skills":[{"uid":90,"title":"Example title 1"},{"goals":"

Example goals

","uid":91,"title":"Example title 2"}]}'); + $skills = $subject->getSkills(); + + static::assertCount(2, $skills); + static::assertSame(90, $skills[0]->getId()); + static::assertSame(91, $skills[1]->getId()); + } + + /** + * @test + */ + public function instanceReturnsSameSkillInstancesA2ndTime() + { + $subject = SkillSet::createFromJson('{"skills":[{"uid":90,"title":"Example title 1"},{"goals":"

Example goals

","uid":91,"title":"Example title 2"}]}'); + $skillsFirstCall = $subject->getSkills(); + $skillsSecondCall = $subject->getSkills(); + + static::assertSame($skillsFirstCall, $skillsSecondCall); + } + + /** + * @test + */ + public function canBeConvertedToArray() + { + $subject = SkillSet::createFromJson('{"uid":90,"name":"Example name"}'); + static::assertSame([ + 'uid' => 90, + 'name' => 'Example name', + ], $subject->toArray()); + } +} diff --git a/tests/Unit/Entity/SkillTest.php b/tests/Unit/Entity/SkillTest.php new file mode 100644 index 0000000..2964cb6 --- /dev/null +++ b/tests/Unit/Entity/SkillTest.php @@ -0,0 +1,98 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +use PHPUnit\Framework\TestCase; +use SkillDisplay\PHPToolKit\Entity\Skill; + +/** + * @covers SkillDisplay\PHPToolKit\Entity\Skill + */ +class SkillTest extends TestCase +{ + /** + * @test + */ + public function instanceCanNotBeCreatedViaConstructor() + { + $this->expectErrorMessage('Call to private SkillDisplay\PHPToolKit\Entity\Skill::__construct() from context \'SkillDisplay\PHPToolKit\Tests\Unit\Entity\SkillTest\''); + new Skill(); + } + + /** + * @test + */ + public function instanceCanBeCreatedFromJson() + { + $subject = Skill::createFromJson('{}'); + static::assertInstanceOf(Skill::class, $subject); + } + + /** + * @test + */ + public function instanceReturnsId() + { + $subject = Skill::createFromJson('{"uid":90}'); + static::assertSame(90, $subject->getId()); + } + + /** + * @test + */ + public function instanceReturnsTitle() + { + $subject = Skill::createFromJson('{"title":"Example title"}'); + static::assertSame('Example title', $subject->getTitle()); + } + + /** + * @test + */ + public function instanceReturnsDescription() + { + $subject = Skill::createFromJson('{"description":"

Example description

"}'); + static::assertSame('

Example description

', $subject->getDescription()); + } + + /** + * @test + */ + public function instanceReturnsGoals() + { + $subject = Skill::createFromJson('{"goals":"

Example goals

"}'); + static::assertSame('

Example goals

', $subject->getGoals()); + } + + /** + * @test + */ + public function canBeConvertedToArray() + { + $subject = Skill::createFromJson('{"goals":"

Example goals

","uid":90,"title":"Example title"}'); + static::assertSame([ + 'goals' => '

Example goals

', + 'uid' => 90, + 'title' => 'Example title', + ], $subject->toArray()); + } +}