11
Pengujian dan Deploy
Repository ini tidak memakai pipeline CI. Semua pemeriksaan dijalankan lewat npm script yang sama di mesin lokal, lalu npm run deploy membangun Worker OpenNext dan mengirimkannya ke Cloudflare (package.json:6-201). README menetapkan urutan npm test, npm run lint, npm run typecheck, dan npm run build sebagai rangkaian verifikasi sebelum deploy (README.md:43-502).
Perintah verifikasi
| Perintah | Yang dijalankan | Fungsi | Sumber |
|---|---|---|---|
npm test | vitest run | menjalankan seluruh berkas uji satu kali lalu keluar | package.json:133 |
npm run test:watch | vitest | mode watch untuk pengembangan | package.json:144 |
npm run lint | eslint . | aturan eslint-config-next dengan globalIgnores untuk .next, .open-next, .wrangler, node_modules, dan worker-configuration.d.ts | package.json:115, eslint.config.mjs:5-156 |
npm run typecheck | tsc --noEmit | memeriksa tipe tanpa menulis keluaran | package.json:127 |
npm run build | prebuild lalu next build | membangun halaman statis Next | package.json:8-98 |
npm run preview | opennextjs-cloudflare build && opennextjs-cloudflare preview | membangun lalu menjalankan Worker secara lokal | package.json:159 |
npm run deploy | opennextjs-cloudflare build && opennextjs-cloudflare deploy | membangun lalu mengirim Worker ke Cloudflare | package.json:1610 |
npm run upload | opennextjs-cloudflare build && opennextjs-cloudflare upload | membangun lalu mengunggah Worker tanpa deploy | package.json:1711 |
prebuild menjalankan npm run cf-typegen, yaitu wrangler types --env-interface CloudflareEnv (package.json:8-98, package.json:1812). Karena itu npm run build selalu memakai tipe CloudflareEnv terbaru sebelum next build membaca worker.ts. Script quran:build berdiri di luar rangkaian verifikasi; ia hanya dipakai saat data Qur'an dibangun ulang, seperti dijelaskan di Data Qur'an dan Mushaf (package.json:1913).
Modul yang dijaga oleh test
vitest.config.ts memasang alias @ ke ./src dan hanya mengambil berkas tests/**/*.test.ts (vitest.config.ts:4-1114). Tidak ada test yang menyentuh Worker atau jaringan; semuanya memanggil fungsi di src/lib, sehingga npm test tidak butuh hasil build.
| Berkas uji | Modul yang dipanggil | Yang dikunci |
|---|---|---|
| tests/lessons.test.ts | listAllLessons, listLessons, getLesson, contentBlocks, drillRows, practiceSections, soundKey | slug unik, urutan position per kategori, dan batas panjang title, summary, content (tests/lessons.test.ts:17-2415); contentBlocks menandai paragraf yang seluruhnya Arab (tests/lessons.test.ts:34-4216) |
| tests/practice-curriculum.test.ts | practiceParts, practicePart, PRACTICE_TOTAL, groupByPart | 39 praktik terbagi menjadi bagian 1–7, 8–18, 19–29, dan 30–39 (tests/practice-curriculum.test.ts:10-2117) |
| tests/practice-curriculum.test.ts | practiceSections atas data src/data/praktik-* | setiap praktik punya guide dan latihan berlabel Latihan A, Latihan B, Latihan C, dengan bagian terakhir bertanda setor ke guru (tests/practice-curriculum.test.ts:85-9518); huruf tebal tidak pernah dibaca o (tests/practice-curriculum.test.ts:103-11019) |
| tests/lesson-layout.test.ts | lessonLayout, verseParts, arabicRuns, exampleGroups, readingMinutes | pemisahan pengantar, bagian bernomor, grup, dan rujukan pada format konten (tests/lesson-layout.test.ts:7-2720) |
| tests/meeting-plan.test.ts | meetingPlan, meetingDrills, meetingPages | langkah materi, drills, mushaf, task terbaca berurutan dari satu content (tests/meeting-plan.test.ts:22-3321) |
| tests/quran.test.ts | listPagesAyahs, listAyahsByRef, meetingPlan, meetingDrills, meetingPages | setiap ayat dan halaman yang dipakai pertemuan Lanjutan ada di src/data/quran.json (tests/quran.test.ts:8-1422, tests/quran.test.ts:25-3323) |
| tests/practice-progress.test.ts | parseProgress, visitPractice, toggleSection, resetPractice, overallProgress | progres rusak jatuh ke emptyProgress dan tanda di luar jumlah latihan dibuang, sesuai progres belajar (tests/practice-progress.test.ts:5-1824) |
| tests/quiz.test.ts | quizBanks, drawQuiz, recordScore, parseScores, QUIZ_LENGTH | setiap bank punya minimal QUIZ_LENGTH * 5 soal dengan empat opsi unik dan lesson yang benar-benar ada (tests/quiz.test.ts:12-2625); skor terbaik dipertahankan bersama jumlah percobaan (tests/quiz.test.ts:52-5726) |
Dari build ke Worker
npm run deploy tidak menambahkan apa pun pada next build. Perintah itu memanggil opennextjs-cloudflare build untuk menghasilkan .open-next/, lalu opennextjs-cloudflare deploy yang membaca wrangler.jsonc dan mengirim Worker (package.json:1610). .open-next/worker.js baru ada setelah langkah build itu, dan worker.ts mengimpornya dengan @ts-ignore supaya npm run typecheck tetap bisa jalan sebelum ada build (worker.ts:1-1027).
sequenceDiagram
actor Dev
participant NPM as npm scripts
participant ESLint as eslint
participant TSC as tsc
participant Vitest as vitest
participant ON as opennextjs-cloudflare
participant CF as Cloudflare Workers
Dev->>NPM: npm test / lint / typecheck
NPM->>Vitest: berkas .test.ts di tests/
NPM->>ESLint: eslint .
NPM->>TSC: tsc --noEmit
Vitest-->>Dev: lulus atau gagal
Dev->>NPM: npm run deploy
NPM->>ON: opennextjs-cloudflare build
ON->>ON: tulis .open-next/worker.js dan .open-next/assets
ON->>CF: opennextjs-cloudflare deploy memakai wrangler.jsonc
CF-->>Dev: Worker quran-academy aktif
style ON fill:#f59e0b,color:#000
style CF fill:#336791,color:#fff
style Vitest fill:#2d7d46,color:#fff
%% fig: Alur verifikasi sampai deploy
%% desc: Perintah uji, lint, dan typecheck berjalan lokal, lalu opennextjs-cloudflare membangun .open-next dan mengirimnya ke Cloudflare.Kunci di wrangler.jsonc | Nilai | Arti |
|---|---|---|
name | quran-academy | nama Worker yang dituju deploy (wrangler.jsonc:328) |
main | worker.ts | entry Worker, bukan berkas hasil build (wrangler.jsonc:429) |
compatibility_date | 2026-10-19 | tanggal acuan perilaku runtime Workers (wrangler.jsonc:530) |
compatibility_flags | ["nodejs_compat"] | mengaktifkan API Node di Worker (wrangler.jsonc:631) |
assets.directory | .open-next/assets | aset statis hasil opennextjs-cloudflare build (wrangler.jsonc:7-932) |
assets.binding | ASSETS | nama binding untuk aset tersebut (wrangler.jsonc:933) |
open-next.config.ts memilih staticAssetsIncrementalCache dan menyalakan enableCacheInterception, sehingga halaman prerender beserta RSC payload-nya dilayani dari aset statis, bukan dirender ulang oleh Worker pada setiap request dan prefetch (open-next.config.ts:4-934).
Cache-Control sesudah deploy
Pembungkus worker.ts mengubah satu hal pada response sebelum dikirim: bila Cache-Control memuat s-maxage, header itu ditulis ulang menjadi public, max-age=0, must-revalidate; response lain dikembalikan apa adanya (worker.ts:11-1535). Alasannya tercatat di komentar berkas: setelah deploy, stale-while-revalidate membuat browser menampilkan halaman dari build sebelumnya yang chunk CSS-nya sudah tidak ada sehingga muncul 404, sedangkan revalidasi per kunjungan hanya menghasilkan 304 lewat ETag (worker.ts:5-736).
graph TD
Req["request masuk ke fetch"] --> ONW["openNextWorker.fetch di .open-next/worker.js"]
ONW --> Resp["Response"]
Resp --> Check{"Cache-Control memuat s-maxage?"}
Check -- tidak --> Pass["dikembalikan apa adanya"]
Check -- ya --> Rewrite["Cache-Control: public, max-age=0, must-revalidate"]
Rewrite --> Sent["response dikirim ke browser"]
Pass --> Sent
style ONW fill:#336791,color:#fff
style Check fill:#f59e0b,color:#000
style Rewrite fill:#8b5cf6,color:#fff
style Pass fill:#2d7d46,color:#fff
style Sent fill:#2d7d46,color:#fff
%% fig: Penulisan ulang Cache-Control di worker.ts
%% desc: Hanya response yang membawa s-maxage yang headernya diganti menjadi must-revalidate; response lain lewat tanpa perubahan.⚠️
npm run deploytidak menjalankan test, lint, atau typecheck (package.json:1610). Apa pun yang ada di working tree saat perintah itu dijalankan langsung masuk ke bundel Worker, jadi jalankannpm testlebih dulu.
⚠️
npm run buildhanya menjalankannext build; bundel.open-next/dan aset.open-next/assetsbaru dibuat olehopennextjs-cloudflare builddi dalamnpm run deploy(package.json:8-98, wrangler.jsonc:7-932). Untuk mencoba hasil build sebelum menyentuh produksi, pakainpm run preview(package.json:159, README.md:52-5437).