Files
MajoorWaldi-ComfyUI-Majoor-…/js/tests/sidebar_controller.vitest.mjs
T
MajoorWaldi 2fa41a0e76 feat: add useGridState and useVirtualGrid composables for asset management
- Implemented useGridState to manage grid state, including asset selection and loading states.
- Created useVirtualGrid to centralize virtualization helpers for improved performance.
- Added createVueApp for isolated Vue 3 + Pinia application instances.
- Introduced Vite configuration for building the ComfyUI-Majoor-AssetsManager with external dependencies.
2026-04-03 11:04:55 +02:00

154 lines
4.6 KiB
JavaScript

import { describe, expect, it, vi } from "vitest";
import { createPinia, setActivePinia } from "pinia";
import { bindSidebarOpen } from "../features/panel/controllers/sidebarController.js";
import { usePanelStore } from "../stores/usePanelStore.js";
class ElementStub {
constructor() {
this.listeners = new Map();
this.dataset = {};
this.style = {};
this.parentElement = null;
this.children = [];
this.classList = {
_set: new Set(),
add: (...names) => names.forEach((name) => this.classList._set.add(name)),
remove: (...names) => names.forEach((name) => this.classList._set.delete(name)),
contains: (name) => this.classList._set.has(name),
};
}
addEventListener(type, handler) {
const list = this.listeners.get(type) || [];
list.push(handler);
this.listeners.set(type, list);
}
removeEventListener(type, handler) {
const list = this.listeners.get(type) || [];
this.listeners.set(
type,
list.filter((item) => item !== handler),
);
}
dispatchEvent(event) {
const payload = event || {};
if (!payload.target) {
try {
payload.target = this;
} catch {
/* ignore readonly event payloads */
}
}
for (const handler of this.listeners.get(payload.type) || []) {
handler(payload);
}
}
contains(target) {
return target === this || this.children.includes(target);
}
appendChild(child) {
this.children.push(child);
child.parentElement = this;
return child;
}
querySelector(selector) {
if (selector === ".mjr-asset-card.is-selected") {
return this.children.find((child) => child.classList?.contains("is-selected")) || null;
}
if (selector.includes('[data-mjr-asset-id="')) {
const id = selector.split('[data-mjr-asset-id="')[1]?.split('"')[0] || "";
return this.children.find((child) => String(child.dataset?.mjrAssetId || "") === id) || null;
}
return null;
}
querySelectorAll(selector) {
if (selector === ".mjr-asset-card") return [...this.children];
if (selector === ".mjr-asset-card.is-selected") {
return this.children.filter((child) => child.classList?.contains("is-selected"));
}
return [];
}
closest(selector) {
if (selector === ".mjr-asset-card") {
return this.classList.contains("mjr-asset-card") ? this : null;
}
if (selector === ".mjr-workflow-dot") return null;
if (selector === "a, button, input, textarea, select, label") return null;
return null;
}
setAttribute() {}
focus() {}
scrollIntoView() {}
}
describe("sidebarController", () => {
it("syncs selected asset ids into Pinia on card click", async () => {
globalThis.Element = ElementStub;
globalThis.ResizeObserver = class {
observe() {}
disconnect() {}
};
globalThis.requestAnimationFrame = (callback) => {
callback();
return 1;
};
globalThis.cancelAnimationFrame = vi.fn();
setActivePinia(createPinia());
const panelStore = usePanelStore();
const gridContainer = new ElementStub();
const scrollRoot = new ElementStub();
gridContainer.parentElement = scrollRoot;
const card = new ElementStub();
card.classList.add("mjr-asset-card");
card.dataset.mjrAssetId = "42";
card._mjrAsset = { id: 42, filename: "cat.png" };
gridContainer.appendChild(card);
const sidebar = new ElementStub();
const state = {
activeAssetId: "",
selectedAssetIds: [],
sidebarOpen: false,
};
const controller = bindSidebarOpen({
gridContainer,
sidebar,
createRatingBadge: vi.fn(),
createTagsBadge: vi.fn(),
showAssetInSidebar: vi.fn(),
closeSidebar: vi.fn(),
state,
});
gridContainer.dispatchEvent({
type: "click",
target: card,
defaultPrevented: false,
ctrlKey: false,
metaKey: false,
shiftKey: false,
preventDefault: vi.fn(),
stopPropagation: vi.fn(),
});
expect(panelStore.selectedAssetIds).toEqual(["42"]);
expect(panelStore.activeAssetId).toBe("42");
controller.dispose();
});
});