Skip to content

test(projects): add real-gremlin test scaffolding via testcontainers#181

Open
svozza wants to merge 2 commits into
mainfrom
test/projects-gremlin-testcontainers
Open

test(projects): add real-gremlin test scaffolding via testcontainers#181
svozza wants to merge 2 commits into
mainfrom
test/projects-gremlin-testcontainers

Conversation

@svozza
Copy link
Copy Markdown
Contributor

@svozza svozza commented May 22, 2026

Summary

Establishes the testing pattern for the ~15 Gremlin-touching lambdas (currently zero coverage) by spiking on lambda/projects. Continues the #41 rollout (ESM + tests).

The approach: a real tinkerpop/gremlin-server runs in a testcontainer for the duration of vitest run, and the lambda under test connects to it the same way it connects to Neptune in production — same getConnection code path, same SigV4 signing (the container ignores the headers). Per-test isolation comes from a PartitionStrategy that is wired into the lambda only when the env var GREMLIN_PARTITION is set; production never sets it, so production behavior is unchanged.

A single tinkerpop/gremlin-server testcontainer is started once at the start of vitest run and shared across every test file. Per-file PartitionStrategy isolates each suite's writes from every other suite's. Even when this rolls out to all 15 Gremlin lambdas, that's still one container per CI job.

The pattern (what subsequent Gremlin lambdas will copy)

For each Gremlin lambda we want to test:

  1. One-line lambda change: in getConnection, conditionally apply PartitionStrategy when GREMLIN_PARTITION is set. No-op in production.
  2. Test file: stub GREMLIN_PARTITION to a fresh UUID in beforeAll, dynamic-import the handler, drive it like API Gateway does. Pin time with vi.useFakeTimers({ toFake: ['Date'] }). Seed non-handler-creatable state (e.g. non-owner member edges) through a small partition-scoped g.

What's in this PR

  • lambda/projects/index.js — ESM-converted (was CJS), added PartitionStrategy guard plus GREMLIN_PORT/GREMLIN_PROTOCOL env hooks for non-Neptune Gremlin servers. SigV4 path unchanged for production.
  • lambda/projects/package.json — aligned with the workspace template (private, scripts, esbuild build). Runtime deps removed; centralised in root devDependencies (matches notify/github-issues).
  • terraform/modules/api/lambda/main.tfprojects_lambda switched from npm_requirements = true to the npm run build -w projects build-script pattern (matches ws-message/notify).
  • test/gremlin-setup.js — vitest globalSetup that boots tinkerpop/gremlin-server:3.7.3, plants inert AWS creds so fromNodeProviderChain resolves cleanly on CI runners.
  • vitest.config.js — wires the global setup once for the whole run.
  • lambda/projects/test/projects.test.js — 22 tests covering every routable branch (HTTP method × auth state × role).
  • Root package.json — adds lambda/projects to workspaces, hoists gremlin/gremlin-aws-sigv4/@aws-sdk/credential-providers/@smithy/*, adds testcontainers.

Notable decisions

  • No DI or handler factory. The original plan proposed splitting handlers into createHandler({ query }) factories. That's dropped — the env-var partition seam is sufficient and keeps the lambda's structure unchanged.
  • neptune-lambda-client adoption (issue [Feature]: Harden Gremlin connection handling in lambdas #43) is out of scope. This PR only establishes the test scaffolding. The library swap is the next change and will benefit from being landable as an isolated diff with a green test suite already in place.
  • ESM migration of lambda/projects. Required to import ../shared/response.js cleanly from the test, matching the convention already used by lambda/github. Production zip layout is unaffected.
  • esbuild createRequire banner. gremlin and gremlin-aws-sigv4 self-require('buffer') at module init; without the banner the ESM bundle fails on Lambda. Will likely change shape under [Feature]: Migrate Lambda bundling from esbuild CLI to Vite #174 (Vite migration).

Test plan

  • npm test — all 175 tests pass (22 new + 153 existing); ~6s after image cached
  • npm run build -w projects produces a 673kb bundle
  • terraform apply against dev — projects_lambda redeployed with new package layout
  • aws lambda invoke against collaborative-ai-dlc-projects-dev returns a real Neptune query result (verified end-to-end)
  • CI green on Node 22 + 24
  • Local Colima users: set TESTCONTAINERS_RYUK_DISABLED=true (Colima can't bind-mount the docker socket Ryuk needs). GHA runners use Docker Engine and don't need this.

Refs #41

svozza added 2 commits May 21, 2026 22:44
Establishes the testing pattern for the ~15 Gremlin-touching lambdas
(currently zero coverage) by spiking on lambda/projects.

A single tinkerpop/gremlin-server testcontainer runs for the whole
vitest run; per-file PartitionStrategy keyed by GREMLIN_PARTITION
isolates each suite's writes. The lambda reads the env var and applies
the strategy when set; production never sets it, so behavior is
unchanged.

lambda/projects is converted to ESM (matches lambda/github convention,
lets tests import ../shared/response.js without packaging tricks) and
gains GREMLIN_PORT/GREMLIN_PROTOCOL hooks so the SigV4 path can target
a non-Neptune Gremlin server in tests. SigV4 still runs in tests; the
container ignores the signed headers.
Switches projects_lambda packaging from npm_requirements (which walks
the lambda's own package.json for runtime deps) to the workspace build
pattern (npm run build -w projects). Required because gremlin and
gremlin-aws-sigv4 are now centralised in the root devDependencies and
hoisted at install time — the old packaging mode couldn't see them.

Also adds a createRequire banner to projects' esbuild invocation.
gremlin's bundled CJS does require('buffer') at module init, which
fails inside an ESM bundle without an injected require. Other workspace
lambdas don't hit this because they don't pull in any CJS deps that
self-require Node builtins.

Verified end-to-end against dev: aws lambda invoke against
collaborative-ai-dlc-projects-dev returns a real Neptune query result.
@svozza svozza force-pushed the test/projects-gremlin-testcontainers branch from 2096505 to 98d3a1f Compare May 22, 2026 05:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant