Skip to content

test: full E2E test suite across processing, backoffice & flows#245

Merged
cbetta merged 11 commits into
mainfrom
cb/e2e-test-suite
Jun 2, 2026
Merged

test: full E2E test suite across processing, backoffice & flows#245
cbetta merged 11 commits into
mainfrom
cb/e2e-test-suite

Conversation

@cbetta
Copy link
Copy Markdown
Member

@cbetta cbetta commented Jun 1, 2026

What

Adds a live end-to-end test suite for the Java SDK that exercises every operation against the Gr4vy sandbox, mirroring the harness already shipped on the PHP, Go, TypeScript and Python SDKs. This is the last SDK in the fleet to get the treatment.

How it works

  • One isolated merchant per shard. util/Harness provisions a fresh random-id merchant + a deterministic mock-card service on first use and caches it in a static holder. Gradle runs each package in its own JVM, so each shard gets exactly one merchant. Harness.client() returns a merchant-bound client.
  • Reaches() — for operations the deterministic mock can't fully satisfy (no live acquirer, network tokens, payouts, 3DS provider…), we assert only that the endpoint was reached: 4xx = reached/pass, 5xx or non-HTTP = fail. CRUD the mock supports (transactions, payment methods, buyers, checkout sessions, merchant accounts, payment services, reports) is asserted as real 2xx with non-empty ids.
  • Forward-compat injectionJsonInterceptorHttpClient injects an unknown unexpected_field_* into every JSON object response so deserializers are continuously exercised against fields they weren't generated for (GR4VY_NO_INJECT=1 to disable).
  • Endpoint-reach coverage — when GR4VY_TRACK_HTTP=1 the client records method+path per JVM; scripts/endpoint_coverage/EndpointCoverage.java builds the operation catalogue from generated source and reports coverage. It's a report, not a gate.

Layout

  • src/test/java/com/gr4vy/sdk/util/Harness, Reaches, Fixtures, Checkout, Gen, enhanced JsonInterceptorHttpClient
  • flows/ — happy-path lifecycles (transaction, buyer, checkout session)
  • processing/ — transactions (+events/actions/settlements/refunds), payment methods (+network tokens/PS tokens), buyers (+shipping/gift cards), checkout sessions, gift cards, digital wallets, payment links, catalog, property
  • backoffice/ — merchant accounts, payment services, 3DS configs/scenarios, reports (+executions), payouts, audit logs, account updater

CI

Sharded by package (flows/processing/backoffice) with a stable ci-complete gate so the required check name doesn't churn as shards change, a build + offline matrix on Java 11/17/21, and a coverage PR comment. Fork PRs have no key, so the live suite skips rather than fails.

Notes

  • The offline JWT/webhook unit tests are preserved and now run in their own matrix job.
  • Supersedes the single-file BaseTest/CheckoutSessionsTest scaffold.
  • Local compile verified on JDK 21 (./gradlew compileTestJava). The live suite needs a sandbox PRIVATE_KEY; coverage closure is verified by the CI coverage comment.

🤖 Generated with Claude Code

cbetta and others added 4 commits June 1, 2026 23:51
Add a live end-to-end test suite that exercises every SDK operation against
the Gr4vy sandbox, mirroring the harness already shipped on the PHP, Go,
TypeScript and Python SDKs.

- Harness (test/util): one isolated merchant per JVM (= per Gradle shard),
  a Reaches() "endpoint reached" assertion (4xx counts as reached), shared
  fixtures/generators, and a JSON interceptor that injects an unknown
  response field for forward-compat plus records reached endpoints when
  GR4VY_TRACK_HTTP=1.
- Tests sharded into flows/ (happy-path lifecycles), processing/ and
  backoffice/, covering CRUD with real 2xx where the mock supports it and
  Reaches() for mock-unsupported operations. Transactions report create is a
  real happy path.
- scripts/endpoint_coverage/EndpointCoverage.java builds the operation
  catalogue from generated source and reports endpoint-reach coverage.
- CI sharded by package with a stable ci-complete gate (so the required
  check name is stable as shards change), a build+offline matrix on Java
  11/17/21, and a coverage PR comment. Fork PRs skip the live suite.
- Supersedes the single-file BaseTest/CheckoutSessionsTest scaffold.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Surface assertion messages and stack traces in the Gradle test log so live
E2E failures are diagnosable from CI output.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Reports: the transactions report spec requires fields/filters/sort in
  params; supply a valid set so create/get/put/executions run as real 2xx.
- Reaches: count any HTTP status < 500 as reached. payment-services verify
  returns an empty text/html 200, which the SDK surfaces as an APIException
  with code=200 — that still reached the endpoint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 1, 2026

Endpoint-reach coverage

107 / 107 operations reached by a real HTTP request (100%).

Every operation in the SDK was reached. 🎉

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a comprehensive live end-to-end (E2E) test harness for the Java SDK that exercises processing, backoffice, and flow lifecycles against the Gr4vy sandbox, plus CI sharding and an endpoint-reach coverage report.

Changes:

  • Introduces a shared E2E test harness (Harness, Reaches, fixtures/generators) and a suite of live tests organized by package (flows/, processing/, backoffice/).
  • Adds a test HTTP client wrapper that injects unknown JSON fields for forward-compat checks and records reached endpoints for coverage reporting.
  • Updates CI to compile across Java 11/17/21, run offline unit tests separately, shard live E2E tests, and post a sticky endpoint-coverage PR comment.

Reviewed changes

Copilot reviewed 32 out of 34 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
TESTING.md Documents how to run the offline vs live E2E suite and the coverage report.
src/test/java/com/gr4vy/sdk/util/Reaches.java Adds a reach-only assertion helper for endpoints that can’t return clean 2xx in the deterministic mock.
src/test/java/com/gr4vy/sdk/util/JsonInterceptorHttpClient.java Wraps the HTTP client to inject unknown JSON fields and record reached endpoints.
src/test/java/com/gr4vy/sdk/util/Harness.java Provisions one sandbox merchant + mock-card payment service per test JVM and exposes a merchant-bound SDK client.
src/test/java/com/gr4vy/sdk/util/Gen.java Adds a seedable generator for light property-style E2E tests.
src/test/java/com/gr4vy/sdk/util/Fixtures.java Adds shared deterministic fixture data (cards, addresses, ids, bodies).
src/test/java/com/gr4vy/sdk/util/Checkout.java Adds raw checkout-session “fields” PUT helpers (session-id-authenticated).
src/test/java/com/gr4vy/sdk/util/BaseTest.java Removes the prior single-suite scaffold.
src/test/java/com/gr4vy/sdk/processing/TransactionsTest.java Adds E2E coverage for transactions and related sub-resources.
src/test/java/com/gr4vy/sdk/processing/PropertyTest.java Adds a small property-style E2E test for transaction creation.
src/test/java/com/gr4vy/sdk/processing/PaymentMethodsTest.java Adds E2E coverage for payment methods and reach-only token sub-resources.
src/test/java/com/gr4vy/sdk/processing/PaymentLinksTest.java Adds E2E coverage for payment links.
src/test/java/com/gr4vy/sdk/processing/GiftCardsTest.java Adds E2E coverage for gift cards (reach-only where unsupported).
src/test/java/com/gr4vy/sdk/processing/DigitalWalletsTest.java Adds E2E coverage for digital wallets (mostly reach-only).
src/test/java/com/gr4vy/sdk/processing/CheckoutSessionsTest.java Adds E2E coverage for checkout sessions.
src/test/java/com/gr4vy/sdk/processing/CatalogTest.java Adds E2E coverage for read-only catalog endpoints.
src/test/java/com/gr4vy/sdk/processing/BuyersTest.java Adds E2E coverage for buyers and nested resources.
src/test/java/com/gr4vy/sdk/flows/TransactionLifecycleTest.java Adds a full happy-path card transaction lifecycle flow test.
src/test/java/com/gr4vy/sdk/flows/CheckoutSessionLifecycleTest.java Adds a full happy-path checkout session lifecycle flow test.
src/test/java/com/gr4vy/sdk/flows/BuyerLifecycleTest.java Adds a full happy-path buyer lifecycle flow test.
src/test/java/com/gr4vy/sdk/CheckoutSessionsTest.java Removes the prior single-file checkout session E2E tests.
src/test/java/com/gr4vy/sdk/backoffice/ThreeDsScenariosTest.java Adds E2E coverage for 3DS scenarios (reach-only where unsupported).
src/test/java/com/gr4vy/sdk/backoffice/ThreeDsConfigurationTest.java Adds E2E coverage for per-merchant 3DS configuration endpoints.
src/test/java/com/gr4vy/sdk/backoffice/ReportsTest.java Adds E2E coverage for reports + report executions.
src/test/java/com/gr4vy/sdk/backoffice/ReportExecutionsTest.java Adds E2E coverage for top-level report executions listing.
src/test/java/com/gr4vy/sdk/backoffice/PayoutsTest.java Adds E2E coverage for payouts (reach-only where unsupported).
src/test/java/com/gr4vy/sdk/backoffice/PaymentServicesTest.java Adds E2E coverage for payment services (reach-only for verify/session).
src/test/java/com/gr4vy/sdk/backoffice/MerchantAccountsTest.java Adds E2E coverage for merchant accounts (admin endpoints).
src/test/java/com/gr4vy/sdk/backoffice/AuditLogsTest.java Adds E2E coverage for audit logs listing.
src/test/java/com/gr4vy/sdk/backoffice/AccountUpdaterTest.java Adds E2E coverage for account updater job creation (reach-only).
build-extras.gradle Improves test logging output to aid debugging failures.
.gitignore Ignores generated endpoint-coverage output under /coverage/.
.github/workflows/ci.yaml Reworks CI into build/offline/e2e shards + coverage report + stable ci-complete gate.
Comments suppressed due to low confidence (1)

src/test/java/com/gr4vy/sdk/util/JsonInterceptorHttpClient.java:154

  • Computing Content-Length from InputStream.available() is unreliable (it changes as the stream is read and isn’t guaranteed to reflect total length). Since the body is already fully materialized and substituted, it’s safer to omit Content-Length entirely rather than emitting a potentially wrong value.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/test/java/com/gr4vy/sdk/util/JsonInterceptorHttpClient.java Outdated
Comment thread src/test/java/com/gr4vy/sdk/util/JsonInterceptorHttpClient.java
Comment thread src/test/java/com/gr4vy/sdk/util/Harness.java Outdated
Comment thread TESTING.md Outdated
Comment thread TESTING.md
…ft balances)

Close the endpoint-reach gap to 107/107:
- Paze digital-wallet sessions: paze, mobile create/review/complete.
- transactions void_ (distinct from cancel) and refunds().all().create().
- gift-cards balances lookup.

All are mock-unsupported, so they assert via Reaches (a 4xx/404 proves the
endpoint was routed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 37 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

src/test/java/com/gr4vy/sdk/util/JsonInterceptorHttpClient.java:146

  • ModifiedHttpResponse.headers() recalculates Content-Length from body.available(), which depends on the stream’s current position. If the SDK reads from the body before accessing headers (or accesses headers multiple times), this can produce an incorrect Content-Length value. Safer approach: omit Content-Length entirely in the wrapped response (it’s not required for streaming reads) rather than risk lying about it.

Comment thread src/test/java/com/gr4vy/sdk/util/JsonInterceptorHttpClient.java
Comment thread src/test/java/com/gr4vy/sdk/util/JsonInterceptorHttpClient.java Outdated
Comment thread src/test/java/com/gr4vy/sdk/util/Reaches.java Outdated
Comment thread src/test/java/com/gr4vy/sdk/util/Checkout.java
- GiftCardBalanceRequest requires items; PazeClient requires id/name/profileId
  and PazeTransactionValue requires currency/amount — populate them so the
  requests actually reach the endpoint (the build() validation ran client-side
  before the call).
- Coverage filename now carries a random suffix so shard artifacts with
  colliding PIDs don't overwrite when merged.
- Clarify that the per-shard-merchant guarantee comes from CI running each
  package as a separate gradle invocation; a single local run shares one JVM.
- Note the coverage script needs Java 17+ (record types); document async
  injection is sync-path only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 37 changed files in this pull request and generated 2 comments.

Comment thread src/test/java/com/gr4vy/sdk/util/Reaches.java Outdated
Comment thread .github/workflows/ci.yaml
…er failures)

- JsonInterceptorHttpClient: apply forward-compat injection on the async path
  too (shared maybeInject helper); drop best-effort stderr logging so the
  injector stays silent across the suite.
- Reaches: drop the unreachable AuthException branch (it extends Gr4vyError)
  and the deprecated statusCode() call; preserve the cause via fail(msg, e).
- Checkout: add connect + request timeouts to the raw field PUT.
- CI: fail fast when PRIVATE_KEY is missing on non-PR runs so a misconfigured
  secret can't silently skip the live suite.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 37 changed files in this pull request and generated 1 comment.

Comment thread TESTING.md Outdated
…sonl)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 37 changed files in this pull request and generated 2 comments.

Comment thread src/test/java/com/gr4vy/sdk/util/JsonInterceptorHttpClient.java Outdated
Comment thread .github/workflows/ci.yaml Outdated
- ModifiedHttpResponse carries the modified byte[] and derives Content-Length
  from its length, instead of the stream's remaining-bytes available() (which
  was read-state dependent and defaulted to 0 on error).
- Drop contents/pull-requests write scope from the e2e job; it only reads the
  repo and uploads artifacts (auto-approve lives in ci-complete).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 37 changed files in this pull request and generated 3 comments.

Comment thread src/test/java/com/gr4vy/sdk/util/JsonInterceptorHttpClient.java
Comment thread src/test/java/com/gr4vy/sdk/util/Checkout.java Outdated
Comment thread .github/workflows/ci.yaml
- sendAsync uses ResponseWithBody's mapping constructor (non-null bodyMapper)
  so previousResponse() can't NPE on a redirect chain, while still returning
  the injected body.
- Checkout.API_BASE_URL is derived from Gr4vy.SERVERS + a shared
  Harness.SERVER_ID so it can't drift from the client the harness builds.
- ci-complete drops contents: write (it only approves the bot PR).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@cbetta cbetta requested a review from Copilot June 2, 2026 07:58
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 37 changed files in this pull request and generated 1 comment.

Comment thread src/test/java/com/gr4vy/sdk/util/JsonInterceptorHttpClient.java
Media types are case-insensitive; normalize the header before checking for
application/json so e.g. Application/JSON still gets the forward-compat field.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 37 changed files in this pull request and generated no new comments.

@cbetta cbetta requested a review from Copilot June 2, 2026 08:10
@cbetta cbetta marked this pull request as ready for review June 2, 2026 08:12
@cbetta cbetta merged commit a48df6b into main Jun 2, 2026
15 checks passed
@cbetta cbetta deleted the cb/e2e-test-suite branch June 2, 2026 08:14
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 37 changed files in this pull request and generated no new comments.

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.

2 participants