Wraps Hasura GraphQL Engine testing patterns: docker-compose test instance, the metadata API for declarative schema/permission setup, x-hasura-role and x-hasura-user-id session headers for role-based permission tests, the v1/graphql endpoint via curl/HTTPie/native HTTP clients, and the role-by-table-by-operation permission-matrix pattern. Use for a metadata-driven Hasura engine where row-level permissions dominate; for a code-first server runtime harness use graphql-yoga-tests, apollo-server-tests, or mercurius-tests instead, not this skill.
75
94%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
High
Do not use without reviewing
Per hasura.io/docs/2.0/auth/authorization/quickstart/, Hasura permissions are configured per table, role, and operation (select / insert / update / delete), with row- filter expressions and column-level scopes.
The testable concerns are different from Apollo / Yoga:
x-hasura-role + custom claims and assert the response shape.cross-tenant-data-leak-tests in the qa-multi-tenancy plugin).hasura/metadata/ changes.docker compose -f docker-compose.test.yml up -d)
with introspection disabled and the console off./v1/metadata API or hasura metadata apply./v1/graphql with the admin secret plus an x-hasura-role
override (and x-hasura-user-id / custom claims) to act as any role.extensions.code = "permission-error" (or affected_rows: 0).-v and reset metadata between suites.# docker-compose.test.yml
services:
postgres:
image: postgres:16
environment:
POSTGRES_PASSWORD: postgrespassword
hasura:
image: hasura/graphql-engine:v2.42.0
ports: ["8080:8080"]
depends_on: [postgres]
environment:
HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:postgrespassword@postgres:5432/postgres
HASURA_GRAPHQL_ADMIN_SECRET: test-secret
HASURA_GRAPHQL_DISABLE_INTROSPECTION_PUBLIC_API: "true" # per introspection-attack-surface-reference
HASURA_GRAPHQL_ENABLE_CONSOLE: "false"docker compose -f docker-compose.test.yml up -dPer Hasura docs, the metadata API at /v1/metadata:
curl -X POST http://localhost:8080/v1/metadata \
-H "x-hasura-admin-secret: test-secret" \
-H "Content-Type: application/json" \
-d @hasura/metadata-fixture.jsonmetadata-fixture.json contains the declarative permission
rules being tested.
Or via hasura CLI:
hasura migrate apply --endpoint http://localhost:8080 --admin-secret test-secret
hasura metadata apply --endpoint http://localhost:8080 --admin-secret test-secretTests act as any role via admin secret + x-hasura-role override, and a full
per-role x per-table x per-operation audit is generated from a checked-in fixture.
Both patterns - the httpx by-role queries and the parametrized matrix - are in
references/permission-matrix-tests.md.
Scenario: a new user role must see only its own rows in the user table.
user a select permission on user filtered by
id = X-Hasura-User-Id; apply it with hasura metadata apply.{ user { id name } } to /v1/graphql with headers x-hasura-admin-secret,
x-hasura-role: user, x-hasura-user-id: 3.status_code == 200 and every returned row has id == 3 - the row filter
held.x-hasura-role: admin (no user-id) and assert
len(rows) > 1 - admin is not restricted.Result: one pair of requests proves the row-filter rule for the restricted role and confirms it does not leak into the admin role.
docker compose -f docker-compose.test.yml up -d
hasura metadata apply --endpoint http://localhost:8080 --admin-secret test-secret
pytest tests/hasura/
docker compose -f docker-compose.test.yml down -vHasura returns standard GraphQL response format:
{
"data": { "user": [{"id": 3, "name": "alice"}] },
"errors": [{"message": "user.id: permission has failed", "extensions": {"code": "permission-error"}}]
}Permission failures use extensions.code = "permission-error".
Assertion patterns:
def test_user_cannot_update_other_users_row():
resp = httpx.post(ENDPOINT, headers={
"x-hasura-admin-secret": "test-secret",
"x-hasura-role": "user",
"x-hasura-user-id": "3",
}, json={
"query": "mutation { update_user_by_pk(pk_columns: {id: 4}, _set: {name: \"hacked\"}) { id } }"
})
body = resp.json()
# Either errors out OR returns affected_rows: 0 depending on permission setup
if "errors" in body:
assert any(
"permission" in e["extensions"].get("code", "")
for e in body["errors"]
)
else:
assert body["data"]["update_user_by_pk"] is None # row was filtered outjobs:
hasura-permission-matrix:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env: { POSTGRES_PASSWORD: postgres }
ports: [5432]
hasura:
image: hasura/graphql-engine:v2.42.0
env:
HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:postgres@postgres:5432/postgres
HASURA_GRAPHQL_ADMIN_SECRET: ci-secret
HASURA_GRAPHQL_DISABLE_INTROSPECTION_PUBLIC_API: "true"
ports: [8080]
steps:
- uses: actions/checkout@v5
- run: |
npm install -g hasura-cli
hasura migrate apply --endpoint http://localhost:8080 --admin-secret ci-secret
hasura metadata apply --endpoint http://localhost:8080 --admin-secret ci-secret
- run: pytest tests/hasura/ --tb=short| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Tests run against shared Hasura instance | Permission changes leak between tests | Per-test or per-suite ephemeral DB + metadata reset |
Skipping HASURA_GRAPHQL_DISABLE_INTROSPECTION_PUBLIC_API in CI | Production-config drift; introspection assertions don't hold | Set in test docker-compose |
Permission tests using admin secret without x-hasura-role override | Tests run as admin -> bypass all permissions | Always add x-hasura-role |
| Hardcoded user IDs across tests | One test mutates user 3 -> next test stale | Per-test user seeding |
| Skipping insert / update / delete tests | Permission rules differ per operation | Cover the full matrix |
| Not testing JWT path | Admin-secret-override bypasses production auth flow | One smoke test using real JWT against HASURA_GRAPHQL_JWT_SECRET config |
| Permission matrix in code only | PR reviewers can't see what changes | Matrix as a checked-in YAML / JSON fixture |
| Tests don't reset metadata between suites | Migration drift between test runs | hasura metadata clear + reapply in setup |
EXPLAIN queries via Hasura's
introspection - admin-only).introspection-attack-surface-reference.cross-tenant-data-leak-tests,
row-level-security-postgres-reference.apollo-server-tests,
graphql-yoga-tests,
mercurius-tests,
pothos-builder-tests.