10
Pengujian dan Kontribusi
Repository ini memisahkan test ke dalam empat direktori di bawah test/: test/unit, test/e2e, test/fuzz, dan test/static. Satu perintah npm run test merangkai hampir semuanya lewat script/test-all.sh, sedangkan npm run build+test menambahkan langkah build di depannya (package.json:244-2561).
Peta suite dan skrip
Setiap suite punya skrip npm sendiri. Diagram berikut memetakan berkas test ke skrip yang menjalankannya. Hanya suite unit, e2e, dan static yang dipanggil dari script/test-all.sh; suite fuzz berdiri di luar gate otomatis itu.
graph LR
main["test/unit/main.js"] --> mocha["test:mocha"]
uach["test/unit/ua-ch.js"] --> mocha
subs["test/unit/submodules"] --> mocha
cli["test/unit/cli/cli.spec.js"] --> mocha
regr["test/unit/redos.js"] --> mocha
e2e["test/e2e/browser.spec.mjs"] --> pw["test:playwright"]
dts["test/static/dts-lint.ts"] --> tsd["test:dts-lint"]
fuzz["test/fuzz/redos.js"] --> jazzer["test:fuzz"]
mocha --> all["script/test-all.sh"]
pw --> all
tsd --> all
style mocha fill:#2d7d46,color:#fff
style pw fill:#2d7d46,color:#fff
style tsd fill:#2d7d46,color:#fff
style all fill:#8b5cf6,color:#fff
style fuzz fill:#dc2626,color:#fff
style jazzer fill:#f59e0b,color:#000
%% fig: Peta suite test ke skrip npm
%% desc: Berkas test di bawah test/unit, test/e2e, dan test/static bermuara ke script/test-all.sh, sedangkan test/fuzz hanya berjalan lewat skrip test:fuzz yang dipanggil manual.| Skrip | Perintah | Fungsi |
|---|---|---|
build | ./script/build-esm.js && ./script/build-dist.sh | menghasilkan bundle distribusi |
build+test | npm run build && npm run test | build lalu seluruh gate test |
test | ./script/test-all.sh | rangkaian gate |
test:jshint | jshint src/main | lint kode sumber utama |
test:eslint | eslint --no-config-lookup src | lint seluruh src |
test:mocha | mocha --recursive test/unit | seluruh test unit |
test:playwright | playwright test test/e2e --browser all | test end-to-end di semua browser |
test:lockfile-lint | lockfile-lint -p package-lock.json | validasi lockfile |
test:dts-lint | tsd --typings src/main/ua-parser.d.ts --files test/static/dts-lint.ts | validasi type declaration |
test:fuzz | jazzer ./test/fuzz/redos.js --sync | fuzzing pola regex |
test:nyc | nyc --timeout=50000 --include=src/**/*.js npm run test | cakupan kode |
Seluruh nilai di tabel di atas diambil apa adanya dari blok scripts (package.json:244-2561).
Isi test/unit
test/unit/main.js adalah berkas terbesar dalam hal cakupan. Ia membaca fixture JSON lewat readJsonFiles() yang menjelajah setiap berkas di satu direktori, lalu memakai daftar itu untuk menguji getBrowser(), getCPU(), getDevice(), getEngine(), dan getOS() (test/unit/main.js:16-222). Berkas yang sama juga memuat pemeriksaan panjang User-Agent: UA_MAX_LENGTH bernilai 500, dan string yang lebih panjang harus terpotong tepat menjadi 500 karakter (test/unit/main.js:212-2213).
Dua berkas khusus menangani Client Hints. test/unit/ua-ch.js mengiterasi UACHTests dari test/data/ua-ch/headers.js dan membandingkan hasil browser untuk setiap entri (test/unit/ua-ch.js:225-2324). Submodule punya berkas *.spec.js sendiri di test/unit/submodules/, dan CLI diuji dengan memanggil npx ua-parser-js sebagai proses anak (test/unit/cli/cli.spec.js:18-265).
test/unit/redos.js adalah test regresi untuk advisory GHSA-9h5v-pfqq-x599. Ia menyusun header sec-ch-ua-model sepanjang 25000 pengulangan 'A ', memanggil withClientHints(), lalu menegaskan waktu proses di bawah 100 ms (test/unit/redos.js:12-166).
Isi test/e2e, test/fuzz, dan test/static
test/e2e/browser.spec.mjs memuat dist/ua-parser.html lewat Playwright dan menguji perilaku di lingkungan browser sungguhan, termasuk kasus navigator.userAgent yang bernilai undefined dan harus dianggap string kosong (test/e2e/browser.spec.mjs:12-267).
test/fuzz/redos.js memakai FuzzedDataProvider dari @jazzer.js/core untuk membangkitkan User-Agent acak sepanjang maksimum 500 karakter, mengukur durasi UAParser(userAgent), dan melempar Error berisi Potential ReDoS bila durasi melewati 1000 ms (test/fuzz/redos.js:1-208). Karena itu test:fuzz adalah pemeriksaan paling lambat dan tidak dipanggil oleh script/test-all.sh.
test/static/dts-lint.ts mengimpor expectType dari tsd dan seluruh tipe dari src/main/ua-parser, lalu memastikan setiap signature mengembalikan tipe yang benar (test/static/dts-lint.ts:1-29).
Gate sebelum sebuah pull request diterima
script/test-all.sh bersifat fail-fast: setiap langkah dipisahkan operator || exit 1, sehingga kegagalan pertama menghentikan seluruh rangkaian (script/test-all.sh:1-3110). Urutan gate-nya adalah build, test:jshint, test:eslint, test:mocha, test:playwright, test:lockfile-lint, dan terakhir test:dts-lint.
gantt
title Urutan gate pada script/test-all.sh
dateFormat X
axisFormat %s
section Build
build :g1, 0, 1
section Lint
jshint :g2, after g1, 1
eslint :g3, after g2, 1
section Unit
mocha :g4, after g3, 1
section Browser
playwright :g5, after g4, 1
section Supply chain
lockfile-lint :g6, after g5, 1
section Types
dts-lint :g7, after g6, 1
%% fig: Urutan gate npm run test
%% desc: Setiap batang adalah satu langkah di script/test-all.sh; batang hanya menunjukkan urutan, bukan durasi, karena langkah berikutnya baru berjalan bila langkah sebelumnya lolos.⚠️
test:fuzztidak ada di dalamscript/test-all.sh. Perubahan pada pola regex tetap harus diuji dengan menjalankannpm run test:fuzzsecara manual sebelum membukapull request.
Gate yang sama dijalankan di CI. Workflow CI: Build & Test berjalan pada push dan pull_request, memakai matriks Node lts/iron, lts/jod, lts/krypton ditambah satu entri ppc64le dengan Node 20, memasang dependensi lewat npm ci dan npx playwright install --with-deps, lalu menutup dengan npm run build+test (.github/workflows/ci-build-test.yml:8-4411).
Aturan kontribusi untuk pola regex
Menambah deteksi berarti menambah pola di src/main/ua-parser.js atau src/extensions/ua-parser-extensions.js, dan setiap pola baru wajib punya unit test pendamping. Kontributor juga diminta menjalankan pemeriksaan safe-regex melalui npm run test, serta mengingat bahwa User-Agent dipotong pada 500 karakter saat parsing (CONTRIBUTING.md:49-5712). Pola safe-regex itu tidak dicek dengan membaca berkas secara manual: test/unit/main.js mem-parse src/main/ua-parser.js dengan @babel/parser, mengumpulkan setiap RegExpLiteral lewat @babel/traverse, dan menegaskan safe(regex) === true untuk semuanya (test/unit/main.js:239-26913). Pemeriksaan yang sama diulang untuk berkas extensions (test/unit/submodules/extensions.spec.js:109-13214).
graph TD
A["Tambah pola di src/main/ua-parser.js atau src/extensions/ua-parser-extensions.js"] --> B["Tambah unit test di test/unit"]
B --> C["npm run test:mocha"]
C --> D["AST: RegExpLiteral dikumpulkan"]
D --> E["safe-regex: safe regex harus true"]
E -->|true| F["npm run test:fuzz"]
E -->|false| G["Pola ditolak, perbaiki regex"]
F --> H["npm run build+test"]
H --> I["pull request ke master"]
style D fill:#8b5cf6,color:#fff
style E fill:#f59e0b,color:#000
style F fill:#2d7d46,color:#fff
style H fill:#2d7d46,color:#fff
style G fill:#dc4026,color:#fff
%% fig: Alur kontribusi pola regex
%% desc: Pola baru harus disertai unit test, lolos pemeriksaan safe-regex berbasis AST, lolos fuzzing ReDoS, lalu melewati rangkaian build+test sebelum pull request dibuka.| Aturan | Sumber |
|---|---|
| Setiap pola regex baru wajib punya unit test | CONTRIBUTING.md:49-5712 |
| User-Agent dipotong pada 500 karakter saat parsing | CONTRIBUTING.md:49-5712 |
Semua pull request harus lolos full test suite | CONTRIBUTING.md:61-6315 |
Dilarang eval(), new Function(), dan pola tidak aman lain | CONTRIBUTING.md:67-7716 |
| Dependency produksi baru butuh persetujuan maintainer lewat issue | CONTRIBUTING.md:67-7716 |
Pesan commit mengikuti Conventional Commits dengan bentuk <type>(<scope>): <short summary>. Breaking change ditandai ! setelah type/scope dan footer BREAKING CHANGE:, dan commit semacam itu memicu kenaikan versi minor atau major saat rilis (CONTRIBUTING.md:90-11217).
Mengirim pull request
Branch dibuat dari master, perubahan disertai test, dan npm run build+test dijalankan sebelum push. Berkas hasil build tidak boleh di-commit: itu mencakup berkas JS di /dist, berkas .mjs, type declaration seperti src/enums/ua-parser-enums.d.ts, dan berkas apa pun yang bertanda DO NOT EDIT. pull request ditujukan ke master dan formulirnya memuat pengakuan CLA (CONTRIBUTING.md:116-13418). Template pull request menegaskan dua hal itu di baris paling atas: telah membaca panduan kontribusi dan telah menandatangani CLA (.github/PULL_REQUEST_TEMPLATE.md:1-419).
Melaporkan celah keamanan
Celah keamanan tidak dilaporkan lewat issue publik, melainkan lewat email ke [email protected] beserta deskripsi, langkah reproduksi, versi terdampak, dan mitigasi bila sudah diketahui. Proyek memakai linimasa pengungkapan 90 hari, dan celah yang terkonfirmasi akan dibuka sebagai security advisory di halaman GitHub Security Advisory (SECURITY.md:12-1820).
| Versi | Didukung |
|---|---|
| 2.x | ✅ |
| 1.x | ✅ |
| 0.7.x | ✅ |
| < 0.7 | ❌ |
Daftar versi di atas adalah yang menerima laporan dan perbaikan (SECURITY.md:12-1820).