Skip to content

test: add unit tests for env config validation schema - #485

Merged
K1NGD4VID merged 6 commits into
mergepay:mainfrom
vrse-vrde:test/446-env-validation-schema
Sep 2, 2026
Merged

test: add unit tests for env config validation schema#485
K1NGD4VID merged 6 commits into
mergepay:mainfrom
vrse-vrde:test/446-env-validation-schema

Conversation

@vrse-vrde

@vrse-vrde vrse-vrde commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #446, Closes #456, Closes #442 — one PR covering three related testing/validation gaps:

  1. Add unit test for environment variable validation schema parser #446 — dedicated unit tests for the environment-variable validation schema in src/config.ts.
  2. Add Zod validation schema for expense creation and splitting payloads #456 — expense creation payload validation (schema already existed; test coverage completed).
  3. Add unit tests for group expense split calculation utility functions #442 — unit tests for the group expense split calculation utilities (coverage completed).

What changed

src/config.ts — exported the Zod schema as envSchema and the error formatter as safeErrorMessage (purely additive; runtime behavior unchanged).

tests/config.test.ts — rewritten to validate the real schema instead of a duplicated, out-of-date copy. The old file re-declared a partial schema that had drifted (referenced AUTH_RATE_LIMIT_MAX / SETTLEMENT_RATE_LIMIT_MAX, which no longer exist, and missed ~80 real fields). A copied schema can pass while the actual startup validation is broken, so tests now import and exercise envSchema directly.

tests/settlement.test.ts — extended the computeShares coverage (the expense split engine in src/services/settlement.ts, BigInt stroop math): exact/even splits, sub-stroop splits with a 1-stroop remainder, single participant, single custom share, zero and negative amount guards, empty participant list, exact 3-way percentage shares, and percentage tolerance.

tests/validations/expense.test.ts — extended createExpenseSchema coverage: zero amount, >7-decimal precision, exponent notation, unsupported asset code, XLM-with-issuer rejection, USDC acceptance (with and without the configured issuer), invalid splitType, and descriptive error-message assertions for title/amount/asset failures.

Key design decisions

  • Test the real module, not a mirror. The schema is exported from src/config.ts so tests can never silently drift from what runs at startup. Importing src/config.ts in tests is an established pattern (20+ test files do it).
  • Mirrored process.env shape. All mock config values are strings (as dotenv would provide them), so coercion paths (PORT: "4000"4000) are exercised realistically.
  • Repo conventions over issue wording. Add Zod validation schema for expense creation and splitting payloads #456 asks for currency ('XLM' | 'USDC') as a plain enum, but the repo validates assets through the shared validateAsset registry in src/lib/money.ts (XLM native; USDC against STABLE_ASSET_ISSUER), which is the single source of truth used by both request validation and XDR construction. Amounts are decimal strings (never floats) validated to 7dp — matching the repo's financial-math conventions. Tests assert the real, descriptive error messages from those shared validators.

Acceptance criteria

#446

  • Locate the environment configuration modulesrc/config.ts (schema + startup parse + safeErrorMessage).
  • Add a test file verifying config parsing with valid mock env objectstests/config.test.ts valid-configuration block: testnet/public, coercion, defaults (PORT 4000, LOG_LEVEL "info", CORS_ALLOW_CREDENTIALS false, ACCESS_TOKEN_TTL_SECONDS 900), optional SEP-10/Horizon fields.
  • Missing mandatory environment variables throw validation errorsit.each over all 10 required keys, both missing and empty, plus assertions the missing variable's name appears in the reported error.

#456

  • Zod schema file/export for expense creation payloadssrc/validations/expense.ts (createExpenseSchema, already present; imported by src/routes/expenses.ts).
  • Validate title (non-empty), amount (positive, ≤7dp), currency, and split array — title min(1).max(80); amount via canonicalAmountSchema (positive, 7dp max, no exponent/whitespace); asset via refineValidatedAsset (XLM/USDC against the shared registry); splitType enum + non-empty shares with split-type-specific checks (custom amounts present, percentages sum to 100 ±0.01).
  • Unit tests: invalid payloads rejected with descriptive messages, valid payloads passtests/validations/expense.test.ts (37 tests): valid equal/custom/percentage/optional-field payloads; invalid title/amount/asset/shares/splitType; message-content assertions ("greater than zero", "7-decimal precision", "Unsupported asset code", "native asset", "at least 1 character").

#442

  • Locate/create test files for expense calculation utilitiestests/settlement.test.ts for computeShares in src/services/settlement.ts (pure, BigInt-stroop math — no I/O).
  • Even splits, uneven splits with remainder distribution, edge cases (zero/negative guards) — exact even split (9/3 → 3 each), uneven with remainder absorbed on first share (10/3 → 3.3333334/3.3333333; 0.01/3 → 0.0033334/0.0033333), single participant, zero amount, negative amount, empty participant list, percentage remainder/exactness and 0.001 tolerance.
  • All tests pass via Vitest — see below.

Test output + coverage

  • npx vitest run tests/config.test.ts tests/settlement.test.ts tests/validations/expense.test.ts99/99 passed (43 config + 37 expense validation + 19 settlement).
  • Full suite: 1518 passed; the 17 failing tests (authorization/health/treasury-proposals/withdraw/worker-shutdown-drain/worker) fail identically on the clean tree without this change (verified via git stash) — pre-existing, environment-dependent (DB/network) failures unrelated to this PR.
  • npx tsc --noEmit → clean. npm run lint → 0 errors (26 pre-existing warnings, none in the changed files).
  • Coverage: no coverage provider installed (@vitest/coverage-v8 not in devDependencies) and no threshold configured in vitest.config.ts. To measure: npm i -D @vitest/coverage-v8 then npx vitest run --coverage tests/config.test.ts tests/settlement.test.ts tests/validations/expense.test.ts --coverage.include="src/config.ts" --coverage.include="src/services/settlement.ts" --coverage.include="src/validations/expense.ts".

Follow-ups (honest)

Security note

Only additive exports from src/config.ts and test-only changes; no validation rules, secrets handling, or runtime behavior changed. No secrets or credentials are introduced by this PR.

Export the env schema and error formatter from src/config.ts and rewrite
tests/config.test.ts to validate the real schema instead of a duplicated,
out-of-date copy. Covers valid configs (testnet/public, coercion, defaults),
every missing/empty mandatory variable, invalid formats, numeric bounds, and
error reporting.
@drips-wave

drips-wave Bot commented Aug 31, 2026

Copy link
Copy Markdown

@vrse-vrde Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@mergekeeper

mergekeeper Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

MergeKeeper review

Scope: in scope for linked issue #446.
Verdict: clean

The pull request correctly implements unit tests for environment configuration validation, expense payload validation, and expense split calculations as requested by the linked issues.

Reviewed commit: bb0b9411e161b958be7cd3af2c2bdbe575b364e0.
CI and merge eligibility are checked separately.

vrse-vrde and others added 5 commits August 31, 2026 11:51
…pay#442, mergepay#456)

Extend tests/settlement.test.ts with even and sub-stroop splits, single
participant, zero/negative amount guards, and empty participant list.
Extend tests/validations/expense.test.ts with zero/exponent amounts,
7-decimal precision, unsupported asset codes, XLM-with-issuer rejection,
USDC acceptance, invalid splitType, and descriptive error messages.
@K1NGD4VID
K1NGD4VID merged commit e07c6ac into mergepay:main Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants