Files
Azornes-Comfyui-Model-Resolver/tests/test_metadata_collapse.mjs
T

199 lines
8.3 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { imageMetadataMethods } from '../web/resolver/views/tabs_image_metadata_methods.js';
import { tabsLoadedMethods } from '../web/resolver/views/tabs_loaded_methods.js';
globalThis.window = globalThis;
function createMockContext() {
const memory = new Map();
const mockStorage = {
getItem: (k) => (memory.has(k) ? memory.get(k) : null),
setItem: (k, v) => memory.set(k, String(v)),
removeItem: (k) => memory.delete(k),
};
return {
...imageMetadataMethods,
...tabsLoadedMethods,
escapeHtml: (s) => String(s ?? ''),
escapeJsString: (s) => JSON.stringify(s),
getMetadataTooltipBadge: (help, label) => `<span class="mr-tooltip-badge" data-tooltip="${help}" aria-label="${label}">?</span>`,
getCategoryDisplayName: (cat) => cat,
getModelToken: (model) => model.name || '',
getContextMenuAttrs: () => '',
stripModelExtension: (name) => String(name || '').replace(/\.[^/.]+$/, ''),
getMissingModelKey: (model) => model.name || 'key',
getModelPreviewTooltipAttrs: () => '',
bindLoadedModelSelection: () => {},
renderStatusMessage: (msg, type = 'info') => `<div class="mr-status-message ${type}">${msg}</div>`,
storage: mockStorage,
};
}
test('image metadata sections default to expanded', () => {
const ctx = createMockContext();
assert.strictEqual(ctx.isImageInspectorSectionCollapsed('tools'), false);
assert.strictEqual(ctx.isImageInspectorSectionCollapsed('summary'), false);
assert.strictEqual(ctx.isImageInspectorSectionCollapsed('prompt-transfer'), false);
assert.strictEqual(ctx.isImageInspectorSectionCollapsed('model-transfer'), false);
assert.strictEqual(ctx.isImageInspectorSectionCollapsed('models'), false);
});
test('toggling section marks it collapsed and persists state', () => {
const ctx = createMockContext();
const state = {};
ctx.toggleImageInspectorSection('prompt-transfer');
assert.strictEqual(ctx.isImageInspectorSectionCollapsed('prompt-transfer'), true);
assert.strictEqual(ctx.isImageInspectorSectionCollapsed('model-transfer'), false);
ctx.toggleImageInspectorSection('prompt-transfer');
assert.strictEqual(ctx.isImageInspectorSectionCollapsed('prompt-transfer'), false);
});
test('renderMetadataPromptTransferPanel renders collapse button with chevron and aria-expanded', () => {
const ctx = createMockContext();
const state = {
promptTransfer: {
loading: false,
applying: false,
error: '',
pairs: {},
prompts: { source: [], target: [] },
},
};
const expandedHtml = ctx.renderMetadataPromptTransferPanel(state);
assert.ok(expandedHtml.includes('data-image-inspector-collapse="prompt-transfer"'));
assert.ok(expandedHtml.includes('aria-expanded="true"'));
assert.ok(!expandedHtml.includes('mr-image-prompt-transfer is-collapsed'));
ctx.toggleImageInspectorSection('prompt-transfer');
const collapsedHtml = ctx.renderMetadataPromptTransferPanel(state);
assert.ok(collapsedHtml.includes('aria-expanded="false"'));
assert.ok(collapsedHtml.includes('mr-image-prompt-transfer is-collapsed'));
});
test('renderMetadataTransferPanel renders collapse button with chevron and aria-expanded', () => {
const ctx = createMockContext();
const state = {
transfer: {
loading: false,
refreshing: false,
applying: false,
undoing: false,
error: '',
targetGroups: [],
selectedNodeKeys: new Set(),
},
};
const expandedHtml = ctx.renderMetadataTransferPanel(state);
assert.ok(expandedHtml.includes('data-image-inspector-collapse="model-transfer"'));
assert.ok(expandedHtml.includes('aria-expanded="true"'));
assert.ok(!expandedHtml.includes('mr-image-transfer is-collapsed'));
ctx.toggleImageInspectorSection('model-transfer');
const collapsedHtml = ctx.renderMetadataTransferPanel(state);
assert.ok(collapsedHtml.includes('aria-expanded="false"'));
assert.ok(collapsedHtml.includes('mr-image-transfer is-collapsed'));
});
test('displayLoadedModels renders collapse button and tooltip badge, hiding subtitle when collapsible', () => {
const ctx = createMockContext();
const container = { innerHTML: '', dataset: {} };
const data = {
total: 1,
loaded_models: [
{ name: 'model.safetensors', category: 'checkpoints', active: true }
],
};
// Non-collapsible (Loaded Models tab) - shows subtitle, no tooltip badge
ctx.displayLoadedModels(container, data, { collapsible: false });
assert.ok(!container.innerHTML.includes('data-image-inspector-collapse'));
assert.ok(container.innerHTML.includes('<h3 class="mr-loaded-models-title">Loaded Models'));
assert.ok(container.innerHTML.includes('class="mr-loaded-models-subtitle"'));
// Collapsible (Metadata tab) - shows tooltip badge, hides subtitle paragraph
ctx.displayLoadedModels(container, data, {
collapsible: true,
isCollapsed: false,
sectionId: 'models',
title: 'Referenced Models',
tooltip: 'Models reported by embedded Civitai metadata.',
});
assert.ok(container.innerHTML.includes('data-image-inspector-collapse="models"'));
assert.ok(container.innerHTML.includes('aria-expanded="true"'));
assert.ok(container.innerHTML.includes('Referenced Models'));
assert.ok(container.innerHTML.includes('class="mr-tooltip-badge"'));
assert.ok(container.innerHTML.includes('Models reported by embedded Civitai metadata.'));
assert.ok(!container.innerHTML.includes('class="mr-loaded-models-subtitle"'));
// Collapsible and collapsed
ctx.displayLoadedModels(container, data, {
collapsible: true,
isCollapsed: true,
sectionId: 'models',
title: 'Referenced Models',
tooltip: 'Models reported by embedded Civitai metadata.',
});
assert.ok(container.innerHTML.includes('data-image-inspector-collapse="models"'));
assert.ok(container.innerHTML.includes('aria-expanded="false"'));
});
test('renderImageMetadataResult renders Extracted Metadata with tooltip badge and no subtitle paragraph', () => {
const ctx = createMockContext();
const resultEl = {
innerHTML: '',
querySelector: () => ({ innerHTML: '', dataset: {} }),
};
ctx.contentElement = {
querySelector: (sel) => {
if (sel === '[data-image-inspector-result]') {
return resultEl;
}
return null;
},
};
ctx.imageInspectorState = {
metadata: {
filename: 'test.png',
image: { width: 512, height: 512, format: 'PNG' },
},
loadedModels: null,
loading: false,
error: '',
};
ctx.renderMetadataPromptTransferPanel = () => '';
ctx.renderMetadataTransferPanel = () => '';
ctx.renderImageMetadataResult();
assert.ok(resultEl.innerHTML.includes('Extracted Metadata'));
assert.ok(resultEl.innerHTML.includes('data-image-inspector-collapse="summary"'));
assert.ok(resultEl.innerHTML.includes('Read-only information from the selected source.'));
assert.ok(resultEl.innerHTML.includes('class="mr-tooltip-badge"'));
assert.ok(!resultEl.innerHTML.includes('class="mr-loaded-models-subtitle"'));
});
test('renderImageMetadataResult without metadata renders prompt transfer panel first', () => {
const ctx = createMockContext();
const resultEl = {
innerHTML: '',
querySelector: () => null,
};
ctx.contentElement = {
querySelector: (sel) => (sel === '[data-image-inspector-result]' ? resultEl : null),
};
ctx.imageInspectorState = {
metadata: null,
loadedModels: null,
loading: false,
error: '',
};
ctx.renderMetadataPromptTransferPanel = () => '<section class="mr-image-prompt-transfer is-collapsed"></section>';
ctx.renderMetadataTransferPanel = () => '<section class="mr-image-transfer is-collapsed"></section>';
ctx.renderImageMetadataResult();
assert.ok(resultEl.innerHTML.startsWith('<section class="mr-image-prompt-transfer'));
assert.ok(!resultEl.innerHTML.includes('Extracted Metadata'));
});