1import { createHash } from 'crypto' 7export const genTestPng = (label: string): Buffer => { 8 const seed = `ipfs-roundtrip-${label}-${Date.now()}` 9 const hash = createHash('sha256').update(seed).digest() 11 const ctx = canvas.getContext('2d') 12 ctx.fillStyle = `rgb(${hash[0]}, ${hash[1]}, ${hash[2]})` 13 ctx.fillRect(0, 0, 100, 100) 14 ctx.fillStyle = 'white' 15 ctx.font = '14px sans-serif' 16 ctx.fillText(seed.slice(0, 12), 5, 55) 17 return canvas.toBuffer('image/png') 20export const runIpfsRoundtripSuite: SuiteRunner = async ({baseUrl, singleTestName}) => { 23 test('ipfsUploadAndProxyFetch', async () => { 24 const buf = genTestPng('e2e') 28 catch (err) { return {passed: false, msg: `uploadToIpfs failed: ${(err as Error).message}`} } 30 const resp = await fetch(`${baseUrl}/ipfs/${cid}.bin`) 31 if (!resp.ok) return {passed: false, msg: `proxy GET ${resp.status}: ${await resp.text().catch(() => '')}`} 33 const contentType = resp.headers.get('content-type') || '' 34 if (!contentType.includes('image')) return {passed: false, msg: `expected image content-type, got: ${contentType}`} 36 const fetched = Buffer.from(await resp.arrayBuffer()) 37 if (!buf.equals(fetched)) return {passed: false, msg: `bytes mismatch: sent ${buf.length}B, got ${fetched.length}B`} 39 const cacheCtrl = resp.headers.get('cache-control') || '' 40 if (!cacheCtrl.includes('immutable')) return {passed: false, msg: `missing immutable cache-control, got: ${cacheCtrl}`} 42 return {passed: true, msg: `cid=${cid.slice(0, 12)}... ${buf.length}B png roundtrip ok`}