Skip to content

Commit

Permalink
Merge pull request #20 from swagger-mock/text-html-support
Browse files Browse the repository at this point in the history
#19 feature: support  of "text/html" response added
  • Loading branch information
strider2038 authored Oct 19, 2019
2 parents d8d2605 + e1c9e50 commit fe665b6
Show file tree
Hide file tree
Showing 11 changed files with 219 additions and 17 deletions.
12 changes: 11 additions & 1 deletion src/API/Responder.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
*/
class Responder
{
private const RAW_MEDIA_TYPES = [
'',
'text/html',
];

/** @var EncoderInterface */
private $encoder;

Expand Down Expand Up @@ -50,7 +55,7 @@ public function createResponse(int $statusCode, string $mediaType, $data): Respo

private function encodeDataByMediaType($data, string $mediaType): string
{
if (is_string($data) && '' === $mediaType) {
if ($this->isRawMediaType($data, $mediaType)) {
$encodedData = $data;
} else {
$format = $this->guessSerializationFormat($mediaType);
Expand Down Expand Up @@ -83,4 +88,9 @@ private function createHeaders(string $mediaType): array

return $headers;
}

private function isRawMediaType($data, string $mediaType): bool
{
return is_string($data) && in_array($mediaType, self::RAW_MEDIA_TYPES, true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class FakerStringGenerator implements ValueGeneratorInterface
'ipv4' => 'ipv4',
'ipv6' => 'ipv6',
'byte' => 'base64',
'html' => 'randomHtml',
];

/** @var Generator */
Expand Down
54 changes: 54 additions & 0 deletions src/OpenAPI/Parsing/MediaParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php
/*
* This file is part of Swagger Mock.
*
* (c) Igor Lazarev <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace App\OpenAPI\Parsing;

use App\Mock\Parameters\Schema\Schema;
use App\Mock\Parameters\Schema\Type\Primitive\StringType;
use App\OpenAPI\SpecificationObjectMarkerInterface;
use Psr\Log\LoggerInterface;

/**
* @author Igor Lazarev <[email protected]>
*/
class MediaParser
{
/** @var ParserInterface */
private $schemaParser;

/** @var LoggerInterface */
private $logger;

public function __construct(ParserInterface $schemaParser, LoggerInterface $logger)
{
$this->schemaParser = $schemaParser;
$this->logger = $logger;
}

public function parseMediaScheme(
SpecificationAccessor $specification,
SpecificationPointer $pointer,
string $mediaType
): SpecificationObjectMarkerInterface {
/** @var Schema $schema */
$schema = $this->schemaParser->parsePointedSchema($specification, $pointer);

if ('text/html' === $mediaType) {
if (!$schema->value instanceof StringType) {
$schema->value = new StringType();
$this->logger->warning('Only string types are supported for media type "text/html".');
}

$schema->value->format = 'html';
}

return $schema;
}
}
10 changes: 5 additions & 5 deletions src/OpenAPI/Parsing/ResponseParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,18 @@
*/
class ResponseParser implements ParserInterface
{
/** @var ParserInterface */
private $schemaParser;
/** @var MediaParser */
private $mediaParser;

/** @var ErrorHandlerInterface */
private $errorHandler;

/** @var LoggerInterface */
private $logger;

public function __construct(ParserInterface $schemaParser, ErrorHandlerInterface $errorHandler, LoggerInterface $logger)
public function __construct(MediaParser $mediaParser, ErrorHandlerInterface $errorHandler, LoggerInterface $logger)
{
$this->schemaParser = $schemaParser;
$this->mediaParser = $mediaParser;
$this->errorHandler = $errorHandler;
$this->logger = $logger;
}
Expand All @@ -45,7 +45,7 @@ public function parsePointedSchema(SpecificationAccessor $specification, Specifi

foreach ($mediaTypes as $mediaType) {
$mediaTypePointer = $contentPointer->withPathElement($mediaType);
$parsedSchema = $this->schemaParser->parsePointedSchema($specification, $mediaTypePointer);
$parsedSchema = $this->mediaParser->parseMediaScheme($specification, $mediaTypePointer, $mediaType);
$response->content->set($mediaType, $parsedSchema);

$this->logger->debug(
Expand Down
7 changes: 7 additions & 0 deletions tests/Acceptance/Features/html-response.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Feature: Html response

Scenario: GET /html | no parameters | 200 html page returned
Given I have OpenAPI specification file "html-response.yaml"
When I send a "GET" request to "/html"
Then the response status code should be 200
And I should see an "html" element
10 changes: 10 additions & 0 deletions tests/Resources/swagger-files/html-response.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
openapi: "3.0.0"
paths:
/html:
get:
responses:
200:
content:
text/html:
schema:
type: string
24 changes: 18 additions & 6 deletions tests/Unit/API/ResponderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,20 +85,32 @@ public function createResponse_statusCodeAndNotSupportedMediaTypeAndData_excepti
$this->expectException(NotSupportedException::class);
$this->expectExceptionMessage('Not supported media type');

$responder->createResponse(Response::HTTP_OK, 'text/html', self::DATA);
$responder->createResponse(Response::HTTP_OK, 'application/octet-stream', self::DATA);
}

/** @test */
public function createResponse_statusCodeAndNoMediaTypeAndStringData_rawResponseCreated(): void
{
/**
* @test
* @dataProvider mediaTypeProvider
*/
public function createResponse_statusCodeAndGivenMediaTypeAndStringData_rawResponseCreated(
string $mediaType
): void {
$responder = $this->creteResponder();
$this->givenEncoder_encode_returnsData(self::ENCODED_DATA);

$response = $responder->createResponse(Response::HTTP_NO_CONTENT, '', self::DATA);
$response = $responder->createResponse(Response::HTTP_NO_CONTENT, $mediaType, self::DATA);

$this->assertSame(Response::HTTP_NO_CONTENT, $response->getStatusCode());
$this->assertFalse($response->headers->has('Content-Type'));
$this->assertSame(self::DATA, $response->getContent());
if ('' === $mediaType) {
$this->assertFalse($response->headers->has('Content-Type'));
}
}

public function mediaTypeProvider(): \Iterator
{
yield 'no media' => [''];
yield 'text/html' => ['text/html'];
}

private function assertEncoder_encode_wasCalledOnceWithDataAndFormat(string $data, string $expectedEncodingFormat): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ public function formatAndFakerMethodProvider(): array
['hostname', 'domainName'],
['ipv4', 'ipv4'],
['ipv6', 'ipv6'],
['html', 'randomHtml'],
];
}

Expand Down
79 changes: 79 additions & 0 deletions tests/Unit/OpenAPI/Parsing/MediaParserTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php
/*
* This file is part of Swagger Mock.
*
* (c) Igor Lazarev <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace App\Tests\Unit\OpenAPI\Parsing;

use App\Mock\Parameters\Schema\Schema;
use App\Mock\Parameters\Schema\Type\Composite\ObjectType;
use App\Mock\Parameters\Schema\Type\Primitive\StringType;
use App\OpenAPI\Parsing\MediaParser;
use App\OpenAPI\Parsing\SpecificationAccessor;
use App\OpenAPI\Parsing\SpecificationPointer;
use App\Tests\Utility\TestCase\ParsingTestCaseTrait;
use PHPUnit\Framework\TestCase;
use Psr\Log\NullLogger;

/**
* @author Igor Lazarev <[email protected]>
*/
class MediaParserTest extends TestCase
{
use ParsingTestCaseTrait;

/** @test */
public function parseMediaScheme_usualScheme_schemeParsedAndReturnedWithoutChanges(): void
{
$parser = new MediaParser($this->internalParser, new NullLogger());
$specification = new SpecificationAccessor([]);
$pointer = new SpecificationPointer();
$expectedSchema = $this->givenInternalParser_parsePointedSchema_returnsObject();

$schema = $parser->parseMediaScheme($specification, $pointer, '');

$this->assertSame($expectedSchema, $schema);
$this->assertInternalParser_parsePointedSchema_wasCalledOnceWithSpecificationAndPointer($specification, $pointer);
}

/** @test */
public function parseMediaScheme_htmlSchemeAndStringSchema_htmlFormatIsSet(): void
{
$parser = new MediaParser($this->internalParser, new NullLogger());
$specification = new SpecificationAccessor([]);
$pointer = new SpecificationPointer();
$expectedSchema = new Schema();
$expectedSchema->value = new StringType();
$this->givenInternalParser_parsePointedSchema_returns($expectedSchema);

/** @var Schema $schema */
$schema = $parser->parseMediaScheme($specification, $pointer, 'text/html');

$this->assertSame($expectedSchema, $schema);
$this->assertSame('html', $schema->value->format);
$this->assertInternalParser_parsePointedSchema_wasCalledOnceWithSpecificationAndPointer($specification, $pointer);
}

/** @test */
public function parseMediaScheme_htmlSchemeAndObjectSchema_stringSchemaWithHtmlFormatIsSet(): void
{
$parser = new MediaParser($this->internalParser, new NullLogger());
$specification = new SpecificationAccessor([]);
$pointer = new SpecificationPointer();
$expectedSchema = new Schema();
$expectedSchema->value = new ObjectType();
$this->givenInternalParser_parsePointedSchema_returns($expectedSchema);

/** @var Schema $schema */
$schema = $parser->parseMediaScheme($specification, $pointer, 'text/html');

$this->assertInstanceOf(StringType::class, $schema->value);
$this->assertSame('html', $schema->value->format);
$this->assertInternalParser_parsePointedSchema_wasCalledOnceWithSpecificationAndPointer($specification, $pointer);
}
}
37 changes: 32 additions & 5 deletions tests/Unit/OpenAPI/Parsing/ResponseParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@

use App\Mock\Parameters\MockResponse;
use App\Mock\Parameters\Schema\Schema;
use App\OpenAPI\Parsing\MediaParser;
use App\OpenAPI\Parsing\ResponseParser;
use App\OpenAPI\Parsing\SpecificationAccessor;
use App\OpenAPI\Parsing\SpecificationPointer;
use App\OpenAPI\SpecificationObjectMarkerInterface;
use App\Tests\Utility\TestCase\ParsingTestCaseTrait;
use PHPUnit\Framework\Assert;
use PHPUnit\Framework\TestCase;
use Psr\Log\NullLogger;

Expand All @@ -32,25 +35,29 @@ class ResponseParserTest extends TestCase
];
private const CONTEXT_PATH = ['content', self::MEDIA_TYPE];

/** @var MediaParser */
private $mediaParser;

protected function setUp(): void
{
$this->setUpParsingContext();
$this->mediaParser = \Phake::mock(MediaParser::class);
}

/** @test */
public function parsePointedSchema_validResponseSpecification_mockResponseCreatedAndReturned(): void
{
$parser = $this->createResponseParser();
$expectedSchema = new Schema();
$this->givenInternalParser_parsePointedSchema_returns($expectedSchema);
$this->givenMediaParser_parseMediaScheme_returns($expectedSchema);
$specification = new SpecificationAccessor(self::VALID_RESPONSE_SPECIFICATION);

/** @var MockResponse $response */
$response = $parser->parsePointedSchema($specification, new SpecificationPointer());

$this->assertInternalParser_parsePointedSchema_wasCalledOnceWithSpecificationAndPointerPath(
$this->assertMediaParser_parseMediaScheme_wasCalledOnceWithSpecificationAndPointerPathAndMediaType(
$specification,
self::CONTEXT_PATH
self::CONTEXT_PATH,
self::MEDIA_TYPE
);
$this->assertResponseHasValidContentWithExpectedSchema($response, $expectedSchema);
}
Expand Down Expand Up @@ -91,8 +98,28 @@ private function assertResponseHasValidContentWithExpectedSchema(MockResponse $r
$this->assertSame([self::MEDIA_TYPE], $response->content->getKeys());
}

private function assertMediaParser_parseMediaScheme_wasCalledOnceWithSpecificationAndPointerPathAndMediaType(
SpecificationAccessor $specification,
array $path,
string $mediaType
): void {
/* @var SpecificationPointer $pointer */
\Phake::verify($this->mediaParser)
->parseMediaScheme($specification, \Phake::capture($pointer), $mediaType);
Assert::assertSame($path, $pointer->getPathElements());
}

private function givenMediaParser_parseMediaScheme_returns(SpecificationObjectMarkerInterface ...$objects): void
{
$parser = \Phake::when($this->mediaParser)->parseMediaScheme(\Phake::anyParameters());

foreach ($objects as $object) {
$parser = $parser->thenReturn($object);
}
}

private function createResponseParser(): ResponseParser
{
return new ResponseParser($this->internalParser, $this->errorHandler, new NullLogger());
return new ResponseParser($this->mediaParser, $this->errorHandler, new NullLogger());
}
}
1 change: 1 addition & 0 deletions tests/Utility/TestCase/ParsingTestCaseTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ trait ParsingTestCaseTrait
/** @var UrlMatcherFactory */
protected $urlMatcherFactory;

/** @before */
protected function setUpParsingContext(): void
{
$this->internalParser = \Phake::mock(ParserInterface::class);
Expand Down

0 comments on commit fe665b6

Please sign in to comment.