import assert from 'node:assert/strict' import { registerHooks } from 'node:module' import { test } from 'node:test' // The Connect page with its Kody shell and Audible calls faked. const fake: any = globalThis fake.connect = { started: 0, completed: [] as unknown[], disconnected: 0 } const mocks: Record = { 'kody:runtime': `export const packageContext={appBasePath:'/packages/audible-auth',hostedUrl:'https://danj.kody.run/packages/audible-auth'}; export const kody={}; export const packageSecrets={}; export const packageStorage=()=>({})`, './status.ts': `export default async()=>({ok:true,connected:false,ready:false,locale:null,hostApprovals:[],archiveEnabled:false})`, './disconnect.ts': `export const disconnect=async()=>{globalThis.connect.disconnected++;return{wasConnected:true,deviceRemoved:true,secretsDeleted:true}}`, './start-auth.ts': `export default async()=>{globalThis.connect.started++;return{loginUrl:'https://www.amazon.ca/ap/signin?x=1&y=2',authSessionId:'abc123'}}`, './complete-auth.ts': `export default async(input)=>{globalThis.connect.completed.push(input);return{ok:true,previousDevice:'removed',message:'Audible connected.',status:{ok:true,connected:true,ready:true,locale:'ca',hostApprovals:[],archiveEnabled:false}}}`, } registerHooks({ resolve(specifier, context, next) { return mocks[specifier] && (specifier.startsWith('kody:') || context.parentURL?.endsWith('/app.ts')) ? { url: `mock:${specifier}`, shortCircuit: true } : next(specifier, context) }, load(url, context, next) { return url.startsWith('mock:') ? { format: 'module', shortCircuit: true, source: mocks[url.slice(5)] } : next(url, context) }, }) const app = (await import('../app.ts')).default const base = 'https://danj.kody.run/packages/audible-auth' const post = (path: string, fields: Record, headers: Record = {}) => app.fetch(new Request(`${base}${path}`, { method: 'POST', body: new URLSearchParams(fields), headers })) test('the page offers Connect and keeps a same-host return link only', async () => { const ok = await (await app.fetch(new Request(`${base}/?return=${encodeURIComponent('https://danj.kody.run/packages/audible/classic')}`))).text() assert.match(ok, /Connect Audible/) assert.match(ok, /Back to the app/) const evil = await (await app.fetch(new Request(`${base}/?return=${encodeURIComponent('https://evil.example/packages/x')}`))).text() assert.doesNotMatch(evil, /Back to the app/) }) test('start shows the login link from this package, then complete finishes Connect', async () => { const started = await (await post('/start', { locale: 'ca' })).text() assert.match(started, /href="https:\/\/www\.amazon\.ca\/ap\/signin\?x=1&y=2"/) assert.match(started, /name="authSessionId" value="abc123"/) const done = await (await post('/complete', { redirectUrl: 'https://www.amazon.ca/ap/maplanding?code=1', authSessionId: 'abc123' })).text() assert.match(done, /previous virtual device was removed/) assert.deepEqual(fake.connect.completed.at(-1), { redirectUrl: 'https://www.amazon.ca/ap/maplanding?code=1', authSessionId: 'abc123' }) }) test('a cross-site form cannot start Connect', async () => { const before = fake.connect.started const response = await post('/start', { locale: 'ca' }, { origin: 'https://evil.example', 'sec-fetch-site': 'cross-site' }) assert.equal(response.status, 403) assert.equal(fake.connect.started, before) }) test('disconnect removes the device and reports it; a cross-site form cannot', async () => { const denied = await post('/disconnect', {}, { origin: 'https://evil.example', 'sec-fetch-site': 'cross-site' }) assert.equal(denied.status, 403) assert.equal(fake.connect.disconnected, 0) const done = await (await post('/disconnect', {})).text() assert.equal(fake.connect.disconnected, 1) assert.match(done, /virtual device was removed/) assert.match(done, /Open your Amazon devices/) })