-
-
Notifications
You must be signed in to change notification settings - Fork 547
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extract operation name and type from execution context (#1286)
* Extract operation name and type from execution context * Fix open telemetry extension and make the operation name fetching more forgiving * Code review updates * Add RELEASE file * Add test for runtime exception * Rename variable * Change version to minor Co-authored-by: Patrick Arminio <[email protected]>
- Loading branch information
Showing
6 changed files
with
278 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Release type: minor | ||
|
||
This release `operation_type` to the `ExecutionContext` type that is available | ||
in extensions. It also gets the `operation_name` from the query if one isn't | ||
provided by the client. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
import pytest | ||
|
||
import strawberry | ||
from strawberry.extensions import Extension | ||
|
||
|
||
@strawberry.type | ||
class Query: | ||
@strawberry.field | ||
def ping(self) -> str: | ||
return "pong" | ||
|
||
|
||
def test_execution_context_operation_name_and_type(): | ||
operation_name = None | ||
operation_type = None | ||
|
||
class MyExtension(Extension): | ||
def on_request_end(self): | ||
nonlocal operation_name | ||
nonlocal operation_type | ||
|
||
execution_context = self.execution_context | ||
|
||
operation_name = execution_context.operation_name | ||
operation_type = execution_context.operation_type | ||
|
||
schema = strawberry.Schema(Query, extensions=[MyExtension]) | ||
|
||
result = schema.execute_sync("{ ping }") | ||
assert not result.errors | ||
|
||
assert operation_name is None | ||
assert operation_type == "QUERY" | ||
|
||
# Try again with an operation_name | ||
result = schema.execute_sync("query MyOperation { ping }") | ||
assert not result.errors | ||
|
||
assert operation_name == "MyOperation" | ||
assert operation_type == "QUERY" | ||
|
||
# Try again with an operation_name override | ||
result = schema.execute_sync( | ||
""" | ||
query MyOperation { ping } | ||
query MyOperation2 { ping } | ||
""", | ||
operation_name="MyOperation2", | ||
) | ||
assert not result.errors | ||
|
||
assert operation_name == "MyOperation2" | ||
assert operation_type == "QUERY" | ||
|
||
|
||
def test_execution_context_operation_type_mutation(): | ||
operation_name = None | ||
operation_type = None | ||
|
||
class MyExtension(Extension): | ||
def on_request_end(self): | ||
nonlocal operation_name | ||
nonlocal operation_type | ||
|
||
execution_context = self.execution_context | ||
|
||
operation_name = execution_context.operation_name | ||
operation_type = execution_context.operation_type | ||
|
||
@strawberry.type | ||
class Mutation: | ||
@strawberry.mutation | ||
def my_mutation(self) -> str: | ||
return "hi" | ||
|
||
schema = strawberry.Schema(Query, mutation=Mutation, extensions=[MyExtension]) | ||
|
||
result = schema.execute_sync("mutation { myMutation }") | ||
assert not result.errors | ||
|
||
assert operation_name is None | ||
assert operation_type == "MUTATION" | ||
|
||
# Try again with an operation_name | ||
result = schema.execute_sync("mutation MyMutation { myMutation }") | ||
assert not result.errors | ||
|
||
assert operation_name == "MyMutation" | ||
assert operation_type == "MUTATION" | ||
|
||
# Try again with an operation_name override | ||
result = schema.execute_sync( | ||
""" | ||
mutation MyMutation { myMutation } | ||
mutation MyMutation2 { myMutation } | ||
""", | ||
operation_name="MyMutation2", | ||
) | ||
assert not result.errors | ||
|
||
assert operation_name == "MyMutation2" | ||
assert operation_type == "MUTATION" | ||
|
||
|
||
def test_execution_context_operation_name_and_type_with_fragmenets(): | ||
operation_name = None | ||
operation_type = None | ||
|
||
class MyExtension(Extension): | ||
def on_request_end(self): | ||
nonlocal operation_name | ||
nonlocal operation_type | ||
|
||
execution_context = self.execution_context | ||
|
||
operation_name = execution_context.operation_name | ||
operation_type = execution_context.operation_type | ||
|
||
schema = strawberry.Schema(Query, extensions=[MyExtension]) | ||
|
||
result = schema.execute_sync( | ||
""" | ||
fragment MyFragment on Query { | ||
ping | ||
} | ||
query MyOperation { | ||
ping | ||
...MyFragment | ||
} | ||
""" | ||
) | ||
assert not result.errors | ||
|
||
assert operation_name == "MyOperation" | ||
assert operation_type == "QUERY" | ||
|
||
|
||
def test_error_when_accessing_operation_type_before_parsing(): | ||
class MyExtension(Extension): | ||
def on_request_start(self): | ||
execution_context = self.execution_context | ||
|
||
# This should raise a RuntimeError | ||
execution_context.operation_type | ||
|
||
schema = strawberry.Schema(Query, extensions=[MyExtension]) | ||
|
||
with pytest.raises(RuntimeError): | ||
schema.execute_sync("mutation { myMutation }") | ||
|
||
|
||
def test_error_when_accessing_operation_type_with_invalid_operation_name(): | ||
class MyExtension(Extension): | ||
def on_parsing_end(self): | ||
execution_context = self.execution_context | ||
|
||
# This should raise a RuntimeError | ||
execution_context.operation_type | ||
|
||
schema = strawberry.Schema(Query, extensions=[MyExtension]) | ||
|
||
with pytest.raises(RuntimeError): | ||
schema.execute_sync("query { ping }", operation_name="MyQuery") |