This directory contains comprehensive end-to-end integration tests for the Stellar Goal Vault API, covering the complete campaign lifecycle: Create → Pledge → Claim/Refund.
The integration test suite provides:
- Isolated Test Database: Each test worker uses a temporary SQLite database (
/tmp/stellar-goal-vault-integration-*.db) to prevent test pollution and cross-contamination - Parallel Execution: Tests run in parallel using 4 worker threads by default
- State Machine Verification: Complete validation of campaign state transitions
- Edge Case Coverage: Double claims, invalid refunds, unauthorized actions, etc.
- Event History Tracking: Full audit trail of all campaign events
- Concurrent Request Handling: Stress tests for data consistency under load
- Node.js 18+
- npm or yarn
- Vitest (installed via
npm install)
npm testThis will:
- Discover all
*.test.tsand*.integration.tsfiles - Start an isolated Express server for each test worker
- Execute tests in parallel (up to 4 concurrent threads)
- Use isolated temporary databases to prevent cross-test pollution
- Clean up after tests complete
npm test -- src/**/*.test.tsnpm test -- tests/**/*.integration.tsnpm test -- tests/integration_test.tsnpm test -- --watchTests will re-run whenever files change.
npm test -- --coverageGenerates coverage reports in HTML format (view in coverage/index.html).
npm test -- --inspect --inspect-brkThen open chrome://inspect in Chrome DevTools.
backend/
├── tests/
│ ├── integration_test.ts # Main integration test suite
│ ├── utils.ts # Shared test utilities and helpers
│ └── README.md # This file
├── src/
│ ├── index.ts # API server
│ ├── index.test.ts # Unit tests
│ └── services/
│ └── campaignStore.test.ts # Unit tests
Vitest automatically discovers test files matching these patterns:
src/**/*.test.ts- Unit teststests/**/*.test.ts- Integration teststests/**/*.integration.ts- Integration tests
- Campaign Lifecycle: Create campaign → Multiple pledges → Reach target → Claim funds → Verify all events recorded
- Double Claim: Prevent claiming the same campaign twice
- Claim Without Funding: Prevent claim before reaching target amount
- Claim Before Deadline: Prevent early claims
- Refund After Claim: Prevent refunds from claimed campaigns
- Failed Campaign Refunds: Allow refunds when campaign fails to reach target
- Non-existent Contributor Refund: Reject refunds for contributors who didn't pledge
- Double Refund: Prevent refunding the same contributor twice
- Unauthorized Claim: Prevent non-creator from claiming
- Field Validation: Ensure all required fields are validated
- Pledge Constraints: Validate pledge amounts and campaign state
- Non-existent Campaigns: Reject all operations on non-existent campaigns
- State Transitions: Verify correct state changes across operations
- Event Ordering: Ensure events are recorded in correct chronological order
- Independent Campaigns: Verify multiple campaigns don't interfere with each other
Each test worker gets a dedicated temporary database:
/tmp/stellar-goal-vault-integration-{PID}-{TIMESTAMP}.db
Key Features:
- Databases are automatically created before tests run
- Databases are automatically cleaned up after tests complete
- No shared state between tests or test workers
- Parallel tests use different process IDs to ensure unique database paths
- WAL (Write-Ahead Logging) mode enabled for reliability
- Foreign key constraints enabled
Perfect isolation ensures:
- ✅ No test pollution - one test's data doesn't affect another
- ✅ Parallel execution - tests can safely run simultaneously
- ✅ CI/CD friendly - consistent results across multiple runs
- ✅ Fast cleanup - simple file deletion after tests
- ✅ No production contamination - uses temporary files only
name: Integration Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: cd backend && npm install
- name: Run integration tests
run: cd backend && npm test
env:
NODE_ENV: test
- name: Upload coverage
uses: codecov/codecov-action@v3
if: always()- Parallel Workers: Tests run on 4 threads by default
- Timeout: Default timeout is 30 seconds per test
- No Persistence: Temporary databases are cleaned up immediately
- No Side Effects: No locks or shared database files
- Fast Cleanup: Uses file system for test databases (not slow network calls)
// Mock data
MOCK_CREATORS.alice
MOCK_CONTRIBUTORS.dave
MOCK_ASSETS.USDC
// Time helpers
nowInSeconds()
generateTxHash()
sleep(ms)
roundAmount(value)
// API helpers
createCampaign(apiClient, overrides)
addPledge(apiClient, campaignId, contributor, amount)
claimCampaign(apiClient, campaignId, creator)
refundContributor(apiClient, campaignId, contributor)
getCampaign(apiClient, campaignId)
getCampaignHistory(apiClient, campaignId)
// Assertion helpers
assertCampaignState(campaign, expectedState)
assertHistoryContains(history, expectedEvents)
assertError(response, expectedCode)
assertSuccess(response)open (default)
├─→ funded (when pledged >= target AND deadline not reached)
└─→ failed (when deadline reached AND pledged < target)
funded
└─→ claimed (when creator claims AND deadline reached)
failed
└─→ (no transition, contributors can refund)
claimed
└─→ (terminal state, no further actions)
| State | Can Pledge | Can Claim | Can Refund |
|---|---|---|---|
| open | ✅ | ❌ | ❌ |
| funded | ❌ | ✅ | ❌ |
| failed | ❌ | ❌ | ✅ |
| claimed | ❌ | ❌ | ❌ |
npm test -- --testTimeout 60000Increase timeout to 60 seconds if tests need more time.
rm /tmp/stellar-goal-vault-integration-*.dbManually clean temporary databases.
The test server uses a random available port (PORT=0), so port conflicts are unlikely. If they occur, check for lingering server processes:
lsof -i :3000 # Check if port 3000 is in useReduce thread count:
npm test -- --maxThreads 2npm test -- --reporter=verbose- Use Test Utilities: Import helpers from
tests/utils.tsfor consistency - Create Separate Campaigns: Don't share campaigns between tests (they use separate databases)
- Verify Events: Always check event history for full audit trail
- Handle Errors: Test both success and error paths
- Clean State: Each test should start with a clean database
- Use Descriptive Names: Test names should clearly describe what's being tested
On a typical machine:
- Total test suite: < 10 seconds
- Per-test average: 100-500ms
- Startup/teardown: < 1 second per worker
- Database operations: < 50ms per operation
it("test name", async () => {
console.log("Campaign:", campaign);
console.log("History:", history);
});Run with:
npm test -- --reporter=verbose 2>&1 | grep -A 10 "test name"The test database files are temporary, but you can add debugging code to inspect them:
const sqlite3 = require("better-sqlite3");
const db = sqlite3(TEST_DB_PATH);
console.log(db.prepare("SELECT * FROM campaigns").all());When adding new tests:
- Add test to
tests/integration_test.tsor create new file - Use utilities from
tests/utils.ts - Ensure tests are idempotent (can run multiple times)
- No external dependencies
- Clean up after tests (Vitest handles database cleanup)