Files
ComfyUI_frontend/src/components/load3d/controls/viewer/ViewerExportControls.test.ts
Terry Jia bb74ec94de test(load3d): add unit tests for 9 previously-untested controls (#11730)
## Summary
Mirror the maskeditor coverage approach for load3d sub-components. Each
component gets behavior tests covering rendering, conditional branches,
v-model bidirectional sync, and emitted events.

- ViewerLightControls: setting-store min/max/step + v-model
- ViewerExportControls: format dropdown + click-to-export
- ViewerCameraControls: type select, FOV slider visibility
- ViewerSceneControls: with/without bg image branches, render mode
- PopupSlider: trigger toggle, click-outside dismissal, defaults
- CameraControls: switch button, FOV PopupSlider visibility
- ExportControls: trigger popup, format selection, click-outside
- AnimationControls: empty-list bypass, controls, time formatting
- ViewerControls: dialog open routing + onClose wiring

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11730-test-load3d-add-unit-tests-for-9-previously-untested-controls-3506d73d365081eaa9e7c5d0b922fc14)
by [Unito](https://www.unito.io)
2026-04-28 19:23:09 -04:00

75 lines
2.2 KiB
TypeScript

import { render, screen } from '@testing-library/vue'
import userEvent from '@testing-library/user-event'
import { describe, expect, it, vi } from 'vitest'
import { createI18n } from 'vue-i18n'
import ViewerExportControls from '@/components/load3d/controls/viewer/ViewerExportControls.vue'
vi.mock('primevue/select', () => ({
default: {
name: 'Select',
props: ['modelValue', 'options', 'optionLabel', 'optionValue'],
emits: ['update:modelValue'],
template: `
<select
:value="modelValue"
@change="$emit('update:modelValue', $event.target.value)"
>
<option v-for="opt in options" :key="opt[optionValue]" :value="opt[optionValue]">
{{ opt[optionLabel] }}
</option>
</select>
`
}
}))
const i18n = createI18n({
legacy: false,
locale: 'en',
messages: { en: { load3d: { export: 'Export' } } }
})
function renderComponent(onExportModel?: (format: string) => void) {
const utils = render(ViewerExportControls, {
props: { onExportModel },
global: { plugins: [i18n] }
})
return { ...utils, user: userEvent.setup() }
}
describe('ViewerExportControls', () => {
it('renders all three export format options', () => {
renderComponent()
const select = screen.getByRole('combobox') as HTMLSelectElement
const optionValues = Array.from(select.options).map((o) => o.value)
expect(optionValues).toEqual(['glb', 'obj', 'stl'])
})
it('defaults the export format to obj', () => {
renderComponent()
expect((screen.getByRole('combobox') as HTMLSelectElement).value).toBe(
'obj'
)
})
it('emits exportModel with the currently selected format when the button is clicked', async () => {
const onExportModel = vi.fn()
const { user } = renderComponent(onExportModel)
await user.click(screen.getByRole('button', { name: 'Export' }))
expect(onExportModel).toHaveBeenCalledWith('obj')
})
it('emits the newly chosen format after the user changes the dropdown', async () => {
const onExportModel = vi.fn()
const { user } = renderComponent(onExportModel)
await user.selectOptions(screen.getByRole('combobox'), 'glb')
await user.click(screen.getByRole('button', { name: 'Export' }))
expect(onExportModel).toHaveBeenCalledWith('glb')
})
})