Files
2026-07-13 12:26:02 +08:00

63 lines
2.2 KiB
TypeScript

import { describe, it, expect, beforeAll, afterAll } from 'vitest'
import { generateIdentity, type Identity } from '../../src/sharing/identity.js'
import { PeerStore, pairingCode } from '../../src/sharing/pairing.js'
import { ShareServer } from '../../src/sharing/share-server.js'
import { pairRequest, fetchUsage } from '../../src/sharing/client.js'
describe('pairingCode', () => {
it('is order-independent, deterministic, and 3 digits', () => {
expect(pairingCode('aaa', 'bbb')).toBe(pairingCode('bbb', 'aaa'))
expect(pairingCode('aaa', 'bbb')).toMatch(/^\d{3}$/)
expect(pairingCode('aaa', 'bbb')).toBe(pairingCode('aaa', 'bbb'))
})
})
describe('approve-style pairing (no PIN)', () => {
let server: ShareServer
let serverId: Identity
let clientId: Identity
let port: number
let seenCode = ''
beforeAll(async () => {
serverId = await generateIdentity('MacBook')
clientId = await generateIdentity('Mac Studio')
server = new ShareServer({
identity: serverId,
peers: new PeerStore(),
getUsage: async () => ({ current: { cost: 7 } }),
approve: async (req) => {
seenCode = req.code
return req.name !== 'Intruder'
},
})
port = await server.listen(0, '127.0.0.1')
})
afterAll(async () => {
await server.close()
})
const ep = () => ({ identity: clientId, host: '127.0.0.1', port, expectedFingerprint: serverId.fingerprint })
it('accepts an approved device, with the same code on both sides, and the token works', async () => {
const r = await pairRequest(ep(), 'Mac Studio')
expect(r.status).toBe(200)
const body = r.json as { token: string; code: string }
expect(body.token).toBeTruthy()
// Both ends derive the same confirmation code from the two fingerprints.
expect(body.code).toBe(pairingCode(serverId.fingerprint, clientId.fingerprint))
expect(seenCode).toBe(body.code)
const usage = await fetchUsage(ep(), body.token)
expect(usage.status).toBe(200)
expect((usage.json as { current: { cost: number } }).current.cost).toBe(7)
})
it('rejects a declined device', async () => {
const r = await pairRequest(ep(), 'Intruder')
expect(r.status).toBe(403)
})
})