import { afterEach, test } from 'node:test'; import assert from 'node:assert/strict'; import { canCopyImage, copyImageFromUrl, toPngBlob } from './copyImage'; const g = globalThis as Record; const saved = { ClipboardItem: Object.getOwnPropertyDescriptor(g, 'ClipboardItem'), navigator: Object.getOwnPropertyDescriptor(g, 'navigator'), fetch: Object.getOwnPropertyDescriptor(g, 'fetch'), }; const stub = (key: keyof typeof saved, value: unknown) => Object.defineProperty(g, key, { value, configurable: true, writable: true }); afterEach(() => { (Object.keys(saved) as (keyof typeof saved)[]).forEach((key) => { const desc = saved[key]; if (desc) Object.defineProperty(g, key, desc); else delete g[key]; }); }); class FakeClipboardItem { constructor(public data: Record>) {} } test('canCopyImage is false without ClipboardItem', () => { stub('ClipboardItem', undefined); assert.equal(canCopyImage(), false); }); test('canCopyImage is true with ClipboardItem and clipboard.write', () => { stub('ClipboardItem', FakeClipboardItem); stub('navigator', { clipboard: { write: async () => undefined } }); assert.equal(canCopyImage(), true); }); test('toPngBlob passes a PNG through untouched', async () => { const png = new Blob(['x'], { type: 'image/png' }); assert.equal(await toPngBlob(png), png); }); test('copyImageFromUrl writes a single image/png item', async () => { const png = new Blob(['x'], { type: 'image/png' }); stub('fetch', async () => ({ ok: true, blob: async () => png })); stub('ClipboardItem', FakeClipboardItem); const written: FakeClipboardItem[][] = []; stub('navigator', { clipboard: { write: async (items: FakeClipboardItem[]) => { written.push(items); }, }, }); await copyImageFromUrl('blob:x'); assert.equal(written.length, 1); assert.deepEqual(Object.keys(written[0][0].data), ['image/png']); assert.equal(await written[0][0].data['image/png'], png); }); test('copyImageFromUrl rejects when the fetch fails', async () => { stub('fetch', async () => ({ ok: false, status: 404 })); stub('ClipboardItem', FakeClipboardItem); stub('navigator', { clipboard: { write: async (items: FakeClipboardItem[]) => { await items[0].data['image/png']; }, }, }); await assert.rejects(copyImageFromUrl('blob:x'), /404/); });