Skip to content

Commit

Permalink
feat: add MockResponse::resource() feature
Browse files Browse the repository at this point in the history
  • Loading branch information
Naoray committed Feb 18, 2025
1 parent 29c6212 commit f8e0974
Show file tree
Hide file tree
Showing 5 changed files with 392 additions and 3 deletions.
5 changes: 3 additions & 2 deletions src/Fake/ListResponseBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,13 @@ public function create(): MockResponse
{
$contents = FakeResponseLoader::load('empty-list');

$contents = str_replace('{{ RESOURCE_ID }}', $this->collectionClass::$collectionName, $contents);
$collectionKey = $this->collectionClass::$collectionName;
$contents = str_replace('{{ RESOURCE_ID }}', $collectionKey, $contents);

$data = json_decode($contents, true);

$data['count'] = count($this->items);
$data['_embedded'][$this->collectionClass::$collectionName] = $this->items;
$data['_embedded'][$collectionKey] = $this->items;

return new MockResponse($data);
}
Expand Down
7 changes: 6 additions & 1 deletion src/Fake/MockResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,16 @@ public static function unprocessableEntity($body = [], string $resourceKey = '')
return new self($body, 422, $resourceKey);
}

public static function list(string $resourceKey = ''): ListResponseBuilder
public static function list(string $resourceKey): ListResponseBuilder
{
return new ListResponseBuilder($resourceKey);
}

public static function resource(string $resourceKey): ResourceResponseBuilder
{
return new ResourceResponseBuilder($resourceKey);
}

public function createPsrResponse(): ResponseInterface
{
$psrResponse = $this
Expand Down
104 changes: 104 additions & 0 deletions src/Fake/ResourceResponseBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php

namespace Mollie\Api\Fake;

use Mollie\Api\Exceptions\LogicException;
use Mollie\Api\Resources\BaseResource;
use Mollie\Api\Traits\ForwardsCalls;

/**
* Builder for creating mock responses for Mollie API resources.
*
* @method self embed(string $collectionClass) Embed a collection of resources into the response
*/
class ResourceResponseBuilder
{
use ForwardsCalls;

private string $resourceClass;

private array $data = [];

/** @var array<string, ListResponseBuilder> */
private array $embeddedBuilders = [];

/** @var ?string */
private ?string $currentEmbedKey = null;

public function __construct(string $resourceClass)
{
if (! is_subclass_of($resourceClass, BaseResource::class)) {
throw new LogicException('Resource class must be a subclass of ' . BaseResource::class);
}

$this->resourceClass = $resourceClass;
}

/**
* Set the resource data.
*/
public function with(array $data): self
{
$this->data = $data;

return $this;
}

/**
* Create the mock response with the resource data and any embedded collections.
*/
public function create(): MockResponse
{
$data = $this->data;
$data['_embedded'] = [];

foreach ($this->embeddedBuilders as $key => $builder) {
$embeddedResponse = $builder->create();
$embeddedData = $embeddedResponse->json();

$data['_embedded'] = array_merge($data['_embedded'], $embeddedData['_embedded']);
}

if (empty($data['_embedded'])) {
unset($data['_embedded']);
}

// add standard links
if (empty($data['_links'])) {
$data['_links'] = [
'self' => [
'href' => '...',
'type' => 'application/hal+json',
],
'documentation' => [
'href' => '...',
'type' => 'text/html',
],
];
}

return new MockResponse($data);
}

public function __call($method, $parameters)
{
if ($method === 'embed') {
/** @var string $collectionClass */
$collectionClass = $parameters[0];

if (!isset($this->embeddedBuilders[$collectionClass])) {
$this->embeddedBuilders[$collectionClass] = new ListResponseBuilder($collectionClass);
}

$this->currentEmbedKey = $collectionClass;

return $this;
}

if ($this->currentEmbedKey && isset($this->embeddedBuilders[$this->currentEmbedKey]) && method_exists($this->embeddedBuilders[$this->currentEmbedKey], $method)) {
return $this->forwardDecoratedCallTo($this->embeddedBuilders[$this->currentEmbedKey], $method, $parameters);
}

throw new \BadMethodCallException("Method {$method} does not exist.");
}
}
10 changes: 10 additions & 0 deletions tests/Fake/MockResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
namespace Tests\Fake;

use Mollie\Api\Fake\ListResponseBuilder;
use Mollie\Api\Fake\ResourceResponseBuilder;
use Mollie\Api\Fake\MockResponse;
use Mollie\Api\Resources\Payment;
use Mollie\Api\Resources\PaymentCollection;
use PHPUnit\Framework\TestCase;

Expand Down Expand Up @@ -56,4 +58,12 @@ public function list_returns_list_builder()

$this->assertInstanceOf(ListResponseBuilder::class, $response);
}

/** @test */
public function resource_returns_resource_builder()
{
$response = MockResponse::resource(Payment::class);

$this->assertInstanceOf(ResourceResponseBuilder::class, $response);
}
}
Loading

0 comments on commit f8e0974

Please sign in to comment.