mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-02 22:37:32 +00:00
style: reformat codebase with oxfmt
This commit is contained in:
@@ -43,7 +43,7 @@ pnpm test:unit
|
||||
# Run a specific test file
|
||||
pnpm test:unit -- src/path/to/file.test.ts
|
||||
|
||||
# Run unit tests in watch mode
|
||||
# Run unit tests in watch mode
|
||||
pnpm test:unit -- --watch
|
||||
```
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ describe('ColorCustomizationSelector', () => {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
it('initializes with predefined color when provided', async () => {
|
||||
const wrapper = mountComponent({
|
||||
modelValue: '#0d6efd'
|
||||
@@ -109,16 +109,16 @@ describe('SidebarIcon with tooltip', () => {
|
||||
it('shows tooltip on hover', async () => {
|
||||
const tooltipShowDelay = 300
|
||||
const tooltipText = 'Settings'
|
||||
|
||||
|
||||
const wrapper = mount(SidebarIcon, {
|
||||
global: {
|
||||
plugins: [PrimeVue],
|
||||
directives: { tooltip: Tooltip }
|
||||
},
|
||||
props: {
|
||||
props: {
|
||||
icon: 'pi pi-cog',
|
||||
selected: false,
|
||||
tooltip: tooltipText
|
||||
tooltip: tooltipText
|
||||
}
|
||||
})
|
||||
|
||||
@@ -137,13 +137,13 @@ describe('SidebarIcon with tooltip', () => {
|
||||
plugins: [PrimeVue],
|
||||
directives: { tooltip: Tooltip }
|
||||
},
|
||||
props: {
|
||||
icon: 'pi pi-cog',
|
||||
props: {
|
||||
icon: 'pi pi-cog',
|
||||
selected: false,
|
||||
tooltip: tooltipText
|
||||
tooltip: tooltipText
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
expect(wrapper.attributes('aria-label')).toEqual(tooltipText)
|
||||
})
|
||||
})
|
||||
@@ -196,10 +196,10 @@ describe('EditableText', () => {
|
||||
|
||||
// Initially in view mode
|
||||
expect(wrapper.find('input').exists()).toBe(false)
|
||||
|
||||
|
||||
// Click to edit
|
||||
await wrapper.find('.editable-text').trigger('click')
|
||||
|
||||
|
||||
// Should switch to edit mode
|
||||
expect(wrapper.find('input').exists()).toBe(true)
|
||||
expect(wrapper.find('input').element.value).toBe('Initial Text')
|
||||
@@ -215,17 +215,17 @@ describe('EditableText', () => {
|
||||
|
||||
// Switch to edit mode
|
||||
await wrapper.find('.editable-text').trigger('click')
|
||||
|
||||
|
||||
// Change input value
|
||||
const input = wrapper.find('input')
|
||||
await input.setValue('New Text')
|
||||
|
||||
|
||||
// Press enter to save
|
||||
await input.trigger('keydown.enter')
|
||||
|
||||
|
||||
// Check if event was emitted with new value
|
||||
expect(wrapper.emitted('update:modelValue')[0]).toEqual(['New Text'])
|
||||
|
||||
|
||||
// Should switch back to view mode
|
||||
expect(wrapper.find('input').exists()).toBe(false)
|
||||
})
|
||||
@@ -247,17 +247,17 @@ it('shows dropdown options when clicked', async () => {
|
||||
selectedVersion: '1.1.0'
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// Initially dropdown should be hidden
|
||||
expect(wrapper.find('.p-dropdown-panel').isVisible()).toBe(false)
|
||||
|
||||
|
||||
// Click dropdown
|
||||
await wrapper.find('.p-dropdown').trigger('click')
|
||||
await nextTick() // Wait for Vue to update the DOM
|
||||
|
||||
|
||||
// Dropdown should be visible now
|
||||
expect(wrapper.find('.p-dropdown-panel').isVisible()).toBe(true)
|
||||
|
||||
|
||||
// Options should match the provided versions
|
||||
const options = wrapper.findAll('.p-dropdown-item')
|
||||
expect(options.length).toBe(3)
|
||||
@@ -286,7 +286,7 @@ const waitForPromises = async () => {
|
||||
|
||||
it('fetches versions on mount', async () => {
|
||||
mockGetPackVersions.mockResolvedValueOnce(defaultMockVersions)
|
||||
|
||||
|
||||
mountComponent()
|
||||
await waitForPromises() // Wait for async operations and reactivity
|
||||
|
||||
@@ -302,13 +302,14 @@ When components use `onMounted` or other lifecycle hooks with async operations:
|
||||
it('shows loading state while fetching versions', async () => {
|
||||
// Delay the promise resolution
|
||||
mockGetPackVersions.mockImplementationOnce(
|
||||
() => new Promise((resolve) =>
|
||||
setTimeout(() => resolve(defaultMockVersions), 1000)
|
||||
)
|
||||
() =>
|
||||
new Promise((resolve) =>
|
||||
setTimeout(() => resolve(defaultMockVersions), 1000)
|
||||
)
|
||||
)
|
||||
|
||||
const wrapper = mountComponent()
|
||||
|
||||
|
||||
// Check loading state before promises resolve
|
||||
expect(wrapper.text()).toContain('Loading versions...')
|
||||
})
|
||||
@@ -347,13 +348,13 @@ Testing components with computed properties that depend on async data:
|
||||
```typescript
|
||||
it('displays special options and version options in the listbox', async () => {
|
||||
mockGetPackVersions.mockResolvedValueOnce(defaultMockVersions)
|
||||
|
||||
|
||||
const wrapper = mountComponent()
|
||||
await waitForPromises() // Wait for data fetching and computed property updates
|
||||
|
||||
|
||||
const listbox = wrapper.findComponent(Listbox)
|
||||
const options = listbox.props('options')!
|
||||
|
||||
|
||||
// Now options should be populated through computed properties
|
||||
expect(options.length).toBe(defaultMockVersions.length + 2)
|
||||
})
|
||||
@@ -367,4 +368,4 @@ it('displays special options and version options in the listbox', async () => {
|
||||
4. **PrimeVue components**: PrimeVue components often have their own internal state and reactivity that needs time to update
|
||||
5. **Computed properties depending on async data**: Always ensure async data is loaded before testing computed properties
|
||||
|
||||
By using the `waitForPromises` helper and being mindful of these patterns, you can write more robust tests for components with complex reactivity.
|
||||
By using the `waitForPromises` helper and being mindful of these patterns, you can write more robust tests for components with complex reactivity.
|
||||
|
||||
@@ -29,10 +29,10 @@ describe('useWorkflowStore', () => {
|
||||
beforeEach(() => {
|
||||
// Create a fresh pinia and activate it for each test
|
||||
setActivePinia(createPinia())
|
||||
|
||||
|
||||
// Initialize the store
|
||||
store = useWorkflowStore()
|
||||
|
||||
|
||||
// Clear any mocks
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
@@ -119,18 +119,21 @@ describe('getters', () => {
|
||||
beforeEach(() => {
|
||||
setActivePinia(createPinia())
|
||||
store = useModelStore()
|
||||
|
||||
|
||||
// Set up test data
|
||||
store.models = {
|
||||
checkpoints: [
|
||||
{ name: 'model1.safetensors', path: 'models/checkpoints/model1.safetensors' },
|
||||
{
|
||||
name: 'model1.safetensors',
|
||||
path: 'models/checkpoints/model1.safetensors'
|
||||
},
|
||||
{ name: 'model2.ckpt', path: 'models/checkpoints/model2.ckpt' }
|
||||
],
|
||||
loras: [
|
||||
{ name: 'lora1.safetensors', path: 'models/loras/lora1.safetensors' }
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
// Mock API
|
||||
vi.mocked(api.getModelInfo).mockImplementation(async (modelName) => {
|
||||
if (modelName.includes('model1')) {
|
||||
@@ -277,4 +280,4 @@ describe('renameWorkflow', () => {
|
||||
expect(bookmarkStore.isBookmarked('workflows/dir/test.json')).toBe(false)
|
||||
})
|
||||
})
|
||||
```
|
||||
```
|
||||
|
||||
@@ -12,7 +12,6 @@ This guide covers patterns and examples for unit testing utilities, composables,
|
||||
6. [Testing with Debounce and Throttle](#testing-with-debounce-and-throttle)
|
||||
7. [Mocking Node Definitions](#mocking-node-definitions)
|
||||
|
||||
|
||||
## Testing Vue Composables with Reactivity
|
||||
|
||||
Testing Vue composables requires handling reactivity correctly:
|
||||
@@ -37,16 +36,18 @@ describe('useServerLogs', () => {
|
||||
|
||||
// Simulate log event handler being called
|
||||
const mockHandler = vi.mocked(useEventListener).mock.calls[0][2]
|
||||
mockHandler(new CustomEvent('logs', {
|
||||
detail: {
|
||||
type: 'logs',
|
||||
entries: [{ m: 'Log message' }]
|
||||
}
|
||||
}))
|
||||
|
||||
mockHandler(
|
||||
new CustomEvent('logs', {
|
||||
detail: {
|
||||
type: 'logs',
|
||||
entries: [{ m: 'Log message' }]
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
// Must wait for Vue reactivity to update
|
||||
await nextTick()
|
||||
|
||||
|
||||
expect(logs.value).toEqual(['Log message'])
|
||||
})
|
||||
})
|
||||
@@ -72,12 +73,12 @@ describe('LGraph', () => {
|
||||
it('should serialize graph nodes', async () => {
|
||||
// Register node type
|
||||
LiteGraph.registerNodeType('dummy', DummyNode)
|
||||
|
||||
|
||||
// Create graph with nodes
|
||||
const graph = new LGraph()
|
||||
const node = new DummyNode()
|
||||
graph.add(node)
|
||||
|
||||
|
||||
// Test serialization
|
||||
const result = graph.serialize()
|
||||
expect(result.nodes).toHaveLength(1)
|
||||
@@ -99,18 +100,18 @@ import { defaultGraph } from '@/scripts/defaultGraph'
|
||||
describe('workflow validation', () => {
|
||||
it('should validate default workflow', async () => {
|
||||
const validWorkflow = JSON.parse(JSON.stringify(defaultGraph))
|
||||
|
||||
|
||||
// Validate workflow
|
||||
const result = await validateComfyWorkflow(validWorkflow)
|
||||
expect(result).not.toBeNull()
|
||||
})
|
||||
|
||||
|
||||
it('should handle position format conversion', async () => {
|
||||
const workflow = JSON.parse(JSON.stringify(defaultGraph))
|
||||
|
||||
|
||||
// Legacy position format as object
|
||||
workflow.nodes[0].pos = { '0': 100, '1': 200 }
|
||||
|
||||
|
||||
// Should convert to array format
|
||||
const result = await validateComfyWorkflow(workflow)
|
||||
expect(result.nodes[0].pos).toEqual([100, 200])
|
||||
@@ -139,7 +140,7 @@ vi.mock('@/scripts/api', () => ({
|
||||
it('should subscribe to logs API', () => {
|
||||
// Call function that uses the API
|
||||
startListening()
|
||||
|
||||
|
||||
// Verify API was called correctly
|
||||
expect(api.subscribeLogs).toHaveBeenCalledWith(true)
|
||||
})
|
||||
@@ -167,9 +168,9 @@ describe('Function using debounce', () => {
|
||||
it('calls debounced function immediately in tests', () => {
|
||||
const mockFn = vi.fn()
|
||||
const debouncedFn = debounce(mockFn, 1000)
|
||||
|
||||
|
||||
debouncedFn()
|
||||
|
||||
|
||||
// No need to wait - our mock makes it execute immediately
|
||||
expect(mockFn).toHaveBeenCalled()
|
||||
})
|
||||
@@ -190,25 +191,25 @@ describe('debounced function', () => {
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers()
|
||||
vi.useRealTimers()
|
||||
})
|
||||
|
||||
it('should debounce function calls', () => {
|
||||
const mockFn = vi.fn()
|
||||
const debouncedFn = debounce(mockFn, 1000)
|
||||
|
||||
|
||||
// Call multiple times
|
||||
debouncedFn()
|
||||
debouncedFn()
|
||||
debouncedFn()
|
||||
|
||||
|
||||
// Function not called yet (debounced)
|
||||
expect(mockFn).not.toHaveBeenCalled()
|
||||
|
||||
|
||||
// Advance time just before debounce period
|
||||
vi.advanceTimersByTime(999)
|
||||
expect(mockFn).not.toHaveBeenCalled()
|
||||
|
||||
|
||||
// Advance to debounce completion
|
||||
vi.advanceTimersByTime(1)
|
||||
expect(mockFn).toHaveBeenCalledTimes(1)
|
||||
@@ -223,7 +224,10 @@ Creating mock node definitions for testing:
|
||||
```typescript
|
||||
// Example from: tests-ui/tests/apiTypes.test.ts
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { type ComfyNodeDef, validateComfyNodeDef } from '@/schemas/nodeDefSchema'
|
||||
import {
|
||||
type ComfyNodeDef,
|
||||
validateComfyNodeDef
|
||||
} from '@/schemas/nodeDefSchema'
|
||||
|
||||
// Create a complete mock node definition
|
||||
const EXAMPLE_NODE_DEF: ComfyNodeDef = {
|
||||
@@ -248,4 +252,4 @@ const EXAMPLE_NODE_DEF: ComfyNodeDef = {
|
||||
it('should validate node definition', () => {
|
||||
expect(validateComfyNodeDef(EXAMPLE_NODE_DEF)).not.toBeNull()
|
||||
})
|
||||
```
|
||||
```
|
||||
|
||||
@@ -36,7 +36,7 @@ describe('MyStore', () => {
|
||||
|
||||
```typescript
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks() // Not individual mock.mockReset() calls
|
||||
vi.resetAllMocks() // Not individual mock.mockReset() calls
|
||||
})
|
||||
```
|
||||
|
||||
@@ -75,9 +75,9 @@ When a store registers event listeners at module load time:
|
||||
|
||||
```typescript
|
||||
function getEventHandler() {
|
||||
const call = vi.mocked(api.addEventListener).mock.calls.find(
|
||||
([event]) => event === 'my_event'
|
||||
)
|
||||
const call = vi
|
||||
.mocked(api.addEventListener)
|
||||
.mock.calls.find(([event]) => event === 'my_event')
|
||||
return call?.[1] as (e: CustomEvent<MyEventType>) => void
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user