ENSv2 GraphQL API Devnet Integration Test Scaffolding#1693
ENSv2 GraphQL API Devnet Integration Test Scaffolding#1693
Conversation
…ration tests Adds prismjs+chalk syntax highlighting for GraphQL/JSON output, a request helper with pretty logging, and parameterized domain resolution tests covering all devnet names. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract DEVNET_NAMES and DEVNET_ETH_LABELS into shared test util. Add Domain.subdomains, Account.domains, and Registry.domains tests verifying devnet state. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (5)
📝 WalkthroughWalkthroughThis PR adds integration-test infrastructure and suites: new Vitest integration configs and npm script, excludes integration tests from default runs, introduces integration tests for ENS GraphQL (accounts, domains, registry, queries), and provides test helpers, devnet constants, syntax-highlighting, and a global health-check setup. Changes
Sequence Diagram(s)sequenceDiagram
participant Runner as "Vitest (integration project)"
participant Setup as "global-setup.ts (health-check)"
participant Client as "Test GraphQL client"
participant ENSAPI as "ensapi GraphQL server"
participant Datasource as "Datasource / ENSv2 Registry"
Runner->>Setup: invoke setup()
Setup->>Client: send introspection-style query
Client->>ENSAPI: HTTP GraphQL request
ENSAPI->>Datasource: query registry / resolve names
Datasource-->>ENSAPI: return domain/registry data
ENSAPI-->>Client: GraphQL response
Client-->>Setup: return success
Runner->>Client: run integration tests (queries)
Client->>ENSAPI: execute test queries
ENSAPI->>Datasource: fetch/resolve domain data
Datasource-->>ENSAPI: data
ENSAPI-->>Client: responses for assertions
Client-->>Runner: test results
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryThis PR establishes integration test scaffolding for the ENSv2 GraphQL API ( Key findings:
Confidence Score: 4/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant Dev as Developer
participant Vitest as Vitest (integration)
participant GS as global-setup.ts
participant Client as GraphQLClient
participant ENSApi as ensapi (live)
Dev->>Vitest: pnpm test:integration
Vitest->>GS: setup()
GS->>Client: request(__schema introspection)
Client->>ENSApi: POST /api/graphql
alt ENSApi reachable
ENSApi-->>Client: schema response
Client-->>GS: ok
GS-->>Vitest: setup complete
Vitest->>Vitest: run *.integration.test.ts suites
Note over Vitest: query / domain / account / registry tests
Vitest->>Client: request(gql`...`, variables)
Client->>ENSApi: POST /api/graphql
ENSApi-->>Client: GraphQL response
Client-->>Vitest: typed result
Vitest->>Vitest: assert expectations
else ENSApi unreachable
ENSApi-->>Client: connection error
Client-->>GS: throws
GS-->>Vitest: throw Error("health check failed …")
Vitest->>Dev: fast-fail with actionable message
end
Last reviewed commit: e32005f |
There was a problem hiding this comment.
Pull request overview
This PR establishes integration test scaffolding for the ENSv2 GraphQL API to enable automated verification against real indexed devnet data. The PR adds a separate integration test project using vitest, creates reusable test utilities with syntax highlighting, defines devnet name fixtures, and implements initial integration tests covering Query, Domain, Account, and Registry resolvers.
Changes:
- Added integration test infrastructure with vitest configs, global setup health check, GraphQL client, and syntax-highlighted request/response logging
- Updated all 12 project vitest configs to exclude
*.integration.test.tsfrom unit test runs - Added initial integration tests for GraphQL schema covering root queries, domain lookups, account domains, and registry domains
- Enhanced documentation for
getDomainIdByInterpretedNameexplaining forward traversal semantics and alias handling
Reviewed changes
Copilot reviewed 27 out of 28 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| vitest.integration.config.ts | Root-level integration test config defining project glob patterns and FORCE_COLOR env |
| package.json | Added test:integration script to run integration tests separately |
| vitest.config.ts (12 projects) | Added integration test exclusion pattern to all unit test configs |
| apps/ensapi/vitest.integration.config.ts | Integration test project config for ensapi with global setup |
| apps/ensapi/package.json | Added test:integration script and dev dependencies (chalk, prismjs, graphql-request) |
| apps/ensapi/src/test/integration/global-setup.ts | Health check via introspection query before tests run |
| apps/ensapi/src/test/integration/ensnode-graphql-api-client.ts | Shared GraphQLClient instance and gql tag export |
| apps/ensapi/src/test/integration/graphql-utils.ts | Request helper with logging and connection flattening utility |
| apps/ensapi/src/test/integration/highlight.ts | Prism+chalk syntax highlighting for GraphQL and JSON |
| apps/ensapi/src/test/integration/devnet-names.ts | Devnet name fixtures with canonical mappings |
| apps/ensapi/src/graphql-api/schema/*.integration.test.ts | Integration tests for Query, Domain, Account, and Registry resolvers |
| apps/ensapi/src/graphql-api/lib/get-domain-by-interpreted-name.ts | Enhanced JSDoc explaining forward traversal, expired names, and alias behavior |
| pnpm-lock.yaml | Lock file updates for new dev dependencies |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
apps/ensapi/src/graphql-api/lib/get-domain-by-interpreted-name.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/ensapi/src/graphql-api/schema/account.integration.test.ts`:
- Around line 45-58: The test's hardcoded expected domains array should be
generated from the central fixture DEVNET_NAMES instead of duplicating values;
update the assertion in account.integration.test.ts to derive expected domain
names by mapping/filtering DEVNET_NAMES (and, if ownership info exists, filter
by the account owner) to produce the same list used in the test, or at minimum
replace the literal array with a short comment referencing devnet-names.ts and a
TODO to derive from DEVNET_NAMES; key symbols to change are the expected
variable in account.integration.test.ts and the DEVNET_NAMES export in
devnet-names.ts.
In `@apps/ensapi/src/graphql-api/schema/query.integration.test.ts`:
- Around line 75-78: The test "requires the name filter" currently calls
expect(request(gql`{ domains { edges { node { id }} } }`)).rejects.toThrow(...)
without awaiting the assertion; update the spec so the rejection assertion is
awaited (i.e., prepend await to the expect(...).rejects.toThrow call) so the
test actually waits for the promise rejection from request/gql and fails
correctly if no error is thrown.
- Around line 81-99: Rename the test "sees both .eth Domains" to reflect current
devnet behavior (e.g., "sees v2 .eth Domain only"), update assertions to
explicitly assert the v2 domain exists (expect(v2EthDomain).toBeDefined() or
toMatchObject(...)) and v1 is absent (keep expect(v1EthDomain).toBeUndefined()),
and remove the dead commented expectations referring to V1_ETH_DOMAIN_ID and
label; locate and change the test declaration it("sees both .eth Domains", ...)
and the variables v1EthDomain / v2EthDomain in the same block.
In `@apps/ensapi/src/test/integration/ensnode-graphql-api-client.ts`:
- Around line 5-8: Export the ENSAPI_GRAPHQL_API_URL constant so other modules
(e.g., global-setup.ts) can import the canonical env var name and default;
specifically, change the declaration of ENSAPI_GRAPHQL_API_URL to be exported
(export const ENSAPI_GRAPHQL_API_URL = ...) and then keep using that same
exported symbol when creating the GraphQLClient (export const client = new
GraphQLClient(ENSAPI_GRAPHQL_API_URL)); this avoids duplicating the env variable
name and default value across files.
In `@apps/ensapi/src/test/integration/global-setup.ts`:
- Line 3: The test setup uses ENSAPI_GRAPHQL_URL while the client module uses
ENSAPI_GRAPHQL_API_URL, causing mismatched runtime URLs; fix by exporting the
canonical URL constant from ensnode-graphql-api-client.ts (export const
ENSAPI_GRAPHQL_API_URL = process.env.ENSAPI_GRAPHQL_API_URL ??
"http://localhost:4334/api/graphql") and then import and use that exported
ENSAPI_GRAPHQL_API_URL in global-setup.ts instead of declaring
ENSAPI_GRAPHQL_URL locally, and also update any related error messages to
reference ENSAPI_GRAPHQL_API_URL so both modules use the exact same identifier
and value.
In `@apps/ensapi/src/test/integration/graphql-utils.ts`:
- Around line 15-21: The request function calls document.toString() unguarded;
update request(document) to handle RequestDocument variants by detecting if
document is a DocumentNode (e.g., check for an object with a "kind" property and
"definitions") and, in that case, call print(document) directly, otherwise treat
document as a string and call parse(document.toString()) before print; adjust
the creation of query to use either print(document as DocumentNode) or
print(parse(documentString)) so DocumentNode inputs produce valid GraphQL text
and string inputs continue to be parsed.
ℹ️ Review info
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (27)
apps/ensadmin/vitest.config.tsapps/ensapi/package.jsonapps/ensapi/src/graphql-api/lib/get-domain-by-interpreted-name.tsapps/ensapi/src/graphql-api/schema/account.integration.test.tsapps/ensapi/src/graphql-api/schema/domain.integration.test.tsapps/ensapi/src/graphql-api/schema/query.integration.test.tsapps/ensapi/src/graphql-api/schema/registry.integration.test.tsapps/ensapi/src/test/integration/devnet-names.tsapps/ensapi/src/test/integration/ensnode-graphql-api-client.tsapps/ensapi/src/test/integration/global-setup.tsapps/ensapi/src/test/integration/graphql-utils.tsapps/ensapi/src/test/integration/highlight.tsapps/ensapi/vitest.config.tsapps/ensapi/vitest.integration.config.tsapps/ensindexer/vitest.config.tsapps/ensrainbow/vitest.config.tsapps/fallback-ensapi/vitest.config.tspackage.jsonpackages/datasources/vitest.config.tspackages/ens-referrals/vitest.config.tspackages/ensnode-react/vitest.config.tspackages/ensnode-sdk/vitest.config.tspackages/ensrainbow-sdk/vitest.config.tspackages/namehash-ui/vitest.config.tspackages/ponder-metadata/vitest.config.tspackages/ponder-sdk/vitest.config.tsvitest.integration.config.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
apps/ensapi/src/graphql-api/lib/get-domain-by-interpreted-name.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 27 out of 28 changed files in this pull request and generated 1 comment.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
apps/ensapi/src/graphql-api/schema/query.integration.test.ts (1)
81-105: 🧹 Nitpick | 🔵 TrivialTest name does not match assertions.
The test is titled "sees both .eth Domains" but actually asserts that
v1EthDomainisundefined(line 93) and only validates the v2 domain. Consider renaming to reflect current devnet behavior (e.g.,"returns the ENSv2 .eth domain") and removing the commented-out expectations to reduce confusion.Suggested cleanup
- it("sees both .eth Domains", async () => { + it("returns the ENSv2 .eth domain on current devnet", async () => { const result = await request<QueryDomainsResult>(QueryDomains, { name: "eth" }); const domains = flattenConnection(result.domains); // there's at least a v2 'eth' domain expect(domains.length).toBeGreaterThanOrEqual(1); const v1EthDomain = domains.find((d) => d.__typename === "ENSv1Domain" && d.name === "eth"); const v2EthDomain = domains.find((d) => d.__typename === "ENSv2Domain" && d.name === "eth"); - // TODO: the v1 eth label should surely exist but i don't see it in devnet at the moment? + // v1 eth domain is not present in current devnet expect(v1EthDomain).toBeUndefined(); - // expect(v1EthDomain).toMatchObject({ - // id: V1_ETH_DOMAIN_ID, - // name: "eth", - // label: { interpreted: "eth" }, - // }); expect(v2EthDomain).toMatchObject({🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/ensapi/src/graphql-api/schema/query.integration.test.ts` around lines 81 - 105, The test title "sees both .eth Domains" is misleading because the assertions expect v1EthDomain to be undefined and only validate v2EthDomain; update the test name string in the it(...) call to reflect current behavior (e.g., "returns the ENSv2 .eth domain") and remove the commented-out v1 expectations to avoid confusion; ensure the assertions still reference v1EthDomain and v2EthDomain and that v2 validation uses V2_ETH_DOMAIN_ID, name "eth", and label.interpreted "eth" as before.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/ensapi/src/test/integration/global-setup.ts`:
- Around line 1-23: Run the repository formatter on this file to fix the CI
formatting error; specifically format
apps/ensapi/src/test/integration/global-setup.ts (trim trailing whitespace and
apply project-prettierrc/ESLint rules) so the existing setup function,
ENSAPI_GRAPHQL_URL constant, and the client.request GraphQL template literal
match the repo style; after formatting, commit the updated file and push to
resolve the pipeline failure.
---
Duplicate comments:
In `@apps/ensapi/src/graphql-api/schema/query.integration.test.ts`:
- Around line 81-105: The test title "sees both .eth Domains" is misleading
because the assertions expect v1EthDomain to be undefined and only validate
v2EthDomain; update the test name string in the it(...) call to reflect current
behavior (e.g., "returns the ENSv2 .eth domain") and remove the commented-out v1
expectations to avoid confusion; ensure the assertions still reference
v1EthDomain and v2EthDomain and that v2 validation uses V2_ETH_DOMAIN_ID, name
"eth", and label.interpreted "eth" as before.
ℹ️ Review info
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
apps/ensapi/src/graphql-api/schema/query.integration.test.tsapps/ensapi/src/test/integration/global-setup.ts
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
apps/ensapi/src/graphql-api/schema/query.integration.test.ts (1)
92-98: 🧹 Nitpick | 🔵 TrivialConsider removing dead code or converting to a tracking issue.
The commented-out assertions and TODO for the v1 eth domain add noise. If this is a known devnet limitation, consider either:
- Removing the dead code entirely and documenting the limitation elsewhere
- Opening an issue to track when v1 eth domain should appear
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/ensapi/src/graphql-api/schema/query.integration.test.ts` around lines 92 - 98, Remove the noisy commented-out assertions and TODO around the v1 eth domain in the test (references: v1EthDomain and V1_ETH_DOMAIN_ID); either delete the commented expect block entirely or replace it with a brief comment pointing to a newly created tracking issue that documents the devnet limitation and desired behavior, and ensure the test only asserts the current known state (v1EthDomain is undefined) so the test stays clean and actionable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/ensapi/src/test/integration/global-setup.ts`:
- Around line 3-4: The constant name ENSAPI_GRAPHQL_URL is inconsistent with the
environment variable ENSAPI_GRAPHQL_API_URL; rename the constant to
ENSAPI_GRAPHQL_API_URL (or alternatively read from ENSAPI_GRAPHQL_URL) so names
match, update the assignment that uses process.env.ENSAPI_GRAPHQL_API_URL
accordingly, and modify any error/log messages that refer to ENSAPI_GRAPHQL_URL
to use the new ENSAPI_GRAPHQL_API_URL identifier to keep names consistent across
the file.
In `@apps/ensapi/src/test/integration/graphql-utils.ts`:
- Around line 15-22: Replace the hardcoded "Document" check in the
isDocumentNode type guard with the graphql Kind enum: import Kind from the
'graphql' package and change the condition to compare obj.kind === Kind.DOCUMENT
so the function isDocumentNode(obj: any): obj is DocumentNode uses Kind.DOCUMENT
for robustness and maintainability.
---
Duplicate comments:
In `@apps/ensapi/src/graphql-api/schema/query.integration.test.ts`:
- Around line 92-98: Remove the noisy commented-out assertions and TODO around
the v1 eth domain in the test (references: v1EthDomain and V1_ETH_DOMAIN_ID);
either delete the commented expect block entirely or replace it with a brief
comment pointing to a newly created tracking issue that documents the devnet
limitation and desired behavior, and ensure the test only asserts the current
known state (v1EthDomain is undefined) so the test stays clean and actionable.
ℹ️ Review info
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (5)
apps/ensapi/src/graphql-api/lib/get-domain-by-interpreted-name.tsapps/ensapi/src/graphql-api/schema/query.integration.test.tsapps/ensapi/src/test/integration/devnet-names.tsapps/ensapi/src/test/integration/global-setup.tsapps/ensapi/src/test/integration/graphql-utils.ts
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 27 out of 28 changed files in this pull request and generated no new comments.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
lightwalker-eth
left a comment
There was a problem hiding this comment.
@shrugs Great to see this! Shared one key point of feedback. Please take the lead to merge when ready 👍
| * This is because this traversal is designed to support access to a Domain via API—not Protocol | ||
| * Acceleration—and consumers likely want to reference Domains regardless of Registration status. | ||
| * | ||
| * This means that not every Domain returned by this function is accessible by ENS Forward Resolution: |
There was a problem hiding this comment.
ENS forward resolution makes no consideration of expiry status -- the resolution protocol has no conception of expiry (and more broadly, has no conception of ownership either)
For example, consider nrg.eth which has no active registration as I write this: https://app.ens.domains/nrg.eth/register
But you can still resolve records for this name based on what was configured for it by its previous owner:
- https://admin.ensnode.io/name?name=nrg.eth&connection=https%3A%2F%2Fapi.alpha.ensnode.io%2F
- https://adraffy.github.io/ens-normalize.js/test/resolver.html#nrg.eth
Did you see something that's changing this for ENSv2?
| const v1EthDomain = domains.find((d) => d.__typename === "ENSv1Domain" && d.name === "eth"); | ||
| const v2EthDomain = domains.find((d) => d.__typename === "ENSv2Domain" && d.name === "eth"); | ||
|
|
||
| // TODO: the v1 eth label should surely exist but i don't see it in devnet at the moment? |
Reviewer Focus (Read This First)
*.integration.test.tsviaconfigDefaults.excludespread. this is necessary because vitest workspace mode doesn't propagate root-level excludes to project configs.graphql-utils.ts,highlight.ts) — these are shared utilities for ensapi integration testsdevnet-names.ts— these encode assumptions about the devnet state and canonical vs aliased names.Problem & Motivation
What Changed (Concrete)
vitest.integration.config.tsat root andapps/ensapi/to define a separate integration test projectvitest.config.tsfiles to exclude**/*.integration.test.tsfrom unit test runspnpm test:integrationscript at root and inapps/ensapi/package.jsonglobal-setup.ts— health check via introspection query before tests runensnode-graphql-api-client.ts— sharedGraphQLClientinstance +gqltaggraphql-utils.ts—request()helper with pretty-printed request/response logging,flattenConnection()helperhighlight.ts— prismjs + chalk syntax highlighting for graphql and json outputdevnet-names.ts— shared devnet name fixtures with canonical mappingsquery.integration.test.ts—Query.root,Query.domains,Query.domain(parameterized over all devnet names)domain.integration.test.ts—Domain.subdomainsfor .ethaccount.integration.test.ts—Account.domainsfor default and transferred ownersregistry.integration.test.ts—Registry.domainsfor ETH registryget-domain-by-interpreted-name.tsexplaining forward traversal semantics, expired name handling, and alias behaviorDesign & Planning
planning was lightweight — started from a plan doc, iterated on patterns (test helpers, assertion style, parameterization) during implementation
key decisions: use
graphql-requestforgqltag and typed client; use prismjs+chalk for terminal highlighting; avoiding too much generalization and keeping the integration tests tightly coupled to a running ensapi w/ an ensindexer that has indexed devnetPlanning artifacts: Claude Code plan mode
Reviewed / approved by: n/a
Self-Review
excludedoesn't propagate to project configs in workspace mode — had to add per-project excludes and overridingexcludewithout spreadingconfigDefaults.excludecaused node_modules test files to runDownstream & Consumer Impact
no public api changes
no runtime behavior changes
the
get-domain-by-interpreted-name.tscomment is documentation-onlyPublic APIs affected: none
Docs updated: added jsdoc to
getDomainIdByInterpretedNameNaming decisions worth calling out:
DEVNET_ETH_LABELSderives fromDEVNET_NAMESby filtering canonical 2ld .eth namesTesting Evidence
tests are designed to run against a live devnet instance via
pnpm test:integrationpnpm testat root confirms integration tests are excluded from unit test runsglobal setup fails fast with actionable error if ensapi is unreachable
Testing performed: manual runs against local devnet
Known gaps: no CI integration yet; tests assume specific devnet state
Scope Reductions
Risk Analysis
pnpm testoutput shows file count, easy to verify no integration tests leak into unit runsPre-Review Checklist (Blocking)