Appearance
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).
| Metrik | Nilai |
|---|---|
| Test files | 4 |
| Total tests | 19 |
| Status | 19 passed ✅ |
| Runner | Vitest v3.2.4 |
| Setup | Neon 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 testsTest Suites
1. Auth Flow (auth.flow.test.ts)
Menguji alur autentikasi Better Auth (email/password).
| # | Test | Status |
|---|---|---|
| 1 | Sign-up membuat user baru | ✅ |
| 2 | Sign-in mengembalikan session cookie (sma.session_token) | ✅ |
| 3 | whoami mengembalikan user saat ini dengan role member | ✅ |
| 4 | Sign-out meminvalidasi session (request berikutnya 401) | ✅ |
| 5 | Sign-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.
| # | Test | Status |
|---|---|---|
| 1 | checkDestinyAccess — allowed dengan 5 free analysis | ✅ |
| 2 | invokeDestiny — mengembalikan 200 dan hasil analisis | ✅ |
| 3 | checkDestinyAccess — free analysis tersisa 4 setelah dipakai 1x | ✅ |
| 4 | Invokasi 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).
| # | Test | Status |
|---|---|---|
| 1 | createTransaction — mengembalikan payment URL dan invoice number | ✅ |
| 2 | checkStatus — mengembalikan status transaksi (real Doku sandbox call) | ✅ |
| 3 | handleWebhook — signature valid memperbarui status ke paid | ✅ |
| 4 | handleWebhook — signature invalid ditolak dengan 401 | ✅ |
Doku Webhook Approach
Test webhook (handleWebhook) menggunakan simulated signature, bukan callback nyata dari Doku:
| Aspek | Detail |
|---|---|
| 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.
| # | Test | Status |
|---|---|---|
| 1 | Create journal entry | ✅ |
| 2 | List journal entries (paginasi) | ✅ |
| 3 | Get journal entry by ID | ✅ |
| 4 | Update journal entry (text & stress) | ✅ |
| 5 | Delete journal entry | ✅ |
| 6 | Get deleted entry mengembalikan 404 | ✅ |
Infrastructure Test
Global Setup (global-setup.ts)
Urutan eksekusi sebelum test dimulai:
- Cleanup orphaned branches — hapus semua branch Neon selain
developmentdanproductionuntuk menghindariBRANCHES_LIMIT_EXCEEDED. - Start Base44 mock server — HTTP server lokal yang membalas
InvokeLLMdengan mock response. - Create Neon branch — via Neon API (
POST /projects/{id}/branches) denganendpoints: [{ type: "read_write" }]. - Poll readiness — SDK
@neondatabase/api-clientpolling sampaicurrent_state === "ready". - Get connection URI — SDK
getConnectionUri(pooled,neondb/neondb_owner). - Run Drizzle migrations —
drizzle-kit migrateke database branch sementara. - Start Worker —
unstable_devpada port 8788 dengan semua env vars (termasukDEEP_INSIGHTS_PRICE=50000). - Persist metadata — simpan
branchId,dbUrl,base44MockUrlke/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):
| Variable | Deskripsi |
|---|---|
NEON_API_KEY | API key Neon untuk create/delete branch |
NEON_PROJECT_ID | ID project Neon |
NEON_PARENT_BRANCH_ID | (opsional) Parent branch ID |
Variabel yang wajib di apps/api/.dev.vars (untuk unstable_dev):
| Variable | Deskripsi |
|---|---|
BETTER_AUTH_SECRET | Secret untuk Better Auth |
DOKU_CLIENT_ID | Doku payment client ID |
DOKU_SECRET_KEY | Doku 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.varsdan.envtidak di-commit ke Git. Pastikanapps/api/.dev.varsdiisi 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.tsMenjalankan E2E
bash
cd apps/web
pnpm test:e2e # headless
pnpm test:e2e --ui # interactive modeStatus
🚧 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:
- Public tunnel (ngrok / localtunnel) saat test berjalan
- Browser automation (Playwright / Cypress) untuk simulasi user bayar di Doku staging
- Callback URL saat create transaction diarahkan ke public tunnel
- Polling / assertion verify DB updated setelah webhook masuk
Mengapa ditunda?
| Alasan | Detail |
|---|---|
| UI revamp incoming | Semua komponen dan class name akan berubah — E2E selector (data-testid, class, text) bakal rusak |
| Effort besar | Setup tunnel + browser automation + menunggu callback asinkron → fragile dan lambat |
| Integration test cukup solid | 19/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-testiduntuk selector yang robust.
Known Issues & Workarounds
| Issue | Penyebab | Solusi |
|---|---|---|
BRANCHES_LIMIT_EXCEEDED | Akumulasi branch Neon dari test sebelumnya | Global setup otomatis cleanup orphaned branches (kecuali development/production) sebelum create branch baru |
| Doku response shape mismatch | Doku 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 Neon | Set SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt sebelum menjalankan test |
UNSUPPORTED_MEDIA_TYPE pada sign-out | POST tanpa body dan tanpa Content-Type ditolak better-auth | ApiClient 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 testDependensi Dev
vitest— test runner@neondatabase/api-client— SDK Neon APIwrangler—unstable_devuntuk local workerdrizzle-kit— migration runner