mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-04 20:06:35 +03:00
server/tests-py: Provide the admin secret to the HGE server.
When we run the HGE server inside the test harness, it needs to run with an admin secret for some tests to make sense. This tags each test that requires an admin secret with `pytest.mark.admin_secret`, which then generates a UUID and injects that into both the server and the test case (if required). It also simplifies the way the test harness picks up an existing admin secret, allowing it to use the environment variable instead of requiring it via a parameter. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/6120 GitOrigin-RevId: 55c5b9e8c99bdad9c8304098444ddb9516749a2c
This commit is contained in:
parent
a5dc3f8440
commit
3cb9bab9f1
@ -74,7 +74,7 @@ init_hge_and_test_jwt() {
|
||||
run_hge_with_args serve
|
||||
wait_for_port 8080
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" --hge-jwt-key-file="$key_file" --hge-jwt-conf="$HASURA_GRAPHQL_JWT_SECRET" \
|
||||
--hge-jwt-key-file="$key_file" --hge-jwt-conf="$HASURA_GRAPHQL_JWT_SECRET" \
|
||||
"$@"
|
||||
kill_hge_servers
|
||||
}
|
||||
@ -266,7 +266,7 @@ admin-secret)
|
||||
|
||||
start_multiple_hge_servers
|
||||
|
||||
run_pytest_parallel --hge-key="$HASURA_GRAPHQL_ADMIN_SECRET"
|
||||
run_pytest_parallel
|
||||
|
||||
kill_hge_servers
|
||||
;;
|
||||
@ -282,7 +282,6 @@ admin-secret-unauthorized-role)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
--test-unauthorized-role \
|
||||
test_graphql_queries.py::TestUnauthorizedRolePermission
|
||||
|
||||
@ -302,7 +301,7 @@ jwt-rs512)
|
||||
|
||||
start_multiple_hge_servers
|
||||
|
||||
run_pytest_parallel --hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" --hge-jwt-key-file="$OUTPUT_FOLDER/ssl/jwt_private.key" --hge-jwt-conf="$HASURA_GRAPHQL_JWT_SECRET"
|
||||
run_pytest_parallel --hge-jwt-key-file="$OUTPUT_FOLDER/ssl/jwt_private.key" --hge-jwt-conf="$HASURA_GRAPHQL_JWT_SECRET"
|
||||
|
||||
kill_hge_servers
|
||||
|
||||
@ -320,7 +319,7 @@ jwt-ed25519)
|
||||
|
||||
start_multiple_hge_servers
|
||||
|
||||
run_pytest_parallel --hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" --hge-jwt-key-file="$OUTPUT_FOLDER/ssl/ed25519_jwt_private.key" --hge-jwt-conf="$HASURA_GRAPHQL_JWT_SECRET"
|
||||
run_pytest_parallel --hge-jwt-key-file="$OUTPUT_FOLDER/ssl/ed25519_jwt_private.key" --hge-jwt-conf="$HASURA_GRAPHQL_JWT_SECRET"
|
||||
|
||||
kill_hge_servers
|
||||
|
||||
@ -574,7 +573,7 @@ jwt-cookie-unauthorized-role)
|
||||
|
||||
wait_for_port 8080
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" --hge-jwt-key-file="$OUTPUT_FOLDER/ssl/jwt_private.key" --hge-jwt-conf="$HASURA_GRAPHQL_JWT_SECRET" \
|
||||
--hge-jwt-key-file="$OUTPUT_FOLDER/ssl/jwt_private.key" --hge-jwt-conf="$HASURA_GRAPHQL_JWT_SECRET" \
|
||||
--test-unauthorized-role \
|
||||
test_graphql_queries.py::TestFallbackUnauthorizedRoleCookie
|
||||
|
||||
@ -586,7 +585,7 @@ jwt-cookie-unauthorized-role)
|
||||
|
||||
wait_for_port 8080
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" --hge-jwt-key-file="$OUTPUT_FOLDER/ssl/jwt_private.key" --hge-jwt-conf="$HASURA_GRAPHQL_JWT_SECRET" \
|
||||
--hge-jwt-key-file="$OUTPUT_FOLDER/ssl/jwt_private.key" --hge-jwt-conf="$HASURA_GRAPHQL_JWT_SECRET" \
|
||||
--test-no-cookie-and-unauth-role \
|
||||
test_graphql_queries.py::TestMissingUnauthorizedRoleAndCookie
|
||||
|
||||
@ -605,7 +604,6 @@ cors-domains)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
test_cors.py
|
||||
|
||||
kill_hge_servers
|
||||
@ -624,7 +622,7 @@ auth-webhook-cookie)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" --hge-webhook="$HASURA_GRAPHQL_AUTH_HOOK" \
|
||||
--hge-webhook="$HASURA_GRAPHQL_AUTH_HOOK" \
|
||||
--test-auth-webhook-header \
|
||||
test_auth_webhook_cookie.py
|
||||
|
||||
@ -644,7 +642,6 @@ ws-init-cookie-read-cors-enabled)
|
||||
|
||||
echo "$(time_elapsed): testcase 1: read cookie, cors enabled"
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
--test-ws-init-cookie=read \
|
||||
test_websocket_init_cookie.py
|
||||
|
||||
@ -662,7 +659,6 @@ ws-init-cookie-noread)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
--test-ws-init-cookie=noread \
|
||||
test_websocket_init_cookie.py
|
||||
|
||||
@ -680,7 +676,6 @@ ws-init-cookie-read-cors-disabled)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
--test-ws-init-cookie=read \
|
||||
test_websocket_init_cookie.py
|
||||
|
||||
@ -698,7 +693,6 @@ ws-graphql-api-disabled)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
test_apis_disabled.py
|
||||
|
||||
kill_hge_servers
|
||||
@ -716,7 +710,6 @@ ws-metadata-api-disabled)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
test_apis_disabled.py
|
||||
|
||||
kill_hge_servers
|
||||
@ -731,7 +724,6 @@ remote-schema-permissions)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
test_remote_schema_permissions.py
|
||||
|
||||
unset HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS
|
||||
@ -748,10 +740,8 @@ function-permissions)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
test_graphql_queries.py::TestGraphQLQueryFunctionPermissions
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
test_graphql_mutations.py::TestGraphQLMutationFunctions
|
||||
|
||||
unset HASURA_GRAPHQL_INFER_FUNCTION_PERMISSIONS
|
||||
@ -771,7 +761,6 @@ roles-inheritance)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
test_roles_inheritance.py
|
||||
|
||||
unset HASURA_GRAPHQL_ADMIN_SECRET
|
||||
@ -791,7 +780,6 @@ naming-conventions)
|
||||
unset HASURA_GRAPHQL_EXPERIMENTAL_FEATURES
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
test_naming_conventions.py
|
||||
|
||||
kill_hge_servers
|
||||
@ -801,7 +789,6 @@ naming-conventions)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
test_naming_conventions.py
|
||||
|
||||
kill_hge_servers
|
||||
@ -815,7 +802,6 @@ naming-conventions)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
test_naming_conventions.py
|
||||
|
||||
unset HASURA_GRAPHQL_ADMIN_SECRET
|
||||
@ -835,8 +821,6 @@ streaming-subscriptions)
|
||||
|
||||
# run all the subscriptions tests with streaming subscriptions enabled
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
--test-streaming-subscriptions \
|
||||
test_subscriptions.py
|
||||
|
||||
unset HASURA_GRAPHQL_ADMIN_SECRET
|
||||
@ -853,7 +837,6 @@ query-caching)
|
||||
run_hge_with_args +RTS -N1 -RTS serve
|
||||
wait_for_port 8080
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
test_graphql_queries.py::TestGraphQLQueryCaching
|
||||
kill_hge_servers
|
||||
;;
|
||||
@ -877,7 +860,6 @@ query-logs)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
--test-logging \
|
||||
test_logging.py
|
||||
|
||||
@ -912,7 +894,6 @@ startup-db-calls)
|
||||
run_hge_with_args serve
|
||||
wait_for_port 8080
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
--test-startup-db-calls \
|
||||
test_startup_db_calls.py
|
||||
|
||||
@ -961,7 +942,6 @@ EOF
|
||||
pytest "${PYTEST_REPORTING_ARGS[@]}" \
|
||||
--hge-urls "$HGE_URL" \
|
||||
--pg-urls "$HASURA_GRAPHQL_PG_SOURCE_URL_1" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
--test-read-only-source \
|
||||
test_graphql_read_only_source.py
|
||||
|
||||
@ -1011,7 +991,7 @@ post-webhook)
|
||||
WH_PID=$!
|
||||
wait_for_port 9090
|
||||
|
||||
run_pytest_parallel --hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" --hge-webhook="$HASURA_GRAPHQL_AUTH_HOOK"
|
||||
run_pytest_parallel --hge-webhook="$HASURA_GRAPHQL_AUTH_HOOK"
|
||||
|
||||
kill_hge_servers
|
||||
;;
|
||||
@ -1028,7 +1008,6 @@ webhook-request-context)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
--hge-webhook="$HASURA_GRAPHQL_AUTH_HOOK" \
|
||||
--test-webhook-request-context \
|
||||
test_webhook_request_context.py
|
||||
@ -1051,7 +1030,7 @@ get-webhook)
|
||||
WH_PID=$!
|
||||
wait_for_port 9090
|
||||
|
||||
run_pytest_parallel --hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" --hge-webhook="$HASURA_GRAPHQL_AUTH_HOOK"
|
||||
run_pytest_parallel --hge-webhook="$HASURA_GRAPHQL_AUTH_HOOK"
|
||||
|
||||
kill_hge_servers
|
||||
;;
|
||||
@ -1077,7 +1056,6 @@ insecure-webhook)
|
||||
wait_for_port 9090
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
--hge-webhook="$HASURA_GRAPHQL_AUTH_HOOK" \
|
||||
--test-webhook-insecure \
|
||||
test_webhook_insecure.py
|
||||
@ -1105,7 +1083,6 @@ insecure-webhook-with-admin-secret)
|
||||
wait_for_port 9090
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
--hge-webhook="$HASURA_GRAPHQL_AUTH_HOOK" \
|
||||
--test-webhook-insecure \
|
||||
test_webhook_insecure.py
|
||||
@ -1124,7 +1101,6 @@ apollo-federation)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
test_apollo_federation.py
|
||||
|
||||
unset HASURA_GRAPHQL_EXPERIMENTAL_FEATURES
|
||||
@ -1142,7 +1118,6 @@ allowlist-queries)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
test_allowlist_queries.py
|
||||
|
||||
kill_hge_servers
|
||||
@ -1157,7 +1132,6 @@ developer-api-tests)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
test_dev_endpoints.py
|
||||
|
||||
unset HASURA_GRAPHQL_ENABLED_APIS
|
||||
@ -1187,7 +1161,6 @@ jwk-url)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
--test-jwk-url \
|
||||
-k 'test_cache_control_header_max_age'
|
||||
|
||||
@ -1200,7 +1173,6 @@ jwk-url)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
--test-jwk-url \
|
||||
-k 'test_cache_control_header_max_age'
|
||||
|
||||
@ -1213,7 +1185,6 @@ jwk-url)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
--test-jwk-url \
|
||||
-k 'test_cache_control_header_no_caching'
|
||||
|
||||
@ -1226,7 +1197,6 @@ jwk-url)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
--test-jwk-url \
|
||||
-k 'test_cache_control_header_no_caching'
|
||||
|
||||
@ -1239,7 +1209,6 @@ jwk-url)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
--test-jwk-url \
|
||||
-k 'test_cache_control_header_no_caching'
|
||||
|
||||
@ -1252,7 +1221,6 @@ jwk-url)
|
||||
wait_for_port 8080
|
||||
|
||||
pytest "${PYTEST_COMMON_ARGS[@]}" \
|
||||
--hge-key="$HASURA_GRAPHQL_ADMIN_SECRET" \
|
||||
--test-jwk-url \
|
||||
-k 'test_expires_header'
|
||||
|
||||
|
@ -7,6 +7,7 @@ import sys
|
||||
import threading
|
||||
import time
|
||||
from typing import Optional
|
||||
import uuid
|
||||
|
||||
import auth_webhook_server
|
||||
from context import HGECtx, HGECtxGQLServer, ActionsWebhookServer, EvtsWebhookServer, GQLWsClient, PytestConf, GraphQLWSClient
|
||||
@ -34,9 +35,6 @@ def pytest_addoption(parser):
|
||||
required=False,
|
||||
nargs='+'
|
||||
)
|
||||
parser.addoption(
|
||||
"--hge-key", metavar="HGE_KEY", help="admin secret key for graphql-engine", required=False
|
||||
)
|
||||
parser.addoption(
|
||||
"--hge-webhook", metavar="HGE_WEBHOOK", help="url for graphql-engine's access control webhook", required=False
|
||||
)
|
||||
@ -85,14 +83,6 @@ def pytest_addoption(parser):
|
||||
help="Run testcases for startup database calls"
|
||||
)
|
||||
|
||||
parser.addoption(
|
||||
"--test-streaming-subscriptions",
|
||||
action="store_true",
|
||||
default=False,
|
||||
required=False,
|
||||
help="Run streaming subscription tests"
|
||||
)
|
||||
|
||||
parser.addoption(
|
||||
"--test-jwk-url",
|
||||
action="store_true",
|
||||
@ -372,8 +362,23 @@ def hge_fixture_env() -> dict[str, str]:
|
||||
return {}
|
||||
|
||||
@pytest.fixture(scope='class')
|
||||
def hge_key(request) -> Optional[str]:
|
||||
return request.config.getoption('--hge-key')
|
||||
def hge_key(
|
||||
request: pytest.FixtureRequest,
|
||||
hge_bin: Optional[str],
|
||||
) -> Optional[str]:
|
||||
marker = request.node.get_closest_marker('admin_secret')
|
||||
if hge_bin:
|
||||
# If the test requests an admin secret, generate one.
|
||||
return str(uuid.uuid4()) if marker else None
|
||||
else:
|
||||
# If the environment variable is set, use it.
|
||||
# This will be used in the event that we start the server outside the test harness.
|
||||
# We skip the test if it explicitly requires that we have no admin secret.
|
||||
anti_marker = request.node.get_closest_marker('no_admin_secret')
|
||||
env_key = os.environ.get('HASURA_GRAPHQL_ADMIN_SECRET')
|
||||
if anti_marker and env_key:
|
||||
pytest.skip('This test requires that the admin secret is not set.')
|
||||
return env_key
|
||||
|
||||
@pytest.fixture(scope='class')
|
||||
def hge_server(
|
||||
@ -381,16 +386,28 @@ def hge_server(
|
||||
hge_bin: Optional[str],
|
||||
hge_port: int,
|
||||
hge_url: str,
|
||||
hge_key: Optional[str],
|
||||
hge_fixture_env: dict[str, str],
|
||||
pg_url: str,
|
||||
) -> Optional[str]:
|
||||
if not hge_bin:
|
||||
return None
|
||||
return fixtures.hge.hge_server(request, hge_bin, hge_port, hge_url, hge_fixture_env, pg_url)
|
||||
return fixtures.hge.hge_server(request, hge_bin, hge_port, hge_url, hge_key, hge_fixture_env, pg_url)
|
||||
|
||||
@pytest.fixture(scope='class')
|
||||
def hge_ctx(request, hge_url, pg_url, hge_server):
|
||||
hge_ctx = HGECtx(hge_url, pg_url, request.config)
|
||||
def enabled_apis(request: pytest.FixtureRequest, hge_bin: Optional[str]) -> Optional[set[str]]:
|
||||
if hge_bin:
|
||||
hge_marker_env: dict[str, str] = {marker.args[0]: marker.args[1] for marker in request.node.iter_markers('hge_env') if marker.args[1] is not None}
|
||||
enabled_apis_str = hge_marker_env.get('HASURA_GRAPHQL_ENABLED_APIS')
|
||||
else:
|
||||
enabled_apis_str = os.environ.get('HASURA_GRAPHQL_ENABLED_APIS')
|
||||
if not enabled_apis_str:
|
||||
return None
|
||||
return set(enabled_apis_str.split(','))
|
||||
|
||||
@pytest.fixture(scope='class')
|
||||
def hge_ctx(request, hge_url, pg_url, hge_key, enabled_apis, hge_server):
|
||||
hge_ctx = HGECtx(hge_url, pg_url, hge_key, enabled_apis, request.config)
|
||||
|
||||
yield hge_ctx
|
||||
|
||||
@ -442,12 +459,6 @@ def auth_hook(hge_fixture_env: dict[str, str]):
|
||||
yield server
|
||||
auth_webhook_server.stop_server(server)
|
||||
|
||||
@pytest.fixture(scope='class')
|
||||
def streaming_subscriptions_fixtures(hge_ctx):
|
||||
if not hge_ctx.streaming_subscriptions:
|
||||
pytest.skip('These tests are meant to be run with --test-streaming-subscriptions set with pytest')
|
||||
return
|
||||
|
||||
@pytest.fixture(scope='class')
|
||||
def pro_tests_fixtures(hge_ctx):
|
||||
if not hge_ctx.pro_tests:
|
||||
|
@ -790,10 +790,9 @@ class HGECtxGQLServer:
|
||||
|
||||
class HGECtx:
|
||||
|
||||
def __init__(self, hge_url, pg_url, config):
|
||||
|
||||
def __init__(self, hge_url, pg_url, hge_key, enabled_apis, config):
|
||||
self.http = requests.Session()
|
||||
self.hge_key = config.getoption('--hge-key')
|
||||
self.hge_key = hge_key
|
||||
self.timeout = 120 # BigQuery can take a while
|
||||
self.hge_url = hge_url
|
||||
self.pg_url = pg_url
|
||||
@ -812,7 +811,6 @@ class HGECtx:
|
||||
self.hge_jwt_algo = "EdDSA"
|
||||
self.webhook_insecure = config.getoption('--test-webhook-insecure')
|
||||
self.may_skip_test_teardown = False
|
||||
self.streaming_subscriptions = config.getoption('--test-streaming-subscriptions')
|
||||
|
||||
# This will be GC'd, but we also explicitly dispose() in teardown()
|
||||
self.engine = sqlalchemy.create_engine(self.pg_url)
|
||||
@ -833,9 +831,6 @@ class HGECtx:
|
||||
self.default_backend = 'postgres'
|
||||
self.is_default_backend = self.backend == self.default_backend
|
||||
|
||||
enabled_apis_str = os.environ.get('HASURA_GRAPHQL_ENABLED_APIS')
|
||||
enabled_apis = set(enabled_apis_str.split(',')) if enabled_apis_str else None
|
||||
|
||||
env_version = os.getenv('VERSION')
|
||||
if env_version:
|
||||
self.version = env_version
|
||||
|
@ -80,6 +80,14 @@ services:
|
||||
volumes:
|
||||
- /var/lib/postgresql/data
|
||||
|
||||
citus-healthy:
|
||||
image: busybox
|
||||
command:
|
||||
- 'true'
|
||||
depends_on:
|
||||
citus:
|
||||
condition: service_healthy
|
||||
|
||||
mssql:
|
||||
# Uses a different image for arm64.
|
||||
image: ${MSSQL_IMAGE:-mcr.microsoft.com/mssql/server:2019-latest@sha256:a098c9ff6fbb8e1c9608ad7511fa42dba8d22e0d50b48302761717840ccc26af}
|
||||
|
@ -24,6 +24,7 @@ def hge_server(
|
||||
hge_bin: str,
|
||||
hge_port: int,
|
||||
hge_url: str,
|
||||
hge_key: Optional[str],
|
||||
hge_fixture_env: dict[str, str],
|
||||
pg_url: str,
|
||||
) -> Optional[str]:
|
||||
@ -35,6 +36,8 @@ def hge_server(
|
||||
**hge_marker_env,
|
||||
}
|
||||
|
||||
hge_key_args = ['--admin-secret', hge_key] if hge_key else []
|
||||
|
||||
print(f'Starting GraphQL Engine on {hge_url}...')
|
||||
hge_process = subprocess.Popen(
|
||||
args = [
|
||||
@ -43,6 +46,7 @@ def hge_server(
|
||||
'serve',
|
||||
'--server-port', str(hge_port),
|
||||
'--stringify-numeric-types',
|
||||
*hge_key_args,
|
||||
],
|
||||
env = env,
|
||||
)
|
||||
|
@ -6,6 +6,7 @@ norecursedirs = queries webhook test_upgrade
|
||||
xfail_strict = true
|
||||
markers =
|
||||
backend: The backends supported by the test case
|
||||
admin_secret: Generate and use an admin secret
|
||||
hge_env: Pass additional environment variables to the GraphQL Engine
|
||||
skip_server_upgrade_test: Tests with this marker should not be run as part of server upgrade test
|
||||
allow_server_upgrade_test: Add tests with this marker to server upgrade test, as far as they don't have the skip_server_upgarde_test market
|
||||
|
@ -30,7 +30,7 @@ if [[ "$(uname -m)" == 'arm64' ]]; then
|
||||
fi
|
||||
|
||||
docker compose rm -svf citus mssql postgres
|
||||
docker compose up -d citus mssql-healthcheck postgres-healthy
|
||||
docker compose up -d citus-healthy mssql-healthcheck postgres-healthy
|
||||
|
||||
HASURA_GRAPHQL_CITUS_SOURCE_URL="postgresql://postgres:hasura@localhost:$(docker compose port citus 5432 | sed -E 's/.*://')/postgres"
|
||||
HASURA_GRAPHQL_MSSQL_SOURCE_URL="DRIVER={ODBC Driver 17 for SQL Server};SERVER=localhost,$(docker compose port mssql 1433 | sed -E 's/.*://');Uid=sa;Pwd=Password!;"
|
||||
|
@ -49,12 +49,12 @@ else
|
||||
fi
|
||||
|
||||
echo "*** Building HGE ***"
|
||||
docker compose run hge-build
|
||||
docker compose run --rm hge-build
|
||||
|
||||
for SERVER_TEST_TO_RUN in "${SERVER_TESTS_TO_RUN[@]}"; do
|
||||
export SERVER_TEST_TO_RUN
|
||||
echo
|
||||
echo "*** Running test suite: ${SERVER_TEST_TO_RUN} ***"
|
||||
docker compose rm -svf citus mssql postgres # tear down databases beforehand
|
||||
docker compose run tests-py
|
||||
docker compose run --rm tests-py
|
||||
done
|
||||
|
@ -6,6 +6,7 @@ from context import PytestConf
|
||||
|
||||
pytestmark = [
|
||||
pytest.mark.usefixtures('auth_hook'),
|
||||
pytest.mark.admin_secret,
|
||||
pytest.mark.hge_env('HASURA_GRAPHQL_AUTH_HOOK_MODE', 'POST'),
|
||||
]
|
||||
|
||||
|
@ -12,18 +12,20 @@ def make_request(url, query):
|
||||
resp = requests.post(url, json=payload)
|
||||
return resp
|
||||
|
||||
@pytest.mark.hge_env('HASURA_GRAPHQL_EXPERIMENTAL_FEATURES', 'apollo_federation')
|
||||
@pytest.mark.usefixtures('per_class_tests_db_state')
|
||||
@pytest.mark.admin_secret
|
||||
@pytest.mark.hge_env('HASURA_GRAPHQL_EXPERIMENTAL_FEATURES', 'apollo_federation')
|
||||
class TestApolloFederation:
|
||||
|
||||
@classmethod
|
||||
def dir(cls):
|
||||
return 'queries/apollo_federation'
|
||||
|
||||
def test_apollo_federated_server_with_hge_only(self, hge_url: str):
|
||||
def test_apollo_federated_server_with_hge_only(self, hge_url: str, hge_key: str):
|
||||
# start the node server
|
||||
fed_server = NodeGraphQL(["node", "remote_schemas/nodejs/apollo_federated_server_with_hge_only.js"], env={
|
||||
'HGE_URL': hge_url,
|
||||
'HASURA_GRAPHQL_ADMIN_SECRET': hge_key,
|
||||
})
|
||||
fed_server.start()
|
||||
|
||||
@ -45,16 +47,16 @@ class TestApolloFederation:
|
||||
assert resp.status_code == 200, resp.text
|
||||
assert 'data' in resp.text
|
||||
|
||||
def test_apollo_federated_server_with_hge_and_apollo_graphql_server(self, hge_url: str):
|
||||
def test_apollo_federated_server_with_hge_and_apollo_graphql_server(self, hge_url: str, hge_key: str):
|
||||
# start the node servers
|
||||
server_1 = NodeGraphQL(["node", "remote_schemas/nodejs/apollo_server_1.js"], env={
|
||||
'HGE_URL': hge_url,
|
||||
})
|
||||
server_env = {
|
||||
fed_server = NodeGraphQL(["node", "remote_schemas/nodejs/apollo_federated_server_with_hge_and_server1.js"], env={
|
||||
'HGE_URL': hge_url,
|
||||
'OTHER_URL': server_1.url,
|
||||
}
|
||||
fed_server = NodeGraphQL(["node", "remote_schemas/nodejs/apollo_federated_server_with_hge_and_server1.js"], env=server_env)
|
||||
'HASURA_GRAPHQL_ADMIN_SECRET': hge_key,
|
||||
})
|
||||
|
||||
server_1.start()
|
||||
fed_server.start()
|
||||
@ -80,8 +82,8 @@ class TestApolloFederation:
|
||||
assert resp.status_code == 200, resp.text
|
||||
assert 'data' in resp.text
|
||||
|
||||
def test_apollo_federation_fields(self,hge_ctx):
|
||||
def test_apollo_federation_fields(self, hge_ctx):
|
||||
check_query_f(hge_ctx, self.dir() + '/root_fields.yaml')
|
||||
|
||||
def test_apollo_federation_entities(self,hge_ctx):
|
||||
def test_apollo_federation_entities(self, hge_ctx):
|
||||
check_query_f(hge_ctx, self.dir() + '/entities.yaml')
|
||||
|
@ -14,6 +14,7 @@ if not PytestConf.config.getoption("--test-auth-webhook-header"):
|
||||
pytest.skip("--test-auth-webhook-header flag is missing, skipping tests", allow_module_level=True)
|
||||
|
||||
@pytest.mark.usefixtures('auth_hook', 'per_class_tests_db_state')
|
||||
@pytest.mark.admin_secret
|
||||
class TestWebhookHeaderCookie(object):
|
||||
'''
|
||||
To run the test, run an instance of the auth_webhook server using `python3 auth_webhook_server.py`
|
||||
|
@ -1,10 +1,6 @@
|
||||
import pytest
|
||||
from context import PytestConf
|
||||
|
||||
if not PytestConf.config.getoption("--hge-key"):
|
||||
pytest.skip("--hge-key flag is missing, skipping tests", allow_module_level=True)
|
||||
|
||||
def v1qCompat(hge_ctx, q, headers = {}):
|
||||
def v1qCompat(hge_ctx, q):
|
||||
h = {'X-Hasura-Access-Key': hge_ctx.hge_key}
|
||||
resp = hge_ctx.http.post(
|
||||
hge_ctx.hge_url + "/v1/query",
|
||||
@ -13,6 +9,7 @@ def v1qCompat(hge_ctx, q, headers = {}):
|
||||
)
|
||||
return resp.status_code, resp.json()
|
||||
|
||||
@pytest.mark.admin_secret
|
||||
class TestGraphQLCompatAccessKey():
|
||||
|
||||
export_metadata = {
|
||||
|
@ -1,6 +1,5 @@
|
||||
import requests
|
||||
import pytest
|
||||
from context import PytestConf
|
||||
|
||||
"""
|
||||
|
||||
@ -25,6 +24,7 @@ def get_headers(hge_ctx, role='admin'):
|
||||
headers['x-hasura-role'] = role
|
||||
return headers
|
||||
|
||||
@pytest.mark.admin_secret
|
||||
@pytest.mark.hge_env('HASURA_GRAPHQL_ENABLED_APIS', 'metadata,graphql,developer,config,pgdump')
|
||||
class TestDevEndpoints:
|
||||
|
||||
|
@ -798,6 +798,7 @@ class TestGraphQLMutateEnums:
|
||||
# Tracking VOLATILE SQL functions as mutations, or queries (#1514)
|
||||
@pytest.mark.parametrize('transport', ['http', 'websocket'])
|
||||
@use_mutation_fixtures
|
||||
@pytest.mark.admin_secret
|
||||
@pytest.mark.hge_env('HASURA_GRAPHQL_INFER_FUNCTION_PERMISSIONS', 'false')
|
||||
class TestGraphQLMutationFunctions:
|
||||
@classmethod
|
||||
|
@ -1,12 +1,12 @@
|
||||
import pytest
|
||||
from validate import assert_response_code, check_query_f, check_query, get_conf_f
|
||||
from context import PytestConf
|
||||
|
||||
import json
|
||||
import textwrap
|
||||
import pytest
|
||||
import ruamel.yaml as yaml
|
||||
import textwrap
|
||||
import warnings
|
||||
|
||||
from context import PytestConf
|
||||
from validate import assert_response_code, check_query_f, get_conf_f
|
||||
|
||||
# Mark that all tests in this module can be run as server upgrade tests
|
||||
pytestmark = pytest.mark.allow_server_upgrade_test
|
||||
|
||||
@ -1303,6 +1303,7 @@ use_function_permission_fixtures = pytest.mark.usefixtures(
|
||||
|
||||
@pytest.mark.parametrize('transport', ['http', 'websocket'])
|
||||
@pytest.mark.usefixtures('per_method_tests_db_state')
|
||||
@pytest.mark.admin_secret
|
||||
@pytest.mark.hge_env('HASURA_GRAPHQL_INFER_FUNCTION_PERMISSIONS', 'false')
|
||||
class TestGraphQLQueryFunctionPermissions:
|
||||
@classmethod
|
||||
|
@ -410,7 +410,7 @@ def gen_rsa_key():
|
||||
|
||||
class TestSubscriptionJwtExpiry(object):
|
||||
|
||||
def test_jwt_expiry(self, hge_ctx, ws_client):
|
||||
def test_jwt_expiry(self, hge_ctx, hge_key, ws_client):
|
||||
curr_time = datetime.now()
|
||||
self.claims = {
|
||||
'sub': '1234567890',
|
||||
@ -433,7 +433,7 @@ class TestSubscriptionJwtExpiry(object):
|
||||
authz_header = mk_authz_header(hge_ctx.hge_jwt_conf, token)
|
||||
payload = dict()
|
||||
payload['headers'] = authz_header
|
||||
init_ws_conn(hge_ctx, ws_client, payload)
|
||||
init_ws_conn(hge_key, ws_client, payload)
|
||||
time.sleep(6)
|
||||
assert ws_client.remote_closed == True, ws_client.remote_closed
|
||||
|
||||
|
@ -7,6 +7,7 @@ from remote_server import NodeGraphQL
|
||||
from validate import check_query_f
|
||||
|
||||
pytestmark = [
|
||||
pytest.mark.admin_secret,
|
||||
pytest.mark.hge_env('HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS', 'true'),
|
||||
]
|
||||
|
||||
|
@ -6,6 +6,7 @@ from remote_server import NodeGraphQL
|
||||
from validate import check_query_f
|
||||
|
||||
pytestmark = [
|
||||
pytest.mark.admin_secret,
|
||||
pytest.mark.hge_env('HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS', 'true'),
|
||||
]
|
||||
|
||||
|
@ -1,111 +1,104 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import datetime
|
||||
import time
|
||||
import pytest
|
||||
import json
|
||||
import queue
|
||||
from validate import check_query_f
|
||||
from collections import OrderedDict
|
||||
from utils import insert_many
|
||||
import json
|
||||
import pytest
|
||||
import queue
|
||||
from ruamel.yaml import YAML
|
||||
import time
|
||||
import uuid
|
||||
|
||||
from validate import check_query_f
|
||||
from utils import insert_many
|
||||
|
||||
usefixtures = pytest.mark.usefixtures
|
||||
yaml=YAML(typ='safe', pure=True)
|
||||
|
||||
@pytest.fixture(scope='class')
|
||||
def ws_conn_init(hge_ctx, ws_client):
|
||||
init_ws_conn(hge_ctx, ws_client)
|
||||
usefixtures = pytest.mark.usefixtures
|
||||
|
||||
@pytest.fixture(scope='class')
|
||||
def ws_conn_init_graphql_ws(hge_ctx, ws_client_graphql_ws):
|
||||
init_graphql_ws_conn(hge_ctx, ws_client_graphql_ws)
|
||||
def ws_conn_init(hge_key, ws_client):
|
||||
init_ws_conn(hge_key, ws_client)
|
||||
|
||||
@pytest.fixture(scope='class')
|
||||
def ws_conn_init_graphql_ws(hge_key, ws_client_graphql_ws):
|
||||
init_graphql_ws_conn(hge_key, ws_client_graphql_ws)
|
||||
|
||||
'''
|
||||
Refer: https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_connection_init
|
||||
'''
|
||||
|
||||
def init_ws_conn(hge_ctx, ws_client, payload = None):
|
||||
if payload is None:
|
||||
payload = {}
|
||||
if hge_ctx.hge_key is not None:
|
||||
payload = {
|
||||
'headers' : {
|
||||
'X-Hasura-Admin-Secret': hge_ctx.hge_key
|
||||
}
|
||||
}
|
||||
|
||||
# This is used in other test files! Be careful when modifying it.
|
||||
def init_ws_conn(hge_key, ws_client, payload = None):
|
||||
init_msg = {
|
||||
'type': 'connection_init',
|
||||
'payload': payload,
|
||||
'payload': payload or ws_payload(hge_key),
|
||||
}
|
||||
ws_client.send(init_msg)
|
||||
ev = ws_client.get_ws_event(3)
|
||||
assert ev['type'] == 'connection_ack', ev
|
||||
|
||||
def init_graphql_ws_conn(hge_ctx, ws_client_graphql_ws, payload = None):
|
||||
if payload is None:
|
||||
payload = {}
|
||||
if hge_ctx.hge_key is not None:
|
||||
payload = {
|
||||
'headers' : {
|
||||
'X-Hasura-Admin-Secret': hge_ctx.hge_key
|
||||
}
|
||||
}
|
||||
|
||||
def init_graphql_ws_conn(hge_key, ws_client_graphql_ws):
|
||||
init_msg = {
|
||||
'type': 'connection_init',
|
||||
'payload': payload,
|
||||
'payload': ws_payload(hge_key),
|
||||
}
|
||||
ws_client_graphql_ws.send(init_msg)
|
||||
ev = ws_client_graphql_ws.get_ws_event(3)
|
||||
assert ev['type'] == 'connection_ack', ev
|
||||
|
||||
def get_explain_graphql_query_response(hge_ctx, query, variables, user_headers = {}):
|
||||
admin_secret = hge_ctx.hge_key
|
||||
def ws_payload(hge_key):
|
||||
if hge_key is not None:
|
||||
return {
|
||||
'headers': {
|
||||
'X-Hasura-Admin-Secret': hge_key,
|
||||
}
|
||||
}
|
||||
else:
|
||||
return {}
|
||||
|
||||
def get_explain_graphql_query_response(hge_ctx, hge_key, query, variables, user_headers = {}):
|
||||
headers = {}
|
||||
if admin_secret is not None:
|
||||
headers['X-Hasura-Admin-Secret'] = admin_secret
|
||||
if hge_key is not None:
|
||||
headers['X-Hasura-Admin-Secret'] = hge_key
|
||||
|
||||
request = { 'query': { 'query': query, 'variables': variables }, 'user': user_headers }
|
||||
status_code, response, _ = hge_ctx.anyq('/v1/graphql/explain', request, headers)
|
||||
assert status_code == 200, (request, status_code, response)
|
||||
return response
|
||||
|
||||
class TestSubscriptionCtrl(object):
|
||||
@pytest.mark.no_admin_secret
|
||||
class TestSubscriptionCtrlWithoutSecret(object):
|
||||
def test_connection(self, ws_client):
|
||||
ws_client.recreate_conn()
|
||||
init_ws_conn(None, ws_client)
|
||||
|
||||
def test_init_without_payload(self, hge_ctx, ws_client):
|
||||
if hge_ctx.hge_key is not None:
|
||||
pytest.skip("Payload is needed when admin secret is set")
|
||||
init_msg = {
|
||||
'type': 'connection_init'
|
||||
}
|
||||
ws_client.send(init_msg)
|
||||
ev = ws_client.get_ws_event(15)
|
||||
assert ev['type'] == 'connection_ack', ev
|
||||
|
||||
|
||||
'''
|
||||
Refer: https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_connection_init
|
||||
'''
|
||||
|
||||
def test_init(self, hge_ctx, ws_client):
|
||||
init_ws_conn(hge_ctx, ws_client)
|
||||
|
||||
'''
|
||||
Refer: https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_connection_terminate
|
||||
'''
|
||||
|
||||
def test_connection_terminate(self, hge_ctx, ws_client):
|
||||
obj = {
|
||||
'type': 'connection_terminate'
|
||||
}
|
||||
ws_client.send(obj)
|
||||
with pytest.raises(queue.Empty):
|
||||
ev = ws_client.get_ws_event(3)
|
||||
ws_client.get_ws_event(3)
|
||||
|
||||
@pytest.mark.admin_secret
|
||||
class TestSubscriptionCtrl(object):
|
||||
'''
|
||||
References:
|
||||
https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_connection_init
|
||||
https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_connection_terminate
|
||||
'''
|
||||
|
||||
def test_connection(self, hge_key, ws_client):
|
||||
ws_client.recreate_conn()
|
||||
init_ws_conn(hge_key, ws_client)
|
||||
|
||||
obj = {
|
||||
'type': 'connection_terminate'
|
||||
}
|
||||
ws_client.send(obj)
|
||||
with pytest.raises(queue.Empty):
|
||||
ws_client.get_ws_event(3)
|
||||
|
||||
@pytest.mark.backend('mssql', 'postgres')
|
||||
@usefixtures('per_class_tests_db_state', 'ws_conn_init')
|
||||
@pytest.mark.admin_secret
|
||||
class TestSubscriptionBasic:
|
||||
@classmethod
|
||||
def dir(cls):
|
||||
@ -129,6 +122,7 @@ class TestSubscriptionBasic:
|
||||
'''
|
||||
|
||||
def test_start(self, ws_client):
|
||||
id = str(uuid.uuid4())
|
||||
query = """
|
||||
subscription {
|
||||
hge_tests_test_t1(order_by: {c1: desc}, limit: 1) {
|
||||
@ -138,7 +132,7 @@ class TestSubscriptionBasic:
|
||||
}
|
||||
"""
|
||||
obj = {
|
||||
'id': '1',
|
||||
'id': id,
|
||||
'payload': {
|
||||
'query': query
|
||||
},
|
||||
@ -148,13 +142,13 @@ class TestSubscriptionBasic:
|
||||
'''
|
||||
Refer: https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_data
|
||||
'''
|
||||
ev = ws_client.get_ws_query_event('1',15)
|
||||
assert ev['type'] == 'data' and ev['id'] == '1', ev
|
||||
ev = ws_client.get_ws_query_event(id, 15)
|
||||
assert ev['type'] == 'data' and ev['id'] == id, ev
|
||||
|
||||
'''
|
||||
Refer https://github.com/apollographql/subscriptions-transport-ws/blob/01e0b2b65df07c52f5831cce5c858966ba095993/src/server.ts#L306
|
||||
'''
|
||||
@pytest.mark.skip(reason="refer https://github.com/hasura/graphql-engine/pull/387#issuecomment-421343098")
|
||||
@pytest.mark.skip(reason="refer to https://github.com/hasura/graphql-engine/pull/387#issuecomment-421343098")
|
||||
def test_start_duplicate(self, ws_client):
|
||||
self.test_start(ws_client)
|
||||
|
||||
@ -187,7 +181,7 @@ class TestSubscriptionBasic:
|
||||
Refer: https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_complete
|
||||
'''
|
||||
|
||||
def test_complete(self, hge_ctx, ws_client):
|
||||
def test_complete(self, ws_client):
|
||||
query = """
|
||||
query {
|
||||
hge_tests_test_t1(order_by: {c1: desc}, limit: 1) {
|
||||
@ -215,6 +209,7 @@ class TestSubscriptionBasic:
|
||||
## FIXME: There's an issue with the tests being parametrized with both
|
||||
## postgres and mssql data sources enabled(See issue #2084).
|
||||
@usefixtures('per_method_tests_db_state', 'ws_conn_init_graphql_ws')
|
||||
@pytest.mark.admin_secret
|
||||
class TestSubscriptionBasicGraphQLWS:
|
||||
@classmethod
|
||||
def dir(cls):
|
||||
@ -224,10 +219,10 @@ class TestSubscriptionBasicGraphQLWS:
|
||||
def test_negative(self, hge_ctx, transport):
|
||||
check_query_f(hge_ctx, self.dir() + '/negative_test.yaml', transport, gqlws=True)
|
||||
|
||||
def test_connection_error(self, hge_ctx, ws_client_graphql_ws):
|
||||
def test_connection_error(self, hge_key, ws_client_graphql_ws):
|
||||
if ws_client_graphql_ws.get_conn_close_state():
|
||||
ws_client_graphql_ws.create_conn()
|
||||
if hge_ctx.hge_key == None:
|
||||
if hge_key == None:
|
||||
ws_client_graphql_ws.init()
|
||||
else:
|
||||
ws_client_graphql_ws.init_as_admin()
|
||||
@ -236,13 +231,15 @@ class TestSubscriptionBasicGraphQLWS:
|
||||
ev = ws_client_graphql_ws.get_conn_close_state()
|
||||
assert ev == True, ev
|
||||
|
||||
def test_start(self, hge_ctx, ws_client_graphql_ws):
|
||||
def test_start(self, hge_key, ws_client_graphql_ws):
|
||||
if ws_client_graphql_ws.get_conn_close_state():
|
||||
ws_client_graphql_ws.create_conn()
|
||||
if hge_ctx.hge_key == None:
|
||||
if hge_key == None:
|
||||
ws_client_graphql_ws.init()
|
||||
else:
|
||||
ws_client_graphql_ws.init_as_admin()
|
||||
|
||||
id = str(uuid.uuid4())
|
||||
query = """
|
||||
subscription {
|
||||
hge_tests_test_t1(order_by: {c1: desc}, limit: 1) {
|
||||
@ -252,30 +249,30 @@ class TestSubscriptionBasicGraphQLWS:
|
||||
}
|
||||
"""
|
||||
obj = {
|
||||
'id': '1',
|
||||
'id': id,
|
||||
'payload': {
|
||||
'query': query
|
||||
},
|
||||
'type': 'subscribe'
|
||||
}
|
||||
ws_client_graphql_ws.send(obj)
|
||||
ev = ws_client_graphql_ws.get_ws_query_event('1',15)
|
||||
assert ev['type'] == 'next' and ev['id'] == '1', ev
|
||||
ev = ws_client_graphql_ws.get_ws_query_event(id, 15)
|
||||
assert ev['type'] == 'next' and ev['id'] == id, ev
|
||||
|
||||
@pytest.mark.skip(reason="refer https://github.com/hasura/graphql-engine/pull/387#issuecomment-421343098")
|
||||
def test_start_duplicate(self, hge_ctx, ws_client_graphql_ws):
|
||||
@pytest.mark.skip(reason="refer to https://github.com/hasura/graphql-engine/pull/387#issuecomment-421343098")
|
||||
def test_start_duplicate(self, hge_key, ws_client_graphql_ws):
|
||||
if ws_client_graphql_ws.get_conn_close_state():
|
||||
ws_client_graphql_ws.create_conn()
|
||||
if hge_ctx.hge_key == None:
|
||||
if hge_key == None:
|
||||
ws_client_graphql_ws.init()
|
||||
else:
|
||||
ws_client_graphql_ws.init_as_admin()
|
||||
self.test_start(ws_client_graphql_ws)
|
||||
self.test_start(hge_key, ws_client_graphql_ws)
|
||||
|
||||
def test_stop_without_id(self, hge_ctx, ws_client_graphql_ws):
|
||||
def test_stop_without_id(self, hge_key, ws_client_graphql_ws):
|
||||
if ws_client_graphql_ws.get_conn_close_state():
|
||||
ws_client_graphql_ws.create_conn()
|
||||
if hge_ctx.hge_key == None:
|
||||
if hge_key == None:
|
||||
ws_client_graphql_ws.init()
|
||||
else:
|
||||
ws_client_graphql_ws.init_as_admin()
|
||||
@ -287,10 +284,10 @@ class TestSubscriptionBasicGraphQLWS:
|
||||
ev = ws_client_graphql_ws.get_conn_close_state()
|
||||
assert ev == True, ev
|
||||
|
||||
def test_stop(self, hge_ctx, ws_client_graphql_ws):
|
||||
def test_stop(self, hge_key, ws_client_graphql_ws):
|
||||
if ws_client_graphql_ws.get_conn_close_state():
|
||||
ws_client_graphql_ws.create_conn()
|
||||
if hge_ctx.hge_key == None:
|
||||
if hge_key == None:
|
||||
ws_client_graphql_ws.init()
|
||||
else:
|
||||
ws_client_graphql_ws.init_as_admin()
|
||||
@ -303,10 +300,10 @@ class TestSubscriptionBasicGraphQLWS:
|
||||
with pytest.raises(queue.Empty):
|
||||
ev = ws_client_graphql_ws.get_ws_event(3)
|
||||
|
||||
def test_start_after_stop(self, hge_ctx, ws_client_graphql_ws):
|
||||
def test_start_after_stop(self, hge_key, hge_ctx, ws_client_graphql_ws):
|
||||
if ws_client_graphql_ws.get_conn_close_state():
|
||||
ws_client_graphql_ws.create_conn()
|
||||
if hge_ctx.hge_key == None:
|
||||
if hge_key == None:
|
||||
ws_client_graphql_ws.init()
|
||||
else:
|
||||
ws_client_graphql_ws.init_as_admin()
|
||||
@ -316,10 +313,11 @@ class TestSubscriptionBasicGraphQLWS:
|
||||
ws_client_graphql_ws.clear_queue()
|
||||
self.test_stop(hge_ctx, ws_client_graphql_ws)
|
||||
|
||||
def test_complete(self, hge_ctx, ws_client_graphql_ws):
|
||||
def test_complete(self, hge_key, ws_client_graphql_ws):
|
||||
id = str(uuid.uuid4())
|
||||
if ws_client_graphql_ws.get_conn_close_state():
|
||||
ws_client_graphql_ws.create_conn()
|
||||
if hge_ctx.hge_key == None:
|
||||
if hge_key == None:
|
||||
ws_client_graphql_ws.init()
|
||||
else:
|
||||
ws_client_graphql_ws.init_as_admin()
|
||||
@ -332,27 +330,28 @@ class TestSubscriptionBasicGraphQLWS:
|
||||
}
|
||||
"""
|
||||
obj = {
|
||||
'id': '2',
|
||||
'id': id,
|
||||
'payload': {
|
||||
'query': query
|
||||
},
|
||||
'type': 'subscribe'
|
||||
}
|
||||
ws_client_graphql_ws.send(obj)
|
||||
ev = ws_client_graphql_ws.get_ws_query_event('2',3)
|
||||
assert ev['type'] == 'next' and ev['id'] == '2', ev
|
||||
ev = ws_client_graphql_ws.get_ws_query_event(id, 3)
|
||||
assert ev['type'] == 'next' and ev['id'] == id, ev
|
||||
# Check for complete type
|
||||
ev = ws_client_graphql_ws.get_ws_query_event('2',3)
|
||||
assert ev['type'] == 'complete' and ev['id'] == '2', ev
|
||||
ev = ws_client_graphql_ws.get_ws_query_event(id, 3)
|
||||
assert ev['type'] == 'complete' and ev['id'] == id, ev
|
||||
|
||||
@usefixtures('per_method_tests_db_state','ws_conn_init')
|
||||
@pytest.mark.admin_secret
|
||||
class TestSubscriptionLiveQueries:
|
||||
|
||||
@classmethod
|
||||
def dir(cls):
|
||||
return 'queries/subscriptions/live_queries'
|
||||
|
||||
def test_live_queries(self, hge_ctx, ws_client):
|
||||
def test_live_queries(self, hge_key, ws_client):
|
||||
'''
|
||||
Create connection using connection_init
|
||||
'''
|
||||
@ -375,8 +374,8 @@ class TestSubscriptionLiveQueries:
|
||||
for i, resultLimit in queries:
|
||||
query = queryTmplt.replace('{0}',str(i))
|
||||
headers={}
|
||||
if hge_ctx.hge_key is not None:
|
||||
headers['X-Hasura-Admin-Secret'] = hge_ctx.hge_key
|
||||
if hge_key is not None:
|
||||
headers['X-Hasura-Admin-Secret'] = hge_key
|
||||
subscrPayload = { 'query': query, 'variables': { 'result_limit': resultLimit } }
|
||||
respLive = ws_client.send_query(subscrPayload, query_id='live_'+str(i), headers=headers, timeout=15)
|
||||
liveQs.append(respLive)
|
||||
@ -427,14 +426,15 @@ class TestSubscriptionLiveQueries:
|
||||
with pytest.raises(queue.Empty):
|
||||
ev = ws_client.get_ws_event(3)
|
||||
|
||||
@usefixtures('per_method_tests_db_state','ws_conn_init','streaming_subscriptions_fixtures')
|
||||
@usefixtures('per_method_tests_db_state', 'ws_conn_init')
|
||||
@pytest.mark.hge_env('HASURA_GRAPHQL_EXPERIMENTAL_FEATURES', 'streaming_subscriptions')
|
||||
class TestStreamingSubscription:
|
||||
|
||||
@classmethod
|
||||
def dir(cls):
|
||||
return 'queries/subscriptions/streaming'
|
||||
|
||||
def test_basic_streaming_subscription_existing_static_data(self, hge_ctx, ws_client):
|
||||
def test_basic_streaming_subscription_existing_static_data(self, hge_key, hge_ctx, ws_client):
|
||||
'''
|
||||
Create connection using connection_init
|
||||
'''
|
||||
@ -455,8 +455,8 @@ class TestStreamingSubscription:
|
||||
for i in range(10):
|
||||
articles_to_insert.append({"id": i + 1, "title": "Article title {}".format(i + 1)})
|
||||
insert_many(hge_ctx, {"schema": "hge_tests", "name": "articles"}, articles_to_insert)
|
||||
if hge_ctx.hge_key is not None:
|
||||
headers['X-Hasura-Admin-Secret'] = hge_ctx.hge_key
|
||||
if hge_key is not None:
|
||||
headers['X-Hasura-Admin-Secret'] = hge_key
|
||||
subscrPayload = { 'query': query, 'variables': { 'batch_size': 2 } }
|
||||
respLive = ws_client.send_query(subscrPayload, query_id='stream_1', headers=headers, timeout=15)
|
||||
liveQs.append(respLive)
|
||||
@ -478,7 +478,7 @@ class TestStreamingSubscription:
|
||||
with pytest.raises(queue.Empty):
|
||||
ev = ws_client.get_ws_event(3)
|
||||
|
||||
def test_streaming_subscriptions_with_concurrent_data_inserts(self, hge_ctx, ws_client):
|
||||
def test_streaming_subscriptions_with_concurrent_data_inserts(self, ws_client):
|
||||
'''
|
||||
Create connection using connection_init
|
||||
'''
|
||||
@ -534,7 +534,7 @@ class TestStreamingSubscription:
|
||||
with pytest.raises(queue.Empty):
|
||||
ev = ws_client.get_ws_event(3)
|
||||
|
||||
def test_streaming_subscription_with_custom_name_set_for_cursor(self, hge_ctx, ws_client):
|
||||
def test_streaming_subscription_with_custom_name_set_for_cursor(self, hge_key, ws_client):
|
||||
'''
|
||||
Create connection using connection_init
|
||||
'''
|
||||
@ -551,8 +551,8 @@ class TestStreamingSubscription:
|
||||
|
||||
liveQs = []
|
||||
headers={}
|
||||
if hge_ctx.hge_key is not None:
|
||||
headers['X-Hasura-Admin-Secret'] = hge_ctx.hge_key
|
||||
if hge_key is not None:
|
||||
headers['X-Hasura-Admin-Secret'] = hge_key
|
||||
subscrPayload = { 'query': query, 'variables': { 'batch_size': 1 } }
|
||||
respLive = ws_client.send_query(subscrPayload, query_id='stream_1', headers=headers, timeout=15)
|
||||
liveQs.append(respLive)
|
||||
@ -574,16 +574,15 @@ class TestStreamingSubscription:
|
||||
with pytest.raises(queue.Empty):
|
||||
ev = ws_client.get_ws_event(3)
|
||||
|
||||
|
||||
|
||||
@usefixtures('per_method_tests_db_state','ws_conn_init_graphql_ws')
|
||||
@usefixtures('per_method_tests_db_state', 'ws_conn_init_graphql_ws')
|
||||
@pytest.mark.admin_secret
|
||||
class TestSubscriptionLiveQueriesForGraphQLWS:
|
||||
|
||||
@classmethod
|
||||
def dir(cls):
|
||||
return 'queries/subscriptions/live_queries'
|
||||
|
||||
def test_live_queries(self, hge_ctx, ws_client_graphql_ws):
|
||||
def test_live_queries(self, hge_key, ws_client_graphql_ws):
|
||||
'''
|
||||
Create connection using connection_init
|
||||
'''
|
||||
@ -606,8 +605,8 @@ class TestSubscriptionLiveQueriesForGraphQLWS:
|
||||
for i, resultLimit in queries:
|
||||
query = queryTmplt.replace('{0}',str(i))
|
||||
headers={}
|
||||
if hge_ctx.hge_key is not None:
|
||||
headers['X-Hasura-Admin-Secret'] = hge_ctx.hge_key
|
||||
if hge_key is not None:
|
||||
headers['X-Hasura-Admin-Secret'] = hge_key
|
||||
subscrPayload = { 'query': query, 'variables': { 'result_limit': resultLimit } }
|
||||
respLive = ws_client_graphql_ws.send_query(subscrPayload, query_id='live_'+str(i), headers=headers, timeout=15)
|
||||
liveQs.append(respLive)
|
||||
@ -658,13 +657,14 @@ class TestSubscriptionLiveQueriesForGraphQLWS:
|
||||
|
||||
@pytest.mark.backend('mssql', 'postgres')
|
||||
@usefixtures('per_class_tests_db_state')
|
||||
@pytest.mark.admin_secret
|
||||
class TestSubscriptionMultiplexingPostgresMSSQL:
|
||||
|
||||
@classmethod
|
||||
def dir(cls):
|
||||
return 'queries/subscriptions/multiplexing'
|
||||
|
||||
def test_extraneous_session_variables_are_discarded_from_query(self, hge_ctx):
|
||||
def test_extraneous_session_variables_are_discarded_from_query(self, hge_key, hge_ctx):
|
||||
with open(self.dir() + '/articles_query.yaml') as c:
|
||||
config = yaml.load(c)
|
||||
|
||||
@ -673,7 +673,7 @@ class TestSubscriptionMultiplexingPostgresMSSQL:
|
||||
"X-Hasura-Role":"public",
|
||||
"X-Hasura-User-Id":"1" # extraneous session variable
|
||||
}
|
||||
response = get_explain_graphql_query_response(hge_ctx, query, {}, session_variables)
|
||||
response = get_explain_graphql_query_response(hge_ctx, hge_key, query, {}, session_variables)
|
||||
# The input session variables should be ignored because the only check for the role is
|
||||
# if `is_public` is `true`
|
||||
assert response["variables"]["session"] == {}, response["variables"]
|
||||
@ -683,35 +683,37 @@ class TestSubscriptionMultiplexingPostgresMSSQL:
|
||||
"X-Hasura-User-Id":"1",
|
||||
"X-Hasura-Allowed-Ids":"{1,3,4}" # extraneous session variable
|
||||
}
|
||||
response = get_explain_graphql_query_response(hge_ctx, query, {}, session_variables)
|
||||
response = get_explain_graphql_query_response(hge_ctx, hge_key, query, {}, session_variables)
|
||||
# The input session variable should not be ignored because the `user` role can only
|
||||
# select those roles where `user_id = X-Hasura-User-Id`
|
||||
assert response["variables"]["session"] == {'x-hasura-user-id':"1"}, response["variables"]
|
||||
|
||||
# test case for https://github.com/hasura/graphql-engine-mono/issues/3689
|
||||
@usefixtures('per_class_tests_db_state')
|
||||
@pytest.mark.admin_secret
|
||||
class TestSubscriptionMultiplexingPostgres:
|
||||
|
||||
@classmethod
|
||||
def dir(cls):
|
||||
return 'queries/subscriptions/multiplexing'
|
||||
|
||||
def test_simple_variables_are_parameterized(self, hge_ctx):
|
||||
def test_simple_variables_are_parameterized(self, hge_key, hge_ctx):
|
||||
with open(self.dir() + '/articles_query_simple_variable.yaml') as c:
|
||||
config = yaml.load(c)
|
||||
|
||||
response = get_explain_graphql_query_response(hge_ctx, config['query'], config['variables'], {})
|
||||
response = get_explain_graphql_query_response(hge_ctx, hge_key, config['query'], config['variables'], {})
|
||||
assert response["variables"]["synthetic"] == ['1'], response["variables"]
|
||||
|
||||
def test_array_variables_are_parameterized(self, hge_ctx):
|
||||
def test_array_variables_are_parameterized(self, hge_key, hge_ctx):
|
||||
with open(self.dir() + '/articles_query_array_variable.yaml') as c:
|
||||
config = yaml.load(c)
|
||||
|
||||
response = get_explain_graphql_query_response(hge_ctx, config['query'], config['variables'], {})
|
||||
response = get_explain_graphql_query_response(hge_ctx, hge_key, config['query'], config['variables'], {})
|
||||
assert response["variables"]["synthetic"] == ['{1,2,3}'], response["variables"]
|
||||
|
||||
@pytest.mark.backend('postgres')
|
||||
@usefixtures('per_class_tests_db_state', 'ws_conn_init')
|
||||
@pytest.mark.admin_secret
|
||||
class TestSubscriptionUDFWithSessionArg:
|
||||
"""
|
||||
Test a user-defined function which uses the entire session variables as argument
|
||||
@ -730,11 +732,11 @@ class TestSubscriptionUDFWithSessionArg:
|
||||
def dir(cls):
|
||||
return 'queries/subscriptions/udf_session_args'
|
||||
|
||||
def test_user_defined_function_with_session_argument(self, hge_ctx, ws_client):
|
||||
def test_user_defined_function_with_session_argument(self, hge_key, ws_client):
|
||||
ws_client.init_as_admin()
|
||||
headers = {'x-hasura-role': 'user', 'x-hasura-user-id': '42'}
|
||||
if hge_ctx.hge_key is not None:
|
||||
headers['X-Hasura-Admin-Secret'] = hge_ctx.hge_key
|
||||
if hge_key is not None:
|
||||
headers['X-Hasura-Admin-Secret'] = hge_key
|
||||
payload = {'query': self.query}
|
||||
resp = ws_client.send_query(payload, headers=headers, timeout=15)
|
||||
ev = next(resp)
|
||||
@ -743,6 +745,7 @@ class TestSubscriptionUDFWithSessionArg:
|
||||
|
||||
@pytest.mark.backend('mssql', 'postgres')
|
||||
@usefixtures('per_class_tests_db_state', 'ws_conn_init')
|
||||
@pytest.mark.admin_secret
|
||||
class TestSubscriptionCustomizedSourceMSSQLPostgres:
|
||||
@classmethod
|
||||
def dir(cls):
|
||||
@ -754,7 +757,8 @@ class TestSubscriptionCustomizedSourceMSSQLPostgres:
|
||||
Refer: https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_complete
|
||||
'''
|
||||
|
||||
def test_complete(self, hge_ctx, ws_client):
|
||||
def test_complete(self, ws_client):
|
||||
id = str(uuid.uuid4())
|
||||
query = """
|
||||
subscription MySubscription {
|
||||
a: my_source {
|
||||
@ -766,7 +770,7 @@ class TestSubscriptionCustomizedSourceMSSQLPostgres:
|
||||
}
|
||||
"""
|
||||
obj = {
|
||||
'id': '1',
|
||||
'id': id,
|
||||
'payload': {
|
||||
'query': query
|
||||
},
|
||||
@ -776,11 +780,11 @@ class TestSubscriptionCustomizedSourceMSSQLPostgres:
|
||||
'''
|
||||
Refer: https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md#gql_data
|
||||
'''
|
||||
ev = ws_client.get_ws_query_event('1',15)
|
||||
assert ev['type'] == 'data' and ev['id'] == '1', ev
|
||||
ev = ws_client.get_ws_query_event(id, 15)
|
||||
assert ev['type'] == 'data' and ev['id'] == id, ev
|
||||
assert ev['payload']['data']['a'] == OrderedDict([('b', [OrderedDict([('id', 1), ('name', 'Author 1')]), OrderedDict([('id', 2), ('name', 'Author 2')])])]), ev
|
||||
|
||||
def test_double_alias(self, hge_ctx, ws_client):
|
||||
def test_double_alias(self, ws_client):
|
||||
'''
|
||||
This should give an error even though @_multiple_top_level_fields is specified.
|
||||
The two different aliases for `my_source` mean that we would have to wrap different
|
||||
@ -819,6 +823,7 @@ class TestSubscriptionCustomizedSourceMSSQLPostgres:
|
||||
|
||||
@pytest.mark.backend('mssql')
|
||||
@usefixtures('per_class_tests_db_state', 'ws_conn_init')
|
||||
@pytest.mark.admin_secret
|
||||
class TestSubscriptionMSSQLChunkedResults:
|
||||
@classmethod
|
||||
def dir(cls):
|
||||
|
@ -19,7 +19,7 @@ usefixtures = pytest.mark.usefixtures
|
||||
def ws_conn_recreate(ws_client):
|
||||
ws_client.recreate_conn()
|
||||
|
||||
def connect_with(hge_ctx, ws_client, headers):
|
||||
def connect_with(hge_key, ws_client, headers):
|
||||
headers['X-Hasura-Role'] = 'user'
|
||||
headers['X-Hasura-User-Id'] = '1234321'
|
||||
headers['X-Hasura-Auth-Mode'] = 'webhook'
|
||||
@ -27,22 +27,22 @@ def connect_with(hge_ctx, ws_client, headers):
|
||||
token = base64.b64encode(json.dumps(headers).encode('utf-8')).decode('utf-8')
|
||||
headers['Authorization'] = 'Bearer ' + token
|
||||
payload = {'headers': headers}
|
||||
init_ws_conn(hge_ctx, ws_client, payload)
|
||||
init_ws_conn(hge_key, ws_client, payload)
|
||||
|
||||
EXPIRE_TIME_FORMAT = '%a, %d %b %Y %T GMT'
|
||||
|
||||
|
||||
@usefixtures('ws_conn_recreate')
|
||||
class TestWebhookSubscriptionExpiry(object):
|
||||
def test_expiry_with_no_header(self, hge_ctx, ws_client):
|
||||
def test_expiry_with_no_header(self, hge_key, ws_client):
|
||||
# no expiry time => the connextion will remain alive
|
||||
connect_with(hge_ctx, ws_client, {})
|
||||
connect_with(hge_key, ws_client, {})
|
||||
time.sleep(5)
|
||||
assert ws_client.remote_closed == False, ws_client.remote_closed
|
||||
|
||||
def test_expiry_with_expires_header(self, hge_ctx, ws_client):
|
||||
def test_expiry_with_expires_header(self, hge_key, ws_client):
|
||||
exp = datetime.utcnow() + timedelta(seconds=6)
|
||||
connect_with(hge_ctx, ws_client, {
|
||||
connect_with(hge_key, ws_client, {
|
||||
'Expires': exp.strftime(EXPIRE_TIME_FORMAT)
|
||||
})
|
||||
time.sleep(4)
|
||||
@ -50,8 +50,8 @@ class TestWebhookSubscriptionExpiry(object):
|
||||
time.sleep(4)
|
||||
assert ws_client.remote_closed == True, ws_client.remote_closed
|
||||
|
||||
def test_expiry_with_cache_control(self, hge_ctx, ws_client):
|
||||
connect_with(hge_ctx, ws_client, {
|
||||
def test_expiry_with_cache_control(self, hge_key, ws_client):
|
||||
connect_with(hge_key, ws_client, {
|
||||
'Cache-Control': 'max-age=6'
|
||||
})
|
||||
time.sleep(4)
|
||||
@ -59,9 +59,9 @@ class TestWebhookSubscriptionExpiry(object):
|
||||
time.sleep(4)
|
||||
assert ws_client.remote_closed == True, ws_client.remote_closed
|
||||
|
||||
def test_expiry_with_both(self, hge_ctx, ws_client):
|
||||
def test_expiry_with_both(self, hge_key, ws_client):
|
||||
exp = datetime.utcnow() + timedelta(seconds=6)
|
||||
connect_with(hge_ctx, ws_client, {
|
||||
connect_with(hge_key, ws_client, {
|
||||
'Expires': exp.strftime(EXPIRE_TIME_FORMAT),
|
||||
'Cache-Control': 'max-age=10',
|
||||
})
|
||||
@ -73,12 +73,12 @@ class TestWebhookSubscriptionExpiry(object):
|
||||
time.sleep(4)
|
||||
assert ws_client.remote_closed == True, ws_client.remote_closed
|
||||
|
||||
def test_expiry_with_parse_error(self, hge_ctx, ws_client):
|
||||
def test_expiry_with_parse_error(self, hge_key, ws_client):
|
||||
exp = datetime.utcnow() + timedelta(seconds=3)
|
||||
connect_with(hge_ctx, ws_client, {
|
||||
connect_with(hge_key, ws_client, {
|
||||
'Expires': exp.strftime('%a, %d %m %Y %T UTC'),
|
||||
'Cache-Control': 'maxage=3',
|
||||
})
|
||||
# neither will parse, the connection will remain alive
|
||||
time.sleep(5)
|
||||
assert ws_client.remote_closed == False, ws_client.remote_closed
|
||||
assert ws_client.remote_closed == False, ws_client.remote_closed
|
||||
|
Loading…
Reference in New Issue
Block a user