Kerbside Car Share

Test Plan — Neighbourhood Car Share

1. Strategy

| Level | Tool | What | |—|—|—| | Unit | node:test — tests/pricing.test.js, tests/rules.test.js | Price calculation and booking rules (src/rules.js) | | Hosted parity | node:test — tests/hosted.test.js; npm run check:hosted | hosted/index.html inlines the current src/rules.js, and its rules section passes the same pricing cases (tests/fixtures/quote-cases.js) | | API / integration | node:test — tests/api.test.js | Each test starts the real Express app on a random port with a fresh in-memory SQLite DB and calls it over HTTP with per-user cookie jars | | Manual UI | Browser checklist below | Layout, map, dialogs, phone width, dark mode |

Run the automated tests with npm test (no network or database setup needed). CI (.github/workflows/ci.yml) runs npm run check:hosted and npm test on every push to main and every pull request.

2. Automated test cases

| ID | Test (file: test name) | Requirement | |—|—|—| | T-01 | pricing: charges hourly for short rentals | §5 pricing | | T-02 | pricing: rounds partial hours up | §5 | | T-03 | pricing: hourly cost is capped at the daily rate | §5 | | T-04 | pricing: one whole day uses the daily rate; whole days plus leftover hours; leftover hours capped at one extra day | §5 | | T-05 | api: register, me, logout, login (case-insensitive username, wrong password rejected) | US-01, US-03 | | T-06 | api: rejects weak passwords and duplicate usernames | US-01, NFR-3 | | T-07 | api: enforces the member limit | US-02 | | T-08 | api: requires the invite code when configured | US-02 | | T-09 | api: API needs login | NFR-3 | | T-10 | api: owner can add, update price/listing and delete a car; unlisted hidden; non-owner gets 403 | US-30, 31, 33, 34 | | T-11 | api: validates car input (negative price, bad latitude, empty make, javascript: URL) | NFR-6 | | T-12 | api: browse filters by seats, price, text and free time; quote returned | US-11 | | T-13 | api: overlapping availability windows are merged | US-32 | | T-14 | api: cannot remove an availability window that holds a booking | US-32 | | T-15 | api: renter books a car; price is calculated; owner and renter both see it | US-20, 22, 23 | | T-16 | api: rejects double bookings, bookings outside availability, own-car, reversed and past bookings; allows back-to-back | US-21 | | T-17 | api: cancelling frees the slot; strangers cannot cancel; can’t cancel twice | US-22, 23 | | T-18 | api: car with upcoming bookings cannot be deleted | US-33 | | T-19 | api: detail hides renter names from other users | NFR-7 | | T-20 | api: owner uploads a photo and attaches it to a car; renters see it; missing files 404 | US-35, US-36 | | T-21 | api: rejects uploads that are not photos, and anonymous uploads | US-35, NFR-3 | | T-22 | api: photo must be an uploaded file, a bundled photo or a web link (no /etc/passwd, no ..) | US-35, NFR-6 | | T-23 | rules: intervals are half-open (touching ones don’t overlap); covers() and contains() edges; ms and ISO times | US-21 | | T-24 | rules: mergeWindow() absorbs overlapping and touching windows only | US-32 | | T-25 | rules: bookingConflict() checks the window first, then existing bookings | US-21 | | T-26 | hosted: hosted/index.html inlines the current src/rules.js | NFR (parity) | | T-27 | hosted: page’s quote(), whyNot() and mergeWindow() match the server cases; old windows pruned (hosted-only) | §5, US-21, US-32 |

Latest result: 37 / 37 passed (Node 24.21, Windows 11).

3. Manual UI checklist

Run npm run seed -- --reset, then npm start, and open http://localhost:3080.

# Steps Expected
M-01 Register a new account Lands on Browse; name in the top bar
M-02 Log out, log in as bob / password123 Browse shows 6 demo cars
M-03 Type “tesla” in search; set seats 7+; set max/hour 8 List updates within ¼ s each time
M-04 Set From/To for tomorrow 10:00–12:00 Only free cars shown, each with “… for your time” price
M-05 Switch to Map Price pins near the default centre; grey pins = not free now; clicking a pin → popup → “Details & book”
M-06 Open the Toyota 7-day timeline shows green and red blocks; booked list shows “Booked” (not names)
M-07 Pick a time overlapping a red block Red error, Confirm button disabled
M-08 Pick a free time and confirm Toast shown; the booking appears under Bookings → My trips
M-09 Log in as alice → My cars → change the Toyota’s hourly price → Save price Toast “Saved”; new price shown in Browse
M-10 Add a time slot; click “Every day 8:00–20:00 for a week”; remove a slot Slot list updates; overlapping slots merge
M-11 Uncheck “Listed” and save Car hidden for bob; shows “Unlisted” for alice
M-12 + Add a car → click the map to set location → Save New car in My cars, and on the map once it has slots
M-13 Bookings → cancel a booking Status becomes “Cancelled”; slot is free again
M-14 Narrow the window to phone width (~375 px) No sideways scrolling; dialogs fit; tabs usable
M-15 Switch the OS to dark mode Colours adapt and text stays readable
M-16 Browse the list Every demo car shows its photo, with the availability badge over the photo
M-17 Open a car; open a map pin Large photo with “Photo: …” credit; map pop-up shows a small photo
M-18 My cars → Edit details → Upload a photo (JPEG) → Save Preview appears, then the new photo shows in Browse, with no credit line
M-19 Try uploading a .txt file renamed to .jpg, or a file over 5 MB Clear error; the car keeps its old photo
M-20 Open from another device on the same Wi-Fi using the “Your network” URL App loads and login works