mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-08-17 11:03:22 -03:00
feat(recipes): add toolbar toggle and settings preview for masonry layout
This commit is contained in:
@@ -530,4 +530,49 @@ describe('SettingsManager recipes layout switch', () => {
|
||||
dispatchSpy.mockRestore();
|
||||
delete state.virtualScroller;
|
||||
});
|
||||
|
||||
it('saveRecipesLayout persists, dispatches the layout event, and syncs controls', async () => {
|
||||
const manager = createManager();
|
||||
|
||||
const gridBtn = document.createElement('button');
|
||||
gridBtn.dataset.recipesLayout = 'grid';
|
||||
gridBtn.setAttribute('aria-pressed', 'false');
|
||||
const masonryBtn = document.createElement('button');
|
||||
masonryBtn.dataset.recipesLayout = 'masonry';
|
||||
masonryBtn.setAttribute('aria-pressed', 'false');
|
||||
masonryBtn.setAttribute('role', 'radio');
|
||||
masonryBtn.setAttribute('aria-checked', 'false');
|
||||
document.body.appendChild(gridBtn);
|
||||
document.body.appendChild(masonryBtn);
|
||||
|
||||
const calculateLayout = vi.fn();
|
||||
state.virtualScroller = { calculateLayout };
|
||||
|
||||
const dispatchSpy = vi.spyOn(window, 'dispatchEvent');
|
||||
|
||||
await manager.saveRecipesLayout('masonry');
|
||||
|
||||
expect(state.global.settings.recipes_layout).toBe('masonry');
|
||||
expect(masonryBtn.classList.contains('active')).toBe(true);
|
||||
expect(masonryBtn.getAttribute('aria-pressed')).toBe('true');
|
||||
expect(masonryBtn.getAttribute('aria-checked')).toBe('true');
|
||||
expect(gridBtn.classList.contains('active')).toBe(false);
|
||||
expect(gridBtn.getAttribute('aria-pressed')).toBe('false');
|
||||
|
||||
const layoutEvent = dispatchSpy.mock.calls
|
||||
.map(([event]) => event)
|
||||
.find(event => event.type === 'lm:recipes-layout-changed');
|
||||
expect(layoutEvent).toBeInstanceOf(CustomEvent);
|
||||
expect(calculateLayout).not.toHaveBeenCalled();
|
||||
expect(showToast).not.toHaveBeenCalled();
|
||||
|
||||
dispatchSpy.mockRestore();
|
||||
delete state.virtualScroller;
|
||||
});
|
||||
|
||||
it('ignores invalid recipes layout values', async () => {
|
||||
const manager = createManager();
|
||||
await manager.saveRecipesLayout('bogus');
|
||||
expect(state.global.settings.recipes_layout).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -163,6 +163,7 @@ describe('RecipeManager', () => {
|
||||
afterEach(() => {
|
||||
delete window.recipeManager;
|
||||
delete window.importManager;
|
||||
delete window.settingsManager;
|
||||
});
|
||||
|
||||
it('initializes page controls, restores filters, and wires sort interactions', async () => {
|
||||
@@ -227,6 +228,38 @@ describe('RecipeManager', () => {
|
||||
expect(initializePageFeaturesMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('wires the layout toggle and reflects the saved recipes layout setting', async () => {
|
||||
const gridBtn = document.createElement('button');
|
||||
gridBtn.className = 'layout-toggle-btn';
|
||||
gridBtn.dataset.recipesLayout = 'grid';
|
||||
gridBtn.setAttribute('aria-pressed', 'false');
|
||||
const masonryBtn = document.createElement('button');
|
||||
masonryBtn.className = 'layout-toggle-btn';
|
||||
masonryBtn.dataset.recipesLayout = 'masonry';
|
||||
masonryBtn.setAttribute('aria-pressed', 'false');
|
||||
document.body.appendChild(gridBtn);
|
||||
document.body.appendChild(masonryBtn);
|
||||
|
||||
const saveRecipesLayoutMock = vi.fn().mockResolvedValue();
|
||||
window.settingsManager = { saveRecipesLayout: saveRecipesLayoutMock };
|
||||
|
||||
const manager = new RecipeManager();
|
||||
await manager.initialize();
|
||||
|
||||
// Initial state follows the saved setting (default grid)
|
||||
expect(gridBtn.classList.contains('active')).toBe(true);
|
||||
expect(gridBtn.getAttribute('aria-pressed')).toBe('true');
|
||||
expect(masonryBtn.classList.contains('active')).toBe(false);
|
||||
|
||||
// Clicking the inactive option saves the new layout
|
||||
masonryBtn.dispatchEvent(new Event('click', { bubbles: true }));
|
||||
expect(saveRecipesLayoutMock).toHaveBeenCalledWith('masonry');
|
||||
|
||||
// Clicking the already-active option is a no-op
|
||||
gridBtn.dispatchEvent(new Event('click', { bubbles: true }));
|
||||
expect(saveRecipesLayoutMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('skips loading when duplicates mode is active and refreshes otherwise', async () => {
|
||||
const manager = new RecipeManager();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user