import { render, screen } from '@testing-library/vue' import userEvent from '@testing-library/user-event' import { beforeEach, describe, expect, it, vi } from 'vitest' import { defineComponent, h } from 'vue' import { i18n } from '@/i18n' const popoverCloseSpy = vi.fn() vi.mock('@/components/ui/Popover.vue', () => { const PopoverStub = defineComponent({ name: 'Popover', setup(_, { slots }) { return () => h('div', [ slots.button?.(), slots.default?.({ close: () => { popoverCloseSpy() } }) ]) } }) return { default: PopoverStub } }) const mockGetSetting = vi.fn<(key: string) => boolean | undefined>((key) => key === 'Comfy.Queue.QPOV2' || key === 'Comfy.Queue.ShowRunProgressBar' ? true : undefined ) const mockSetSetting = vi.fn() const mockSetMany = vi.fn() const mockSidebarTabStore = { activeSidebarTabId: null as string | null } vi.mock('@/platform/settings/settingStore', () => ({ useSettingStore: () => ({ get: mockGetSetting, set: mockSetSetting, setMany: mockSetMany }) })) vi.mock('@/stores/workspace/sidebarTabStore', () => ({ useSidebarTabStore: () => mockSidebarTabStore })) import QueueOverlayHeader from './QueueOverlayHeader.vue' import * as tooltipConfig from '@/composables/useTooltipConfig' const tooltipDirectiveStub = { mounted: vi.fn(), updated: vi.fn() } const renderHeader = (props = {}) => render(QueueOverlayHeader, { props: { headerTitle: 'Job queue', queuedCount: 3, ...props }, global: { plugins: [i18n], directives: { tooltip: tooltipDirectiveStub } } }) describe('QueueOverlayHeader', () => { beforeEach(() => { i18n.global.locale.value = 'en' popoverCloseSpy.mockClear() mockSetSetting.mockClear() mockSetMany.mockClear() mockSidebarTabStore.activeSidebarTabId = null mockGetSetting.mockImplementation((key: string) => key === 'Comfy.Queue.QPOV2' ? true : undefined ) }) it('renders header title', () => { renderHeader() expect(screen.getByText('Job queue')).toBeInTheDocument() }) it('shows clear queue text and emits clear queued', async () => { const user = userEvent.setup() const clearQueuedSpy = vi.fn() renderHeader({ queuedCount: 4, onClearQueued: clearQueuedSpy }) expect(screen.getByText('Clear queue')).toBeInTheDocument() expect(screen.queryByText('4 queued')).not.toBeInTheDocument() await user.click(screen.getByRole('button', { name: 'Clear queued' })) expect(clearQueuedSpy).toHaveBeenCalledOnce() }) it('disables clear queued button when queued count is zero', () => { renderHeader({ queuedCount: 0 }) expect(screen.getByRole('button', { name: 'Clear queued' })).toBeDisabled() expect(screen.getByText('Clear queue')).toBeInTheDocument() }) it('emits clear history from the menu', async () => { const user = userEvent.setup() const spy = vi.spyOn(tooltipConfig, 'buildTooltipConfig') const clearHistorySpy = vi.fn() renderHeader({ onClearHistory: clearHistorySpy }) expect( screen.getByRole('button', { name: 'More options' }) ).toBeInTheDocument() expect(spy).toHaveBeenCalledWith('More') await user.click(screen.getByTestId('clear-history-action')) expect(popoverCloseSpy).toHaveBeenCalledTimes(1) expect(clearHistorySpy).toHaveBeenCalledOnce() }) it('opens floating queue progress overlay when disabling from the menu', async () => { const user = userEvent.setup() renderHeader() await user.click(screen.getByTestId('docked-job-history-action')) expect(popoverCloseSpy).toHaveBeenCalledTimes(1) expect(mockSetMany).toHaveBeenCalledTimes(1) expect(mockSetMany).toHaveBeenCalledWith({ 'Comfy.Queue.QPOV2': false, 'Comfy.Queue.History.Expanded': true }) expect(mockSetSetting).not.toHaveBeenCalled() expect(mockSidebarTabStore.activeSidebarTabId).toBe(null) }) it('opens docked job history sidebar when enabling from the menu', async () => { const user = userEvent.setup() mockGetSetting.mockImplementation((key: string) => key === 'Comfy.Queue.QPOV2' ? false : undefined ) renderHeader() await user.click(screen.getByTestId('docked-job-history-action')) expect(popoverCloseSpy).toHaveBeenCalledTimes(1) expect(mockSetSetting).toHaveBeenCalledTimes(1) expect(mockSetSetting).toHaveBeenCalledWith('Comfy.Queue.QPOV2', true) expect(mockSetMany).not.toHaveBeenCalled() expect(mockSidebarTabStore.activeSidebarTabId).toBe('job-history') }) it('keeps docked target open even when enabling persistence fails', async () => { const user = userEvent.setup() mockGetSetting.mockImplementation((key: string) => key === 'Comfy.Queue.QPOV2' ? false : undefined ) mockSetSetting.mockRejectedValueOnce(new Error('persistence failed')) renderHeader() await user.click(screen.getByTestId('docked-job-history-action')) expect(popoverCloseSpy).toHaveBeenCalledTimes(1) expect(mockSetSetting).toHaveBeenCalledWith('Comfy.Queue.QPOV2', true) expect(mockSidebarTabStore.activeSidebarTabId).toBe('job-history') }) it('closes the menu when disabling persistence fails', async () => { const user = userEvent.setup() mockSetMany.mockRejectedValueOnce(new Error('persistence failed')) renderHeader() await user.click(screen.getByTestId('docked-job-history-action')) expect(popoverCloseSpy).toHaveBeenCalledTimes(1) expect(mockSetMany).toHaveBeenCalledWith({ 'Comfy.Queue.QPOV2': false, 'Comfy.Queue.History.Expanded': true }) }) it('toggles show run progress bar setting from the menu', async () => { const user = userEvent.setup() renderHeader() await user.click(screen.getByTestId('show-run-progress-bar-action')) expect(mockSetSetting).toHaveBeenCalledTimes(1) expect(mockSetSetting).toHaveBeenCalledWith( 'Comfy.Queue.ShowRunProgressBar', false ) }) })