Skip to content

test(wallet-service): harden /version contract#428

Open
tuliomir wants to merge 5 commits into
masterfrom
chore/pr-420-hardening
Open

test(wallet-service): harden /version contract#428
tuliomir wants to merge 5 commits into
masterfrom
chore/pr-420-hardening

Conversation

@tuliomir
Copy link
Copy Markdown
Contributor

@tuliomir tuliomir commented May 11, 2026

Motivation

Completes the follow-up work after #420, which was a one-line emergency bugfix (allowing native_token.version on the fullnode /version payload). The fix shipped narrow on purpose; both CodeRabbit and Copilot flagged that it left loose ends — TypeScript typing and tests. This PR closes those out, scoped tightly to native_token.version.

Changes

  • Type alignmentFullNodeApiVersionResponse.native_token gains version?: number so the TS type matches the Joi schema. The as FullNodeApiVersionResponse cast in fullnode.ts is dropped (it was masking the drift; Joi.object<T>() already types the validator's output).
  • Schema unit tests (new tests/schemas.test.ts, 4 cases) — first direct coverage of FullnodeVersionSchema, all scoped to the native_token.version field:
    • PR 420 regression guard: the modern testnet payload (with native_token.version: 0) validates.
    • Legacy payload (no native_token.version) validates.
    • Unknown fields under native_token fail validation (design intent — keep nested object strict).
    • Non-integer native_token.version (e.g. 1.5) fails validation.
  • fullnode.version() tests (extend tests/fullnode.test.ts) — happy-path and schema-rejection cases that verify the schema wiring inside fullnode.ts actually runs and throws. Rejection case uses a native_token.version violation.

Out of scope (intentionally)

A live-fullnode contract test (that would fail CI when the /version response drifts) was considered and removed from this PR, since there is no existing precedent for tests making real HTTP calls in the wallet-service workspace — PR #394 went the other direction. That can be a separate PR if we want to introduce that pattern.

Acceptance Criteria

  • FullnodeVersionSchema accepts the post-PR 420 native_token payload and rejects misuse of the new version field; covered by unit tests.
  • FullNodeApiVersionResponse reflects the schema, removing the type cast that was hiding the drift.

Checklist

  • If you are requesting a merge into master, confirm this code is production-ready and can be included in future releases as soon as it gets merged
  • Make sure either the unit tests and/or the QA tests are capable of testing the new features
  • Make sure you do not include new dependencies in the project unless strictly necessary and do not include dev-dependencies as production ones. More dependencies increase the possibility of one of them being hijacked and affecting us.

Summary by CodeRabbit

  • New Features

    • Native token responses now optionally include a version property for richer metadata.
  • Refactor

    • Version validation now returns the validated result directly, improving type-safety and clarity.
  • Tests

    • Added tests covering modern and legacy native-token payloads, strict schema validation, and rejection on invalid version values.

Review Change Stack

@tuliomir tuliomir added the tests label May 11, 2026
@tuliomir tuliomir self-assigned this May 11, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 11, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0176b843-e066-491f-86d4-e09e103770f5

📥 Commits

Reviewing files that changed from the base of the PR and between a6f62c2 and 3281c44.

📒 Files selected for processing (1)
  • packages/wallet-service/tests/fullnode.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/wallet-service/tests/fullnode.test.ts

📝 Walkthrough

Walkthrough

Widen native_token to include optional numeric version, return the schema-validated value from fullnode.version(), and add tests validating modern and legacy payloads plus schema strictness and handler error behavior.

Changes

Fullnode Version Schema & Handler Validation

Layer / File(s) Summary
Data Contract
packages/wallet-service/src/types.ts
FullNodeApiVersionResponse.native_token now optionally includes version?: number alongside name and symbol.
Handler Implementation
packages/wallet-service/src/fullnode.ts
version() now returns the value from FullnodeVersionSchema.validate(...) directly instead of using a TypeScript assertion; schema validation errors are still thrown.
Schema Validation Tests
packages/wallet-service/tests/schemas.test.ts
Added tests: accept modern payload with native_token.version, accept legacy payload without version, reject unknown native_token fields, and reject non-integer native_token.version.
Handler Unit Tests
packages/wallet-service/tests/fullnode.test.ts
Added tests for fullnode.version() covering responses with and without native_token.version and a case where schema validation fails due to invalid native_token.version.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • pedroferreira1
  • luislhl
  • raul-oliveira

Poem

I’m a rabbit who validates with cheer, 🐇
A tiny version field hops near,
Old payloads welcomed, new ones too,
Tests on guard to see it through,
Schema and handler in sync — hip, hooray!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: adding tests to strengthen validation of the /version endpoint contract in wallet-service, particularly around the native_token.version field handling.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/pr-420-hardening

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@tuliomir tuliomir moved this from Todo to In Progress (WIP) in Hathor Network May 11, 2026
Adds direct schema unit tests for FullnodeVersionSchema, two
fullnode.version() tests, and a live-fullnode contract test that
fails CI when the /version response stops matching the schema.

Aligns FullNodeApiVersionResponse with the native_token.version
field added in #420 and drops
the type cast that was masking the drift.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tuliomir tuliomir force-pushed the chore/pr-420-hardening branch from de286a6 to df1493e Compare May 11, 2026 21:33
Both schemas.test.ts and fullnode.test.ts duplicated a ~17-line
FullNodeApiVersionResponse fixture. Replaces both with reuse of the
existing `defaultTestVersionData()` factory in tests/utils.ts —
already the canonical fixture (used by `seedFullnodeVersionData` and
referenced from jestSetup.ts) — spreading and overriding only the
`native_token` field under test.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tuliomir tuliomir requested review from r4mmer and raul-oliveira May 11, 2026 23:05
tuliomir and others added 2 commits May 12, 2026 11:38
Wraps the three version()-related cases in a `describe('version', ...)`
block for readability. Adds a case asserting `fullnode.version()` still
parses successfully when the fullnode response omits the new
`native_token.version` field, mirroring older fullnodes that predate
#420.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/wallet-service/tests/fullnode.test.ts (1)

4-53: ⚡ Quick win

Add mock cleanup to keep tests isolated.

Each test in this describe('version') block uses jest.spyOn(fullnode.api, 'get') but never restores it. Add an afterEach(() => jest.restoreAllMocks()) to avoid cross-test leakage as this suite grows. This aligns with the cleanup patterns already used elsewhere in the test suite.

Suggested addition
describe('version', () => {
+  afterEach(() => {
+    jest.restoreAllMocks();
+  });
+
  test('returns parsed payload when native_token includes the version field', async () => {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/wallet-service/tests/fullnode.test.ts` around lines 4 - 53, Add test
teardown to the describe('version') suite to restore spies after each test: in
the same describe block that contains tests calling jest.spyOn(fullnode.api,
'get'), add an afterEach hook that calls jest.restoreAllMocks() so the spy on
fullnode.api.get is cleared between tests and prevents cross-test leakage.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/wallet-service/tests/fullnode.test.ts`:
- Around line 4-53: Add test teardown to the describe('version') suite to
restore spies after each test: in the same describe block that contains tests
calling jest.spyOn(fullnode.api, 'get'), add an afterEach hook that calls
jest.restoreAllMocks() so the spy on fullnode.api.get is cleared between tests
and prevents cross-test leakage.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 60830d12-ee76-45b4-a177-edb9e362eac9

📥 Commits

Reviewing files that changed from the base of the PR and between d9f1823 and a6f62c2.

📒 Files selected for processing (1)
  • packages/wallet-service/tests/fullnode.test.ts

Adds `afterEach(() => jest.restoreAllMocks())` to the `describe('version', ...)`
block so the `jest.spyOn(fullnode.api, 'get')` set up by each test is reverted
between tests. Prevents implicit cross-test leakage as the suite grows; aligns
with the cleanup pattern used in tests/auth.readonly.test.ts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tuliomir tuliomir moved this from In Progress (WIP) to In Progress (Done) in Hathor Network May 12, 2026
import { FullnodeVersionSchema } from '@src/schemas';
import { defaultTestVersionData } from '@tests/utils';

// Regression guard for the testnet outage that motivated PR 420: the
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should not reference the PR solving the outage if possible, the comment should document the core issue this addresses instead.

I think a link to an issue describing the problem would be good if the core issue was too complex to describe in the comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: In Progress (Done)

Development

Successfully merging this pull request may close these issues.

2 participants