Files
AEmotionStudio-ComfyUI-Magn…/tests/unit/PopOutTheme.test.ts
T
Æmotion StudioandClaude Opus 5.5 f748f7b333 Fix reconnecting, duplicated tabs and idle rendering in the pop-out viewer
- Listen for the viewer once ComfyUI is set up, so a viewer left open over a reload connects fully
- A duplicated tab starts its own session instead of sharing the viewer
- Ignore requests from a viewer that is not connected
- Stop the render loop while the glass is hidden and the viewer shows no frames
- Do not place the panel again on the 250 ms refresh
- Build output URLs from filename, subfolder and type only
- Viewer: skip undecodable frames, tolerate showPicker and blocked storage, keep the channel open on unload, shorten "Go to node…"

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 10:39:27 -08:00

66 lines
2.8 KiB
TypeScript

import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { PopOutManager } from '../../src/magnify-glass/PopOutManager';
describe('Pop-out palette', () => {
let manager: PopOutManager;
let posted: any[];
beforeEach(() => {
vi.useFakeTimers();
posted = [];
vi.stubGlobal('app', { api: new EventTarget(), ui: {}, extensionManager: { workflow: { activeWorkflow: null } } });
vi.stubGlobal('BroadcastChannel', class {
onmessage: ((e: MessageEvent) => void) | null = null;
postMessage(message: unknown) { posted.push(message); }
close() { }
});
manager = new PopOutManager(() => ({ glass: 'on', inspector: true, reduceMotion: false, zoom: 300 }), () => { }, () => { });
manager.listen();
});
afterEach(() => {
manager.cleanup();
document.body.classList.remove('dark-theme');
document.body.removeAttribute('style');
vi.unstubAllGlobals();
vi.useRealTimers();
});
const pong = () => (manager as any).handleMessage({ type: 'pong' });
const palettes = () => posted.filter(m => m.type === 'config').map(m => m.data.palette);
it('sends the computed allowlisted properties, the scheme and the font, and resends only when they change', () => {
document.body.classList.add('dark-theme');
document.body.style.setProperty('--fg-color', '#dddddd');
document.body.style.setProperty('--comfy-menu-bg', '#202020');
document.body.style.setProperty('--not-allowlisted', 'red');
document.body.style.fontFamily = 'Inter, Arial, sans-serif';
pong();
pong();
expect(palettes()).toHaveLength(1);
const [palette] = palettes();
expect(palette.scheme).toBe('dark');
expect(palette.fontFamily).toBe('Inter, Arial, sans-serif');
expect(palette.properties['--fg-color']).toBe('#dddddd');
expect(palette.properties['--comfy-menu-bg']).toBe('#202020');
// Unset properties are sent empty, so the viewer drops an override that went away
expect(palette.properties['--mg-panel-accent']).toBe('');
expect(palette.properties).not.toHaveProperty('--not-allowlisted');
document.body.classList.remove('dark-theme');
document.body.style.setProperty('--mg-panel-accent', '#ff8800');
pong();
expect(palettes()).toHaveLength(2);
expect(palettes()[1].scheme).toBe('light');
expect(palettes()[1].properties['--mg-panel-accent']).toBe('#ff8800');
});
it('sends the palette again when the viewer reconnects', () => {
pong();
(manager as any).handleMessage({ type: 'close' });
pong();
expect(palettes()).toHaveLength(2);
expect(palettes()[1]).toEqual(palettes()[0]);
});
});