Files
ComfyUI_frontend/src/components/templatePublishing/TemplatePublishingStepperNav.test.ts
John Haugeland fdd963a630 feat: template publishing dialog, stepper, and step components
Rename template marketplace to template publishing throughout:
- Replace useTemplateMarketplaceDialog with useTemplatePublishingDialog
- Update core command from Comfy.ShowTemplateMarketplace to
  Comfy.ShowTemplatePublishing
- Update workflow actions menu label and command reference

Add multi-step publishing dialog infrastructure:
- TemplatePublishingDialog.vue with step-based navigation
- TemplatePublishingStepperNav.vue for step progress indicator
- useTemplatePublishingStepper composable managing step state,
  navigation, and validation
- Step components for each phase: landing, metadata, description,
  preview generation, category/tagging, preview, submission, complete
- StepTemplatePublishingMetadata with form fields for title, category,
  tags, difficulty, and license selection
- StepTemplatePublishingDescription with markdown editor and live
  preview via vue-i18n

Add comprehensive i18n entries for all publishing steps, form labels,
difficulty levels, license types, and category names.

Add tests for dialog lifecycle, stepper navigation/validation, metadata
form interaction, and description editing.

Bump version to 1.42.0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 13:30:25 -08:00

104 lines
3.2 KiB
TypeScript

import { mount } from '@vue/test-utils'
import { createI18n } from 'vue-i18n'
import { describe, expect, it } from 'vitest'
import type { PublishingStepDefinition } from './types'
import TemplatePublishingStepperNav from './TemplatePublishingStepperNav.vue'
const STEP_DEFINITIONS: PublishingStepDefinition[] = [
{
number: 1,
titleKey: 'steps.landing.title',
descriptionKey: 'steps.landing.description'
},
{
number: 2,
titleKey: 'steps.metadata.title',
descriptionKey: 'steps.metadata.description'
},
{
number: 3,
titleKey: 'steps.preview.title',
descriptionKey: 'steps.preview.description'
}
]
const i18n = createI18n({
legacy: false,
locale: 'en',
messages: {
en: {
steps: {
landing: { title: 'Getting Started', description: '' },
metadata: { title: 'Metadata', description: '' },
preview: { title: 'Preview', description: '' }
}
}
}
})
function mountNav(props?: { currentStep?: number }) {
return mount(TemplatePublishingStepperNav, {
props: {
currentStep: props?.currentStep ?? 1,
stepDefinitions: STEP_DEFINITIONS
},
global: { plugins: [i18n] }
})
}
describe('TemplatePublishingStepperNav', () => {
it('renders a button for each step definition', () => {
const wrapper = mountNav()
const buttons = wrapper.findAll('button')
expect(buttons).toHaveLength(STEP_DEFINITIONS.length)
})
it('displays translated step titles', () => {
const wrapper = mountNav()
const buttons = wrapper.findAll('button')
expect(buttons[0].text()).toContain('Getting Started')
expect(buttons[1].text()).toContain('Metadata')
expect(buttons[2].text()).toContain('Preview')
})
it('marks the current step button as aria-selected', () => {
const wrapper = mountNav({ currentStep: 2 })
const buttons = wrapper.findAll('button')
expect(buttons[0].attributes('aria-selected')).toBe('false')
expect(buttons[1].attributes('aria-selected')).toBe('true')
expect(buttons[2].attributes('aria-selected')).toBe('false')
})
it('shows a check icon for completed steps', () => {
const wrapper = mountNav({ currentStep: 3 })
const buttons = wrapper.findAll('button')
expect(buttons[0].find('i.icon-\\[lucide--check\\]').exists()).toBe(true)
expect(buttons[1].find('i.icon-\\[lucide--check\\]').exists()).toBe(true)
expect(buttons[2].find('i.icon-\\[lucide--check\\]').exists()).toBe(false)
})
it('shows step numbers for current and future steps', () => {
const wrapper = mountNav({ currentStep: 2 })
const buttons = wrapper.findAll('button')
expect(buttons[0].find('i.icon-\\[lucide--check\\]').exists()).toBe(true)
expect(buttons[1].text()).toContain('2')
expect(buttons[2].text()).toContain('3')
})
it('emits update:currentStep when a step button is clicked', async () => {
const wrapper = mountNav({ currentStep: 1 })
await wrapper.findAll('button')[1].trigger('click')
expect(wrapper.emitted('update:currentStep')).toEqual([[2]])
})
it('renders separators between steps', () => {
const wrapper = mountNav()
const separators = wrapper.findAll('div.bg-border-default')
expect(separators).toHaveLength(STEP_DEFINITIONS.length - 1)
})
})