Skip to content

Laporan Testing API Integration

Tanggal: 14 Mei 2026
Scope: apps/api — integration test suite

Ringkasan

Suite integration test untuk backend API Soul Map Atlas. Test menjalankan worker Cloudflare Workers secara lokal via unstable_dev, memakai database sementara dari Neon (branch on-demand), dan mock server untuk eksternal API (Base44).

MetrikNilai
Test files4
Total tests19
Status19 passed
RunnerVitest v3.2.4
SetupNeon branch + Drizzle migrate + Wrangler unstable_dev

Struktur Test

apps/api/test/
├── vitest.config.ts          # Konfigurasi Vitest
├── global-setup.ts           # Spin-up: mock, DB, worker
├── global-teardown.ts        # Cleanup: hapus Neon branch
├── helpers/
│   ├── client.ts             # ApiClient dengan cookie jar
│   ├── auth.ts               # Helper sign-up / sign-in / sign-out
│   └── base44-mock.ts        # Mock server Base44 InvokeLLM
└── integration/
    ├── auth.flow.test.ts     # 5 tests
    ├── destiny.flow.test.ts  # 4 tests
    ├── doku.flow.test.ts     # 4 tests
    └── journal.flow.test.ts  # 6 tests

Test Suites

1. Auth Flow (auth.flow.test.ts)

Menguji alur autentikasi Better Auth (email/password).

#TestStatus
1Sign-up membuat user baru
2Sign-in mengembalikan session cookie (sma.session_token)
3whoami mengembalikan user saat ini dengan role member
4Sign-out meminvalidasi session (request berikutnya 401)
5Sign-in dengan password salah gagal (401)

2. Destiny Flow (destiny.flow.test.ts)

Menguji endpoint destinasi (BaZi, numerologi, dll.) dengan rate-limiting 5 analisis gratis.

#TestStatus
1checkDestinyAccess — allowed dengan 5 free analysis
2invokeDestiny — mengembalikan 200 dan hasil analisis
3checkDestinyAccess — free analysis tersisa 4 setelah dipakai 1x
4Invokasi ke-6 (habis kuota) ditolak dengan 403

3. Doku Payment Flow (doku.flow.test.ts)

Menguji alur pembayaran via Doku (create transaction, check status, webhook).

#TestStatus
1createTransaction — mengembalikan payment URL dan invoice number
2checkStatus — mengembalikan status transaksi (real Doku sandbox call)
3handleWebhook — signature valid memperbarui status ke paid
4handleWebhook — signature invalid ditolak dengan 401

Doku Webhook Approach

Test webhook (handleWebhook) menggunakan simulated signature, bukan callback nyata dari Doku:

AspekDetail
Kenapa simulated?Test worker jalan di localhost:8788 — Doku sandbox tidak bisa callback ke localhost
Bagaimana?Test generate payload + HMAC-SHA256 signature sendiri (pakai secret key sama), lalu POST ke /api/v1/handleWebhook
Apa diverifikasi?App bisa verify signature dan update record transaksi ke paid di database
Apa tidak diverifikasi?Doku sendiri mengirim request ke app (butuh public URL + tunnel)

🔄 Full end-to-end (Doku kirim real callback ke app → user bayar di staging → webhook masuk) direkomendasikan setelah UI revamp selesai.

4. Journal Flow (journal.flow.test.ts)

Menguji CRUD journal entry lengkap.

#TestStatus
1Create journal entry
2List journal entries (paginasi)
3Get journal entry by ID
4Update journal entry (text & stress)
5Delete journal entry
6Get deleted entry mengembalikan 404

Infrastructure Test

Global Setup (global-setup.ts)

Urutan eksekusi sebelum test dimulai:

  1. Cleanup orphaned branches — hapus semua branch Neon selain development dan production untuk menghindari BRANCHES_LIMIT_EXCEEDED.
  2. Start Base44 mock server — HTTP server lokal yang membalas InvokeLLM dengan mock response.
  3. Create Neon branch — via Neon API (POST /projects/{id}/branches) dengan endpoints: [{ type: "read_write" }].
  4. Poll readiness — SDK @neondatabase/api-client polling sampai current_state === "ready".
  5. Get connection URI — SDK getConnectionUri (pooled, neondb/neondb_owner).
  6. Run Drizzle migrationsdrizzle-kit migrate ke database branch sementara.
  7. Start Workerunstable_dev pada port 8788 dengan semua env vars (termasuk DEEP_INSIGHTS_PRICE=50000).
  8. Persist metadata — simpan branchId, dbUrl, base44MockUrl ke /tmp/.sma-test-meta.json.

Global Teardown (global-teardown.ts)

  • Baca metadata dari /tmp/.sma-test-meta.json.
  • Hapus Neon branch via SDK deleteProjectBranch.
  • Bisa di-skip dengan KEEP_NEON_BRANCH=1.

Environment Variables

Variabel yang wajib tersedia (via shell env / direnv / .env):

VariableDeskripsi
NEON_API_KEYAPI key Neon untuk create/delete branch
NEON_PROJECT_IDID project Neon
NEON_PARENT_BRANCH_ID(opsional) Parent branch ID

Variabel yang wajib di apps/api/.dev.vars (untuk unstable_dev):

VariableDeskripsi
BETTER_AUTH_SECRETSecret untuk Better Auth
DOKU_CLIENT_IDDoku payment client ID
DOKU_SECRET_KEYDoku payment secret

Variabel lain seperti DEEP_INSIGHTS_PRICE sudah didefinisikan di wrangler.jsonc (env development) dan di-overwrite secara eksplisit di setup test.

⚠️ File .dev.vars dan .env tidak di-commit ke Git. Pastikan apps/api/.dev.vars diisi manual lokal.


E2E Test Scaffolding (Playwright)

Scaffolding E2E test dengan Playwright sudah dibuat di apps/web/e2e/:

apps/web/e2e/
├── fixtures/base.ts           # Auth helper, API base URL
├── pages/                     # Page objects (Login, Dashboard, Destiny, Journal, Compatibility, Payment)
├── flows/                     # Test stubs per user flow
│   ├── auth.spec.ts
│   ├── destiny.spec.ts
│   ├── journal.spec.ts
│   ├── compatibility.spec.ts
│   └── payment.spec.ts
├── README.md
└── playwright.config.ts

Menjalankan E2E

bash
cd apps/web
pnpm test:e2e        # headless
pnpm test:e2e --ui   # interactive mode

Status

🚧 Stubs only — implementasi lengkap setelah UI revamp selesai. Selector page objects menggunakan placeholder yang akan diupdate saat komponen UI final sudah ada.


Rekomendasi E2E Test (Future)

Test saat ini adalah integration test — semua API call real ke Doku sandbox, tapi webhook simulated. Untuk full end-to-end payment flow (create → user bayar → Doku kirim real callback → DB update), dibutuhkan:

  1. Public tunnel (ngrok / localtunnel) saat test berjalan
  2. Browser automation (Playwright / Cypress) untuk simulasi user bayar di Doku staging
  3. Callback URL saat create transaction diarahkan ke public tunnel
  4. Polling / assertion verify DB updated setelah webhook masuk

Mengapa ditunda?

AlasanDetail
UI revamp incomingSemua komponen dan class name akan berubah — E2E selector (data-testid, class, text) bakal rusak
Effort besarSetup tunnel + browser automation + menunggu callback asinkron → fragile dan lambat
Integration test cukup solid19/19 test passing, semua business logic (create, check status, verify signature, update DB) sudah tercover

📅 Jadwalkan E2E setelah UI revamp selesai. Saat itu komponen sudah stabil dan bisa ditambahkan data-testid untuk selector yang robust.


Known Issues & Workarounds

IssuePenyebabSolusi
BRANCHES_LIMIT_EXCEEDEDAkumulasi branch Neon dari test sebelumnyaGlobal setup otomatis cleanup orphaned branches (kecuali development/production) sebelum create branch baru
Doku response shape mismatchDoku sandbox API mengembalikan response.payment.url (nested), sedangkan kode expect payment.url (flat)createDokuPayment di @packages/payment menormalisasi response — flatten response.* ke top-level jika ada
TLS peer certificate is not trusted (workerd)Runtime Cloudflare workerd di Nix tidak mempercayai CA bundle NeonSet SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt sebelum menjalankan test
UNSUPPORTED_MEDIA_TYPE pada sign-outPOST tanpa body dan tanpa Content-Type ditolak better-authApiClient sekarang mengirim "{}" body + Content-Type: application/json untuk setiap POST/PUT/PATCH tanpa body

Cara Menjalankan

bash
cd apps/api

# Pastikan env tersedia
export NEON_API_KEY=...
export NEON_PROJECT_ID=...
export NEON_PARENT_BRANCH_ID=...

# Pastikan .dev.vars terisi
cat apps/api/.dev.vars
# BETTER_AUTH_SECRET=...
# DOKU_CLIENT_ID=...
# DOKU_SECRET_KEY=...

# Jalankan test
SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt pnpm test

Dependensi Dev

  • vitest — test runner
  • @neondatabase/api-client — SDK Neon API
  • wranglerunstable_dev untuk local worker
  • drizzle-kit — migration runner