Skip to content

Commit ffe0df3

Browse files
committed
BlackHoleService
1 parent 2bec6b4 commit ffe0df3

2 files changed

Lines changed: 200 additions & 0 deletions

File tree

src/Services/BlackHoleService.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Peso\Core\Services;
6+
7+
use Override;
8+
use Peso\Core\Exceptions\ConversionNotPerformedException;
9+
use Peso\Core\Exceptions\ExchangeRateNotFoundException;
10+
use Peso\Core\Exceptions\RequestNotSupportedException;
11+
use Peso\Core\Requests\CurrentConversionRequest;
12+
use Peso\Core\Requests\CurrentExchangeRateRequest;
13+
use Peso\Core\Requests\HistoricalConversionRequest;
14+
use Peso\Core\Requests\HistoricalExchangeRateRequest;
15+
use Peso\Core\Responses\ErrorResponse;
16+
17+
final readonly class BlackHoleService implements PesoServiceInterface
18+
{
19+
/**
20+
* @var array<class-string>
21+
*/
22+
private array $requests;
23+
24+
/**
25+
* @param class-string ...$requests
26+
*/
27+
public function __construct(string ...$requests)
28+
{
29+
$this->requests = $requests;
30+
}
31+
32+
#[Override]
33+
public function send(object $request): ErrorResponse
34+
{
35+
if ($this->requests !== [] && !\in_array($request::class, $this->requests)) {
36+
goto notSupported;
37+
}
38+
39+
if ($request instanceof CurrentExchangeRateRequest || $request instanceof HistoricalExchangeRateRequest) {
40+
return new ErrorResponse(ExchangeRateNotFoundException::fromRequest($request));
41+
}
42+
43+
if ($request instanceof CurrentConversionRequest || $request instanceof HistoricalConversionRequest) {
44+
return new ErrorResponse(ConversionNotPerformedException::fromRequest($request));
45+
}
46+
47+
notSupported:
48+
return new ErrorResponse(RequestNotSupportedException::fromRequest($request));
49+
}
50+
51+
#[Override]
52+
public function supports(object $request): bool
53+
{
54+
if ($this->requests !== [] && !\in_array($request::class, $this->requests)) {
55+
return false;
56+
}
57+
58+
// only standard requests
59+
return
60+
$request instanceof CurrentExchangeRateRequest ||
61+
$request instanceof HistoricalExchangeRateRequest ||
62+
$request instanceof CurrentConversionRequest ||
63+
$request instanceof HistoricalConversionRequest;
64+
}
65+
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Peso\Core\Tests\Services;
6+
7+
use Arokettu\Date\Date;
8+
use Peso\Core\Exceptions\ConversionNotPerformedException;
9+
use Peso\Core\Exceptions\ExchangeRateNotFoundException;
10+
use Peso\Core\Exceptions\RequestNotSupportedException;
11+
use Peso\Core\Requests\CurrentConversionRequest;
12+
use Peso\Core\Requests\CurrentExchangeRateRequest;
13+
use Peso\Core\Requests\HistoricalConversionRequest;
14+
use Peso\Core\Requests\HistoricalExchangeRateRequest;
15+
use Peso\Core\Responses\ErrorResponse;
16+
use Peso\Core\Services\BlackHoleService;
17+
use Peso\Core\Types\Decimal;
18+
use PHPUnit\Framework\TestCase;
19+
use stdClass;
20+
21+
final class BlackHoleServiceTest extends TestCase
22+
{
23+
public function testSupportsAllSupported(): void
24+
{
25+
$service = new BlackHoleService();
26+
27+
self::assertTrue($service->supports(new CurrentExchangeRateRequest('PHP', 'USD')));
28+
self::assertTrue($service->supports(new HistoricalExchangeRateRequest('PHP', 'USD', Date::today())));
29+
self::assertTrue($service->supports(new CurrentConversionRequest(Decimal::init(1), 'PHP', 'USD')));
30+
self::assertTrue($service->supports(
31+
new HistoricalConversionRequest(Decimal::init(1), 'PHP', 'USD', Date::today()),
32+
));
33+
34+
self::assertFalse($service->supports(new stdClass()));
35+
}
36+
37+
public function testSupportsLimited(): void
38+
{
39+
$service = new BlackHoleService(
40+
CurrentExchangeRateRequest::class,
41+
HistoricalConversionRequest::class,
42+
stdClass::class, // still not supported
43+
);
44+
45+
self::assertTrue($service->supports(new CurrentExchangeRateRequest('PHP', 'USD')));
46+
self::assertFalse($service->supports(new HistoricalExchangeRateRequest('PHP', 'USD', Date::today())));
47+
self::assertFalse($service->supports(new CurrentConversionRequest(Decimal::init(1), 'PHP', 'USD')));
48+
self::assertTrue($service->supports(
49+
new HistoricalConversionRequest(Decimal::init(1), 'PHP', 'USD', Date::today()),
50+
));
51+
52+
self::assertFalse($service->supports(new stdClass()));
53+
}
54+
55+
public function testReturnsAppropriateErrors(): void
56+
{
57+
$service = new BlackHoleService();
58+
$today = Date::today();
59+
60+
$response = $service->send(new CurrentExchangeRateRequest('PHP', 'USD'));
61+
self::assertInstanceOf(ErrorResponse::class, $response);
62+
self::assertInstanceOf(ExchangeRateNotFoundException::class, $response->exception);
63+
self::assertEquals('Unable to find exchange rate for PHP/USD', $response->exception->getMessage());
64+
65+
$response = $service->send(new HistoricalExchangeRateRequest('PHP', 'USD', $today));
66+
self::assertInstanceOf(ErrorResponse::class, $response);
67+
self::assertInstanceOf(ExchangeRateNotFoundException::class, $response->exception);
68+
self::assertEquals(
69+
'Unable to find exchange rate for PHP/USD on ' . $today->toString(),
70+
$response->exception->getMessage(),
71+
);
72+
73+
$response = $service->send(new CurrentConversionRequest(Decimal::init(1), 'PHP', 'USD'));
74+
self::assertInstanceOf(ErrorResponse::class, $response);
75+
self::assertInstanceOf(ConversionNotPerformedException::class, $response->exception);
76+
self::assertEquals('Unable to convert 1 PHP to USD', $response->exception->getMessage());
77+
78+
$response = $service->send(new HistoricalConversionRequest(Decimal::init(1), 'PHP', 'USD', $today));
79+
self::assertInstanceOf(ErrorResponse::class, $response);
80+
self::assertInstanceOf(ConversionNotPerformedException::class, $response->exception);
81+
self::assertEquals(
82+
'Unable to convert 1 PHP to USD on ' . $today->toString(),
83+
$response->exception->getMessage(),
84+
);
85+
86+
$response = $service->send(new stdClass());
87+
self::assertInstanceOf(ErrorResponse::class, $response);
88+
self::assertInstanceOf(RequestNotSupportedException::class, $response->exception);
89+
self::assertEquals('Unsupported request type: "stdClass"', $response->exception->getMessage());
90+
}
91+
92+
public function testReturnsAppropriateErrorsWhenLimited(): void
93+
{
94+
$service = new BlackHoleService(
95+
CurrentExchangeRateRequest::class,
96+
HistoricalConversionRequest::class,
97+
stdClass::class, // still not supported
98+
);
99+
$today = Date::today();
100+
101+
$response = $service->send(new CurrentExchangeRateRequest('PHP', 'USD'));
102+
self::assertInstanceOf(ErrorResponse::class, $response);
103+
self::assertInstanceOf(ExchangeRateNotFoundException::class, $response->exception);
104+
self::assertEquals('Unable to find exchange rate for PHP/USD', $response->exception->getMessage());
105+
106+
$response = $service->send(new HistoricalExchangeRateRequest('PHP', 'USD', $today));
107+
self::assertInstanceOf(ErrorResponse::class, $response);
108+
self::assertInstanceOf(RequestNotSupportedException::class, $response->exception);
109+
self::assertEquals(\sprintf(
110+
'Unsupported request type: "%s"',
111+
HistoricalExchangeRateRequest::class,
112+
), $response->exception->getMessage());
113+
114+
$response = $service->send(new CurrentConversionRequest(Decimal::init(1), 'PHP', 'USD'));
115+
self::assertInstanceOf(ErrorResponse::class, $response);
116+
self::assertInstanceOf(RequestNotSupportedException::class, $response->exception);
117+
self::assertEquals(\sprintf(
118+
'Unsupported request type: "%s"',
119+
CurrentConversionRequest::class,
120+
), $response->exception->getMessage());
121+
122+
$response = $service->send(new HistoricalConversionRequest(Decimal::init(1), 'PHP', 'USD',$today));
123+
self::assertInstanceOf(ErrorResponse::class, $response);
124+
self::assertInstanceOf(ConversionNotPerformedException::class, $response->exception);
125+
self::assertEquals(
126+
'Unable to convert 1 PHP to USD on ' . $today->toString(),
127+
$response->exception->getMessage(),
128+
);
129+
130+
$response = $service->send(new stdClass());
131+
self::assertInstanceOf(ErrorResponse::class, $response);
132+
self::assertInstanceOf(RequestNotSupportedException::class, $response->exception);
133+
self::assertEquals('Unsupported request type: "stdClass"', $response->exception->getMessage());
134+
}
135+
}

0 commit comments

Comments
 (0)