mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-04 13:12:10 +00:00
## 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>
121 lines
3.6 KiB
TypeScript
121 lines
3.6 KiB
TypeScript
import { fireEvent, render, screen } from '@testing-library/vue'
|
|
import userEvent from '@testing-library/user-event'
|
|
import PrimeVue from 'primevue/config'
|
|
import InputText from 'primevue/inputtext'
|
|
import { describe, expect, it, vi } from 'vitest'
|
|
|
|
import EditableText from './EditableText.vue'
|
|
|
|
describe('EditableText', () => {
|
|
function renderComponent(
|
|
props: { modelValue: string; isEditing?: boolean },
|
|
callbacks: {
|
|
onEdit?: (...args: unknown[]) => void
|
|
onCancel?: (...args: unknown[]) => void
|
|
} = {}
|
|
) {
|
|
const user = userEvent.setup()
|
|
|
|
render(EditableText, {
|
|
global: {
|
|
plugins: [PrimeVue],
|
|
components: { InputText }
|
|
},
|
|
props: {
|
|
...props,
|
|
...(callbacks.onEdit && { onEdit: callbacks.onEdit }),
|
|
...(callbacks.onCancel && { onCancel: callbacks.onCancel })
|
|
}
|
|
})
|
|
|
|
return { user }
|
|
}
|
|
|
|
it('renders span with modelValue when not editing', () => {
|
|
renderComponent({ modelValue: 'Test Text', isEditing: false })
|
|
expect(screen.getByText('Test Text')).toBeInTheDocument()
|
|
expect(screen.queryByRole('textbox')).not.toBeInTheDocument()
|
|
})
|
|
|
|
it('renders input with modelValue when editing', () => {
|
|
renderComponent({ modelValue: 'Test Text', isEditing: true })
|
|
expect(screen.queryByText('Test Text')).not.toBeInTheDocument()
|
|
expect(screen.getByRole('textbox')).toHaveValue('Test Text')
|
|
})
|
|
|
|
it('emits edit event when input is submitted', async () => {
|
|
const onEdit = vi.fn()
|
|
const { user } = renderComponent(
|
|
{ modelValue: 'Test Text', isEditing: true },
|
|
{ onEdit }
|
|
)
|
|
|
|
const input = screen.getByRole('textbox')
|
|
await user.clear(input)
|
|
await user.type(input, 'New Text')
|
|
await user.keyboard('{Enter}')
|
|
|
|
expect(onEdit).toHaveBeenCalledWith('New Text')
|
|
})
|
|
|
|
it('finishes editing on blur', async () => {
|
|
const onEdit = vi.fn()
|
|
renderComponent({ modelValue: 'Test Text', isEditing: true }, { onEdit })
|
|
|
|
await fireEvent.blur(screen.getByRole('textbox'))
|
|
|
|
expect(onEdit).toHaveBeenCalledWith('Test Text')
|
|
})
|
|
|
|
it('cancels editing on escape key', async () => {
|
|
const onEdit = vi.fn()
|
|
const onCancel = vi.fn()
|
|
const { user } = renderComponent(
|
|
{ modelValue: 'Original Text', isEditing: true },
|
|
{ onEdit, onCancel }
|
|
)
|
|
|
|
const input = screen.getByRole('textbox')
|
|
await user.clear(input)
|
|
await user.type(input, 'Modified Text')
|
|
await user.keyboard('{Escape}')
|
|
|
|
expect(onCancel).toHaveBeenCalled()
|
|
expect(onEdit).not.toHaveBeenCalled()
|
|
expect(input).toHaveValue('Original Text')
|
|
})
|
|
|
|
it('does not save changes when escape is pressed', async () => {
|
|
const onEdit = vi.fn()
|
|
const onCancel = vi.fn()
|
|
const { user } = renderComponent(
|
|
{ modelValue: 'Original Text', isEditing: true },
|
|
{ onEdit, onCancel }
|
|
)
|
|
|
|
const input = screen.getByRole('textbox')
|
|
await user.clear(input)
|
|
await user.type(input, 'Modified Text')
|
|
// Escape triggers cancelEditing → blur internally, so no separate blur needed
|
|
await user.keyboard('{Escape}')
|
|
|
|
expect(onCancel).toHaveBeenCalled()
|
|
expect(onEdit).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('saves changes on enter but not on escape', async () => {
|
|
const onEditEnter = vi.fn()
|
|
const { user: userEnter } = renderComponent(
|
|
{ modelValue: 'Original Text', isEditing: true },
|
|
{ onEdit: onEditEnter }
|
|
)
|
|
|
|
const enterInput = screen.getByRole('textbox')
|
|
await userEnter.clear(enterInput)
|
|
await userEnter.type(enterInput, 'Saved Text')
|
|
await userEnter.keyboard('{Enter}')
|
|
|
|
expect(onEditEnter).toHaveBeenCalledWith('Saved Text')
|
|
})
|
|
})
|