aboutsummaryrefslogtreecommitdiffstats
path: root/tools/upload-progress-test.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/upload-progress-test.js')
-rw-r--r--tools/upload-progress-test.js37
1 files changed, 37 insertions, 0 deletions
diff --git a/tools/upload-progress-test.js b/tools/upload-progress-test.js
new file mode 100644
index 0000000..25bf91c
--- /dev/null
+++ b/tools/upload-progress-test.js
@@ -0,0 +1,37 @@
+// uploadPublicMedia reports how much of the file has gone out (XMLHttpRequest
+// upload events — fetch() can't), from 0 to 1, on a slow uplink.
+//
+// Run: bun tools/upload-progress-test.js
+import puppeteer from 'puppeteer-core';
+let ok = true;
+const check = (n, c, d = '') => { console.log(` ${c ? '✓' : '✗'} ${n}${d ? ' — ' + d : ''}`); if (!c) ok = false; };
+const js = await Bun.build({ entrypoints: ['src/media-upload.js'], target: 'browser' }).then((b) => b.outputs[0].text());
+let got = 0;
+const server = Bun.serve({ port: 5289, async fetch(req) {
+ const cors = { 'access-control-allow-origin': '*', 'access-control-allow-methods': 'PUT, HEAD', 'access-control-allow-headers': '*', 'access-control-expose-headers': 'x-reason' };
+ const p = new URL(req.url).pathname;
+ if (req.method === 'OPTIONS') return new Response(null, { status: 204, headers: cors });
+ if (p === '/upload' && req.method === 'PUT') { got = (await req.arrayBuffer()).byteLength; return Response.json({ url: 'http://localhost:5289/' + 'a'.repeat(64) }, { status: 201, headers: cors }); }
+ if (p === '/m.js') return new Response(js, { headers: { 'content-type': 'text/javascript' } });
+ return new Response('<script type=module>import * as m from "/m.js"; window.m = m;</script>', { headers: { 'content-type': 'text/html' } });
+} });
+const browser = await puppeteer.launch({ executablePath: '/usr/bin/google-chrome', headless: 'new', args: ['--no-sandbox'] });
+const page = await browser.newPage();
+try {
+ await page.goto('http://localhost:5289/');
+ await page.waitForFunction(() => !!window.m);
+ const cdp = await page.createCDPSession();
+ await cdp.send('Network.emulateNetworkConditions', { offline: false, latency: 20, downloadThroughput: 5e6, uploadThroughput: 400e3 });
+ const r = await page.evaluate(async () => {
+ const seen = [];
+ const file = new File([new Uint8Array(1_200_000)], 'v.mp4', { type: 'video/mp4' });
+ const sign = async (e) => ({ ...e, id: '1'.repeat(64), pubkey: '2'.repeat(64), sig: '3'.repeat(128) });
+ const url = await window.m.uploadPublicMedia(file, sign, { servers: ['http://localhost:5289'], onProgress: (p) => seen.push(Math.round(p * 100)) });
+ return { url, seen };
+ });
+ check('the upload lands', r.url.startsWith('http://localhost:5289/') && got === 1_200_000, got + ' bytes');
+ check('progress climbs from 0 to 100 as the bytes go', r.seen[0] === 0 && r.seen.at(-1) === 100 && r.seen.filter((p) => p > 0 && p < 100).length >= 3
+ && r.seen.every((p, i) => !i || p >= r.seen[i - 1]), JSON.stringify(r.seen.slice(0, 15)) + (r.seen.length > 15 ? '…' : ''));
+} finally { await browser.close(); server.stop(true); }
+console.log(ok ? '\n✅ uploads report their progress' : '\n❌ failed');
+process.exit(ok ? 0 : 1);