<?php
declare(strict_types=1);
namespace App\Tests\Support\Helper;
use Codeception\Module\REST;
use Codeception\Util\JsonType;
class ApiPlatform extends REST
{
protected array $config = ['base_path' => ''];
public function _beforeSuite(array $settings = []): void
{
JsonType::addCustomFilter('path', function ($value) {
return preg_match('@^'.$this->getBasePath().'(?:/\w+)*$@', $value);
});
}
public function sendPatch(string $url, $params = [], array $files = []): ?string
{
$this->haveHttpHeader('Content-Type', 'application/merge-patch+json');
return parent::sendPatch($url, $params, $files);
}
public function sendPost(string $url, $params = [], array $files = []): ?string
{
$this->haveHttpHeader('Content-Type', 'application/ld+json');
return parent::sendPost($url, $params, $files);
}
public function sendPut(string $url, $params = [], array $files = []): ?string
{
$this->haveHttpHeader('Content-Type', 'application/ld+json');
return parent::sendPut($url, $params, $files);
}
protected function getBasePath(): string
{
return $this->_getConfig('base_path');
}
protected static function arrayAsJsonString(array $json): string
{
return json_encode($json, JSON_UNESCAPED_SLASHES);
}
protected function getShortClassName(string $className): ?string
{
try {
return (new \ReflectionClass($className))->getShortName();
} catch (\ReflectionException) {
$this->fail('Unable to get short class name from fully qualified class name '.$className);
return null;
}
}
protected static function getJsonLdPropertiesTypes(array $propertiesTypes): array
{
return array_merge([
'@context' => 'string:path',
'@id' => 'string:path',
'@type' => 'string',
], $propertiesTypes);
}
public function seeResponseIsAnEntity(string $className, string $entityPath): void
{
$entityName = $this->getShortClassName($className);
$this->seeResponseContainsJson([
'@context' => $this->getBasePath().'/contexts/'.$entityName,
'@type' => $entityName,
'@id' => $entityPath,
]);
}
public function seeResponseIsAnItem(array $propertiesTypes, array $values = []): void
{
$jsonResponse = $this->grabJsonResponse();
$jsonLdPropertiesTypes = self::getJsonLdPropertiesTypes($propertiesTypes);
$this->seeResponseMatchesJsonType($jsonLdPropertiesTypes);
foreach ($jsonLdPropertiesTypes as $property => $type) {
self::assertArrayHasKey($property, $jsonResponse, 'property '.$property.' not found in '.self::arrayAsJsonString($jsonResponse));
if (isset($values[$property])) {
self::assertSame($values[$property], $jsonResponse[$property]);
}
}
foreach ($jsonResponse as $property => $value) {
self::assertArrayHasKey($property, $jsonLdPropertiesTypes, 'property '.$property.' not expected in '.self::arrayAsJsonString($jsonResponse));
}
foreach ($values as $property => $value) {
self::assertArrayHasKey($property, $jsonResponse, 'property '.$property.' expected in '.self::arrayAsJsonString($jsonResponse));
}
}
public function seeResponseIsACollection(string $className, string $collectionPath, array $propertiesTypes = []): void
{
$entityName = $this->getShortClassName($className);
$this->seeResponseMatchesJsonType(self::getJsonLdPropertiesTypes($propertiesTypes));
$this->seeResponseContainsJson([
'@context' => $this->getBasePath().'/contexts/'.$entityName,
'@type' => 'Collection',
'@id' => $collectionPath,
]);
}
public function grabJsonResponse(): ?array
{
try {
return $this->grabDataFromResponseByJsonPath('$')[0];
} catch (\Exception) {
$this->fail('Response is not JSON');
return null;
}
}
}