Skip to content

Commit

Permalink
Merge f97dfe2 into 46e010b
Browse files Browse the repository at this point in the history
  • Loading branch information
OndraM committed Nov 16, 2017
2 parents 46e010b + f97dfe2 commit cd8110c
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 24 deletions.
9 changes: 6 additions & 3 deletions src/Exception/InvalidDomainModelArgumentException.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,18 @@ public static function forInconsistentNumberOfCommands(
public static function forInconsistentNumbersOfCommandProperties(
int $numberOfCommands,
$numberOfSuccessfulCommands,
$numberOfFailedCommands
$numberOfFailedCommands,
$numberOfSkippedCommands
): self {
return new self(
sprintf(
'Provided numberOfCommands (%d) is inconsistent with provided sum of '
. 'numberOfSuccessfulCommands (%d) and numberOfFailedCommands (%d)',
. 'numberOfSuccessfulCommands (%d) + numberOfFailedCommands (%d)'
. ' + numberOfSkippedCommands (%d)',
$numberOfCommands,
$numberOfSuccessfulCommands,
$numberOfFailedCommands
$numberOfFailedCommands,
$numberOfSkippedCommands
)
);
}
Expand Down
10 changes: 10 additions & 0 deletions src/Exception/ResponseDecodingException.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,14 @@ public static function forJsonError(string $jsonErrorMsg, ResponseInterface $res
)
);
}

public static function forInvalidData(ResponseInterface $response): self
{
return new self(
sprintf(
"Error decoding Matej response: required data missing.\n\nBody:\n%s",
$response->getBody()
)
);
}
}
2 changes: 1 addition & 1 deletion src/Http/Plugin/ExceptionPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ private function transformResponseToException(RequestInterface $request, Respons
throw AuthorizationException::fromRequestAndResponse($request, $response);
}

if ($responseCode >= 401 && $responseCode < 600) {
if ($responseCode >= 400 && $responseCode < 600) {
// TODO: use more specific exceptions
throw new RequestException($response->getReasonPhrase(), $request, $response);
}
Expand Down
19 changes: 19 additions & 0 deletions src/Http/ResponseDecoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,30 @@ public function decode(ResponseInterface $httpResponse): Response
throw ResponseDecodingException::forJsonError(json_last_error_msg(), $httpResponse);
}

if (!$this->isResponseValid($responseData)) {
throw ResponseDecodingException::forInvalidData($httpResponse);
}

return new Response(
(int) $responseData->commands->number_of_commands,
(int) $responseData->commands->number_of_successful_commands,
(int) $responseData->commands->number_of_failed_commands,
(int) $responseData->commands->number_of_skipped_commands,
$responseData->commands->responses
);
}

private function isResponseValid(\stdClass $responseData): bool
{
return isset(
$responseData->commands,
$responseData->commands->number_of_commands,
$responseData->commands->number_of_successful_commands,
$responseData->commands->number_of_failed_commands,
$responseData->commands->number_of_skipped_commands,
$responseData->commands->responses,
$responseData->message,
$responseData->status
);
}
}
17 changes: 15 additions & 2 deletions src/Model/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,20 @@ class Response
private $numberOfSuccessfulCommands;
/** @var int */
private $numberOfFailedCommands;
/** @var int */
private $numberOfSkippedCommands;

public function __construct(
int $numberOfCommands,
int $numberOfSuccessfulCommands,
int $numberOfFailedCommands,
int $numberOfSkippedCommands,
array $commandResponses = []
) {
$this->numberOfCommands = $numberOfCommands;
$this->numberOfSuccessfulCommands = $numberOfSuccessfulCommands;
$this->numberOfFailedCommands = $numberOfFailedCommands;
$this->numberOfSkippedCommands = $numberOfSkippedCommands;

foreach ($commandResponses as $rawCommandResponse) {
$this->commandResponses[] = CommandResponse::createFromRawCommandResponseObject($rawCommandResponse);
Expand All @@ -36,11 +40,15 @@ public function __construct(
);
}

if ($this->numberOfCommands !== ($this->numberOfSuccessfulCommands + $this->numberOfFailedCommands)) {
$commandSum = $this->numberOfSuccessfulCommands + $this->numberOfFailedCommands
+ $this->numberOfSkippedCommands;

if ($this->numberOfCommands !== $commandSum) {
throw InvalidDomainModelArgumentException::forInconsistentNumbersOfCommandProperties(
$this->numberOfCommands,
$this->numberOfSuccessfulCommands,
$this->numberOfFailedCommands
$this->numberOfFailedCommands,
$this->numberOfSkippedCommands
);
}
}
Expand All @@ -60,6 +68,11 @@ public function getNumberOfFailedCommands(): int
return $this->numberOfFailedCommands;
}

public function getNumberOfSkippedCommands(): int
{
return $this->numberOfSkippedCommands;
}

/**
* Each Command which was part of request batch has here corresponding CommandResponse - on the same index on which
* the Command was added to the request batch.
Expand Down
5 changes: 5 additions & 0 deletions tests/Http/Fixtures/invalid-response-format.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"invalid": [],
"message": "",
"status": "OK"
}
1 change: 1 addition & 0 deletions tests/Http/Fixtures/response-item-properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"commands": {
"number_of_commands": 3,
"number_of_failed_commands": 1,
"number_of_skipped_commands": 0,
"number_of_successful_commands": 2,
"responses": [
{
Expand Down
1 change: 1 addition & 0 deletions tests/Http/Fixtures/response-one-successful-command.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"commands": {
"number_of_commands": 1,
"number_of_failed_commands": 0,
"number_of_skipped_commands": 0,
"number_of_successful_commands": 1,
"responses": [
{
Expand Down
4 changes: 1 addition & 3 deletions tests/Http/Plugin/ExceptionPluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ public function provideSuccessStatusCodes(): array
return [
'HTTP 200' => [StatusCodeInterface::STATUS_OK],
'HTTP 201' => [StatusCodeInterface::STATUS_CREATED],
'HTTP 400 (batch was successfully executed, but all commands were rejected)' => [
StatusCodeInterface::STATUS_BAD_REQUEST,
],
];
}

Expand Down Expand Up @@ -75,6 +72,7 @@ public function shouldThrowExceptionBasedOnStatusCode(int $statusCode, string $e
public function provideErrorStatusCodes(): array
{
return [
'HTTP 401' => [StatusCodeInterface::STATUS_BAD_REQUEST, AuthorizationException::class],
'HTTP 401' => [StatusCodeInterface::STATUS_UNAUTHORIZED, AuthorizationException::class],
'HTTP 404' => [StatusCodeInterface::STATUS_NOT_FOUND, RequestException::class],
'HTTP 500' => [StatusCodeInterface::STATUS_INTERNAL_SERVER_ERROR, RequestException::class],
Expand Down
14 changes: 14 additions & 0 deletions tests/Http/ResponseDecoderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public function shouldDecodeSimpleOkResponse(): void
$this->assertSame(1, $output->getNumberOfCommands());
$this->assertSame(1, $output->getNumberOfSuccessfulCommands());
$this->assertSame(0, $output->getNumberOfFailedCommands());
$this->assertSame(0, $output->getNumberOfSkippedCommands());

$commandResponses = $output->getCommandResponses();
$this->assertCount(1, $commandResponses);
Expand All @@ -48,6 +49,7 @@ public function shouldDecodeResponseMultipleResponses(): void
$this->assertSame(3, $output->getNumberOfCommands());
$this->assertSame(2, $output->getNumberOfSuccessfulCommands());
$this->assertSame(1, $output->getNumberOfFailedCommands());
$this->assertSame(0, $output->getNumberOfSkippedCommands());

$commandResponses = $output->getCommandResponses();
$this->assertCount(3, $commandResponses);
Expand All @@ -70,6 +72,18 @@ public function shouldThrowExceptionWhenDecodingFails(): void
$this->decoder->decode($response);
}

/** @test */
public function shouldThrowExceptionWhenJsonWithInvalidDataIsDecoded(): void
{
$notJsonData = file_get_contents(__DIR__ . '/Fixtures/invalid-response-format.json');
$response = new Response(StatusCodeInterface::STATUS_NOT_FOUND, [], $notJsonData);

$this->expectException(ResponseDecodingException::class);
$this->expectExceptionMessage('Error decoding Matej response: required data missing.');
$this->expectExceptionMessage('"invalid": [],');
$this->decoder->decode($response);
}

private function createJsonResponseFromFile(string $fileName): ResponseInterface
{
$jsonData = file_get_contents($fileName);
Expand Down
41 changes: 26 additions & 15 deletions tests/Model/ResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,23 @@ class ResponseTest extends TestCase
*/
public function shouldBeInstantiable(
int $numberOfCommands,
int $numberOfSuccessfulCommands,
int $numberOfFailedCommands,
int $numberOfSuccessful,
int $numberOfFailed,
int $numberOfSkipped,
array $commandResponses
): void {
$response = new Response(
$numberOfCommands,
$numberOfSuccessfulCommands,
$numberOfFailedCommands,
$numberOfSuccessful,
$numberOfFailed,
$numberOfSkipped,
$commandResponses
);

$this->assertSame($numberOfCommands, $response->getNumberOfCommands());
$this->assertSame($numberOfSuccessfulCommands, $response->getNumberOfSuccessfulCommands());
$this->assertSame($numberOfFailedCommands, $response->getNumberOfFailedCommands());
$this->assertSame($numberOfSuccessful, $response->getNumberOfSuccessfulCommands());
$this->assertSame($numberOfFailed, $response->getNumberOfFailedCommands());
$this->assertSame($numberOfSkipped, $response->getNumberOfSkippedCommands());

$this->assertContainsOnlyInstancesOf(CommandResponse::class, $response->getCommandResponses());
$this->assertCount(count($commandResponses), $response->getCommandResponses());
Expand All @@ -40,19 +43,23 @@ public function provideResponseData(): array
{
$okCommandResponse = (object) ['status' => CommandResponse::STATUS_OK, 'message' => '', 'data' => []];
$failedCommandResponse = (object) ['status' => CommandResponse::STATUS_ERROR, 'message' => 'KO', 'data' => []];
$skippedCommandResponse = (object) ['status' => CommandResponse::STATUS_SKIPPED, 'message' => '', 'data' => []];

return [
'empty response data' => [0, 0, 0, []],
'multiple successful commands' => [2, 2, 0, [$okCommandResponse, $okCommandResponse]],
'multiple failed commands' => [2, 0, 2, [$failedCommandResponse, $failedCommandResponse]],
'multiple failed and successful commands' => [
4,
'empty response data' => [0, 0, 0, 0, []],
'multiple successful commands' => [2, 2, 0, 0, [$okCommandResponse, $okCommandResponse]],
'multiple failed commands' => [2, 0, 2, 0, [$failedCommandResponse, $failedCommandResponse]],
'multiple skipped commands' => [2, 0, 0, 2, [$skippedCommandResponse, $skippedCommandResponse]],
'multiple successful , failed and skipped commands' => [
5,
2,
2,
1,
[
$failedCommandResponse,
$okCommandResponse,
$okCommandResponse,
$skippedCommandResponse,
$failedCommandResponse,
],
],
Expand All @@ -65,15 +72,16 @@ public function provideResponseData(): array
*/
public function shouldThrowExceptionWhenInconsistentDataProvided(
int $numberOfCommands,
int $numberOfSuccessfulCommands,
int $numberOfFailedCommands,
int $numberOfSuccessful,
int $numberOfFailed,
int $numberOfSkipped,
array $commandResponses,
string $expectedExceptionMessage
): void {
$this->expectException(InvalidDomainModelArgumentException::class);
$this->expectExceptionMessage($expectedExceptionMessage);

new Response($numberOfCommands, $numberOfSuccessfulCommands, $numberOfFailedCommands, $commandResponses);
new Response($numberOfCommands, $numberOfSuccessful, $numberOfFailed, $numberOfSkipped, $commandResponses);
}

/**
Expand All @@ -88,23 +96,26 @@ public function provideInconsistentData(): array
5,
0,
0,
0,
[],
'Provided numberOfCommands (5) is inconsistent with actual count of command responses (0)',
],
'numberOfCommands is less than command responses count' => [
0,
0,
0,
0,
[$commandResponse, $commandResponse],
'Provided numberOfCommands (0) is inconsistent with actual count of command responses (2)',
],
'numberOfCommands does not match sum of successful and failed numbers' => [
2,
2,
1,
1,
[$commandResponse, $commandResponse],
'Provided numberOfCommands (2) is inconsistent with provided sum of numberOfSuccessfulCommands (2)'
. ' and numberOfFailedCommands (1)',
. ' + numberOfFailedCommands (1) + numberOfSkippedCommands (1)',
],
];
}
Expand Down

0 comments on commit cd8110c

Please sign in to comment.