10 KiB
QA Test Plan
Branch: experimental-polar-steps. Tester role: Senior Staff QA Engineer.
Scope
All features implemented in Phase 4 (Milestones 1–4):
- M1: Entry enrichment (location badge, weather badge, photo gallery, hero image)
- M2: Interactive map page
- M3: Statistics page
- M4: Mini-map on tracker feed
Test URLs:
- Desktop: http://localhost:8081
- Mobile: http://100.96.115.96:8081 (Tailscale — requires physical phone)
Milestone 1 — Entry Enrichment
TC-1.1: Location badge on entry page
| Step | Action | Expected Result |
|---|---|---|
| 1 | Open http://localhost:8081/tracker/2026-06-17.entry | Entry page loads (200) |
| 2 | Look at entry header | 📍 Amsterdam, Netherlands visible below date |
| 3 | Inspect HTML | <p class="entry-location"> present with city and country |
Automation: grep for .entry-location and "Amsterdam" in curl output
TC-1.2: Weather badge on entry page
| Step | Action | Expected Result |
|---|---|---|
| 1 | Open http://localhost:8081/tracker/2026-06-17.entry | Entry page loads |
| 2 | Look at entry header | ⛅ Partly cloudy · 19°C visible |
| 3 | Inspect HTML | <p class="entry-weather"> present |
Automation: grep for .entry-weather and "Partly cloudy" and "19°C"
TC-1.3: Location badge hidden when fields empty
| Step | Action | Expected Result |
|---|---|---|
| 1 | Create test entry with no location_city/location_country | — |
| 2 | Open that entry | No 📍 badge shown, no empty <p> rendered |
Automation: Check example entry before fields were added (not needed — fields are now set); create a second test entry without location
TC-1.4: Weather badge hidden when fields empty
| Step | Action | Expected Result |
|---|---|---|
| 1 | Entry with no weather fields | No weather section in HTML |
Automation: grep for entry-weather in HTML — should only appear if value present
TC-1.5: Hero image on tracker feed card
| Step | Action | Expected Result |
|---|---|---|
| 1 | Open http://localhost:8081/tracker | Feed loads |
| 2 | Entry card for 2026-06-17 | No image shown (example entry has no photos) |
| 3 | Upload a photo to the entry via Admin media manager | — |
| 4 | Reload tracker | Hero image shows as 16:9 thumbnail |
Manual verification required: Photo upload requires browser Admin interaction
TC-1.6: Location badge on tracker feed card
| Step | Action | Expected Result |
|---|---|---|
| 1 | Open http://localhost:8081/tracker | Feed loads |
| 2 | Entry card | 📍 Amsterdam, Netherlands visible |
Automation: grep feed HTML for entry-location--card and "Amsterdam"
TC-1.7: Photo gallery renders on entry page (with photos)
| Step | Action | Expected Result |
|---|---|---|
| 1 | Upload 3 photos to the example entry via Admin | — |
| 2 | Open entry page | Gallery grid appears below entry body |
| 3 | Count thumbnails | 3 thumbnails in 2-col (mobile) / 3-col (desktop) grid |
| 4 | Click a thumbnail | Lightbox overlay opens with full-size image |
| 5 | Press Escape | Lightbox closes |
| 6 | Click left/right arrow buttons | Navigates between images |
| 7 | Click outside lightbox | Lightbox closes |
Manual verification required: Photo upload and interactive lightbox require browser
TC-1.8: Post form has location and weather fields
| Step | Action | Expected Result |
|---|---|---|
| 1 | Open http://localhost:8081/post (logged in) | Post form renders |
| 2 | Inspect form | City and Country text inputs present |
| 3 | Inspect form | 📍 Get Current Location and 🌤 Get Weather buttons present |
Automation: grep /post HTML for location_city, location_country, get-location, get-weather
TC-1.9: Get Weather button fills fields
| Step | Action | Expected Result |
|---|---|---|
| 1 | Open /post on phone | Post form loads |
| 2 | Tap "Get Current Location" | Lat/lng fields fill with coordinates |
| 3 | Tap "Get Weather" | Status shows "🌤 Weather set: [desc] · [temp]°C" |
| 4 | Submit form | New entry created with weather in frontmatter |
| 5 | Open entry in Admin | weather_temp_c and weather_desc fields populated |
Manual verification required: Geolocation and form submission require mobile browser
Milestone 2 — Interactive Map
TC-2.1: Map page loads
| Step | Action | Expected Result |
|---|---|---|
| 1 | GET http://localhost:8081/map | HTTP 200 |
| 2 | Inspect HTML | <div id="trip-map"> present |
| 3 | Inspect HTML | Leaflet CSS and JS from CDN present |
Automation: curl + HTTP status check; grep for "trip-map" and "leaflet"
TC-2.2: Entry with GPS appears in ENTRIES JSON
| Step | Action | Expected Result |
|---|---|---|
| 1 | curl http://localhost:8081/map | Map page HTML |
| 2 | grep for var ENTRIES |
Array contains Amsterdam entry with lat 52.3676 |
| 3 | Check entry has title, date, url | All fields present |
Automation: grep output for ENTRIES and lat value
TC-2.3: Map renders marker and route in browser
| Step | Action | Expected Result |
|---|---|---|
| 1 | Open /map in browser | Map tiles load, marker visible |
| 2 | Click marker | Popup opens with "The Journey Begins" title and "Read entry →" link |
| 3 | Click "Read entry →" | Navigates to entry page |
Manual verification required: Leaflet rendering requires browser
TC-2.4: Map navigation link in header
| Step | Action | Expected Result |
|---|---|---|
| 1 | Open any page | Header shows Journal, Map, Stats nav links |
| 2 | Click Map | Navigates to /map |
Automation: grep base template output for "/map" nav link
TC-2.5: Empty state (no GPS entries)
| Step | Action | Expected Result |
|---|---|---|
| 1 | Remove lat/lng from test entry temporarily | — |
| 2 | Visit /map | Map at world zoom, "No locations yet" message shown |
| 3 | Restore lat/lng | — |
Manual verification required: Requires temporarily editing entry
TC-2.6: Map page is full-height on mobile
| Step | Action | Expected Result |
|---|---|---|
| 1 | Open /map on mobile browser | Map fills screen below header |
| 2 | Pinch to zoom | Map zooms without page scrolling |
| 3 | Pan with finger | Map pans without page scrolling |
Manual verification required: Touch interaction requires physical device
Milestone 3 — Statistics Page
TC-3.1: Stats page loads
| Step | Action | Expected Result |
|---|---|---|
| 1 | GET http://localhost:8081/stats | HTTP 200 |
| 2 | Inspect HTML | Four stat blocks present |
Automation: curl + HTTP status + grep for "stat-block"
TC-3.2: Days on the road count
| Step | Action | Expected Result |
|---|---|---|
| 1 | curl /stats | Page HTML |
| 2 | grep for "days" | Shows "1 day on the road" (entry date: 2026-06-17, today: 2026-06-18) |
Automation: grep stat-value output and compare to expected day count
TC-3.3: Entries count
| Step | Action | Expected Result |
|---|---|---|
| 1 | curl /stats | grep for "entry posted" |
Automation: grep for "entry posted"
TC-3.4: Countries visited
| Step | Action | Expected Result |
|---|---|---|
| 1 | curl /stats | grep for "Netherlands" |
| 2 | grep for "country visited" | Shows "1 country visited" |
Automation: grep output
TC-3.5: Distance shows "—" for single GPS point
| Step | Action | Expected Result |
|---|---|---|
| 1 | curl /stats | grep for GPS_POINTS |
| 2 | In browser, check stat-distance | Shows "—" (JS computes, needs browser) |
Automation: grep GPS_POINTS array length from page source
TC-3.6: Stats navigation link
| Step | Action | Expected Result |
|---|---|---|
| 1 | Open any page header | "Stats" link present in nav |
| 2 | Click Stats | Navigates to /stats |
Automation: grep any page HTML for "/stats" in nav
Milestone 4 — Mini-map on Tracker Feed
TC-4.1: Mini-map appears on tracker feed
| Step | Action | Expected Result |
|---|---|---|
| 1 | GET http://localhost:8081/tracker | HTTP 200 |
| 2 | grep for "feed-map" | Mini-map div present |
| 3 | grep for "FEED_ENTRIES" | JSON array with Amsterdam entry |
| 4 | grep for "View full map →" | Link to /map present |
Automation: curl + grep
TC-4.2: Mini-map hidden when no GPS entries
| Step | Action | Expected Result |
|---|---|---|
| 1 | Remove lat/lng from example entry | — |
| 2 | curl /tracker | No "feed-map" div in output |
| 3 | Restore lat/lng | — |
Manual verification: Requires temporarily editing entry
TC-4.3: Marker click navigates to entry (mobile)
| Step | Action | Expected Result |
|---|---|---|
| 1 | Open /tracker on phone | Mini-map renders above entry list |
| 2 | Tap Amsterdam marker | Navigates to /tracker/2026-06-17.entry |
Manual verification required: Touch interaction requires browser
TC-4.4: Entry list still visible below mini-map
| Step | Action | Expected Result |
|---|---|---|
| 1 | Open /tracker | Mini-map shows, scroll down |
Manual verification required: Visual layout check
Cross-cutting Tests
TC-X.1: Nav links present on all pages
| Page | Expected nav links |
|---|---|
| /tracker | Journal, Map, Stats |
| /map | Journal, Map, Stats |
| /stats | Journal, Map, Stats |
| /tracker/2026-06-17.entry | Journal, Map, Stats |
Automation: curl each page, grep for all three links
TC-X.2: All pages return 200
| Page | Expected HTTP status |
|---|---|
| / (redirects to /tracker) | 200 or 302→200 |
| /tracker | 200 |
| /tracker/2026-06-17.entry | 200 |
| /map | 200 |
| /stats | 200 |
| /post | 200 (after login) or 302 (login redirect) |
Automation: curl HTTP status checks
TC-X.3: Mobile touch targets ≥44px
| Element | Expected min height/width |
|---|---|
| Nav links | 44px height |
| Gallery thumbnails | 44px on shortest side |
| Lightbox close/prev/next buttons | 44px |
| Post form buttons | 44px height |
| "Get Location" button | 44px height |
| "Get Weather" button | 44px height |
Manual verification required: Inspect computed CSS or measure visually on device
TC-X.4: No JS errors in browser console
| Page | Expected |
|---|---|
| /tracker | No console errors |
| /map | No console errors (may have tile 404s for tiles not in viewport — acceptable) |
| /stats | No console errors |
| /tracker/2026-06-17.entry | No console errors |
Manual verification required: Open browser DevTools