Skip to content

Commit

Permalink
Add testing for GraphQL Mutation Types (#281)
Browse files Browse the repository at this point in the history
*  Add testing for graphql mutations.

*  Add version check in test_basic.

*  Modifying response assertion statements for version compatibility.
  • Loading branch information
umaannamalai authored and TimPansino committed Jul 29, 2021
1 parent 1e43d4f commit b2a0088
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 20 deletions.
6 changes: 3 additions & 3 deletions newrelic/api/graphql_trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ def __repr__(self):
return '<%s %s>' % (self.__class__.__name__, dict())

def finalize_data(self, *args, **kwargs):
self._add_agent_attribute("graphql.operation.type", self.operation_type)
self._add_agent_attribute("graphql.operation.name", self.operation_name)
self._add_agent_attribute("graphql.operation.deepestPath", self.deepest_path)
self._add_agent_attribute("graphql.operation.type", self.operation_type or "<unknown>")
self._add_agent_attribute("graphql.operation.name", self.operation_name or "<anonymous>")
self._add_agent_attribute("graphql.operation.deepestPath", self.deepest_path or "<unknown>")

return super(GraphQLOperationTrace, self).finalize_data(*args, **kwargs)

Expand Down
39 changes: 38 additions & 1 deletion tests/framework_graphql/_target_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,19 @@
{"name": "Portland Public Library", "book": [{"name": "E", "author": "F"}]},
]

storage = []


def resolve_library(parent, info, index):
return libraries[index]

def resolve_storage_add(parent, info, string):
storage.append(string)
return string

def resolve_storage(parent, info):
return storage


Book = GraphQLObjectType(
"Book",
Expand All @@ -52,6 +61,8 @@ def resolve_library(parent, info, index):
},
)

Storage = GraphQLList(GraphQLString)


def resolve_hello(root, info):
return "Hello!"
Expand All @@ -68,6 +79,15 @@ def resolve_error(root, info):
resolver=resolve_library,
args={"index": GraphQLArgument(GraphQLNonNull(GraphQLInt))},
)
storage_field = GraphQLField(
Storage,
resolver=resolve_storage,
)
storage_add_field = GraphQLField(
Storage,
resolver=resolve_storage_add,
args={"string": GraphQLArgument(GraphQLNonNull(GraphQLString))},
)
error_field = GraphQLField(GraphQLString, resolver=resolve_error)
error_non_null_field = GraphQLField(
GraphQLNonNull(GraphQLString), resolver=resolve_error
Expand All @@ -79,6 +99,15 @@ def resolve_error(root, info):
resolve=resolve_library,
args={"index": GraphQLArgument(GraphQLNonNull(GraphQLInt))},
)
storage_field = GraphQLField(
Storage,
resolve=resolve_storage,
)
storage_add_field = GraphQLField(
GraphQLString,
resolve=resolve_storage_add,
args={"string": GraphQLArgument(GraphQLNonNull(GraphQLString))},
)
error_field = GraphQLField(GraphQLString, resolve=resolve_error)
error_non_null_field = GraphQLField(
GraphQLNonNull(GraphQLString), resolve=resolve_error
Expand All @@ -88,10 +117,18 @@ def resolve_error(root, info):
name="Query",
fields={
"hello": hello_field,
"storage": storage_field,
"error": error_field,
"error_non_null": error_non_null_field,
"library": library_field,
},
)

_target_application = GraphQLSchema(query=query)
mutation = GraphQLObjectType(
name="Mutation",
fields={
"storage_add": storage_add_field,
},
)

_target_application = GraphQLSchema(query=query, mutation=mutation)
65 changes: 49 additions & 16 deletions tests/framework_graphql/test_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# limitations under the License.

import pytest
import sys
from testing_support.fixtures import validate_transaction_metrics, validate_transaction_errors, dt_enabled
from testing_support.validators.validate_span_events import validate_span_events

Expand Down Expand Up @@ -49,11 +50,6 @@ def error_middleware(next, root, info, **args):

_runtime_error_name = callable_name(RuntimeError)
_test_runtime_error = [(_runtime_error_name, "Runtime Error!")]
_expected_attributes = {
"graphql.operation.name": "MyQuery",
"graphql.operation.type": "query",
"graphql.operation.deepestPath": "hello"
}
_graphql_base_rollup_metrics = [
("OtherTransaction/all", 1),
("GraphQL/all", 1),
Expand All @@ -64,25 +60,61 @@ def error_middleware(next, root, info, **args):


@dt_enabled
def test_basic(app, graphql_run, is_graphql_2):
_test_basic_metrics = [
("OtherTransaction/Function/_target_application:resolve_hello", 1),
("GraphQL/operation/GraphQL/query/MyQuery/hello", 1),
#("Function/_target_application:resolve_hello", 1),
def test_basic(app, graphql_run):
_test_mutation_scoped_metrics = [
("GraphQL/resolve/GraphQL/storage", 1),
("GraphQL/resolve/GraphQL/storage_add", 1),
("GraphQL/operation/GraphQL/query/<anonymous>/storage", 1),
("GraphQL/operation/GraphQL/mutation/<anonymous>/storage_add", 1),
]

_test_mutation_unscoped_metrics = [
("OtherTransaction/all", 1),
("GraphQL/all", 2),
("GraphQL/GraphQL/all", 2),
("GraphQL/allOther", 2),
("GraphQL/GraphQL/allOther", 2),
] + _test_mutation_scoped_metrics

_expected_mutation_operation_attributes = {
"graphql.operation.type": "mutation",
"graphql.operation.name": "<anonymous>",
"graphql.operation.deepestPath": "storage_add",
}
_expected_mutation_resolver_attributes = {
"graphql.field.name": "storage_add",
"graphql.field.parentType": "Mutation",
"graphql.field.path": "storage_add",
}
_expected_query_operation_attributes = {
"graphql.operation.type": "query",
"graphql.operation.name": "<anonymous>",
"graphql.operation.deepestPath": "storage",
}
_expected_query_resolver_attributes = {
"graphql.field.name": "storage",
"graphql.field.parentType": "Query",
"graphql.field.path": "storage",
}
@validate_transaction_metrics(
"_target_application:resolve_hello",
rollup_metrics=_test_basic_metrics + _graphql_base_rollup_metrics,
"_target_application:resolve_storage",
scoped_metrics=_test_mutation_scoped_metrics,
rollup_metrics=_test_mutation_unscoped_metrics,
background_task=True,
)
@validate_span_events(exact_agents=_expected_attributes)
@validate_span_events(exact_agents=_expected_mutation_operation_attributes)
@validate_span_events(exact_agents=_expected_mutation_resolver_attributes)
@validate_span_events(exact_agents=_expected_query_operation_attributes)
@validate_span_events(exact_agents=_expected_query_resolver_attributes)
@background_task()
def _test():
response = graphql_run(app, "query MyQuery{ hello }")
response = graphql_run(app, 'mutation { storage_add(string: "abc") }')
assert not response.errors
response = graphql_run(app, "query { storage }")
assert not response.errors
assert "Hello!" in str(response.data)

# These are separate assertions because pypy stores 'abc' as a unicode string while other Python versions do not
assert "storage" in str(response.data)
assert "abc" in str(response.data)
_test()


Expand Down Expand Up @@ -193,3 +225,4 @@ def _test():
assert "Hello!" in str(response.data)

_test()

0 comments on commit b2a0088

Please sign in to comment.