View source
<?php
namespace Drupal\Tests\graphql\Traits;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Render\RenderContext;
use Drupal\Core\Render\RendererInterface;
use Drupal\graphql\GraphQL\Execution\ExecutionResult;
use GraphQL\Server\OperationParams;
trait QueryResultAssertionTrait {
protected $server;
protected $renderer;
protected abstract function defaultCacheMaxAge();
protected abstract function defaultCacheTags();
protected abstract function defaultCacheContexts();
protected function defaultCacheMetaData() {
$metadata = new CacheableMetadata();
$metadata
->setCacheMaxAge($this
->defaultCacheMaxAge());
$metadata
->setCacheTags($this
->defaultCacheTags());
$metadata
->setCacheContexts($this
->defaultCacheContexts());
return $metadata;
}
protected function defaultMutationCacheMetaData() {
$metadata = new CacheableMetadata();
$metadata
->setCacheMaxAge(0);
$metadata
->setCacheTags($this
->defaultCacheTags());
$metadata
->setCacheContexts($this
->defaultCacheContexts());
return $metadata;
}
protected function assertResults($query, array $variables, array $expected, CacheableMetadata $metadata = NULL) : void {
$context = new RenderContext();
$result = $this
->getRenderer()
->executeInRenderContext($context, function () use ($query, $variables) {
return $this->server
->executeOperation(OperationParams::create([
'query' => $query,
'variables' => $variables,
]));
});
$this
->assertResultErrors($result, []);
$this
->assertResultData($result, $expected);
$this
->assertResultMetadata($result, $metadata ?: $this
->defaultCacheMetaData());
self::assertTrue($context
->isEmpty(), "Metadata was leaked during operation execution: {$context->serialize()}");
}
protected function assertErrors($query, array $variables, $expected, CacheableMetadata $metadata) : void {
$context = new RenderContext();
$result = $this
->getRenderer()
->executeInRenderContext($context, function () use ($query, $variables) {
return $this->server
->executeOperation(OperationParams::create([
'query' => $query,
'variables' => $variables,
]));
});
$this
->assertResultErrors($result, $expected);
$this
->assertResultMetadata($result, $metadata);
self::assertTrue($context
->isEmpty(), "Metadata was leaked during operation execution: {$context->serialize()}");
}
private function assertResultData(ExecutionResult $result, $expected) : void {
$data = $result
->toArray();
$this
->assertArrayHasKey('data', $data, 'No result data.');
$this
->assertEquals($expected, $data['data'], 'Unexpected query result.');
}
private function assertResultErrors(ExecutionResult $result, array $expected) : void {
$unexpected = [];
$matchCount = array_fill_keys($expected, 0);
foreach ($result->errors as $error) {
$error_message = $error
->getMessage();
$match = FALSE;
foreach ($expected as $pattern) {
if (@preg_match($pattern, $error_message) === FALSE) {
$match = $match || $pattern == $error_message;
$matchCount[$pattern]++;
}
else {
$match = $match || preg_match($pattern, $error_message);
$matchCount[$pattern]++;
}
}
if (!$match) {
$original_error = $error;
while ($original_error
->getPrevious() !== NULL) {
$original_error = $original_error
->getPrevious();
}
$unexpected[] = "Error message: {$error_message}\n Originated in: {$original_error->getFile()}:{$original_error->getLine()}";
}
}
$missing = array_keys(array_filter($matchCount, function ($count) {
return $count == 0;
}));
self::assertEmpty($missing, "Missing errors:\n* " . implode("\n* ", $missing));
self::assertEmpty($unexpected, "Unexpected errors:\n* " . implode("\n* ", $unexpected));
}
private function assertResultMetadata(ExecutionResult $result, CacheableMetadata $expected) : void {
$this
->assertEquals($expected
->getCacheMaxAge(), $result
->getCacheMaxAge(), 'Unexpected cache max age.');
$missingContexts = array_diff($expected
->getCacheContexts(), $result
->getCacheContexts());
$this
->assertEmpty($missingContexts, 'Missing cache contexts: ' . implode(', ', $missingContexts));
$unexpectedContexts = array_diff($result
->getCacheContexts(), $expected
->getCacheContexts());
$this
->assertEmpty($unexpectedContexts, 'Unexpected cache contexts: ' . implode(', ', $unexpectedContexts));
$missingTags = array_diff($expected
->getCacheTags(), $result
->getCacheTags());
$this
->assertEmpty($missingTags, 'Missing cache tags: ' . implode(', ', $missingTags));
$unexpectedTags = array_diff($result
->getCacheTags(), $expected
->getCacheTags());
$this
->assertEmpty($unexpectedTags, 'Unexpected cache tags: ' . implode(', ', $unexpectedTags));
}
private function getRenderer() : RendererInterface {
if (!isset($this->renderer)) {
$this->renderer = \Drupal::service('renderer');
}
return $this->renderer;
}
}