test(infra): add vitest unit tests and CI quality gates - #20
Merged
ibrahimmosouf-png merged 1 commit intoAug 23, 2026
Merged
Conversation
nasalehj
force-pushed
the
fix/issue-10-test-infra-ci
branch
2 times, most recently
from
August 23, 2026 16:58
05b4d9c to
2ae7ba2
Compare
The repository had no test infrastructure and no CI: package.json had no test script, no test files existed, and .github/workflows did not exist, so pure logic (Stellar formatting/validation/error mapping, the cache manager, the auth and UI stores, image uploads) had zero regression protection. Introduce Vitest as the runner (TS-native, zero-config unit tests, built-in jsdom for browser-API tests, and a path to React Testing Library for future component tests), add a test script, and write 76 unit tests across the seven modules the issue lists. Add a GitHub Actions workflow that runs type-check, lint, test, and build on push and pull request with no required secrets, and document npm test in the README. Also fixes pre-existing type errors in adminStore, draftStore, and campaignDeployer that blocked the required type-check and build gates (identical to PRs OrbitChainLabs#18 and OrbitChainLabs#19).
nasalehj
force-pushed
the
fix/issue-10-test-infra-ci
branch
from
August 23, 2026 17:08
2ae7ba2 to
9a0cd6c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #10
The repository had no test infrastructure and no CI:
package.jsondefined notestscript, a search for*.test.*/*.spec.*found nothing, and.github/workflowsdid not exist. This PR introduces Vitest as the test runner, adds atestscript, writes 76 unit tests across the seven modules the issue lists, and adds a GitHub Actions workflow that gates every push/PR on type-check, lint, test, and build with no required secrets.Runner rationale — Vitest over Jest: it is TypeScript-native with zero config for unit tests (no ts-jest/babel ceremony), has jsdom built in (used here for the browser-API image tests, and a direct path to React Testing Library for the component tests the issue anticipates), and is significantly faster. It coexists with the existing Storybook scripts without touching the Next.js 14 build.
Why
Before this change the only verification a contributor could run was
npm run type-checkandnpm run lint. Pure logic had zero regression protection: Stellar amount/address formatting, address validation, Stellar/Web3 error mapping, the TTL cache manager, the auth and UI stores, and the image-upload utilities were all unguarded, so behavioral fixes could regress silently and reviewers had no test output to judge changes on. The milestone issues (JWT verification, draft storage, wallet balance, env contract) each call for tests, and none could be written before this infrastructure existed.What was built
vitest.config.tsinclude: ['tests/**/*.test.ts'], Node environment by default; browser-API tests opt into jsdom via a per-file// @vitest-environment jsdompragma.package.json"test": "vitest run"and devDependenciesvitest+jsdom.tests/stellar-formatting.test.tstoStroops/fromStroops(incl. round-trip and error cases),formatAmount,formatCurrency,formatAsset(native + issued via the SDKAssettype),getBaseFee,formatFee,truncateAddress,parseAssetString— 13 tests.tests/stellar-validation.test.tsStrKeyencodings, plusgetAddressTypeclassification — 10 tests.tests/stellar-errorHandler.test.tsparseStellarErrorover JSON-RPC numeric codes, Horizon operation/transaction result codes, string codes, message-substring matching, and both fallbacks;isUserRejection— 10 tests.tests/cacheManager.test.tsgetOrSetcaching + refresh-after-expiry, and metrics snapshot immutability — 10 tests.tests/authStore.test.tssetUser/setLoading/setTokensstate transitions (persist middleware no-ops in Node sincelocalStorageis unavailable) — 7 tests.tests/uiStore.test.tstests/imageUpload.test.tsFileReader/Imagestubs (within bounds, oversized, decode failure), preview URL create/revoke,formatFileSize,getFileExtension— 13 tests..github/workflows/ci.ymlmainand on every PR, runsnpm cithennpm run type-check,npm run lint,npm test, andnpm run build(Node 22, npm cache). No secrets; any failing step fails the run and blocks the PR.README.mdnpm testcommand, and the CI workflow in the Testing section and scripts table.The tests exercise the modules' real behavior — including error paths and edge cases (negative/NaN amounts, malformed addresses, TTL expiry, eviction, oversized images) — rather than implementation details, so they double as regression protection for the milestone's behavioral fixes.
Integration changes outside
tests/lib/server/adminStore.ts,lib/server/draftStore.ts,lib/server/campaignDeployer.ts— pre-existing type errors onmain(12 total) that madenpm run type-checkandnpm run buildfail before any test change, which would have made the new CI gates red out of the box. These are the same mechanical fixes as in PRs fix(env): reconcile env schema with reads and fail fast at boot #18 and fix(wallet): resolve balance from the configured network's Horizon #19 (issue Environment contract is drifting: lib/env.ts schema omits variables read elsewhere and assertEnv is never invoked #9 / Wallet balance is hardcoded to Horizon testnet: mainnet wallets always display a zero balance #8):noUncheckedIndexedAccessspread guards in the stores, and a port ofcampaignDeployer.tsfrom the removed@stellar/stellar-sdkv11SorobanRpc/scvalAPI to the v14rpc/nativeToScVal/xdrAPI. Identical content across all three PRs merges cleanly regardless of order.tsconfig.json—"target": "ES2020"(was unset, defaulting to ES3, which broke BigInt literals incampaignDeployer.ts) and"allowImportingTsExtensions": true(safe withnoEmit), identical to PRs fix(env): reconcile env schema with reads and fail fast at boot #18/fix(wallet): resolve balance from the configured network's Horizon #19.package-lock.json— vitest/jsdom dependency tree.No other files were modified.
Acceptance criteria coverage
npm testexists and runs green in a fresh clone with onlynpm install. (package.json—"test": "vitest run"; verified locally:npm test→ 76/76 passing. Vitest/jsdom are declared devDependencies, sonpm installis sufficient.)lib/stellar/formatting.ts,lib/stellar/validation.ts,lib/stellar/errorHandler.ts,lib/cache/cacheManager.ts,store/authStore.ts,store/uiStore.ts, andutils/imageUpload.ts. (One test file per module intests/— 76 tests total.).github/workflows/runs type-check, lint, build, and test on push and pull request, with no required secrets. (.github/workflows/ci.yml— four steps on push tomainand onpull_request; no secrets, onlyactions/checkout,actions/setup-node,npm ci.)README.md— Testing section withnpm testand the CI description.)Test plan
npm test— 76/76 passing (76 new tests across 7 files)npm run type-check— no errorsnpm run lint— no warnings or errorsnpm run build— succeedsEnv vars / Notes
No new environment variables and no runtime dependency changes (
vitestandjsdomare devDependencies only).Notes:
FileReader/Imageare stubbed so dimension validation is deterministic (jsdom cannot decode real images).compressImage(canvastoBlobre-encoding needs a real rendering engine — out of the unit-test scope; the issue's out-of-scope section covers component/E2E tests), and the wallet/notification stores which were not listed in the acceptance criteria.localStorage); it is informational and the assertions pass.testscript (vitest run) supersedes thenode --testscript added in PRs fix(env): reconcile env schema with reads and fail fast at boot #18/fix(wallet): resolve balance from the configured network's Horizon #19 (issue Environment contract is drifting: lib/env.ts schema omits variables read elsewhere and assertEnv is never invoked #9/Wallet balance is hardcoded to Horizon testnet: mainnet wallets always display a zero balance #8) — all three PRs add the same devDependency-free runner setup otherwise, and the gate-unblocking changes inlib/server/*andtsconfig.jsonare byte-identical across all three.