mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-20 14:30:41 +00:00
fix: unit tests
This commit is contained in:
22
src/components/common/MarqueeLine.test.ts
Normal file
22
src/components/common/MarqueeLine.test.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import MarqueeLine from './MarqueeLine.vue'
|
||||
|
||||
describe(MarqueeLine, () => {
|
||||
it('renders slot content', () => {
|
||||
const wrapper = mount(MarqueeLine, {
|
||||
slots: { default: 'Hello World' }
|
||||
})
|
||||
expect(wrapper.text()).toBe('Hello World')
|
||||
})
|
||||
|
||||
it('renders content inside a span within the container', () => {
|
||||
const wrapper = mount(MarqueeLine, {
|
||||
slots: { default: 'Test Text' }
|
||||
})
|
||||
const span = wrapper.find('span')
|
||||
expect(span.exists()).toBe(true)
|
||||
expect(span.text()).toBe('Test Text')
|
||||
})
|
||||
})
|
||||
@@ -1,58 +1,105 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { nextTick } from 'vue'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import { splitTextAtWordBoundary } from './textTickerUtils'
|
||||
import MarqueeLine from './MarqueeLine.vue'
|
||||
import TextTickerMultiLine from './TextTickerMultiLine.vue'
|
||||
|
||||
describe('splitTextAtWordBoundary', () => {
|
||||
it('returns full text when ratio >= 1 (fits in one line)', () => {
|
||||
expect(splitTextAtWordBoundary('Load Checkpoint', 1)).toEqual([
|
||||
'Load Checkpoint',
|
||||
''
|
||||
])
|
||||
expect(splitTextAtWordBoundary('Load Checkpoint', 1.5)).toEqual([
|
||||
'Load Checkpoint',
|
||||
''
|
||||
])
|
||||
type Callback = () => void
|
||||
|
||||
const resizeCallbacks: Callback[] = []
|
||||
const mutationCallbacks: Callback[] = []
|
||||
|
||||
vi.mock('@vueuse/core', async () => {
|
||||
const actual = await vi.importActual('@vueuse/core')
|
||||
return {
|
||||
...actual,
|
||||
useResizeObserver: (_target: unknown, cb: Callback) => {
|
||||
resizeCallbacks.push(cb)
|
||||
return { stop: vi.fn() }
|
||||
},
|
||||
useMutationObserver: (_target: unknown, cb: Callback) => {
|
||||
mutationCallbacks.push(cb)
|
||||
return { stop: vi.fn() }
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function mockElementSize(
|
||||
el: HTMLElement,
|
||||
clientWidth: number,
|
||||
scrollWidth: number
|
||||
) {
|
||||
Object.defineProperty(el, 'clientWidth', {
|
||||
value: clientWidth,
|
||||
configurable: true
|
||||
})
|
||||
Object.defineProperty(el, 'scrollWidth', {
|
||||
value: scrollWidth,
|
||||
configurable: true
|
||||
})
|
||||
}
|
||||
|
||||
describe(TextTickerMultiLine, () => {
|
||||
let wrapper: ReturnType<typeof mount>
|
||||
|
||||
afterEach(() => {
|
||||
wrapper?.unmount()
|
||||
resizeCallbacks.length = 0
|
||||
mutationCallbacks.length = 0
|
||||
})
|
||||
|
||||
it('splits at last word boundary before estimated break', () => {
|
||||
// "Load Checkpoint Loader" = 22 chars, ratio 0.5 → estimate at char 11
|
||||
// lastIndexOf(' ', 11) → 15? No: "Load Checkpoint Loader"
|
||||
// 0123456789...
|
||||
// ' ' at index 4 and 15
|
||||
// lastIndexOf(' ', 11) → 4
|
||||
expect(splitTextAtWordBoundary('Load Checkpoint Loader', 0.5)).toEqual([
|
||||
'Load',
|
||||
'Checkpoint Loader'
|
||||
])
|
||||
function mountComponent(text: string) {
|
||||
wrapper = mount(TextTickerMultiLine, {
|
||||
slots: { default: text }
|
||||
})
|
||||
return wrapper
|
||||
}
|
||||
|
||||
function getMeasureEl(): HTMLElement {
|
||||
return wrapper.find('[aria-hidden="true"]').element as HTMLElement
|
||||
}
|
||||
|
||||
async function triggerSplitLines() {
|
||||
resizeCallbacks.forEach((cb) => cb())
|
||||
await nextTick()
|
||||
}
|
||||
|
||||
it('renders slot content', () => {
|
||||
mountComponent('Load Checkpoint')
|
||||
expect(wrapper.text()).toContain('Load Checkpoint')
|
||||
})
|
||||
|
||||
it('splits longer text proportionally', () => {
|
||||
// ratio 0.7 → estimate at char 15
|
||||
// lastIndexOf(' ', 15) → 15 (the space between "Checkpoint" and "Loader")
|
||||
expect(splitTextAtWordBoundary('Load Checkpoint Loader', 0.7)).toEqual([
|
||||
'Load Checkpoint',
|
||||
'Loader'
|
||||
])
|
||||
it('renders a single MarqueeLine when text fits', async () => {
|
||||
mountComponent('Short')
|
||||
mockElementSize(getMeasureEl(), 200, 100)
|
||||
await triggerSplitLines()
|
||||
|
||||
expect(wrapper.findAllComponents(MarqueeLine)).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('returns full text when no word boundary found', () => {
|
||||
expect(splitTextAtWordBoundary('Superlongwordwithoutspaces', 0.5)).toEqual([
|
||||
'Superlongwordwithoutspaces',
|
||||
''
|
||||
])
|
||||
it('renders two MarqueeLines when text overflows', async () => {
|
||||
mountComponent('Load Checkpoint Loader Simple')
|
||||
mockElementSize(getMeasureEl(), 100, 300)
|
||||
await triggerSplitLines()
|
||||
|
||||
expect(wrapper.findAllComponents(MarqueeLine)).toHaveLength(2)
|
||||
})
|
||||
|
||||
it('handles single word text', () => {
|
||||
expect(splitTextAtWordBoundary('Checkpoint', 0.5)).toEqual([
|
||||
'Checkpoint',
|
||||
''
|
||||
])
|
||||
it('splits text at word boundary when overflowing', async () => {
|
||||
mountComponent('Load Checkpoint Loader')
|
||||
mockElementSize(getMeasureEl(), 100, 200)
|
||||
await triggerSplitLines()
|
||||
|
||||
const lines = wrapper.findAllComponents(MarqueeLine)
|
||||
expect(lines[0].text()).toBe('Load')
|
||||
expect(lines[1].text()).toBe('Checkpoint Loader')
|
||||
})
|
||||
|
||||
it('handles ratio near zero', () => {
|
||||
expect(splitTextAtWordBoundary('Load Checkpoint Loader', 0.1)).toEqual([
|
||||
'Load Checkpoint Loader',
|
||||
''
|
||||
])
|
||||
it('has hidden measurement element with aria-hidden', () => {
|
||||
mountComponent('Test')
|
||||
const measureEl = wrapper.find('[aria-hidden="true"]')
|
||||
expect(measureEl.exists()).toBe(true)
|
||||
expect(measureEl.classes()).toContain('invisible')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -25,7 +25,7 @@ import { useMutationObserver, useResizeObserver } from '@vueuse/core'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import MarqueeLine from './MarqueeLine.vue'
|
||||
import { splitTextAtWordBoundary } from './textTickerUtils'
|
||||
import { splitTextAtWordBoundary } from '@/utils/textTickerUtils'
|
||||
|
||||
const measureRef = ref<HTMLElement | null>(null)
|
||||
const firstLine = ref('')
|
||||
|
||||
58
src/utils/textTickerUtils.test.ts
Normal file
58
src/utils/textTickerUtils.test.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import { splitTextAtWordBoundary } from '@/utils/textTickerUtils'
|
||||
|
||||
describe('splitTextAtWordBoundary', () => {
|
||||
it('returns full text when ratio >= 1 (fits in one line)', () => {
|
||||
expect(splitTextAtWordBoundary('Load Checkpoint', 1)).toEqual([
|
||||
'Load Checkpoint',
|
||||
''
|
||||
])
|
||||
expect(splitTextAtWordBoundary('Load Checkpoint', 1.5)).toEqual([
|
||||
'Load Checkpoint',
|
||||
''
|
||||
])
|
||||
})
|
||||
|
||||
it('splits at last word boundary before estimated break', () => {
|
||||
// "Load Checkpoint Loader" = 22 chars, ratio 0.5 → estimate at char 11
|
||||
// lastIndexOf(' ', 11) → 15? No: "Load Checkpoint Loader"
|
||||
// 0123456789...
|
||||
// ' ' at index 4 and 15
|
||||
// lastIndexOf(' ', 11) → 4
|
||||
expect(splitTextAtWordBoundary('Load Checkpoint Loader', 0.5)).toEqual([
|
||||
'Load',
|
||||
'Checkpoint Loader'
|
||||
])
|
||||
})
|
||||
|
||||
it('splits longer text proportionally', () => {
|
||||
// ratio 0.7 → estimate at char 15
|
||||
// lastIndexOf(' ', 15) → 15 (the space between "Checkpoint" and "Loader")
|
||||
expect(splitTextAtWordBoundary('Load Checkpoint Loader', 0.7)).toEqual([
|
||||
'Load Checkpoint',
|
||||
'Loader'
|
||||
])
|
||||
})
|
||||
|
||||
it('returns full text when no word boundary found', () => {
|
||||
expect(splitTextAtWordBoundary('Superlongwordwithoutspaces', 0.5)).toEqual([
|
||||
'Superlongwordwithoutspaces',
|
||||
''
|
||||
])
|
||||
})
|
||||
|
||||
it('handles single word text', () => {
|
||||
expect(splitTextAtWordBoundary('Checkpoint', 0.5)).toEqual([
|
||||
'Checkpoint',
|
||||
''
|
||||
])
|
||||
})
|
||||
|
||||
it('handles ratio near zero', () => {
|
||||
expect(splitTextAtWordBoundary('Load Checkpoint Loader', 0.1)).toEqual([
|
||||
'Load Checkpoint Loader',
|
||||
''
|
||||
])
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user