Files
cinny/src/app/utils/copyImage.test.ts
T

73 lines
2.3 KiB
TypeScript
Raw Normal View History

import { afterEach, test } from 'node:test';
import assert from 'node:assert/strict';
import { canCopyImage, copyImageFromUrl, toPngBlob } from './copyImage';
const g = globalThis as Record<string, unknown>;
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<string, Promise<Blob>>) {}
}
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/);
});