Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Naoray committed Dec 4, 2024
1 parent 7757a39 commit 2a21c70
Show file tree
Hide file tree
Showing 12 changed files with 246 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/Contracts/Hydratable.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

interface Hydratable
{
public static function shouldAutoHydrate(bool $shouldAutoHydrate = true): void;
public static function setAutoHydrate(bool $shouldAutoHydrate = true): void;

/**
* @return mixed
Expand Down
2 changes: 1 addition & 1 deletion src/EndpointCollection/EndpointCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public function __construct(Connector $connector)
/**
* Default hydration decision to true to maintain legacy compatibility.
*/
$connector::shouldAutoHydrate();
$connector::setAutoHydrate();
}

/**
Expand Down
39 changes: 39 additions & 0 deletions src/Helpers/Arr.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,45 @@ public static function get(array $array, string $keys, $default = null)
return $value;
}

/**
* Get and remove an item from an array using "dot" notation.
*
* @param array $array
* @param string $key
* @param mixed $default
* @return mixed
*/
public static function pull(array &$array, string $key, $default = null)
{
$value = static::get($array, $key, $default);

static::forget($array, $key);

return $value;
}

/**
* Remove an item from an array using "dot" notation.
*
* @param array $array
* @param string $key
*/
public static function forget(array &$array, string $key): void
{
$keys = explode('.', $key);
$last = array_pop($keys);
$array = &$array;

foreach ($keys as $segment) {
if (!is_array($array) || !array_key_exists($segment, $array)) {
break;
}
$array = &$array[$segment];
}

unset($array[$last]);
}

/**
* Checks if the given key/s exist in the provided array.
*
Expand Down
40 changes: 37 additions & 3 deletions src/Resources/CursorCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,43 @@

use Generator;
use Mollie\Api\Http\Requests\DynamicGetRequest;
use Mollie\Api\Http\Requests\ResourceHydratableRequest;

abstract class CursorCollection extends ResourceCollection
{
private bool $autoHydrate = false;

public function setAutoHydrate(bool $shouldAutoHydrate = true): void
{
$this->autoHydrate = $shouldAutoHydrate;
}

public function shouldAutoHydrate(): bool
{
if ($this->response === null) {
return $this->autoHydrate;
}

$request = $this->response->getRequest();

/**
* Don't try to hydrate when the request
* already has auto-hydration enabled. The
* Hydrate Middleware will take care of that.
*/
if ($request instanceof ResourceHydratableRequest && $request->shouldAutoHydrate()) {
return false;
}

return $this->autoHydrate;
}

/**
* Return the next set of resources when available
*
* @throws \Mollie\Api\Exceptions\ApiException
*/
final public function next(): ?CursorCollection
public function next(): ?CursorCollection
{
if (! $this->hasNext()) {
return null;
Expand All @@ -26,7 +54,7 @@ final public function next(): ?CursorCollection
*
* @throws \Mollie\Api\Exceptions\ApiException
*/
final public function previous(): ?CursorCollection
public function previous(): ?CursorCollection
{
if (! $this->hasPrevious()) {
return null;
Expand All @@ -37,9 +65,13 @@ final public function previous(): ?CursorCollection

private function fetchCollection(string $url): CursorCollection
{
return $this
$response = $this
->connector
->send(new DynamicGetRequest($url, static::class));

return $this->shouldAutoHydrate()
? $response->toResource()
: $response;
}

/**
Expand All @@ -66,6 +98,8 @@ public function getAutoIterator(bool $iterateBackwards = false): LazyCollection
$page = $this;

return new LazyCollection(function () use ($page, $iterateBackwards): Generator {
$page->setAutoHydrate();

while (true) {
foreach ($page as $item) {
yield $item;
Expand Down
2 changes: 1 addition & 1 deletion src/Traits/HandlesAutoHydration.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ trait HandlesAutoHydration
{
protected static $hydrationSettingResolver = null;

public static function shouldAutoHydrate(bool $shouldAutoHydrate = true): void
public static function setAutoHydrate(bool $shouldAutoHydrate = true): void
{
static::$hydrationSettingResolver = static function () use ($shouldAutoHydrate) {
ResourceHydratableRequest::hydrate($shouldAutoHydrate);
Expand Down
5 changes: 5 additions & 0 deletions tests/Fixtures/SequenceMockResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,9 @@ public function pop(): MockResponse

return $response;
}

public function isEmpty(): bool
{
return count($this->responses) === 0;
}
}
19 changes: 19 additions & 0 deletions tests/Helpers/ArrTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,25 @@ public function get(): void
$this->assertEquals('default', Arr::get($array, 'foo.baz', 'default'));
}

/** @test */
public function pull(): void
{
$array = ['foo' => ['bar' => 'baz']];

$this->assertEquals('baz', Arr::pull($array, 'foo.bar'));
$this->assertEquals(['foo' => []], $array);
}

/** @test */
public function forget(): void
{
$array = ['foo' => ['bar' => 'baz']];

Arr::forget($array, 'foo.bar');

$this->assertEquals(['foo' => []], $array);
}

/** @test */
public function has(): void
{
Expand Down
34 changes: 28 additions & 6 deletions tests/Http/Adapter/MockMollieHttpAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,13 @@ public function __construct(array $expectedResponses = [])
*/
public function sendRequest(PendingRequest $pendingRequest): Response
{
if (! Arr::has($this->expectedResponses, $requestClass = get_class($pendingRequest->getRequest()))) {
$requestClass = get_class($pendingRequest->getRequest());

if (! Arr::has($this->expectedResponses, $requestClass)) {
throw new \RuntimeException('The request class '.$requestClass.' is not expected.');
}

$mockedResponse = $this->expectedResponses[$requestClass];

if ($mockedResponse instanceof SequenceMockResponse) {
$mockedResponse = $mockedResponse->pop();
}
$mockedResponse = $this->getResponse($requestClass);

return new Response(
$mockedResponse->createPsrResponse(),
Expand All @@ -46,6 +44,30 @@ public function sendRequest(PendingRequest $pendingRequest): Response
);
}

/**
* Get the mocked response and remove it from the expected responses.
*
* @param string $requestClass
* @return MockResponse
*/
private function getResponse(string $requestClass): MockResponse
{
$mockedResponse = Arr::get($this->expectedResponses, $requestClass);

if (!($mockedResponse instanceof SequenceMockResponse)) {
Arr::forget($this->expectedResponses, $requestClass);
return $mockedResponse;
}

$response = $mockedResponse->pop();

if ($mockedResponse->isEmpty()) {
Arr::forget($this->expectedResponses, $requestClass);
}

return $response;
}

/**
* {@inheritDoc}
*/
Expand Down
39 changes: 39 additions & 0 deletions tests/Http/Requests/CreatePaymentRequestTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace Tests\Http\Requests;

use Mollie\Api\Http\Payload\CreatePaymentPayload;
use Mollie\Api\Http\Payload\Money;
use Mollie\Api\Http\Query\CreatePaymentQuery;
use Mollie\Api\Http\Requests\CreatePaymentRequest;
use Mollie\Api\Http\Response;
use Mollie\Api\Resources\Payment;
use Tests\Fixtures\MockClient;
use Tests\Fixtures\MockResponse;
use Tests\TestCase;

class CreatePaymentRequestTest extends TestCase
{
/** @test */
public function it_can_create_payment()
{
$client = new MockClient([
CreatePaymentRequest::class => new MockResponse(201, 'payment'),
]);

$payload = new CreatePaymentPayload(
'Test payment',
new Money('EUR', '10.00'),
'https://example.org/redirect',
'https://example.org/webhook'
);

$request = new CreatePaymentRequest($payload);

/** @var Response */
$response = $client->send($request);

$this->assertTrue($response->successful());
$this->assertInstanceOf(Payment::class, $response->toResource());
}
}
65 changes: 65 additions & 0 deletions tests/Http/Requests/GetPaginatedPaymentsRequestTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace Tests\Http\Requests;

use Mollie\Api\Http\Requests\DynamicGetRequest;
use Mollie\Api\Http\Requests\GetPaginatedPaymentsRequest;
use Mollie\Api\Http\Response;
use Mollie\Api\Resources\LazyCollection;
use Mollie\Api\Resources\Payment;
use Mollie\Api\Resources\PaymentCollection;
use Tests\Fixtures\MockClient;
use Tests\Fixtures\MockResponse;
use Tests\TestCase;

class GetPaginatedPaymentsRequestTest extends TestCase
{
/** @test */
public function it_can_get_paginated_payments()
{
$client = new MockClient([
GetPaginatedPaymentsRequest::class => new MockResponse(200, 'payment-list'),
]);

$request = new GetPaginatedPaymentsRequest();

/** @var Response */
$response = $client->send($request);

$this->assertTrue($response->successful());

/** @var PaymentCollection */
$payments = $response->toResource();
// Assert response was properly handled
$this->assertInstanceOf(PaymentCollection::class, $payments);
$this->assertGreaterThan(0, $payments->count());

foreach ($payments as $payment) {
$this->assertInstanceOf(Payment::class, $payment);
$this->assertEquals('payment', $payment->resource);
}
}

/** @test */
public function it_can_iterate_over_payments()
{
$client = new MockClient([
GetPaginatedPaymentsRequest::class => new MockResponse(200, 'payment-list'),
DynamicGetRequest::class => new MockResponse(200, 'payment-list'),

Check failure on line 48 in tests/Http/Requests/GetPaginatedPaymentsRequestTest.php

View workflow job for this annotation

GitHub Actions / PHP - 7.4

Array has 2 duplicate keys with value 'Mollie\\Api\\Http\\Requests\\DynamicGetRequest' (\Mollie\Api\Http\Requests\DynamicGetRequest::class, \Mollie\Api\Http\Requests\DynamicGetRequest::class).

Check failure on line 48 in tests/Http/Requests/GetPaginatedPaymentsRequestTest.php

View workflow job for this annotation

GitHub Actions / PHP - 8

Array has 2 duplicate keys with value 'Mollie\\Api\\Http\\Requests\\DynamicGetRequest' (\Mollie\Api\Http\Requests\DynamicGetRequest::class, \Mollie\Api\Http\Requests\DynamicGetRequest::class).

Check failure on line 48 in tests/Http/Requests/GetPaginatedPaymentsRequestTest.php

View workflow job for this annotation

GitHub Actions / PHP - 8.1

Array has 2 duplicate keys with value 'Mollie\\Api\\Http\\Requests\\DynamicGetRequest' (\Mollie\Api\Http\Requests\DynamicGetRequest::class, \Mollie\Api\Http\Requests\DynamicGetRequest::class).

Check failure on line 48 in tests/Http/Requests/GetPaginatedPaymentsRequestTest.php

View workflow job for this annotation

GitHub Actions / PHP - 8.2

Array has 2 duplicate keys with value 'Mollie\\Api\\Http\\Requests\\DynamicGetRequest' (\Mollie\Api\Http\Requests\DynamicGetRequest::class, \Mollie\Api\Http\Requests\DynamicGetRequest::class).

Check failure on line 48 in tests/Http/Requests/GetPaginatedPaymentsRequestTest.php

View workflow job for this annotation

GitHub Actions / PHP - 8.3

Array has 2 duplicate keys with value 'Mollie\\Api\\Http\\Requests\\DynamicGetRequest' (\Mollie\Api\Http\Requests\DynamicGetRequest::class, \Mollie\Api\Http\Requests\DynamicGetRequest::class).
DynamicGetRequest::class => new MockResponse(200, 'empty-list', 'payments'),
]);

$request = (new GetPaginatedPaymentsRequest())->useIterator();

/** @var Response */
$response = $client->send($request);
$this->assertTrue($response->successful());

/** @var LazyCollection */
$payments = $response->toResource();

foreach ($payments as $payment) {
$this->assertInstanceOf(Payment::class, $payment);
}
}
}
Loading

0 comments on commit 2a21c70

Please sign in to comment.