diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..f65db30 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,31 @@ +name: CI + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.3 + + - name: Install dependencies + run: composer install --prefer-dist --no-progress --no-suggest + + - name: Run PHPUnit + run: vendor/bin/phpunit + + - name: Run PHPStan + run: vendor/bin/phpstan analyze -l 6 src \ No newline at end of file diff --git a/composer.json b/composer.json index a90c38c..31496ac 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "airlst/sdk-php", "description": "This package is a SDK for handling AirLST Core API calls", "type": "library", - "minimum-stability": "dev", + "minimum-stability": "stable", "authors": [ { "name": "Jantinn Erezo", @@ -12,13 +12,12 @@ ], "require": { "guzzlehttp/guzzle": "^6.0|^7.0", - "php": "^8.2" + "php": "^8.3" }, "require-dev": { "friendsofphp/php-cs-fixer": "^2.0|^3.14", "mockery/mockery": "^1.4", - "nunomaduro/larastan": "^1.0|^2.4", - "orchestra/testbench": "^6.0|^7.0|^8.0", + "orchestra/testbench": "^6.0|^7.0|^8.0|^9.0", "phpunit/phpunit": "^8.0|^9.0|^10.0" }, "autoload": { @@ -35,16 +34,9 @@ "test": "./vendor/bin/phpunit", "test-coverage": "XDEBUG_MODE=coverage ./vendor/bin/phpunit --coverage-html .coverage", "fix": "PHP_CS_FIXER_IGNORE_ENV=1 ./vendor/bin/php-cs-fixer fix --verbose --config=.php-cs-fixer.php", - "phpstan": "./vendor/bin/phpstan analyse" + "phpstan": "./vendor/bin/phpstan analyse src" }, "config": { "sort-packages": true - }, - "extra": { - "laravel": { - "providers": [ - "AirLST\\SdkPhp\\Laravel\\AirLSTSdkPhpServiceProvider" - ] - } } -} \ No newline at end of file +} diff --git a/config/config.php b/config/config.php deleted file mode 100644 index ca4a388..0000000 --- a/config/config.php +++ /dev/null @@ -1,9 +0,0 @@ - env('AIRLST_API_BASE_URL', 'https://airlst.app'), - 'api_key' => env('AIRLST_API_KEY', null), - 'event_id' => env('AIRLST_EVENT_ID', null), -]; diff --git a/src/Client.php b/src/Client.php deleted file mode 100644 index 858b336..0000000 --- a/src/Client.php +++ /dev/null @@ -1,57 +0,0 @@ -handler = $handler; - } - - public function getRequestHeaders(): array - { - return [ - 'content-type' => 'application/json', - 'accept' => 'application/json', - 'x-api-key' => $this->apiKey, - ]; - } - - public function send(string $uri, RequestMethod $method = RequestMethod::GET, array $options = []): array - { - try { - $client = new GuzzleClient([ - 'base_uri' => $this->baseURL, - 'headers' => $this->getRequestHeaders(), - 'handler' => $this->handler, - ]); - - $response = $client->request($method->value, $uri, $options); - - $body = (string) $response->getBody(); - - return json_decode($body, true); - } catch (ClientException $exception) { - throw new \RuntimeException( - $exception->getResponse()->getBody()->getContents(), - $exception->getCode(), - $exception - ); - } - } -} diff --git a/src/CoreApi.php b/src/CoreApi.php new file mode 100644 index 0000000..9505762 --- /dev/null +++ b/src/CoreApi.php @@ -0,0 +1,95 @@ +baseURL = $baseURL; + + return $this; + } + + public function setApiKey(string $apiKey): self + { + $this->apiKey = $apiKey; + + return $this; + } + + public function setLocale(string $locale): self + { + $this->locale = $locale; + + return $this; + } + + public function setEventId(string $eventId): self + { + $this->eventId = $eventId; + + return $this; + } + + /** + * @return array + */ + public function getRequestHeaders(): array + { + return [ + 'content-type' => 'application/json', + 'accept' => 'application/json', + 'x-api-key' => $this->apiKey, + 'accept-language' => $this->locale, + ]; + } + + public function setHandler(HandlerStack $handler): void + { + $this->handler = $handler; + } + + /** + * @param string $uri + * @param RequestMethod $method + * @param array $options + * @return array + */ + public function send( + string $uri, + RequestMethod $method = RequestMethod::GET, + array $options = [] + ): array + { + try { + $client = new Client([ + 'base_uri' => $this->baseURL, + 'headers' => $this->getRequestHeaders(), + 'handler' => $this->handler + ]); + + $response = $client->request($method->value, "/api$uri", $options); + + return json_decode((string) $response->getBody(), true); + } catch (ClientException $exception) { + throw new \RuntimeException( + $exception->getResponse()->getBody()->getContents(), + $exception->getCode(), + $exception + ); + } + } +} \ No newline at end of file diff --git a/src/Laravel/AirLSTSdkPhpServiceProvider.php b/src/Laravel/AirLSTSdkPhpServiceProvider.php deleted file mode 100644 index d13745f..0000000 --- a/src/Laravel/AirLSTSdkPhpServiceProvider.php +++ /dev/null @@ -1,32 +0,0 @@ -app->runningInConsole()) { - $this->publishes([ - __DIR__ . '/../../config/config.php' => config_path('airlst.php'), - ], 'config'); - } - } - - public function register(): void - { - $this->mergeConfigFrom(__DIR__ . '/../../config/config.php', 'airlst'); - - $this->app->bind(Client::class, function () { - return new Client( - config('airlst.base_url'), - config('airlst.api_key') - ); - }); - } -} diff --git a/src/Resources/Event.php b/src/Resources/Event.php new file mode 100644 index 0000000..bf82ade --- /dev/null +++ b/src/Resources/Event.php @@ -0,0 +1,16 @@ + + */ + public function get(): array + { + return $this->send("/events/{$this->eventId}"); + } +} \ No newline at end of file diff --git a/src/Resources/Guest.php b/src/Resources/Guest.php index 98f5c53..2eeffbb 100644 --- a/src/Resources/Guest.php +++ b/src/Resources/Guest.php @@ -4,38 +4,59 @@ namespace AirLST\SdkPhp\Resources; -use AirLST\SdkPhp\Client; +use AirLST\SdkPhp\CoreApi; use AirLST\SdkPhp\RequestMethod; -class Guest extends Resource +class Guest extends CoreApi { - public function __construct(protected Client $client) - { - } - + /** + * @return array{'data': array{'code': string}} + */ public function validateCode(string $code): array { - return $this->client->send("{$this->getEventURL()}/guests/validate-code", RequestMethod::POST, [ - 'form_params' => ['code' => $code], - ]); + return $this->send( + uri: "{$this->getEventURL()}/guests/validate-code", + method: RequestMethod::POST, + options: ['form_params' => ['code' => $code]] + ); } + /** + * @return array{'data': array} + */ public function get(string $code): array { - return $this->client->send("{$this->getEventURL()}/guests/{$code}"); + return $this->send("{$this->getEventURL()}/guests/{$code}"); } + /** + * @param array $data + * @return array{'data': array} + */ public function create(array $data): array { - return $this->client->send("{$this->getEventURL()}/guests", RequestMethod::POST, [ - 'form_params' => $data - ]); + return $this->send( + uri: "{$this->getEventURL()}/guests", + method: RequestMethod::POST, + options: ['form_params' => $data] + ); } + /** + * @param array $data + * @return array{'data': array} + */ public function update(string $code, array $data): array { - return $this->client->send("{$this->getEventURL()}/guests/{$code}", RequestMethod::PUT, [ - 'form_params' => $data - ]); + return $this->send( + uri: "{$this->getEventURL()}/guests/{$code}", + method: RequestMethod::PUT, + options: ['form_params' => $data] + ); + } + + public function getEventURL(): string + { + return "/events/{$this->eventId}"; } } diff --git a/src/Resources/Resource.php b/src/Resources/Resource.php deleted file mode 100644 index 681492b..0000000 --- a/src/Resources/Resource.php +++ /dev/null @@ -1,20 +0,0 @@ -eventId = $eventId; - } - - public function getEventURL(): string - { - return "/api/events/{$this->eventId}"; - } -} diff --git a/tests/ClientTest.php b/tests/ClientTest.php deleted file mode 100644 index b8e54b2..0000000 --- a/tests/ClientTest.php +++ /dev/null @@ -1,71 +0,0 @@ -assertEquals([ - 'content-type' => 'application/json', - 'accept' => 'application/json', - 'x-api-key' => 'api-key', - ], $this->client->getRequestHeaders()); - } - - public function testSend(): void - { - $mock = new MockHandler([ - new Response(200, [], json_encode(['data' => ['event' => [ - 'uuid' => 'event-uuid', - ]]])), - ]); - - $handlerStack = HandlerStack::create($mock); - $this->client->setHandler($handlerStack); - - $response = $this->client->send('/events/event-uuid', RequestMethod::PUT, ['event' => [ - 'uuid' => 'event-uuid', - ]]); - - $this->assertEquals(['data' => [ - 'event' => [ - 'uuid' => 'event-uuid', - ], - ]], $response); - } - - public function testSendThrowsExceptionOnHttpError(): void - { - $mock = new MockHandler([ - new RequestException('Error Communicating with Server', new Request( - RequestMethod::GET->value, - 'test' - )), - ]); - - $handlerStack = HandlerStack::create($mock); - $this->client->setHandler($handlerStack); - - $this->expectException(RequestException::class); - $this->client->send('/events/event-uuid/guests/guest-code'); - } - - protected function setUp(): void - { - $this->client = new Client('https://example.com', 'api-key'); - } -} diff --git a/tests/CoreApiTest.php b/tests/CoreApiTest.php new file mode 100644 index 0000000..6b23394 --- /dev/null +++ b/tests/CoreApiTest.php @@ -0,0 +1,84 @@ +api->setBaseURL('https://airlst.test'); + + $this->assertEquals( + 'https://airlst.test', + $this->api->baseURL + ); + } + + public function testSetEventId(): void + { + $this->api->setEventId('event-id'); + + $this->assertEquals('event-id', $this->api->eventId); + } + + public function testSetApiKey(): void + { + $this->api->setApiKey('api-key'); + + $this->assertEquals('api-key', $this->api->apiKey); + } + + public function testSetLocale(): void + { + $this->api->setLocale('en-US'); + + $this->assertEquals('en-US', $this->api->locale); + } + + public function testGetEventUrl(): void + { + $this->api->setEventId('event-id'); + + $this->assertEquals('event-id', $this->api->eventId); + } + + public function testGetRequestHeaders(): void + { + $this->api->setApiKey('api-key')->setLocale('en-GB'); + + $this->assertEquals([ + 'content-type' => 'application/json', + 'accept' => 'application/json', + 'x-api-key' => 'api-key', + 'accept-language' => 'en-GB', + ], $this->api->getRequestHeaders()); + } + + public function testSendSuccessful(): void + { + $expects = ['data' => [ + 'event' => [ + 'uuid' => 'event-uuid', + ] + ]]; + + $this->fake($expects); + + $this->api->setApiKey('api-key'); + $this->api->setEventId('event-id'); + + $response = $this->api->send('/events/event-uuid', RequestMethod::GET); + + $this->assertEquals($expects, $response); + } + + protected function setUp(): void + { + $this->api = new CoreApi(); + } +} \ No newline at end of file diff --git a/tests/Resources/EventTest.php b/tests/Resources/EventTest.php new file mode 100644 index 0000000..99739cd --- /dev/null +++ b/tests/Resources/EventTest.php @@ -0,0 +1,41 @@ + [ + ['name' => 'event-name'] + ]]; + + $this->fake($expects); + + $response = $this->api->get(); + + $this->assertEquals($expects, $response); + $this->assertCount(count($expects['data']), $response); + } + + public function testGet(): void + { + $expects = ['data' => ['name' => 'event-name']]; + + $this->fake($expects); + + $this->assertEquals($expects, $this->api->get()); + } + + protected function setUp(): void + { + $this->api = new Event(); + $this->api->setApiKey('api-key'); + $this->api->setEventId('event-id'); + } +} diff --git a/tests/Resources/GuestTest.php b/tests/Resources/GuestTest.php index 38a3894..ec200e1 100644 --- a/tests/Resources/GuestTest.php +++ b/tests/Resources/GuestTest.php @@ -4,80 +4,67 @@ namespace AirLST\SdkPhp\Tests\Resources; -use AirLST\SdkPhp\Client; use AirLST\SdkPhp\Resources\Guest; -use PHPUnit\Framework\MockObject\MockObject; -use PHPUnit\Framework\TestCase; +use AirLST\SdkPhp\Tests\TestCase; class GuestTest extends TestCase { - protected MockObject $client; - protected Guest $guest; - public function testValidateCode(): void { - $this->client->expects($this->once()) - ->method('send') - ->willReturn(['data' => ['code' => 'guest-code']]); - - $this->assertEquals( - ['data' => ['code' => 'guest-code']], - $this->guest->validateCode('guest-code') - ); + $expects = ['data' => ['code' => 'guest-code']]; + + $this->fake($expects); + + $this->assertEquals($expects, $this->api->validateCode('guest-code')); } public function testGet(): void { - $this->client->expects($this->once()) - ->method('send') - ->willReturn(['data' => ['code' => 'guest-code']]); - - $this->assertEquals( - ['data' => ['code' => 'guest-code']], - $this->guest->get('guest-code') - ); + $expects = ['data' => ['code' => 'guest-code']]; + + $this->fake($expects); + + $this->assertEquals($expects, $this->api->get('guest-code')); } public function testCreate(): void { - $data = ['contact' => ['first_name' => 'John Lennon']]; + $expects = [ + 'data' => [ + 'contact' => ['first_name' => 'John Lennon'] + ] + ]; - $this->client->expects($this->once()) - ->method('send') - ->willReturn(['data' => $data]); + $this->fake($expects); - $this->assertEquals( - ['data' => $data], - $this->guest->create($data) - ); + $this->assertEquals($expects, $this->api->create($expects)); } public function testUpdate(): void { $code = 'guest-code'; - $data = ['contact' => ['first_name' => 'John Lennon']]; + $expects = [ + 'data' => [ + 'contact' => ['first_name' => 'John Lennon'] + ] + ]; - $this->client->expects($this->once()) - ->method('send') - ->willReturn(['data' => $data]); + $this->fake($expects); + + $this->assertEquals($expects, $this->api->update($code, $expects)); + } + + public function testGetEventURL(): void + { + $this->api->setEventId('event-id'); - $this->assertEquals( - ['data' => $data], - $this->guest->update($code, $data) - ); + $this->assertEquals('/events/event-id', $this->api->getEventURL()); } protected function setUp(): void { - $this->client = $this->getMockBuilder(Client::class) - ->setConstructorArgs([ - 'baseURL' => 'https://example.com', - 'apiKey' => 'api-key', - ]) - ->disableOriginalConstructor() - ->getMock(); - - $this->guest = new Guest($this->client); - $this->guest->setEventId('event-uuid'); + $this->api = new Guest(); + $this->api->setApiKey('api-key'); + $this->api->setEventId('event-id'); } } diff --git a/tests/Resources/ResourceTest.php b/tests/Resources/ResourceTest.php deleted file mode 100644 index bfd0f0c..0000000 --- a/tests/Resources/ResourceTest.php +++ /dev/null @@ -1,32 +0,0 @@ -resource->setEventId('event-uuid'); - - $this->assertEquals('event-uuid', $this->resource->eventId); - } - - public function testGetEventURL(): void - { - $this->resource->setEventId('event-uuid'); - - $this->assertEquals('/api/events/event-uuid', $this->resource->getEventURL()); - } - - public function setUp(): void - { - $this->resource = new Resource(); - } -} diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100644 index 0000000..cb53830 --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,25 @@ +api->setHandler(HandlerStack::create( + new MockHandler([new Response($status, [], json_encode($expects))]) + )); + } +} \ No newline at end of file