Overview
The Supertest harness (located in dapp/e2e/supertest) exercises the public-facing API routes using Vitest + Supertest. It currently ships three suites:
api.test.ts— covers the token gate surfaces (/api/openapi,/api/token-status/:tokenId,/api/nonce,/api/gate-access,/api/form-submission-gate) with both happy/sad wallet scenarios and optional OpenAPI validation.jwt.test.ts— drills into JWT issuance/consumption, SIWE vs legacy branches, payload shape, and abuse cases.pinecone.test.ts— runs the MCP JSON-RPC bridge (/api/mcp) includingtools/list,tools/call, JWT gating, and Pinecone vector searches.
Every suite imports the shared validateSupertestEnv helper (env.schema.ts) so test runs fail fast when required configuration is missing.
Environment & Configuration
Environment resolution is centralized in vitest.config.supertest.ts:
- Start with
process.env(CI/job variables win). - Overlay
.env.supertestif it exists indapp/. - Fall back to
.envonly when.env.supertestis absent. - Validate the merged object with
supertestEnvSchema.
Key variables (see dapp/.env.supertest.example):
| Variable | Purpose |
|---|---|
TEST_BASE_URL | Target origin (default http://localhost:3000). |
PRIVATE_KEY / TOKEN_ID / CHAIN_ID | Test wallet + token that owns a Colored Key on the configured chain. |
NEXT_PUBLIC_ENABLE_STATE_WORKER | Controls whether tests expect SIWE (true) or legacy auth (false). |
NEXT_PUBLIC_AI_CHAT_REQUIRES_JWT | Tells MCP tests whether a JWT is mandatory. |
MCP_ENDPOINT | Path to the MCP JSON-RPC bridge (defaults to /api/mcp). |
setup.ts logs the resolved values (with masked secrets) before the first test so you can confirm the harness picked up the right environment.
Running the suites
pnpm vitest --config dapp/e2e/supertest/vitest.config.supertest.tsTips:
- Tests intentionally sleep (
waitForRateLimit) between cases to avoid backend throttles. Keep that helper intact if you extend the suite. - The harness attempts to load
public/openapi.json. If the file is missing in a given deployment, the OpenAPI validator quietly disables itself and tests continue. - Output includes a summarized OpenAPI validation report plus JWT payload snippets to help debug server responses.
What each suite covers
api.test.ts
- OpenAPI surface — Fetches
/api/openapi, asserts version3.0.3, and (when available) validates the response against the generated schema viaopenapi-validator.ts. - Token lifecycle — Runs
describe.eachhappy/sad cases to hit/api/token-status/:tokenId(existing vs bogus token IDs) and/api/nonce(expects 200 with nonce when SIWE is enabled or 501 with RFC7807 payload otherwise). - Gate access — Exercises
/api/gate-accessthrough SIWE or legacy envelopes depending on runtime config. Successful paths store any returned JWTs for reuse tests. - JWT reuse edge cases — Sends valid/invalid/mismatched Bearer headers, tokenId body overrides, malformed headers, and concurrent requests to ensure the handler enforces strict matching.
- Form submission — Posts to
/api/form-submission-gatewith a properly signed legacy envelope, tolerating rate limits or backend 500s but asserting success/authorization codes otherwise. - Global assertions — Waits between tests, prints structured logs, and emits the OpenAPI validation report in
afterAll.
jwt.test.ts
- JWT minting — Verifies that a successful SIWE or legacy gate access call returns an
accessTokenwhen the server is configured to issue JWTs. - Payload inspection — Uses
jwtAssertionsto checksub,tokenId,kind,scopes, timestamp claims, SIWE projection (siwe.*), and the deterministicsiwe_hash. - Authenticated reuse — Replays stored tokens against
/api/gate-accesswith/withouttokenIdin the body, expecting success or precise failures (401 on mismatched IDs, 403 when already used). - Bearer permutations — Validates lower/upper/missing space variants as well as outright malformed tokens, mock JWTs, and invalid formats defined in
jwtScenarios. - Rate limiting & uniqueness — Drives bursts of Bearer calls to detect 429s and confirms new authentications mint unique JWT IDs (
jti) and timestamps. - Introspection — Parses TTL to ensure it falls within the expected 5 minutes–24 hours window and logs helpful debug information when a server declines to issue tokens.
pinecone.test.ts
- Protocol guards — Ensures
/api/mcprejects GET (405), invalid JSON (400), and missing JWTs whenNEXT_PUBLIC_AI_CHAT_REQUIRES_JWTis true. - Tool discovery — Calls
tools/list, asserts the response containspinecone_search, and inspects the tool’s schema. - Vector searches — Issues multiple
tools/callrequests covering default topK, custom topK, metadata toggles, invalid index/namespace, missing params, empty query strings, and concurrent invocations. - JWT handling — Acquires a JWT up front (via SIWE or legacy gate access) when required, then reuses it for the MCP calls; also checks invalid tokens and malformed Bearer headers return 401s.
- Diagnostics — Logs the JWT payload (when present) plus Pinecone content to simplify debugging remote responses.
Coverage map
| Endpoint / Surface | Supertest file | Notes |
|---|---|---|
GET /api/openapi | api.test.ts | Validates status, schema shape, and (optionally) OpenAPI compliance. |
GET /api/token-status/:tokenId | api.test.ts | Happy/sad token IDs plus OpenAPI response validation. |
GET /api/nonce | api.test.ts | Covers SIWE-enabled (200) and disabled (501 ProblemDetails) responses. |
POST /api/gate-access | api.test.ts, jwt.test.ts | Legacy + SIWE auth, JWT minting, Bearer reuse, malformed headers, rate limits. |
POST /api/form-submission-gate | api.test.ts | Legacy envelope validation, success/error handling, tolerates 429/500 noise. |
POST /api/mcp (JSON-RPC) | pinecone.test.ts | GET guard, invalid JSON, JWT requirements, tools/list, tools/call permutations. |
/api/chat and /api/quota-reset do not have Supertest coverage yet; they rely on unit tests and manual verification. Additions here should be tracked as follow-up work.
Extending the harness
- Share helpers via
jwt.helpers.tsor new modules instead of duplicating logic inside a test file. - Keep rate-limit sleeps configurable so suites remain reliable both locally and in CI.
- When you add a new endpoint to the tests, update this page (and the relevant API doc) so readers always know which specs are backed by automated coverage.
- If you introduce another OpenAPI slice, register its schema in
openapi-validator.tsor extend the validator to support multiple specs.