Files
ComfyUI_frontend/src/components/sidebar/SidebarIcon.test.ts
Alexander Brown 3de387429a test: migrate 11 interactive component tests from VTU to VTL (Phase 2) (#10490)
## Summary

Phase 2 of the VTL migration: migrate 11 interactive component tests
from @vue/test-utils to @testing-library/vue (69 tests).

Stacked on #10471.

## Changes

- **What**: Migrate BatchCountEdit, BypassButton, BuilderFooterToolbar,
ComfyActionbar, SidebarIcon, EditableText, UrlInput, SearchInput,
TagsInput, TreeExplorerTreeNode, ColorCustomizationSelector from VTU to
VTL
- **Pattern transforms**: `trigger('click')` → `userEvent.click()`,
`setValue()` → `userEvent.type()`, `findComponent().props()` →
`getByRole/getByText/getByTestId`, `emitted()` → callback props
- **Removed**: 4 `@ts-expect-error` annotations, 1 change-detector test
(SearchInput `vm.focus`)
- **PrimeVue**: `data-pc-name` selectors + `aria-pressed` for
SelectButton, container queries for ColorPicker/InputIcon

## Review Focus

- PrimeVue escape hatches in ColorCustomizationSelector
(SelectButton/ColorPicker lack standard ARIA roles)
- Teleport test in ComfyActionbar uses `container.querySelector`
intentionally (scoped to teleport target)
- SearchInput debounce tests use `fireEvent.update` instead of
`userEvent.type` due to fake timer interaction
- EditableText escape-then-blur test simplified:
`userEvent.keyboard('{Escape}')` already triggers blur internally

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-10490-test-migrate-11-interactive-component-tests-from-VTU-to-VTL-Phase-2-32e6d73d3650817ca40fd61395499e3f)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-03-26 19:46:31 -07:00

88 lines
2.2 KiB
TypeScript

import { render, screen, waitFor } from '@testing-library/vue'
import userEvent from '@testing-library/user-event'
import PrimeVue from 'primevue/config'
import Tooltip from 'primevue/tooltip'
import { describe, expect, it } from 'vitest'
import { createI18n } from 'vue-i18n'
import SidebarIcon from './SidebarIcon.vue'
type SidebarIconProps = {
icon: string
selected: boolean
tooltip?: string
class?: string
iconBadge?: string | (() => string | null)
}
const i18n = createI18n({
legacy: false,
locale: 'en',
messages: {
en: {}
}
})
describe('SidebarIcon', () => {
const exampleProps: SidebarIconProps = {
icon: 'pi pi-cog',
selected: false
}
function renderSidebarIcon(props: Partial<SidebarIconProps> = {}) {
const user = userEvent.setup()
const result = render(SidebarIcon, {
global: {
plugins: [PrimeVue, i18n],
directives: { tooltip: Tooltip }
},
props: { ...exampleProps, ...props }
})
return { ...result, user }
}
it('renders button element', () => {
renderSidebarIcon()
expect(screen.getByRole('button')).toBeInTheDocument()
})
it('renders icon', () => {
const { container } = renderSidebarIcon()
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access -- Icon escape hatch: iconify icons have no ARIA role
expect(container.querySelector('.side-bar-button-icon')).not.toBeNull()
})
it('creates badge when iconBadge prop is set', () => {
const badge = '2'
renderSidebarIcon({ iconBadge: badge })
expect(screen.getByText(badge)).toBeInTheDocument()
})
it('shows tooltip on hover', async () => {
const tooltipText = 'Settings'
const { user } = renderSidebarIcon({ tooltip: tooltipText })
expect(screen.queryByRole('tooltip')).not.toBeInTheDocument()
await user.hover(screen.getByRole('button'))
await waitFor(
() => {
expect(screen.getByRole('tooltip')).toBeInTheDocument()
},
{ timeout: 1000 }
)
})
it('sets aria-label attribute when tooltip is provided', () => {
const tooltipText = 'Settings'
renderSidebarIcon({ tooltip: tooltipText })
expect(screen.getByRole('button')).toHaveAttribute(
'aria-label',
tooltipText
)
})
})