Files
Azornes-Comfyui-LayerForge/tests/test_canvas_export_utils.mjs

151 lines
3.8 KiB
JavaScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { exportCanvasImage } from '../js/media/canvas_export_utils.js';
function installBrowserStubs() {
const globalKeys = ['ClipboardItem', 'URL', 'document', 'navigator', 'window'];
const originalDescriptors = new Map(
globalKeys.map((key) => [key, Object.getOwnPropertyDescriptor(globalThis, key)])
);
const openedUrls = [];
const revokedUrls = [];
const clipboardItems = [];
const downloads = [];
let nextUrl = 0;
Object.defineProperty(globalThis, 'ClipboardItem', {
configurable: true,
value: class ClipboardItem {
constructor(items) {
this.items = items;
}
},
});
Object.defineProperty(globalThis, 'URL', {
configurable: true,
value: {
createObjectURL() {
nextUrl += 1;
return `blob:test-${nextUrl}`;
},
revokeObjectURL(url) {
revokedUrls.push(url);
},
},
});
Object.defineProperty(globalThis, 'window', {
configurable: true,
value: {
open(url, target) {
openedUrls.push({ url, target });
},
},
});
Object.defineProperty(globalThis, 'navigator', {
configurable: true,
value: {
clipboard: {
async write(items) {
clipboardItems.push(...items.map((item) => item.items));
},
},
},
});
Object.defineProperty(globalThis, 'document', {
configurable: true,
value: {
body: {
appendChild() {},
removeChild() {},
},
createElement(tagName) {
assert.equal(tagName, 'a');
return {
click() {
downloads.push({ href: this.href, filename: this.download });
},
};
},
},
});
return {
openedUrls,
revokedUrls,
clipboardItems,
downloads,
restore() {
for (const key of globalKeys) {
const descriptor = originalDescriptors.get(key);
if (descriptor) {
Object.defineProperty(globalThis, key, descriptor);
} else {
delete globalThis[key];
}
}
},
};
}
test('exportCanvasImage selects the requested canvas variant and action', async () => {
const stubs = installBrowserStubs();
const plainBlob = new Blob(['plain'], { type: 'image/png' });
const maskedBlob = new Blob(['masked'], { type: 'image/png' });
const calls = [];
const canvas = {
canvasLayers: {
async getFlattenedCanvasAsBlob() {
calls.push('plain');
return plainBlob;
},
async getFlattenedCanvasWithMaskAsBlob() {
calls.push('with-mask');
return maskedBlob;
},
},
};
try {
assert.equal(await exportCanvasImage(canvas, { action: 'open', variant: 'plain' }), true);
assert.equal(await exportCanvasImage(canvas, { action: 'copy', variant: 'with-mask' }), true);
assert.equal(await exportCanvasImage(canvas, {
action: 'download',
variant: 'plain',
filename: 'canvas_output.png',
}), true);
assert.deepEqual(calls, ['plain', 'with-mask', 'plain']);
assert.deepEqual(stubs.openedUrls, [{ url: 'blob:test-1', target: '_blank' }]);
assert.deepEqual(stubs.clipboardItems, [{ 'image/png': maskedBlob }]);
assert.deepEqual(stubs.downloads, [{ href: 'blob:test-2', filename: 'canvas_output.png' }]);
assert.deepEqual(stubs.revokedUrls, []);
} finally {
stubs.restore();
}
});
test('exportCanvasImage preserves the empty-blob no-op behavior', async () => {
const stubs = installBrowserStubs();
const canvas = {
canvasLayers: {
async getFlattenedCanvasAsBlob() {
return null;
},
},
};
try {
assert.equal(await exportCanvasImage(canvas, { action: 'open', variant: 'plain' }), false);
assert.deepEqual(stubs.openedUrls, []);
assert.deepEqual(stubs.downloads, []);
} finally {
stubs.restore();
}
});