also looking at this
feat: native trail maps and complete native mobile screens
#1017
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.
| @@ -1,13 +1,50 @@ | ||
| 1 | 1 | import { beforeAll, describe, expect, it } from 'bun:test' |
| 2 | 2 | import { readFileSync } from 'node:fs' |
| 3 | 3 | import { join } from 'node:path' |
| 4 | import { answer, compileNativeBundle, nativeBundle, nodesByTestId, requests, start, waitForRequest } from '../fixtures/nativeScreen' | |
| 4 | import { answer, compileNativeBundle, nativeBundle, nativeNodeProps, nodesByTestId, requests, start, waitForRequest, waitForText } from '../fixtures/nativeScreen' | |
| 5 | 5 | |
| 6 | 6 | const ROOT = join(import.meta.dir, '../..') |
| 7 | 7 | |
| 8 | 8 | beforeAll(compileNativeBundle, 30000) |
| 9 | 9 | |
| 10 | 10 | describe('Wildloop native manual activity flow', () => { |
| 11 | it('keeps a system UUID and the exact manual payload when retrying a failed save',async()=>{ | |
| 12 | const manual=await start('ManualActivity',{},['fetch','secureStorage','crypto','haptics','lifecycle','dialog'],new Map([['auth_token','native-token']])) | |
| 13 | await manual.event('distance-input','onChangeText',{text:'3.1'}) | |
| 14 | await manual.event('duration-input','onChangeText',{text:'28:00'}) | |
| 15 | await manual.event('save-activity','onPress') | |
| 16 | const uuid=await waitForRequest(manual,0,r=>r.payload.module==='Crypto' && r.payload.method==='randomUUID') | |
| 17 | answer(manual,uuid,'2b53ece4-8df1-49fa-9e70-752ddc901cf7') | |
| 18 | const post=await waitForRequest(manual,0,r=>r.payload.module==='Network') | |
| 19 | expect(JSON.parse(post.payload.args[0].body).upload_id).toBe('manual:2b53ece4-8df1-49fa-9e70-752ddc901cf7') | |
| 20 | answer(manual,post,{status:503,body:JSON.stringify({message:'Try again later'})}) | |
| 21 | await waitForText(manual,'Try again later') | |
| 22 | const before=requests(manual).length | |
| 23 | await manual.event('save-activity','onPress') | |
| 24 | const again=await waitForRequest(manual,before,r=>r.payload.module==='Network') | |
| 25 | expect(again.payload.args[0].body).toBe(post.payload.args[0].body) | |
| 26 | expect(requests(manual).filter(r=>r.payload.module==='Crypto')).toHaveLength(1) | |
| 27 | }) | |
| 28 | it('clears private manual notes and ignores a save response after an account change',async()=>{ | |
| 29 | const keychain=new Map([['auth_token','native-token']]) | |
| 30 | const manual=await start('ManualActivity',{},['fetch','secureStorage','crypto','haptics','lifecycle','dialog'],keychain) | |
| 31 | await manual.event('distance-input','onChangeText',{text:'3'}) | |
| 32 | await manual.event('duration-input','onChangeText',{text:'30:00'}) | |
| 33 | await manual.event('notes-input','onChangeText',{text:'private route notes'}) | |
| 34 | await manual.event('save-activity','onPress') | |
| 35 | // The original screen has no UUID request. Answer one only when the real | |
| 36 | // host protocol asks for it, so both versions reach the held HTTP response. | |
| 37 | const uuid=requests(manual).find(r=>r.payload.module==='Crypto') | |
| 38 | if(uuid) answer(manual,uuid,'b6506ad4-d9d2-40df-8a32-bf4194adce26') | |
| 39 | const post=await waitForRequest(manual,0,r=>r.payload.module==='Network') | |
| 40 | keychain.set('auth_token','other-token') | |
| 41 | await manual.scope.craft.snapshots.set('wildloop-session',{user:{id:13},version:1}) | |
| 42 | answer(manual,post,{status:201,body:JSON.stringify({activity:{id:42,userId:12}})}) | |
| 43 | await Bun.sleep(0) | |
| 44 | expect(nativeNodeProps(manual,'notes-input').value).toBe('') | |
| 45 | expect(requests(manual).some(r=>r.payload.module==='Haptics')).toBe(false) | |
| 46 | expect(manual.sent.some(r=>r.type==='NAVIGATE')).toBe(false) | |
| 47 | }) | |
| 11 | 48 | it('uses app components and sends the real activity payload through the Craft protocol', async () => { |
| 12 | 49 | expect(nativeBundle()).not.toContain('WebView') |
| 13 | 50 | expect(readFileSync(join(ROOT, 'resources/native/ManualActivity.stx'), 'utf8')).toContain('<NativeRunMetric') |