ReviewOS

also looking at this

stacks/wildloop

feat: native trail maps and complete native mobile screens

#1017
Draft chris wants to merge codex/trail-experience into main
60 files +2505 -823

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

scripts/run-native-trail-e2e.tsmodified+2-2
Changes to scripts/run-native-trail-e2e.ts
@@ -58,7 +58,7 @@ export async function runNativeTrailE2e(): Promise<void> { formatting only
5858 throw new Error('Native iOS QA requires a selectable recorded route profile.')
5959 const endElevation=endpoint.ft===null ? 'elevation unavailable' : `${endpoint.ft} ft`
6060 const review=`Native QA ${crypto.randomUUID().slice(0,8)}: clear signposts and a beautiful ridge.`
61 const edit=' Updated after a return visit.'
61 const edit='Updated after a return visit.'
6262 const readReviews=async()=>{
6363 const response=await fetch(`${origin}/api/trails/${trail.id}/reviews`,{cache:'no-store'})
6464 if(!response.ok)throw new Error(`Reading persisted reviews failed: ${response.status}`)
@@ -88,7 +88,7 @@ export async function runNativeTrailE2e(): Promise<void> {
8888 createdReviewId=rows[0].id
8989 return new Response('PASS created review text and rating persisted')
9090 }
91 if(rows[0].id!==createdReviewId || rows[0].rating!==4 || !rows[0].content.includes(edit.trim()))
91 if(rows[0].id!==createdReviewId || rows[0].rating!==4 || rows[0].content!==edit)
9292 throw new Error('The native edit did not retain the review identity and persist its new text and rating.')
9393 return new Response('PASS edited review retained its identity and persisted')
9494 }
tests/native/trail-journey.tsmodified+5-2
Changes to tests/native/trail-journey.ts
@@ -144,7 +144,10 @@ const reviews:SimulatorStep[] = [
144144 {command:'tapid',text:'trail-write-review'},
145145 {command:'expectid',text:'trail-review-composer',seconds:10},
146146 {command:'tapid',text:'trail-review-star-4'},
147 {command:'typeid',id:'trail-review-content',text:input.edit},
147 {command:'longpressid',text:'trail-review-content'},
148 {command:'tap',text:'Select All'},
149 {command:'type',text:input.edit},
150 {command:'valueid',id:'trail-review-content',text:input.edit},
148151 {command:'scrollto',text:'Save review'},
149152 {command:'tapid',text:'trail-review-submit'},
150153 {command:'expect',text:input.edit.trim(),seconds:15},
@@ -183,7 +186,7 @@ const sharing:SimulatorStep[] = [
183186 {command:'expectid',text:'login-email',seconds:10},
184187 {command:'valueid',id:'login-email',text:''},
185188 {command:'longpressid',text:'login-email'},
186 {command:'tapexact',text:'Paste'},
189 {command:'tap',text:'Paste'},
187190 {command:'valueid',id:'login-email',text:`https://wildloop.org/trail/${input.trailId}`},
188191 {command:'shot',name:'native-shared-link-pasted'},
189192 {command:'tree',name:'native-shared-link-pasted'},