Repository navigation
Testing
Two complementary suites: unit tests catch broken logic, smoke tests catch broken plumbing.
From v2.7.0, npm test runs 285 unit tests over the parts of the server that have historically broken. Node's built-in test runner is used, so there is no framework and no extra dependency.
cd /opt/ip-manager
npm testThey need no running server and no database — an overridable DB_PATH points them at a throwaway file.
| Module | What is checked |
|---|---|
lib/net.js |
Subnet validation (the shell-injection guard), interface names, IP sorting across all four octets, the ping status vocabulary, derived label and serviceUrl
|
lib/redact.js |
That support bundles cannot leak passwords, hashes, API keys or tokens, and that ordinary log lines are untouched |
lib/credentials.js |
Every path through credential loading and the bcrypt migration — the module that has caused two lockout incidents |
lib/sessions.js |
Session lifetime, and that the login throttle engages, isolates by address, and resets on success |
lib/apikeys.js |
Scope enforcement: read keys cannot write, query-string keys cannot write, account routes stay session-only |
lib/totp.js |
The RFC 4226 and RFC 6238 published test vectors, base32 handling, drift and replay |
lib/twoFactor.js |
Enrolment, recovery codes, and that enabling requires a verified code |
lib/topology.js |
Graph derivation, hypervisor name matching, gateway inference, and that a circular dependency terminates |
lib/watch.js |
That the Network Watch ledger cannot grow without bound — a simulated year of scanning, a flood of fabricated MACs, per-record caps, retention and eviction order |
apiDocs.test.js |
That every API-key-reachable route, capability flag and the served apiVersion appear in the API reference — so a platform change cannot ship without its documentation |
shared/common.js |
Modal ordering: only the topmost overlay responds to Escape, including when they close out of order |
lib/releaseNotes.js |
Numeric version ordering, multi-version catch-up, and that the running version actually has notes written for it |
lib/pihole.js |
Session reuse (20 fetches must produce 1 login), retry bounds, credential handling, and that a DHCP name never overrides a better one |
lib/mdns.js |
Wire-format parsing of hostile packets — compression loops, lying length fields, truncated records — and that discovery never proposes overwriting a name the user set |
Every test corresponds to something that actually went wrong at some point. The suite was validated by reintroducing two historical bugs and confirming it catches them.
npm run api:check # show any change to the API surface
npm run api:accept # accept it deliberatelyserver/api-manifest.json records every route, every capability flag and the served apiVersion. A test compares the live surface against it, so adding, removing or renaming a route fails the build until the change is accepted — and accepting it is the prompt to update API, iOS Client Handover and the CHANGELOG.
The documentation-coverage checks catch an absence. This catches a change, which is the case where the documentation stays internally consistent while quietly breaking a client.
See Release Checklist for the three questions no test can answer.
npm run check:modalsFrom v2.12.0, this renders every lazily-loaded modal server-side and fails if one throws.
It exists because a build cannot catch this class of error. When those modals were extracted into their own files, three of them used <React.Fragment> without importing React — an undefined identifier inside a function body, which compiles perfectly and only fails when the component actually renders. All three would have opened as a blank modal.
Run it after moving any component between files.
scripts/smoke-test.cjs verifies a running install end-to-end in a few seconds.
It is safe to run against a live server. Almost every check is read-only; the API-key group creates two temporary keys and one temporary entry at 203.0.113.253 (a reserved TEST-NET-3 address that can never be a real device) and removes all three afterwards. Pass --read-only to skip that group and touch nothing at all.
cd /opt/ip-manager
SMOKE_USER=yourname SMOKE_PASS='yourpassword' node scripts/smoke-test.cjsWrap the password in single quotes — bash will otherwise try to interpret characters like !.
No npm install is needed; the script uses only built-in Node modules.
| Variable / flag | Purpose |
|---|---|
SMOKE_HA_KEY |
Home Assistant API key. Optional — if omitted, the script reads the key from the server using your session. |
--url <base> |
Target a different host. Default http://127.0.0.1:3001, which bypasses Nginx and tests the API directly. |
--build |
Also run npm run build and fail if the frontend build breaks. |
--read-only |
Skip the write tests. Nothing is created or deleted. |
--verbose |
Print response bodies for failing checks. |
Exit code is 0 when everything passes and 1 on any failure, so it can gate a deployment:
node scripts/smoke-test.cjs --build && ip-manager-update1. Reachability and authentication — the server responds, unauthenticated requests are rejected, wrong passwords and unknown usernames are refused, correct credentials succeed and issue a session cookie, and usernames are matched case-insensitively.
2. Protected endpoints — every API route returns the expected status code and response shape, including routes that require query parameters.
3. Status caches — the ping and service-health caches return well-formed results, and ping values are within the expected set.
4. Home Assistant API — missing and incorrect API keys are rejected, all three endpoints return the documented shape, device counts add up, and the reported statuses are real rather than all-unknown.
4b. API keys and entry endpoints — keys can be created with a label and scope; a read-only key is refused on writes; a key cannot be used in a query string for writes, cannot manage other keys, and cannot download a support bundle; entries can be created, fetched, patched and deleted individually; conflicting updates are rejected. Temporary keys and entries are cleaned up.
5. Security regressions — every route that should require a session actually does, and the support bundle contains no credentials.
6. Build — optionally, that the frontend still compiles.
4. Home Assistant API
PASS GET /api/ha/summary returns the expected shape
FAIL HA reports device status rather than all-unknown
ping cache holds 87 live result(s) but HA reports every device
as unknown (online=0, offline=0, unknown=87)
Summary
40 passed 2 failed 1 skipped (9.4s)
Failures repeat at the end with their detail, so a truncated terminal still shows everything that went wrong.
A SKIP is not a failure — it means a check couldn't run, usually because no Home Assistant key has been generated or --build wasn't passed.
The most useful habit is to run it before and after updating:
node scripts/smoke-test.cjs > /tmp/before.txt
ip-manager-update
node scripts/smoke-test.cjs > /tmp/after.txt
diff /tmp/before.txt /tmp/after.txtAnything that passed before and fails afterwards is a regression introduced by the update, and worth reporting.
Worth being clear about what a clean run does not prove:
- It exercises the API, not the user interface. A passing run says nothing about whether the front end renders correctly.
- The support-bundle credential check reflects the bundle at that moment. The bundle embeds recent log lines, so on a freshly installed server it may contain the generated startup password even when the check passes on an older one.
- Checks that depend on data — device counts, domain expiry — pass trivially when there is no data to look at.
- If the run is interrupted part-way through the API-key group, a key labelled
smoke-test-readorsmoke-test-writemay be left behind. Delete it in Settings → API Keys.
It is a fast way to catch broken plumbing, not a substitute for trying the app.
IP Manager · GitHub · Releases · PolyForm Noncommercial License
IP Manager
Getting Started
Features
- Importing Devices
- Service Health Checks
- Domain Tracker
- API
- iOS Client Handover
- Home Assistant API
- Notifications
- Topology
- mDNS Discovery
- Network Watch
- Maintenance & Offline Filter
- Backup & Restore
Maintenance
Project