Files
intotheeast-com/docs/working/qa/test-plan.md
T
m038 05d65652bd docs: move remaining untracked files to restructured locations
- milestone specs: docs/milestone-*-spec.md → docs/working/milestones/milestone-*.md
- qa files: docs/qa-*.md → docs/working/qa/*.md
- research files: docs/research-*.md → docs/research/*.md
- design spec: docs/design/design-spec.md → docs/reference/design-system.md
- backlog, pm-analysis, summary: moved to docs/working/
2026-06-21 12:42:32 +02:00

21 KiB
Raw Blame History

QA Test Plan

Branch: experimental-polar-steps. Tester role: Senior Staff QA Engineer.


Scope

All features implemented in Phase 4 (Milestones 14):

  • 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:


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


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


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


Post Submission Flow

These scenarios cover the full round-trip: filling the form → saving → verifying values in the UI and on disk. Use the exact test values specified so that each assertion can be precise.

Test data (use verbatim):

Field Value
Title QA Test Entry
Date & Time 2026-06-18 10:00
Content This is the QA test body. Second sentence for length.
City Tokyo
Country Japan
Latitude 35.689487
Longitude 139.691711
Photos none (keep simple for first run)

Expected slug: 2026-06-18-1000-qa-test-entry Expected folder: 2026-06-18-1000-qa-test-entry.entry/ Expected URL: /tracker/2026-06-18-1000-qa-test-entry.entry

The slug is built from date(Y-m-d-Hi) + title lowercased with [^a-z0-9]+ replaced by hyphens.


TC-P.1: Post form requires authentication

Step Action Expected Result
1 Open private/incognito tab (no session)
2 GET http://100.96.115.96:8081/post Page loads at /post URL (no redirect) but renders the login form inline
3 Inspect page content Login form fields (username, password) visible; post form fields absent

Automation: curl /post without auth; assert login-form-nonce present AND data[title] absent


TC-P.2: Post form renders all fields

Step Action Expected Result
1 Log in at /login Redirected to /tracker
2 Navigate to /post Post form page loads (200)
3 Check form fields present Title, Date & Time, description textarea, Photos upload
4 Check location fields Latitude, Longitude, City, Country inputs visible
5 Check action buttons 📍 Get Current Location and 🌤 Get Weather buttons visible
6 Check submit button Post Entry button visible
7 Check date field default Pre-filled with today's date and time (not blank)

Automation: curl /post with auth; grep for data[title], data[lat], data[location_city], get-location, get-weather


TC-P.3: Required field validation

Step Action Expected Result
1 Log in and open /post Form loads
2 Leave Title blank, fill in only the description
3 Submit form Page reloads with validation error on Title
4 Error message Indicates title is required
5 Fill in Title, clear Description/Content, submit Validation error on Content field
6 Confirm No new entry file created in pages/01.tracker/ during failed submissions

Manual verification required: Validation feedback requires browser


TC-P.4: Successful post submission — all fields

Step Action Expected Result
1 Log in and open /post Form loads
2 Enter Title: QA Test Entry
3 Set Date to 2026-06-18 10:00
4 Enter Content: This is the QA test body. Second sentence for length.
5 Enter City: Tokyo, Country: Japan
6 Enter Latitude: 35.689487, Longitude: 139.691711
7 Leave Photos empty
8 Click Post Entry Form submits (POST to /post)
9 Observe result Success message Entry posted successfully! shown on page
10 Form state Form is reset / fields cleared

Manual verification required: Form submission and success message require browser


TC-P.5: Entry file created on disk with correct values

Step Action Expected Result
1 After TC-P.4 completes
2 Check directory user/pages/01.tracker/ Folder 2026-06-18-1000-qa-test-entry.entry/ exists (add-page-by-form appends template name per physical_template_name: true)
3 Read user/pages/01.tracker/2026-06-18-1000-qa-test-entry.entry/entry.md File exists
4 Verify frontmatter title Equals QA Test Entry
5 Verify frontmatter date Equals 2026-06-18 10:00
6 Verify frontmatter location_city Equals Tokyo
7 Verify frontmatter location_country Equals Japan
8 Verify frontmatter lat Equals 35.689487
9 Verify frontmatter lng Equals 139.691711
10 Verify frontmatter template Equals entry
11 Verify frontmatter published Equals true
12 Verify page body Contains This is the QA test body. Second sentence for length.

Automation: Read file from filesystem; parse YAML frontmatter; assert each field value exactly


TC-P.6: Entry appears in tracker feed

Step Action Expected Result
1 BUG-001 fixed — no manual cache clear needed
2 GET http://100.96.115.96:8081/tracker Page loads (200)
3 Entry card present Card with title QA Test Entry visible
4 Date shown on card 18 Jun 2026
5 Location badge on card 📍 Tokyo, Japan visible
6 Entry card link href points to /tracker/2026-06-18-1000-qa-test-entry.entry
7 Excerpt shown Partial text of the body content visible

Automation: curl /tracker; grep for "QA Test Entry", "18 Jun 2026", "Tokyo", "Japan", "/tracker/2026-06-18-1000-qa-test-entry.entry"


TC-P.7: Entry detail page shows correct values

Step Action Expected Result
1 GET http://100.96.115.96:8081/tracker/2026-06-18-1000-qa-test-entry.entry Page loads (200)
2 Page title QA Test Entry in <h1>
3 Date header Thursday, 18 June 2026 (or locale equivalent)
4 Location badge 📍 Tokyo, Japan
5 Body content Full text This is the QA test body. Second sentence for length. rendered
6 No gallery Photo gallery section absent (no photos were uploaded)
7 Back link ← Back to journal link present, points to /tracker

Automation: curl /tracker/2026-06-18-1000-qa-test-entry.entry; grep for "QA Test Entry", "Tokyo", "Japan", "This is the QA test body", "Back to journal"


TC-P.8: Entry appears on map and mini-map

Step Action Expected Result
1 GET http://100.96.115.96:8081/tracker Mini-map section visible
2 Inspect FEED_ENTRIES JSON Contains entry with lat: "35.689487", lng: "139.691711", title: "QA Test Entry"
3 GET http://100.96.115.96:8081/map Map page loads
4 Inspect ENTRIES JSON Contains same entry

Automation: curl /tracker and /map; grep FEED_ENTRIES and ENTRIES JSON for lat/lng values


TC-P.9: Entry appears in stats

Step Action Expected Result
1 GET http://100.96.115.96:8081/stats Page loads (200)
2 Entries count Shows 2 entries (existing test entry + new QA entry)
3 Countries list Japan and Netherlands both listed

Automation: curl /stats; grep entry count and country names


TC-P.10: Two posts on the same day

Step Action Expected Result
1 Submit a first post: date 2026-06-18 10:00, title Morning Update Success message shown
2 Submit a second post: date 2026-06-18 14:30, title Afternoon Update Success message shown
3 Check filesystem Two separate folders exist: 2026-06-18-1000-morning-update.entry/ and 2026-06-18-1430-afternoon-update.entry/
4 Visit /tracker Both entries visible as separate cards

Note: The slug encodes date + time + title, so same-day posts are fully supported as long as they have different times or titles. A true collision (same date, same time, same title) would silently fail — treat this as acceptable given solo use.

Manual verification required: Requires two browser submissions


Cross-cutting Tests

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


Visual Design QA — Redesign Checklist

Design spec: user/docs/design/design-spec.md
Implementation plan: user/docs/superpowers/plans/2026-06-18-ui-redesign.md

Typography

  • DM Serif Display loads for: entry titles, page headings (h1), stat numbers, site title
  • DM Sans loads for: body text, nav links, labels, form fields, timestamps
  • No fallback font (Georgia / system-sans) visible in place of custom fonts
  • Body text font-size ≥ 16px (no iOS zoom on form focus)

Colors

  • Page background is warm paper (#F7F5F2), not pure white
  • All links and CTAs use teal (#1F6B5A), not blue (#0066cc)
  • Active nav link is teal and bold
  • Map markers and route polylines are teal

Header

  • 3px teal border-top visible at top of header
  • Site title renders in DM Serif Display ("into the east")
  • Header sticks to top on scroll
  • On 320px viewport: title and nav both visible without overlap

Entry feed cards

  • Cards with photos show full-bleed 16:9 image with rounded corners
  • Date + location text overlay visible on gradient at bottom of photo
  • Entry title below photo in DM Serif Display
  • Subtle photo scale animation on hover (desktop)
  • Cards without photos show date/location meta row above title
  • "Read entry →" link is teal

Single entry page

  • If entry has photos: hero image spans full content width, max 480px tall
  • Entry title in DM Serif Display at large size (~48px desktop)
  • Thin border rule separates header from body text
  • Body text at 18px (--text-md)
  • "← Back to journal" footer link in teal

Post form

  • Lat/lng inputs NOT visible (hidden by CSS :has() selector)
  • Inputs have rounded corners and correct border
  • Focus ring on inputs is teal, not default browser blue
  • "Post Entry" submit button is teal, full-width, ≥52px height
  • After tapping "Get Location": status line shows "✓ Location captured · lat, lng" in teal
  • After tapping "Get Weather": status line shows "✓ Weather set · desc · temp°C" in teal
  • On error: status line shows in brick red, not teal

Stats page

  • Page heading "Trip Statistics" in DM Serif Display
  • Stat numbers in DM Serif Display, teal color
  • Stat cards on white background (not paper), with subtle shadow
  • Labels uppercase, muted gray, small

Map page

  • Map fills viewport below header with no gap
  • Map container height uses CSS variable (not hardcoded 61px)
  • Markers are teal circles (not blue)
  • Route polyline is teal

Mobile (375px viewport)

  • All pages scroll without horizontal overflow
  • Header title and nav fit in one row
  • Entry card photo fills full width
  • Post form buttons are thumb-reachable (44px+ targets)
  • Map page: map pans without page scrolling underneath (touch-action)

Accessibility

  • Focus ring visible on all interactive elements (keyboard navigation)
  • With prefers-reduced-motion: no animations/transitions fire