graphql-engine/server/tests-py/test_remote_relationships.py
Rakesh Emmadi 362230e8d0 server: async action query subscription
Multi source support had limited the availability of async action queries in subscriptions. This PR
adds support for async action query subscriptions with new implementation. Also addresses https://github.com/hasura/graphql-engine/issues/6460.

GitOrigin-RevId: 5ddc321073d224f287dc4b86ce2239ff55190b36
2021-03-31 10:40:15 +00:00

364 lines
16 KiB
Python

#!/usr/bin/env python3
import pytest
import subprocess
import time
from validate import check_query_f, check_query
from remote_server import NodeGraphQL
@pytest.fixture(scope="module")
def graphql_service():
svc = NodeGraphQL(["node", "remote_schemas/nodejs/index.js"])
svc.start()
yield svc
svc.stop()
use_test_fixtures = pytest.mark.usefixtures(
"graphql_service",
"per_method_tests_db_state"
)
@use_test_fixtures
class TestCreateRemoteRelationship:
@classmethod
def dir(cls):
return "queries/remote_schemas/remote_relationships/"
# @pytest.fixture(autouse=True)
# def transact(self, hge_ctx, graphql_service):
# print("In setup method")
# graphql_service.start()
# try:
# st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup.yaml')
# assert st_code == 200, resp
# yield
# st_code, resp = hge_ctx.v1q_f(self.dir() + 'teardown.yaml')
# assert st_code == 200, resp
# finally:
# graphql_service.stop()
def test_create_valid(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_basic.yaml')
assert st_code == 200, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_nested_args.yaml')
assert st_code == 200, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_array.yaml')
assert st_code == 200, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_nested_fields.yaml')
assert st_code == 200, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_multiple_fields.yaml')
assert st_code == 200, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_joining_singleton_with_array.yaml')
assert st_code == 200, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_with_interface.yaml')
assert st_code == 200, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_with_union.yaml')
assert st_code == 200, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_with_enum.yaml')
assert st_code == 200, resp
def test_create_invalid(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_invalid_remote_rel_hasura_field.yaml')
assert st_code == 400, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_invalid_remote_rel_literal.yaml')
assert st_code == 400, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_invalid_remote_rel_variable.yaml')
assert st_code == 400, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_invalid_remote_rel_remote_args.yaml')
assert st_code == 400, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_invalid_remote_rel_remote_schema.yaml')
assert st_code == 400, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_invalid_remote_rel_remote_field.yaml')
assert st_code == 400, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_invalid_remote_rel_type.yaml')
assert st_code == 400, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_invalid_remote_rel_nested_args.yaml')
assert st_code == 400, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_invalid_remote_rel_array.yaml')
assert st_code == 400, resp
def test_generation(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_basic.yaml')
assert st_code == 200, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_nested_args.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'select_remote_fields.yaml')
@use_test_fixtures
class TestDeleteRemoteRelationship:
@classmethod
def dir(cls):
return "queries/remote_schemas/remote_relationships/"
def test_delete(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_basic.yaml')
assert st_code == 200, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'delete_remote_rel.yaml')
assert st_code == 200, resp
def test_delete_dependencies(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_basic.yaml')
assert st_code == 200, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'remove_remote_schema.yaml')
assert st_code == 400, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'delete_remote_rel.yaml')
assert st_code == 200, resp
def test_deleting_column_with_remote_relationship_dependency(self, hge_ctx):
check_query_f(hge_ctx, self.dir() + 'drop_col_with_remote_rel_dependency.yaml')
self._check_no_remote_relationships(hge_ctx, 'profiles')
def test_deleting_table_with_remote_relationship_dependency(self, hge_ctx):
check_query_f(hge_ctx, self.dir() + 'drop_table_with_remote_rel_dependency.yaml')
self._check_no_remote_relationships(hge_ctx, 'profiles')
def _check_no_remote_relationships(self, hge_ctx, table):
export_metadata_q = {
'type': 'export_metadata',
'args': {}
}
status_code, resp = hge_ctx.v1q(export_metadata_q)
assert status_code == 200, resp
tables = resp['sources'][0]['tables']
for t in tables:
if t['table']['name'] == table:
assert 'event_triggers' not in t
@use_test_fixtures
class TestUpdateRemoteRelationship:
@classmethod
def dir(cls):
return "queries/remote_schemas/remote_relationships/"
def test_update(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_basic.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'basic_relationship.yaml')
st_code, resp = hge_ctx.v1q_f(self.dir() + 'update_remote_rel_basic.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'update_basic_query.yaml')
@use_test_fixtures
class TestExecution:
@classmethod
def dir(cls):
return "queries/remote_schemas/remote_relationships/"
# def test_basic_mixed(self, hge_ctx):
# check_query_f(hge_ctx, self.dir() + 'basic_mixed.yaml')
def test_basic_relationship(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_basic.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'basic_relationship.yaml')
def test_basic_relationship_on_object(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_basic.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'query_with_object_rel.yaml')
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_nested_args.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'query_with_arr_rel.yaml')
def test_basic_relationship_joining_singleton_to_array(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_joining_singleton_with_array.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'basic_relationship_joining_singleton_with_array.yaml')
def test_basic_array(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_array.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'basic_array.yaml')
def test_basic_array_without_join_key(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_array.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'basic_array_without_join_key.yaml')
def test_multiple_fields(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_multiple_fields.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'basic_multiple_fields.yaml')
# https://github.com/hasura/graphql-engine/issues/5448
def test_remote_join_fields_with_null_joining_fields(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_null_joining_fields.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'remote_rel_with_null_joining_fields.yaml')
def test_nested_fields(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_nested_fields.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'basic_nested_fields.yaml')
def test_arguments(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_nested_args.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'query_with_arguments.yaml')
def test_with_variables(self, hge_ctx):
# check_query_f(hge_ctx, self.dir() + 'mixed_variables.yaml') -- uses heterogenous execution, due to which this assert fails
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_nested_args.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'remote_rel_variables.yaml')
def test_with_fragments(self, hge_ctx):
check_query_f(hge_ctx, self.dir() + 'mixed_fragments.yaml')
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_basic.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'remote_rel_fragments.yaml')
def test_with_interface(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_with_interface.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'mixed_interface.yaml')
check_query_f(hge_ctx, self.dir() + 'remote_rel_interface.yaml')
def test_with_union(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_with_union.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'remote_rel_union.yaml')
def test_with_enum(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_with_enum.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'remote_rel_enum.yaml')
def test_with_errors(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_basic.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'query_with_errors_obj.yaml')
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_nested_args.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'query_with_errors_arr.yaml')
def test_with_scalar_relationship(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_scalar.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'query_with_scalar_rel.yaml')
def test_renaming_column_with_remote_relationship_dependency(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_nested_args.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'rename_col_with_remote_rel_dependency.yaml')
def test_renaming_table_with_remote_relationship_dependency(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_nested_args.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'rename_table_with_remote_rel_dependency.yaml')
# The check for the presence of the remote relationships is deferred to later stage
# in the server source code. To run this test we need to use proper websocket client
# instead of HTTP.
# def test_remote_joins_with_subscription_should_throw_error(self, hge_ctx):
# st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_basic.yaml')
# assert st_code == 200, resp
# check_query_f(hge_ctx, self.dir() + 'subscription_with_remote_join_fields.yaml')
def test_remote_joins_in_mutation_response(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_basic_with_authors.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'mutation_output_with_remote_join_fields.yaml')
class TestDeepExecution:
@classmethod
def dir(cls):
return "queries/remote_schemas/remote_relationships/"
@pytest.fixture(autouse=True)
def transact(self, hge_ctx, graphql_service):
print("In setup method")
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup.yaml')
assert st_code == 200, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_address.yaml')
assert st_code == 200, resp
yield
st_code, resp = hge_ctx.v1q_f(self.dir() + 'teardown_address.yaml')
assert st_code == 200, resp
st_code, resp = hge_ctx.v1q_f(self.dir() + 'teardown.yaml')
assert st_code == 200, resp
def test_with_deep_object(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_basic.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'query_with_deep_nesting_obj.yaml')
def test_with_deep_array(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_nested_args.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'query_with_deep_nesting_arr.yaml')
def test_with_complex_path_object(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_basic.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'query_with_deep_nesting_complex_path_obj.yaml')
check_query_f(hge_ctx, self.dir() + 'query_with_deep_nesting_complex_path_obj2.yaml')
def test_with_complex_path_array(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_basic.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'query_with_deep_nesting_complex_path_arr.yaml')
check_query_f(hge_ctx, self.dir() + 'query_with_deep_nesting_complex_path_arr2.yaml')
class TestExecutionWithPermissions:
@classmethod
def dir(cls):
return "queries/remote_schemas/remote_relationships/"
@pytest.fixture(autouse=True)
def transact(self, hge_ctx, graphql_service):
print("In setup method")
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_with_permissions.yaml')
assert st_code == 200, resp
yield
st_code, resp = hge_ctx.v1q_f(self.dir() + 'teardown.yaml')
assert st_code == 200, resp
def test_basic_relationship(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_basic.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'basic_relationship_with_permissions1.yaml')
check_query_f(hge_ctx, self.dir() + 'basic_relationship_with_permissions2.yaml')
# Test queries that combine several remote relationships, nested in
# different ways, variously filtering different bits using permissions.
def test_complex_multiple_joins(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_multiple_remote_rel.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + 'complex_multiple_joins.yaml')
@use_test_fixtures
class TestWithRelay:
@classmethod
def dir(cls):
return "queries/remote_schemas/remote_relationships/"
def test_with_relay_fail(self, hge_ctx):
st_code, resp = hge_ctx.v1q_f(self.dir() + 'setup_remote_rel_basic.yaml')
assert st_code == 200, resp
check_query_f(hge_ctx, self.dir() + "with_relay.yaml")