Skip to content

Commit cfb6031

Browse files
Kingdutchklausi
authored andcommitted
tests(assertions): Implement leaked metadata detection for QueryResultAssertionTrait (drupal-graphql#1207)
This adds detection of leaked cacheability metadata to assertResults and assertErrors in the QueryResultAssertionTrait. The context is serialized in the error message because this is always possible and while serialized content isn't the most readable it provides the most robust method of easily showing what metadata was leaked. Fixes drupal-graphql#1206
1 parent 699a479 commit cfb6031

1 file changed

Lines changed: 47 additions & 10 deletions

File tree

tests/src/Traits/QueryResultAssertionTrait.php

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace Drupal\Tests\graphql\Traits;
44

55
use Drupal\Core\Cache\CacheableMetadata;
6+
use Drupal\Core\Render\RenderContext;
7+
use Drupal\Core\Render\RendererInterface;
68
use Drupal\graphql\GraphQL\Execution\ExecutionResult;
79
use GraphQL\Server\OperationParams;
810

@@ -16,6 +18,11 @@ trait QueryResultAssertionTrait {
1618
*/
1719
protected $server;
1820

21+
/**
22+
* @var \Drupal\Core\Render\RendererInterface
23+
*/
24+
protected $renderer;
25+
1926
/**
2027
* Return the default cache max age for this test case.
2128
*
@@ -81,16 +88,23 @@ protected function defaultMutationCacheMetaData() {
8188
* The expected cache metadata object.
8289
*/
8390
protected function assertResults($query, array $variables, array $expected, CacheableMetadata $metadata = NULL): void {
84-
$result = $this->server->executeOperation(
85-
OperationParams::create([
86-
'query' => $query,
87-
'variables' => $variables,
88-
])
91+
$context = new RenderContext();
92+
$result = $this->getRenderer()->executeInRenderContext(
93+
$context,
94+
function () use ($query, $variables) {
95+
return $this->server->executeOperation(
96+
OperationParams::create([
97+
'query' => $query,
98+
'variables' => $variables,
99+
])
100+
);
101+
}
89102
);
90103

91104
$this->assertResultErrors($result, []);
92105
$this->assertResultData($result, $expected);
93106
$this->assertResultMetadata($result, $metadata ?: $this->defaultCacheMetaData());
107+
self::assertTrue($context->isEmpty(), "Metadata was leaked during operation execution: {$context->serialize()}");
94108
}
95109

96110
/**
@@ -106,15 +120,22 @@ protected function assertResults($query, array $variables, array $expected, Cach
106120
* The expected cache metadata object.
107121
*/
108122
protected function assertErrors($query, array $variables, $expected, CacheableMetadata $metadata): void {
109-
$result = $this->server->executeOperation(
110-
OperationParams::create([
111-
'query' => $query,
112-
'variables' => $variables,
113-
])
123+
$context = new RenderContext();
124+
$result = $this->getRenderer()->executeInRenderContext(
125+
$context,
126+
function () use ($query, $variables) {
127+
return $this->server->executeOperation(
128+
OperationParams::create([
129+
'query' => $query,
130+
'variables' => $variables,
131+
])
132+
);
133+
}
114134
);
115135

116136
$this->assertResultErrors($result, $expected);
117137
$this->assertResultMetadata($result, $metadata);
138+
self::assertTrue($context->isEmpty(), "Metadata was leaked during operation execution: {$context->serialize()}");
118139
}
119140

120141
/**
@@ -210,4 +231,20 @@ private function assertResultMetadata(ExecutionResult $result, CacheableMetadata
210231
$this->assertEmpty($unexpectedTags, 'Unexpected cache tags: ' . implode(', ', $unexpectedTags));
211232
}
212233

234+
/**
235+
* Get the Drupal renderer.
236+
*
237+
* Uses either the renderer available in the test class or fetches the Drupal
238+
* renderer service.
239+
*
240+
* @return \Drupal\Core\Render\RendererInterface
241+
* The renderer service for the test.
242+
*/
243+
private function getRenderer() : RendererInterface {
244+
if (!isset($this->renderer)) {
245+
$this->renderer = \Drupal::service('renderer');
246+
}
247+
return $this->renderer;
248+
}
249+
213250
}

0 commit comments

Comments
 (0)