Files
ComfyUI_frontend/src/components/common/TextTicker.test.ts
Comfy Org PR Bot a53f352ff0 [backport core/1.43] test: migrate 132 test files from @vue/test-utils to @testing-library/vue (#11488)
Backport of #10965 to `core/1.43`

Automatically created by backport workflow.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11488-backport-core-1-43-test-migrate-132-test-files-from-vue-test-utils-to-testing-libra-3496d73d365081d4bfc2d8db3cb27317)
by [Unito](https://www.unito.io)

Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: Christian Byrne <cbyrne@comfy.org>
2026-04-20 18:57:39 -07:00

134 lines
3.4 KiB
TypeScript

import { render, screen } from '@testing-library/vue'
import userEvent from '@testing-library/user-event'
import { nextTick } from 'vue'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import TextTicker from './TextTicker.vue'
function mockScrollWidth(el: HTMLElement, scrollWidth: number) {
Object.defineProperty(el, 'scrollWidth', {
value: scrollWidth,
configurable: true
})
}
describe(TextTicker, () => {
let rafCallbacks: ((time: number) => void)[]
let user: ReturnType<typeof userEvent.setup>
let cleanup: (() => void) | undefined
beforeEach(() => {
vi.useFakeTimers()
rafCallbacks = []
vi.spyOn(window, 'requestAnimationFrame').mockImplementation((cb) => {
rafCallbacks.push(cb)
return rafCallbacks.length
})
vi.spyOn(window, 'cancelAnimationFrame').mockImplementation(() => {})
user = userEvent.setup({ advanceTimers: vi.advanceTimersByTime })
})
afterEach(() => {
cleanup?.()
vi.useRealTimers()
vi.restoreAllMocks()
})
it('renders slot content', () => {
const { unmount } = render(TextTicker, {
slots: { default: 'Hello World' }
})
cleanup = unmount
expect(screen.getByText('Hello World')).toBeInTheDocument()
})
it('scrolls on hover after delay', async () => {
const { unmount } = render(TextTicker, {
slots: { default: 'Very long text that overflows' },
props: { speed: 100 }
})
cleanup = unmount
const el = screen.getByText('Very long text that overflows')
mockScrollWidth(el, 300)
await nextTick()
await user.hover(el)
await nextTick()
expect(rafCallbacks.length).toBe(0)
vi.advanceTimersByTime(350)
await nextTick()
expect(rafCallbacks.length).toBeGreaterThan(0)
rafCallbacks[0](performance.now() + 500)
expect(el.scrollLeft).toBeGreaterThan(0)
})
it('cancels delayed scroll on mouse leave before delay elapses', async () => {
const { unmount } = render(TextTicker, {
slots: { default: 'Very long text that overflows' },
props: { speed: 100 }
})
cleanup = unmount
const el = screen.getByText('Very long text that overflows')
mockScrollWidth(el, 300)
await nextTick()
await user.hover(el)
await nextTick()
vi.advanceTimersByTime(200)
await user.unhover(el)
await nextTick()
vi.advanceTimersByTime(350)
await nextTick()
expect(rafCallbacks.length).toBe(0)
})
it('resets scroll position on mouse leave', async () => {
const { unmount } = render(TextTicker, {
slots: { default: 'Very long text that overflows' },
props: { speed: 100 }
})
cleanup = unmount
const el = screen.getByText('Very long text that overflows')
mockScrollWidth(el, 300)
await nextTick()
await user.hover(el)
await nextTick()
vi.advanceTimersByTime(350)
await nextTick()
rafCallbacks[0](performance.now() + 500)
expect(el.scrollLeft).toBeGreaterThan(0)
await user.unhover(el)
await nextTick()
expect(el.scrollLeft).toBe(0)
})
it('does not scroll when content fits', async () => {
const { unmount } = render(TextTicker, {
slots: { default: 'Short' }
})
cleanup = unmount
const el = screen.getByText('Short')
await nextTick()
await user.hover(el)
await nextTick()
vi.advanceTimersByTime(350)
await nextTick()
expect(rafCallbacks.length).toBe(0)
})
})