[test] Add component tests for some Vue Widget components (#5409)

* add component tests for vue widgets

* [refactor] improve widget test readability and type safety - addresses @DrJKL's review feedback

- Add mountComponent utility function for consistent test setup
- Add setInputValueAndTrigger helper to batch common test operations
- Replace type assertions with proper instanceof checks for type safety
- Remove duplicate test setup code to improve test readability
- Fix TypeScript errors in WidgetSlider tests

These changes address all review comments by making tests easier to read
and understand while ensuring proper type checking.

* [refactor] apply consistent test patterns to WidgetSelect.test.ts

- Add mountComponent utility function for consistent test setup
- Add setSelectValueAndEmit helper to batch select operations
- Remove repetitive mount boilerplate code throughout tests
- Maintain existing test coverage while improving readability

This ensures all widget component tests follow the same patterns
established in WidgetInputText and WidgetSlider tests.
This commit is contained in:
Christian Byrne
2025-09-06 23:08:54 -07:00
committed by GitHub
parent 5c3b67bc6b
commit 0d3b15503f
4 changed files with 671 additions and 0 deletions

View File

@@ -0,0 +1,160 @@
import { mount } from '@vue/test-utils'
import PrimeVue from 'primevue/config'
import ToggleSwitch from 'primevue/toggleswitch'
import type { ToggleSwitchProps } from 'primevue/toggleswitch'
import { describe, expect, it } from 'vitest'
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
import WidgetToggleSwitch from './WidgetToggleSwitch.vue'
describe('WidgetToggleSwitch Value Binding', () => {
const createMockWidget = (
value: boolean = false,
options: Partial<ToggleSwitchProps> = {},
callback?: (value: boolean) => void
): SimplifiedWidget<boolean> => ({
name: 'test_toggle',
type: 'boolean',
value,
options,
callback
})
const mountComponent = (
widget: SimplifiedWidget<boolean>,
modelValue: boolean,
readonly = false
) => {
return mount(WidgetToggleSwitch, {
props: {
widget,
modelValue,
readonly
},
global: {
plugins: [PrimeVue],
components: { ToggleSwitch }
}
})
}
describe('Vue Event Emission', () => {
it('emits Vue event when toggled from false to true', async () => {
const widget = createMockWidget(false)
const wrapper = mountComponent(widget, false)
const toggle = wrapper.findComponent({ name: 'ToggleSwitch' })
await toggle.setValue(true)
const emitted = wrapper.emitted('update:modelValue')
expect(emitted).toBeDefined()
expect(emitted![0]).toContain(true)
})
it('emits Vue event when toggled from true to false', async () => {
const widget = createMockWidget(true)
const wrapper = mountComponent(widget, true)
const toggle = wrapper.findComponent({ name: 'ToggleSwitch' })
await toggle.setValue(false)
const emitted = wrapper.emitted('update:modelValue')
expect(emitted).toBeDefined()
expect(emitted![0]).toContain(false)
})
it('handles value changes gracefully', async () => {
const widget = createMockWidget(false)
const wrapper = mountComponent(widget, false)
// Should not throw when changing values
const toggle = wrapper.findComponent({ name: 'ToggleSwitch' })
await toggle.setValue(true)
await toggle.setValue(false)
// Should emit events for all changes
const emitted = wrapper.emitted('update:modelValue')
expect(emitted).toHaveLength(2)
expect(emitted![0]).toContain(true)
expect(emitted![1]).toContain(false)
})
})
describe('Component Rendering', () => {
it('renders toggle switch component', () => {
const widget = createMockWidget(false)
const wrapper = mountComponent(widget, false)
expect(wrapper.findComponent({ name: 'ToggleSwitch' }).exists()).toBe(
true
)
})
it('displays correct initial state for false', () => {
const widget = createMockWidget(false)
const wrapper = mountComponent(widget, false)
const toggle = wrapper.findComponent({ name: 'ToggleSwitch' })
expect(toggle.props('modelValue')).toBe(false)
})
it('displays correct initial state for true', () => {
const widget = createMockWidget(true)
const wrapper = mountComponent(widget, true)
const toggle = wrapper.findComponent({ name: 'ToggleSwitch' })
expect(toggle.props('modelValue')).toBe(true)
})
it('disables component in readonly mode', () => {
const widget = createMockWidget(false)
const wrapper = mountComponent(widget, false, true)
const toggle = wrapper.findComponent({ name: 'ToggleSwitch' })
expect(toggle.props('disabled')).toBe(true)
})
})
describe('Multiple Value Changes', () => {
it('handles rapid toggling correctly', async () => {
const widget = createMockWidget(false)
const wrapper = mountComponent(widget, false)
const toggle = wrapper.findComponent({ name: 'ToggleSwitch' })
// Rapid toggle sequence
await toggle.setValue(true)
await toggle.setValue(false)
await toggle.setValue(true)
// Should have emitted 3 Vue events with correct values
const emitted = wrapper.emitted('update:modelValue')
expect(emitted).toHaveLength(3)
expect(emitted![0]).toContain(true)
expect(emitted![1]).toContain(false)
expect(emitted![2]).toContain(true)
})
it('maintains state consistency during multiple changes', async () => {
const widget = createMockWidget(false)
const wrapper = mountComponent(widget, false)
const toggle = wrapper.findComponent({ name: 'ToggleSwitch' })
// Multiple state changes
await toggle.setValue(true)
await toggle.setValue(false)
await toggle.setValue(true)
await toggle.setValue(false)
const emitted = wrapper.emitted('update:modelValue')
expect(emitted).toHaveLength(4)
// Verify alternating pattern
expect(emitted![0]).toContain(true)
expect(emitted![1]).toContain(false)
expect(emitted![2]).toContain(true)
expect(emitted![3]).toContain(false)
})
})
})