Skip to content

Latest commit

 

History

History
388 lines (359 loc) · 19.4 KB

File metadata and controls

388 lines (359 loc) · 19.4 KB

Integration Test Architecture Diagram

System Overview

┌─────────────────────────────────────────────────────────────────┐
│                     Integration Test Suite                      │
│                                                                 │
│  File: backend/tests/integration_test.ts (770 lines)           │
│                                                                 │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  TEST SUITES (15 test groups, 70+ assertions):                 │
│                                                                 │
│  1. Happy Path Tests               (1 suite, 8 assertions)      │
│     - Complete campaign lifecycle                              │
│     - Create → Pledge → Claim → Verify events                  │
│                                                                 │
│  2. Edge Cases Tests               (7 suites, 35+ assertions)  │
│     - Double claim prevention                                  │
│     - Invalid state transitions                                │
│     - Refund logic validation                                  │
│                                                                 │
│  3. Authorization Tests            (5 suites, 20+ assertions)  │
│     - Non-authorized claims                                    │
│     - Field validation                                         │
│     - Campaign existence checks                                │
│                                                                 │
│  4. State Consistency Tests        (3 suites, 15+ assertions)  │
│     - State machine integrity                                  │
│     - Event ordering                                           │
│     - Campaign independence                                    │
│                                                                 │
│  5. Health & Stability Tests       (2 suites, 8+ assertions)   │
│     - API health endpoint                                      │
│     - Concurrent request handling                              │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Test Execution Flow

START
  │
  ├─→ beforeAll()
  │   ├─ Set environment variables:
  │   │  ├─ DB_PATH = /tmp/stellar-goal-vault-integration-{PID}-{TIMESTAMP}.db
  │   │  ├─ CONTRACT_ID = "" (blockchain disabled)
  │   │  └─ PORT = "0" (random available port)
  │   ├─ Import Express app
  │   ├─ Start HTTP server on random port
  │   └─ Initialize Axios API client
  │
  ├─→ FOR EACH TEST SUITE:
  │   │
  │   ├─→ beforeEach() [if exists]
  │   │
  │   ├─→ TEST 1
  │   │   ├─ Create campaign(s)
  │   │   ├─ Add pledges
  │   │   ├─ Claim/Refund
  │   │   ├─ Verify events
  │   │   └─ Assert results (multiple assertions)
  │   │
  │   ├─→ TEST 2 (same pattern)
  │   ├─→ TEST 3 (same pattern)
  │   └─→ ... more tests
  │
  ├─→ afterAll()
  │   ├─ Close HTTP server
  │   ├─ Delete temporary database file
  │   └─ Cleanup complete
  │
END

Parallel Execution Architecture

┌──────────────────────────────────────────────────────────────────┐
│           VITEST PARALLEL EXECUTION (4 threads)                  │
├──────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Vitest Worker Pool                                             │
│  ├─ maxThreads: 4                                               │
│  ├─ minThreads: 1                                               │
│  └─ isolate: true (separate test files)                         │
│                                                                  │
│  ┌─────────────────┐  ┌─────────────────┐                       │
│  │ Worker Thread 1 │  │ Worker Thread 2 │                       │
│  ├─────────────────┤  ├─────────────────┤                       │
│  │ PID: 12345      │  │ PID: 12346      │                       │
│  │ DB: /tmp/test-1 │  │ DB: /tmp/test-2 │                       │
│  │ Port: 54321     │  │ Port: 54322     │                       │
│  │ [Test 1]        │  │ [Test 2]        │                       │
│  │ [Test 2]        │  │ [Test 3]        │                       │
│  │ [Test 3]        │  │ [Test 4]        │                       │
│  └─────────────────┘  └─────────────────┘                       │
│                                                                  │
│  ┌─────────────────┐  ┌─────────────────┐                       │
│  │ Worker Thread 3 │  │ Worker Thread 4 │                       │
│  ├─────────────────┤  ├─────────────────┤                       │
│  │ PID: 12347      │  │ PID: 12348      │                       │
│  │ DB: /tmp/test-3 │  │ DB: /tmp/test-4 │                       │
│  │ Port: 54323     │  │ Port: 54324     │                       │
│  │ [Test 5]        │  │ [Test 6]        │                       │
│  │ [Test 6]        │  │ [Test 7]        │                       │
│  │ [Test 7]        │  │ [Test 8]        │                       │
│  └─────────────────┘  └─────────────────┘                       │
│                                                                  │
│  All workers run simultaneously:                                │
│  Test 1 ████   Test 5 ████                                      │
│  Test 2 ████   Test 6 ████                                      │
│  Test 3 ████   Test 7 ████                                      │
│  Test 4 ████   Test 8 ████                                      │
│                                                                  │
│  ↓ All 8 tests complete                                         │
│  Sequential time: 8 × 500ms = 4000ms                           │
│  Parallel time:   max(500ms) = 500ms                           │
│  Speedup: 8x for 4 workers                                      │
└──────────────────────────────────────────────────────────────────┘

Database Isolation Strategy

UNIQUE DATABASE PATH GENERATION
  │
  ├─ Timestamp: Date.now()            (1710000000000)
  ├─ Process ID: process.pid          (12345)
  └─ Filename: stellar-goal-vault-integration-{PID}-{TIMESTAMP}.db
     │
     └─ RESULT: /tmp/stellar-goal-vault-integration-12345-1710000000000.db

GUARANTEE:
  ✓ No process has same PID at same millisecond (mathematically impossible)
  ✓ Each test worker gets completely unique database
  ✓ Zero collision probability
  ✓ Automatic cleanup (.db file deletion)
  ✓ No production impact (only /tmp/)

TEST ISOLATION EXAMPLE:

  Test Time: 1710000000000ms

  Worker 1              Worker 2              Worker 3              Worker 4
  PID: 12345            PID: 12346            PID: 12347            PID: 12348
  DB: /tmp/...345      DB: /tmp/...346      DB: /tmp/...347      DB: /tmp/...348
  ├─ Campaign 1        ├─ Campaign 1        ├─ Campaign 1        ├─ Campaign 1
  ├─ Pledge 1          ├─ Pledge 1          ├─ Pledge 1          ├─ Pledge 1
  └─ Claim              └─ Refund             └─ Claim (fails)      └─ Claim
     (success)             (success)             (success)            (success)

  ↓ All operations succeed WITHOUT interfering with each other
  ↓ Complete test isolation achieved

Campaign State Machine Coverage

┌─────────────────────────────────────────────────────────────────┐
│              CAMPAIGN STATE MACHINE - ALL PATHS TESTED           │
└─────────────────────────────────────────────────────────────────┘

State: OPEN (Initial state)
┌──────────────────────────────────────┐
│ canPledge: ✓ YES                     │
│ canClaim:  ✗ NO                      │
│ canRefund: ✗ NO                      │
└──────────────────────────────────────┘
  │
  ├─→ Add Pledge 1 (300)
  │   └─ Status: OPEN (not yet 100%)
  │
  ├─→ Add Pledge 2 (350)
  │   └─ Status: OPEN (still 650 < 1000)
  │
  ├─→ Add Pledge 3 (350)
  │   └─ Status: FUNDED (1000 >= 1000)
  │      ┌──────────────────────────────┐
  │      │ canPledge: ✗ NO              │
  │      │ canClaim:  ✓ YES (if deadline passed)
  │      │ canRefund: ✗ NO              │
  │      └──────────────────────────────┘
  │
  └─→ Deadline Reached
      │
      ├─→ Claim Campaign ✓ SUCCESS
      │   └─ Status: CLAIMED (final state)
      │      ┌──────────────────────────────┐
      │      │ canPledge: ✗ NO              │
      │      │ canClaim:  ✗ NO (already)    │
      │      │ canRefund: ✗ NO              │
      │      └──────────────────────────────┘
      │
      └─→ [ALTERNATE] Claim Without Funding
          └─ ✗ FAILS (pledged < target)

FAILED CAMPAIGN PATH:
┌──────────────────────┐
│ Deadline Reached     │
│ Pledged: 500 < 1000  │
│ Status: FAILED       │
├──────────────────────┤
│ canPledge: ✗ NO      │
│ canClaim:  ✗ NO      │
│ canRefund: ✓ YES     │
└──────────────────────┘
  │
  ├─→ Refund Contributor 1 (300) ✓ SUCCESS
  ├─→ Refund Contributor 2 (200) ✓ SUCCESS
  └─ Status: FAILED (contributors refunded)

TEST COVERAGE: ✓ All paths tested and verified

Event History Recording

CAMPAIGN LIFECYCLE → COMPLETE EVENT AUDIT TRAIL

Campaign: ID = "1"
Timeline:
│
├─ Event 1: CREATED
│  ├─ Timestamp: 1710000000
│  ├─ Actor: Creator1
│  ├─ Type: created
│  └─ Metadata:
│     ├─ title: "Test Campaign"
│     ├─ assetCode: "USDC"
│     ├─ targetAmount: 1000
│     └─ deadline: 1710086400
│
├─ Event 2: PLEDGED
│  ├─ Timestamp: 1710000010
│  ├─ Actor: Contributor1
│  ├─ Amount: 300
│  ├─ Type: pledged
│  └─ Metadata:
│     └─ newTotalPledged: 300
│
├─ Event 3: PLEDGED
│  ├─ Timestamp: 1710000020
│  ├─ Actor: Contributor2
│  ├─ Amount: 350
│  ├─ Type: pledged
│  └─ Metadata:
│     └─ newTotalPledged: 650
│
├─ Event 4: PLEDGED
│  ├─ Timestamp: 1710000030
│  ├─ Actor: Contributor3
│  ├─ Amount: 350
│  ├─ Type: pledged
│  └─ Metadata:
│     └─ newTotalPledged: 1000
│
└─ Event 5: CLAIMED
   ├─ Timestamp: 1710086401 (after deadline)
   ├─ Actor: Creator1
   ├─ Amount: 1000 (total claimed)
   ├─ Type: claimed
   └─ Metadata:
      └─ targetAmount: 1000

TESTS VERIFY:
✓ Events recorded in chronological order
✓ Timestamps increase monotonically
✓ Actors are correct (Creator, Contributors)
✓ Amounts are accurate and cumulative
✓ Event types match operations
✓ Metadata is complete and consistent

Test Utility Architecture

TEST UTILITIES (backend/tests/utils.ts)
│
├─ MOCK DATA FIXTURES
│  ├─ MOCK_CREATORS
│  │  ├─ alice: "GAAA..."
│  │  ├─ bob: "GBBB..."
│  │  └─ charlie: "GCCC..."
│  ├─ MOCK_CONTRIBUTORS
│  │  ├─ dave: "GDDD..."
│  │  ├─ eve: "GEEE..."
│  │  ├─ frank: "GFFF..."
│  │  ├─ grace: "GGGG..."
│  │  └─ henry: "GHHH..."
│  └─ MOCK_ASSETS
│     ├─ USDC
│     └─ XLM
│
├─ TIME HELPERS
│  ├─ nowInSeconds()
│  ├─ generateTxHash()
│  ├─ sleep(ms)
│  └─ roundAmount(value)
│
├─ API REQUEST HELPERS
│  ├─ createCampaign(apiClient, overrides)
│  ├─ addPledge(apiClient, campaignId, contributor, amount)
│  ├─ addMultiplePledges(apiClient, campaignId, pledges)
│  ├─ claimCampaign(apiClient, campaignId, creator)
│  ├─ reconcilePledge(apiClient, campaignId, contributor, amount, txHash)
│  ├─ refundContributor(apiClient, campaignId, contributor)
│  ├─ getCampaign(apiClient, campaignId)
│  ├─ getCampaignHistory(apiClient, campaignId)
│  ├─ listCampaigns(apiClient, filters)
│  └─ getHealth(apiClient)
│
└─ ASSERTION HELPERS
   ├─ assertCampaignState(campaign, expectedState)
   ├─ assertHistoryContains(history, expectedEvents)
   ├─ assertError(response, expectedCode)
   └─ assertSuccess(response)

USAGE IN TESTS:
  const campaign = await createCampaign(apiClient, {
    targetAmount: 500,
    deadline: nowInSeconds() + 50,
  });
  assertCampaignState(campaign, {
    status: "open",
    pledgedAmount: 0,
  });

CI/CD Integration Pipeline

┌─────────────────────────────────────────────────────────────────┐
│                  GITHUB ACTIONS WORKFLOW                         │
│         (.github/workflows/backend-integration-tests.yml)        │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│ TRIGGER EVENTS:                                                │
│   • Push to main     ────────┐                                 │
│   • Push to develop  ──────┐ │                                 │
│   • Pull Request     ──────┌─│─◄                               │
│                           │ │                                 │
│ ┌────────────────────────▼─▼─────────────────────────────────┐ │
│ │ GITHUB ACTIONS INFRASTRUCTURE                            │ │
│ ├────────────────────────────────────────────────────────────┤ │
│ │ runs-on: ubuntu-latest                                  │ │
│ │ strategy:                                               │ │
│ │   matrix:                                               │ │
│ │     node-version: [18.x, 20.x]                         │ │
│ │                                                         │ │
│ │ JOB 1: integration-tests (Node 18.x)                   │ │
│ │ ├─ Checkout code                                       │ │
│ │ ├─ Setup Node 18.x                                    │ │
│ │ ├─ npm ci (install dependencies)                      │ │
│ │ ├─ npm test (Run all tests)                           │ │
│ │ │  ├─ Vitest spawns 4 worker threads                  │ │
│ │ │  ├─ Each gets unique temp database                  │ │
│ │ │  └─ All assertions verified                         │ │
│ │ └─ Upload coverage to Codecov                         │ │
│ │                                                         │ │
│ │ JOB 2: integration-tests (Node 20.x)                   │ │
│ │ └─ [Same as Job 1]                                     │ │
│ │                                                         │ │
│ │ JOB 3: test-results                                    │ │
│ │ └─ Summary: Report pass/fail status                    │ │
│ │                                                         │ │
│ └────────────────────────────────────────────────────────────┘ │
│                           │                                     │
│                           └─→ Report to PR Checks Tab           │
│                               ├─ ✓ All tests passed             │
│                               ├─ ✗ Tests failed                 │
│                               └─ Coverage report linked         │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

OUTCOME:
  ✓ All tests pass → Merge enabled
  ✗ Tests fail → Merge blocked

This comprehensive architecture ensures:

  • ✅ Complete test coverage
  • ✅ Fast parallel execution
  • ✅ Perfect database isolation
  • ✅ Production safety
  • ✅ Full CI/CD automation