// E2E: drive Collect flow via PB SDK to verify the B (toast) wiring. import PocketBase from 'pocketbase'; import fs from 'node:fs'; const PB = 'https://pocketbase-gnqc88suy8fqk6wyryjjdpvl.169.239.180.130.sslip.io'; const pb = new PocketBase(PB); const auth = await pb.collection('users').authWithPassword('david.els1@outlook.com', '1234567890'); const me = auth?.record?.id; if (!me) { console.log('LOGIN FAILED — authStore=', JSON.stringify(pb.authStore)); process.exit(1); } console.log('logged in as', me); const items = await pb.collection('order_items').getFullList({ filter: `drv_id = "${me}" && item_status = "assigned"`, perPage: 5, }); if (items.length === 0) { console.log('NO ASSIGNED — abort'); process.exit(1); } // === HAPPY PATH: PDF === const target = items[0]; await pb.collection('order_items').update(target.id, { item_status: 'collected', drv_status: 'collected', drv_collected_at: new Date().toISOString(), qty_collected: target.order_qty || target.quantity || 1, }); try { const pdfBytes = Buffer.from('%PDF-1.4\n%\xE2\xE3\xCF\xD3\ntest', 'utf-8'); const pdfFile = new File([pdfBytes], 'collect_proof.pdf', { type: 'application/pdf' }); const att = await pb.collection('order_item_attachments').create({ order_item: target.id, filename: pdfFile.name, file: pdfFile, content_type: pdfFile.type, size_bytes: String(pdfFile.size), source: 'driver_proof', notes: 'e2e collect test', }); console.log('HAPPY OK: attachment', att.id); } catch (e) { console.log('HAPPY FAIL:', e.message); } await pb.collection('order_items').update(target.id, { item_status: 'assigned', drv_status: 'assigned', drv_collected_at: null, qty_collected: null, }); // === BROKEN PATH: image (mime bug) === const target2 = items[1] || items[0]; await pb.collection('order_items').update(target2.id, { item_status: 'collected', drv_status: 'collected', drv_collected_at: new Date().toISOString(), qty_collected: target2.order_qty || target2.quantity || 1, }); try { // real JPEG header bytes — what a phone camera would produce const jpegBytes = Buffer.from([ 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01, 0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0xff,0xdb,0x00,0x43,0x00, ]); // pad to look more like a real photo const padded = Buffer.concat([jpegBytes, Buffer.alloc(20000, 0x80)]); const jpegFile = new File([padded], 'collect_photo.jpg', { type: 'image/jpeg' }); const r = await pb.collection('order_item_attachments').create({ order_item: target2.id, filename: jpegFile.name, file: jpegFile, content_type: jpegFile.type, size_bytes: String(jpegFile.size), source: 'driver_proof', }); console.log('BROKEN UNEXPECTED OK:', r.id); } catch (e) { // This is what page.tsx will receive — e.message contains the PB reason console.log('BROKEN EXPECTED THROW — toast would render:'); console.log(' "Item collected — but photo upload failed (' + e.message + ')"'); } await pb.collection('order_items').update(target2.id, { item_status: 'assigned', drv_status: 'assigned', drv_collected_at: null, qty_collected: null, }); // verify clean state const stuck = await pb.collection('order_items').getFullList({ filter: `item_status = "collected" && drv_id = "${me}"`, }); console.log('Final assigned-to-david collected rows:', stuck.length, '(expect 0)'); process.exit(0);