From 9bc956c65b573e78073073f923bea707eb0c509c Mon Sep 17 00:00:00 2001 From: Ruud Kamphuis Date: Mon, 11 Nov 2024 12:05:57 +0100 Subject: [PATCH] Add `reset` method to Type, Directive and Introspection See #1424 This library uses a static cache for standard types and the internal directives. While not ideal, this works fine. As long as you don't have a scenario where you want to change them. In my situation, we have 2 schema's with a custom ID type. They are not the same instance. This still works fine, but as soon as we run our whole test suite at once, the static cache is initialized in some test, and another test later expects something else. While I think the better solution would be to remove these static caches completely, and store them on an instance instead of statically. But that will be a much bigger task given the current architecture. With these 2 reset methods, we can manually reset the caches in our test suite. It could also be used for people that run their GraphQL server in tools like RoadRunner and FrankenPHP. --- src/Type/Definition/Directive.php | 13 +++++++++++-- src/Type/Definition/Type.php | 7 ++++++- src/Type/Introspection.php | 5 +++++ tests/Type/Definition/TypeTest.php | 19 +++++++++++++++++++ tests/Type/DirectiveTest.php | 9 +++++++++ 5 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 tests/Type/Definition/TypeTest.php diff --git a/src/Type/Definition/Directive.php b/src/Type/Definition/Directive.php index 0a6db42e5..f2c546f93 100644 --- a/src/Type/Definition/Directive.php +++ b/src/Type/Definition/Directive.php @@ -33,7 +33,7 @@ class Directive * * @var array */ - protected static array $internalDirectives; + protected static array $internalDirectives = []; public string $name; @@ -90,7 +90,11 @@ public static function includeDirective(): Directive */ public static function getInternalDirectives(): array { - return self::$internalDirectives ??= [ + if (self::$internalDirectives !== []) { + return self::$internalDirectives; + } + + return self::$internalDirectives = [ 'include' => new self([ 'name' => self::INCLUDE_NAME, 'description' => 'Directs the executor to include this field or fragment only when the `if` argument is true.', @@ -162,4 +166,9 @@ public static function isSpecifiedDirective(Directive $directive): bool { return \array_key_exists($directive->name, self::getInternalDirectives()); } + + public static function reset(): void + { + self::$internalDirectives = []; + } } diff --git a/src/Type/Definition/Type.php b/src/Type/Definition/Type.php index cd734b99c..e757e7d32 100644 --- a/src/Type/Definition/Type.php +++ b/src/Type/Definition/Type.php @@ -31,7 +31,7 @@ abstract class Type implements \JsonSerializable ]; /** @var array */ - protected static array $standardTypes; + protected static array $standardTypes = []; /** * @api @@ -261,4 +261,9 @@ public function jsonSerialize(): string { return $this->toString(); } + + public static function reset(): void + { + static::$standardTypes = []; + } } diff --git a/src/Type/Introspection.php b/src/Type/Introspection.php index 9aaa5341a..9d29dde3d 100644 --- a/src/Type/Introspection.php +++ b/src/Type/Introspection.php @@ -795,4 +795,9 @@ public static function typeNameMetaFieldDef(): FieldDefinition 'resolve' => static fn ($source, array $args, $context, ResolveInfo $info): string => $info->parentType->name, ]); } + + public static function reset(): void + { + self::$map = []; + } } diff --git a/tests/Type/Definition/TypeTest.php b/tests/Type/Definition/TypeTest.php new file mode 100644 index 000000000..b123a26aa --- /dev/null +++ b/tests/Type/Definition/TypeTest.php @@ -0,0 +1,19 @@ +isDeprecated()); } + public function testReset(): void + { + $directives = Directive::getInternalDirectives(); + + Directive::reset(); + + self::assertNotSame($directives, Directive::getInternalDirectives()); + } + // TODO implement all of https://github.com/graphql/graphql-js/blob/master/src/type/__tests__/directive-test.js }