This project includes two real-browser Chrome scripts for the production site or any deployed CF-Navs origin.
npm run perf:auditchecks performance-sensitive behavior and thresholds.npm run regression:chromechecks broader functional regression paths without modifying data.
Read docs/reference/PERFORMANCE_CONTRACT.md before changing data freshness, icon loading, Service Worker caching, or admin loading behavior.
Start a dedicated Chrome with a DevTools endpoint. By default regression:chrome starts an isolated temporary profile and fails if the configured port is already occupied. Reuse of an existing browser is opt-in only and must target a browser dedicated to this test.
Default endpoint:
http://127.0.0.1:9223Each script creates a dedicated test tab for BASE_URL, logs in through the page, runs the audit, prints JSON metrics, removes cf-navs.auth, and closes only that test tab before exit. Existing user tabs are never reused or closed.
Copy the tracked template once, then put the real deployment origin in the git-ignored local file:
Copy-Item verify.local.example.json verify.local.json{
"baseUrl": "https://your-cf-navs-domain.example",
"chromeDebugPort": "9223"
}verify.local.json may contain deployment origin and browser settings, but never administrator credentials. BASE_URL, CHROME_DEBUG_PORT, CHROME_EXE, CHROME_PROFILE_ROOT, and CHROME_USER_DATA_DIR environment variables override matching local values. A missing target fails immediately instead of falling back to another deployment.
$env:ADMIN_USER = '<admin user>'
$env:ADMIN_PASS = '<admin password>'
npm run perf:auditFunctional regression:
$env:CHROME_DEBUG_PORT = '9228'
$env:ADMIN_USER = '<admin user>'
$env:ADMIN_PASS = '<admin password>'
npm run regression:chrome受管 Windows 环境如果隔离无头 Chrome 启动后无法保持 CDP 端口,可仅对本次临时 profile 显式启用:
$env:CHROME_NO_SANDBOX = '1'
npm run regression:chrome该选项只适用于脚本创建的临时 profile,不要用于用户已有浏览器或默认 profile。脚本仍以临时 profile 的 DevToolsActivePort 为启动成功条件,并在退出时按完整 profile 路径清理进程。
By default regression:chrome starts a temporary Chrome profile under the operating system temporary directory, named cf-navs-chrome-profile-<port>. Its finally cleanup closes the test-owned browser, stops only Chrome processes matching that exact profile, verifies the remaining process count is zero, and then removes the profile.
When Chrome is already running with a dynamic DevTools port, the script can connect through the browser websocket only if REGRESSION_ALLOW_EXISTING_CHROME=1 and CHROME_DEVTOOLS_ACTIVE_PORT_FILE are set for a browser dedicated to this test. In that mode the JSON output reports browserConnectionMode: "dedicated-existing-browser" and does not start a temporary Chrome process. The helper scripts/discover-devtools.ps1 never scans the default Chrome profile; existing-browser discovery requires an explicit active-port file and opt-in switch.
Explicit existing-browser opt-in:
$env:REGRESSION_ALLOW_EXISTING_CHROME = '1'
$env:CHROME_DEVTOOLS_ACTIVE_PORT_FILE = 'D:\path\to\dedicated-test-profile\DevToolsActivePort'Existing Chrome and every visible/headed Chrome are user-owned unless current-task authorization says otherwise. Both scripts create and close only their dedicated test target. They must never call Browser.close or terminate a Chrome process in those modes.
For unattended runs where an existing Chrome profile must not be used, force a temporary headless profile and choose a free port:
$env:REGRESSION_FORCE_TEMP_CHROME = '1'
$env:CHROME_DEBUG_PORT = '9230'
$env:CHROME_USER_DATA_DIR = "$env:TEMP\cf-navs-chrome-profile-9230"
npm run regression:chromeWith REGRESSION_FORCE_TEMP_CHROME=1, the regression script skips DevToolsActivePort. If the configured port is already in use, it fails instead of attaching to an existing browser.
For safety, CHROME_USER_DATA_DIR must end with cf-navs-chrome-profile-<unique-id>. The script refuses arbitrary profile paths so it can never delete a normal Chrome profile during cleanup. REGRESSION_CLEAR_ORIGIN_DATA=1 is rejected when the run reuses an existing browser.
Never clean up with taskkill /IM chrome.exe, Get-Process chrome | Stop-Process, or another process-name-wide command. If exact-profile process cleanup fails, treat the regression run as failed and report the remaining process count.
Optional:
$env:PERF_AUDIT_ALLOW_FAILURES = '1'Use this only when collecting diagnostics from a known-bad run. By default, the script exits non-zero if it sees failed network requests or cannot complete a core scenario.
Thresholds can be tuned per deployment:
$env:PERF_MAX_FAILED_REQUESTS = '0'
$env:PERF_MAX_ADMIN_DATA_TRANSFER = '60000'
$env:PERF_MAX_CACHE_BYTES = '5242880'
$env:PERF_MIN_BOOKMARK_CARDS = '300'
$env:PERF_MAX_ICON_REQUESTS = '260'The JSON output includes a checks array with pass/fail status, actual values, and expected thresholds.
For regression diagnostics, use:
$env:REGRESSION_ALLOW_FAILURES = '1'
$env:REGRESSION_MIN_BOOKMARK_CARDS = '1'
$env:REGRESSION_MIN_CATEGORIES = '1'
$env:REGRESSION_MIN_BOOKMARKS = '1'
$env:REGRESSION_CLEAR_ORIGIN_DATA = '1'Use these regression diagnostics with the default isolated browser. The script rejects origin-level cleanup when it is attached to an existing browser.
- Login through
/api/loginin page context and authenticated reload. - API smoke checks for
/api/health,/api/config,/api/data/version,/api/admin/data, and/api/iconify-search. - Home render, bookmark cards, section count, theme toggle, local search and broken image count.
- Admin entry from the home toolbar.
- Admin category, bookmark, settings, and backup tabs.
- Admin bookmark search input and clear.
- Bookmark card right-click using CDP
Input.dispatchMouseEvent, context menu edit action, edit modal open/cancel. - Logout and local auth cleanup.
- Console errors, page exceptions, failed requests, and unexpected HTTP 4xx/5xx.
- Authenticated home reload.
- Full-page scroll to trigger lazy bookmark icons.
- Rapid home search input and clear.
- Admin entry from the home toolbar.
- Admin bookmark search input and clear.
- Network request summary, including
/api/admin/data,/api/icon/*,/api/iconify/*, and failed requests. - Storage summary for
navigator.storage.estimate()and Cache Storage entries.
Both scripts intentionally avoid save, delete, import, sort-save, and icon-cache refresh endpoints by default. That keeps them suitable for production regression checks without modifying cloud data or increasing request volume beyond measured browsing scenarios.