Skip to content

Commit

Permalink
Merge branch 'main' into feature/INTEG-252-checkout-get
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/Service/CheckoutService.php
  • Loading branch information
JoeyDeHaas committed Sep 6, 2024
2 parents d0d0175 + 5f23e5e commit a445bee
Show file tree
Hide file tree
Showing 9 changed files with 410 additions and 9 deletions.
58 changes: 58 additions & 0 deletions Tests/Feature/Checkout/DeleteCheckoutTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

/** @noinspection PhpUnhandledExceptionInspection */

declare(strict_types=1);

namespace PlugAndPay\Sdk\Tests\Feature\Checkout;

use PHPUnit\Framework\TestCase;
use PlugAndPay\Sdk\Entity\Response;
use PlugAndPay\Sdk\Exception\NotFoundException;
use PlugAndPay\Sdk\Exception\UnauthenticatedException;
use PlugAndPay\Sdk\Service\CheckoutService;
use PlugAndPay\Sdk\Tests\Feature\Checkout\Mock\CheckoutDestroyMockClient;

class DeleteCheckoutTest extends TestCase
{
/** @test */
public function it_should_throw_not_found_exception(): void
{
$client = new CheckoutDestroyMockClient(Response::HTTP_NOT_FOUND, []);
$service = new CheckoutService($client);
$exception = null;

try {
$service->delete(1);
} catch (NotFoundException $exception) {
}

static::assertInstanceOf(NotFoundException::class, $exception);
}

/** @test */
public function it_should_throw_unauthorised_exception(): void
{
$client = new CheckoutDestroyMockClient(Response::HTTP_UNAUTHORIZED, []);
$service = new CheckoutService($client);
$exception = null;

try {
$service->delete(1);
} catch (UnauthenticatedException $exception) {
}

static::assertInstanceOf(UnauthenticatedException::class, $exception);
}

/** @test */
public function it_should_delete_checkout(): void
{
$client = new CheckoutDestroyMockClient(Response::HTTP_NO_CONTENT, []);
$service = new CheckoutService($client);

$service->delete(1);

static::assertEquals('/v2/checkouts/1', $client->path());
}
}
38 changes: 38 additions & 0 deletions Tests/Feature/Checkout/Mock/CheckoutDestroyMockClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace PlugAndPay\Sdk\Tests\Feature\Checkout\Mock;

use JsonException;
use PlugAndPay\Sdk\Entity\Response;
use PlugAndPay\Sdk\Exception\ExceptionFactory;
use PlugAndPay\Sdk\Exception\NotFoundException;
use PlugAndPay\Sdk\Exception\ValidationException;
use PlugAndPay\Sdk\Tests\Feature\ClientMock;

class CheckoutDestroyMockClient extends ClientMock
{
private string $path;

/**
* @throws NotFoundException
* @throws ValidationException
* @throws JsonException
*/
public function delete(string $path): Response
{
$this->path = $path;
$exception = ExceptionFactory::create($this->status);
if ($exception) {
throw $exception;
}

return new Response(Response::HTTP_NO_CONTENT);
}

public function path(): string
{
return $this->path;
}
}
30 changes: 30 additions & 0 deletions Tests/Feature/Checkout/Mock/CheckoutStoreMockClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace PlugAndPay\Sdk\Tests\Feature\Checkout\Mock;

use PlugAndPay\Sdk\Entity\Response;

class CheckoutStoreMockClient extends CheckoutShowMockClient
{
protected array $requestBody;

public function path(): string
{
return $this->path;
}

public function post(string $path, array $body): Response
{
$this->path = $path;
$this->requestBody = $body;

return new Response(Response::HTTP_CREATED, $this->responseBody);
}

public function requestBody(): array
{
return $this->requestBody;
}
}
27 changes: 27 additions & 0 deletions Tests/Feature/Checkout/Mock/CheckoutUpdateMockClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace PlugAndPay\Sdk\Tests\Feature\Checkout\Mock;

use PlugAndPay\Sdk\Entity\Response;
use PlugAndPay\Sdk\Support\Arr;

class CheckoutUpdateMockClient extends CheckoutShowMockClient
{
protected array $requestBody;

public function patch(string $path, array $data): Response
{
$this->responseBody = Arr::mergeDistinct($this->responseBody, ['data' => $data]);
$this->path = $path;
$this->requestBody = $data;

return new Response(Response::HTTP_OK, $this->responseBody);
}

public function path(): string
{
return $this->path;
}
}
142 changes: 142 additions & 0 deletions Tests/Feature/Checkout/StoreCheckoutTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<?php

/** @noinspection EfferentObjectCouplingInspection */
/* @noinspection PhpUnhandledExceptionInspection */

declare(strict_types=1);

namespace PlugAndPay\Sdk\Tests\Feature\Checkout;

use BadFunctionCallException;
use PHPUnit\Framework\TestCase;
use PlugAndPay\Sdk\Director\ToBody\CheckoutToBody;
use PlugAndPay\Sdk\Entity\Checkout;
use PlugAndPay\Sdk\Entity\Response;
use PlugAndPay\Sdk\Exception\ValidationException;
use PlugAndPay\Sdk\Service\CheckoutService;
use PlugAndPay\Sdk\Tests\Feature\Checkout\Mock\CheckoutStoreMockClient;
use PlugAndPay\Sdk\Tests\Feature\ClientMock;

class StoreCheckoutTest extends TestCase
{
/** @test */
public function it_should_throw_exception_when_calling_non_existing_method(): void
{
$exception = null;

try {
$checkout = new Checkout();
$checkout->isset('bad_function');
} catch (BadFunctionCallException $exception) {
}

static::assertInstanceOf(BadFunctionCallException::class, $exception);
}

/** @test */
public function it_should_convert_basic_checkout_to_body(): void
{
$body = CheckoutToBody::build($this->generateCheckout());

static::assertEquals([
'is_active' => true,
'is_expired' => false,
'name' => 'the-name',
'preview_url' => 'the-url',
'primary_color' => 'the-primary-color',
'return_url' => 'the-return-url',
'secondary_color' => 'the-secondary-color',
'slug' => 'the-slug',
'url' => 'the-url',
'product' => [
'id' => 1,
],
], $body);
}

/** @test */
public function it_should_store_basic_checkout(): void
{
$client = new CheckoutStoreMockClient();
$service = new CheckoutService($client);

$checkout = $this->generateCheckout();
$checkout = $service->create($checkout);

static::assertEquals('/v2/checkouts', $client->path());
static::assertEquals(1, $checkout->id());
}

/** @test */
public function create_order_with_validation_error(): void
{
$client = new ClientMock(
Response::HTTP_UNPROCESSABLE_ENTITY,
[
'message' => 'The given data was invalid.',
'errors' => [
'name' => [
'Naam is verplicht.',
],
],
],
);
$service = new CheckoutService($client);
$exception = null;

try {
$service->find(1);
} catch (ValidationException $exception) {
}

static::assertEquals('Naam is verplicht.', $exception->getMessage());
static::assertEquals('Naam is verplicht.', $exception->errors()[0]->message());
static::assertEquals('name', $exception->errors()[0]->field());
}

/** @test */
public function create_order_with_multiple_validation_errors(): void
{
$client = new ClientMock(
Response::HTTP_UNPROCESSABLE_ENTITY,
[
'message' => 'The given data was invalid.',
'errors' => [
'name' => [
'First error.',
'Second error.',
],
'productId' => [
'Last error.',
],
],
],
);
$service = new CheckoutService($client);
$exception = null;

try {
$service->find(1);
} catch (ValidationException $exception) {
}

static::assertEquals('First error. Second error. Last error.', $exception->getMessage());
static::assertEquals('First error.', $exception->errors()[0]->message());
static::assertEquals('name', $exception->errors()[0]->field());
}

private function generateCheckout(): Checkout
{
return (new Checkout())
->setIsActive(true)
->setIsExpired(false)
->setName('the-name')
->setPreviewUrl('the-url')
->setPrimaryColor('the-primary-color')
->setProductId(1)
->setReturnUrl('the-return-url')
->setSecondaryColor('the-secondary-color')
->setSlug('the-slug')
->setUrl('the-url');
}
}
61 changes: 61 additions & 0 deletions Tests/Feature/Checkout/UpdateCheckoutTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

/** @noinspection PhpUnhandledExceptionInspection */

declare(strict_types=1);

namespace PlugAndPay\Sdk\Tests\Feature\Checkout;

use PHPUnit\Framework\TestCase;
use PlugAndPay\Sdk\Entity\Checkout;
use PlugAndPay\Sdk\Entity\Response;
use PlugAndPay\Sdk\Exception\UnauthenticatedException;
use PlugAndPay\Sdk\Service\CheckoutService;
use PlugAndPay\Sdk\Tests\Feature\Checkout\Mock\CheckoutShowMockClient;
use PlugAndPay\Sdk\Tests\Feature\Checkout\Mock\CheckoutUpdateMockClient;

class UpdateCheckoutTest extends TestCase
{
/** @test */
public function it_should_throw_unauthorized_exception(): void
{
$client = new CheckoutShowMockClient(status: Response::HTTP_UNAUTHORIZED);
$service = new CheckoutService($client);
$exception = null;

try {
$service->update(999, function (Checkout $checkout) {
});
} catch (UnauthenticatedException $exception) {
}

static::assertEquals('Unable to connect with Plug&Pay. Request is unauthenticated.', $exception->getMessage());
}

/** @test */
public function it_should_update_basic_checkout(): void
{
$client = new CheckoutUpdateMockClient();
$service = new CheckoutService($client);

$checkout = $service->update(1, function (Checkout $checkout) {
$checkout->setIsActive(false);
});

static::assertFalse($checkout->isActive());
static::assertEquals('/v2/checkouts/1', $client->path());
}

/** @test */
public function it_should_update_product_id(): void
{
$client = (new CheckoutUpdateMockClient())->productPricing();
$service = new CheckoutService($client);

$checkout = $service->update(1, function (Checkout $checkout) {
$checkout->setProductId(123);
});

static::assertEquals(123, $checkout->product()->id());
}
}
11 changes: 2 additions & 9 deletions src/Entity/Checkout.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,9 @@ public function product(): Product
return $this->product;
}

public function setProduct(Product $product): self
public function setProductId(int $id): self
{
$this->product = $product;
$this->product = (new ProductInternal())->setId($id);

return $this;
}
Expand All @@ -134,13 +134,6 @@ public function productPricing(): ProductPricing
return $this->productPricing;
}

public function setProductPricing(ProductPricing $productPricing): self
{
$this->productPricing = $productPricing;

return $this;
}

public function returnUrl(): ?string
{
return $this->returnUrl;
Expand Down
Loading

0 comments on commit a445bee

Please sign in to comment.