* feat(bridge): add guarded PromptManager prompt destinations * fix(ci): install shared contracts before frontend unit tests * test(comfyui): wait for paired editor resize before measuring layout
69 lines
3.1 KiB
JavaScript
69 lines
3.1 KiB
JavaScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { installPromptBridge } from '../../web/js/prompt-bridge-host.js';
|
|
|
|
function fixture() {
|
|
const runtime = new EventTarget();
|
|
runtime.location = { origin: 'https://comfy.example', href: 'https://comfy.example/team/' };
|
|
runtime.document = { title: 'My workflow' };
|
|
const warnings = []; runtime.console = { warn: (...args) => warnings.push(args) };
|
|
const hosts = [], adapter = {};
|
|
const options = { runtime, baseUrl: '/team/prompt_manager/', adapterFactory: () => adapter,
|
|
hostFactory: config => { const host = { config, disposed: 0, dispose() { this.disposed++; } }; hosts.push(host); return host; } };
|
|
return { runtime, options, hosts, adapter, warnings };
|
|
}
|
|
|
|
test('host uses the exact deployment prefix and explicit pack label', () => {
|
|
const f = fixture(), app = {};
|
|
const controller = installPromptBridge(app, f.options);
|
|
assert.equal(f.hosts.length, 1);
|
|
assert.equal(f.hosts[0].config.namespace, '/team/');
|
|
assert.equal(f.hosts[0].config.origin, 'https://comfy.example');
|
|
assert.equal(f.hosts[0].config.label, 'PromptManager — My workflow');
|
|
assert.equal(f.hosts[0].config.adapter, f.adapter);
|
|
assert.equal(installPromptBridge(app, f.options), controller);
|
|
controller.dispose(); controller.dispose();
|
|
assert.equal(f.hosts[0].disposed, 1);
|
|
});
|
|
|
|
test('page hide disposes and cached restoration mounts exactly one fresh host', () => {
|
|
const f = fixture(), controller = installPromptBridge({}, f.options);
|
|
f.runtime.dispatchEvent(new Event('pagehide'));
|
|
assert.equal(f.hosts[0].disposed, 1);
|
|
f.runtime.dispatchEvent(new Event('pageshow'));
|
|
f.runtime.dispatchEvent(new Event('pageshow'));
|
|
assert.equal(f.hosts.length, 2);
|
|
controller.dispose();
|
|
f.runtime.dispatchEvent(new Event('pageshow'));
|
|
assert.equal(f.hosts.length, 2);
|
|
assert.equal(f.hosts[1].disposed, 1);
|
|
});
|
|
|
|
test('a disposed installation can be installed again', () => {
|
|
const f = fixture(), app = {};
|
|
installPromptBridge(app, f.options).dispose();
|
|
const next = installPromptBridge(app, f.options);
|
|
assert.equal(f.hosts.length, 2);
|
|
next.dispose();
|
|
});
|
|
|
|
test('unavailable messaging leaves the existing host usable and can recover after restoration', () => {
|
|
const f = fixture(); let unavailable = true;
|
|
const factory = f.options.hostFactory;
|
|
f.options.hostFactory = config => { if (unavailable) throw new Error('BroadcastChannel unavailable'); return factory(config); };
|
|
const controller = installPromptBridge({}, f.options);
|
|
assert.equal(f.warnings.length, 1);
|
|
unavailable = false;
|
|
f.runtime.dispatchEvent(new Event('pageshow'));
|
|
assert.equal(f.hosts.length, 1);
|
|
controller.dispose();
|
|
});
|
|
|
|
test('deployment namespace rejects external origins and unexpected paths', () => {
|
|
for (const baseUrl of ['https://comfy.example.attacker.test/prompt_manager/', '/wrong/', 'data:text/plain,hello']) {
|
|
const f = fixture();
|
|
assert.throws(() => installPromptBridge({}, { ...f.options, baseUrl }), /deployment|origin|path/i);
|
|
assert.equal(f.hosts.length, 0);
|
|
}
|
|
});
|