Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { mount } from '@vue/test-utils'
import { nextTick } from 'vue'
import PrimeVue from 'primevue/config'
import { describe, expect, it } from 'vitest'

import SelectPlus from '@/components/primevueOverride/SelectPlus.vue'
import type { SimplifiedWidget } from '@/types/simplifiedWidget'

import WidgetSelectDefault from './WidgetSelectDefault.vue'

describe('WidgetSelectDefault', () => {
const createWidget = (
values: unknown
): SimplifiedWidget<string | undefined> => ({
name: 'test_combo',
type: 'combo',
value: undefined,
options: { values } as SimplifiedWidget['options']
})

const mountComponent = (widget: SimplifiedWidget<string | undefined>) =>
mount(WidgetSelectDefault, {
props: { widget },
global: {
plugins: [PrimeVue],
components: { SelectPlus }
}
})

describe('array-valued options', () => {
it('resolves options from a plain array', () => {
const widget = createWidget(['a', 'b', 'c'])
const wrapper = mountComponent(widget)

expect(wrapper.findComponent(SelectPlus).props('options')).toEqual([
'a',
'b',
'c'
])
})

it('reactively updates when widget prop changes', async () => {
const widget = createWidget(['x', 'y'])
const wrapper = mountComponent(widget)

await wrapper.setProps({ widget: createWidget(['x', 'y', 'z']) })

expect(wrapper.findComponent(SelectPlus).props('options')).toEqual([
'x',
'y',
'z'
])
})
})

describe('undefined/empty options', () => {
it('returns empty array when values is undefined', () => {
const widget = createWidget(undefined)
const wrapper = mountComponent(widget)

expect(wrapper.findComponent(SelectPlus).props('options')).toEqual([])
})
})

describe('function-valued options', () => {
it('resolves options from a function', () => {
const widget = createWidget(() => ['a', 'b', 'c'])
const wrapper = mountComponent(widget)

expect(wrapper.findComponent(SelectPlus).props('options')).toEqual([
'a',
'b',
'c'
])
})

it('re-evaluates function on show event', async () => {
let items = ['x', 'y']
const widget = createWidget(() => items)
const wrapper = mountComponent(widget)

items = ['x', 'y', 'z']
wrapper.findComponent(SelectPlus).vm.$emit('show')
await nextTick()

expect(wrapper.findComponent(SelectPlus).props('options')).toEqual([
'x',
'y',
'z'
])
})

it('re-evaluates function on filter event', async () => {
let items = ['a']
const widget = createWidget(() => items)
const wrapper = mountComponent(widget)

items = ['a', 'b']
wrapper.findComponent(SelectPlus).vm.$emit('filter')
await nextTick()

expect(wrapper.findComponent(SelectPlus).props('options')).toEqual([
'a',
'b'
])
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
overlay: 'w-fit min-w-full'
}"
data-capture-wheel="true"
@show="refreshOptions"
@filter="refreshOptions"
>
<template #dropdownicon>
<i
Expand All @@ -31,7 +33,7 @@
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { computed, ref } from 'vue'

import SelectPlus from '@/components/primevueOverride/SelectPlus.vue'
import { useTransformCompatOverlayProps } from '@/composables/useTransformCompatOverlayProps'
Expand All @@ -51,25 +53,30 @@ interface Props {

const props = defineProps<Props>()

function resolveValues(values: unknown): string[] {
if (typeof values === 'function') return values()
if (Array.isArray(values)) return values
return []
}

const modelValue = defineModel<string | undefined>({
default(props: Props) {
const values = props.widget.options?.values
return (Array.isArray(values) ? values[0] : undefined) ?? ''
const resolved = typeof values === 'function' ? values() : values
return Array.isArray(resolved) ? (resolved[0] ?? '') : ''
}
})

// Transform compatibility props for overlay positioning
const transformCompatProps = useTransformCompatOverlayProps()

// Extract select options from widget options
const refreshTrigger = ref(0)
function refreshOptions() {
refreshTrigger.value++
}
const selectOptions = computed(() => {
const options = props.widget.options

if (options?.values && Array.isArray(options.values)) {
return options.values
}

return []
void refreshTrigger.value
return resolveValues(props.widget.options?.values)
})
const invalid = computed(
() => !!modelValue.value && !selectOptions.value.includes(modelValue.value)
Expand Down
Loading