mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-07 18:07:47 +08:00
feat(models): add external catalog proxy selection
This commit is contained in:
@@ -2,10 +2,13 @@
|
||||
<div class="space-y-1.5">
|
||||
<Select
|
||||
:model-value="modelValue"
|
||||
:disabled="proxyNodesStore.loading || nodeOptions.length === 0"
|
||||
:disabled="disabled || proxyNodesStore.loading || nodeOptions.length === 0"
|
||||
@update:model-value="(v: string) => $emit('update:modelValue', v)"
|
||||
>
|
||||
<SelectTrigger :class="triggerClass">
|
||||
<SelectTrigger
|
||||
:class="triggerClass"
|
||||
:aria-label="triggerAriaLabel"
|
||||
>
|
||||
<SelectValue
|
||||
:placeholder="proxyNodesStore.loading
|
||||
? legacyT('加载节点列表中...')
|
||||
@@ -40,10 +43,16 @@ import { useProxyNodesStore } from '@/stores/proxy-nodes'
|
||||
import { useI18n } from '@/i18n'
|
||||
import { formatRegion } from '@/utils/region'
|
||||
|
||||
const props = defineProps<{
|
||||
const props = withDefaults(defineProps<{
|
||||
modelValue: string
|
||||
triggerClass?: string
|
||||
}>()
|
||||
triggerAriaLabel?: string
|
||||
disabled?: boolean
|
||||
}>(), {
|
||||
triggerClass: '',
|
||||
triggerAriaLabel: undefined,
|
||||
disabled: false,
|
||||
})
|
||||
|
||||
defineEmits<{
|
||||
'update:modelValue': [value: string]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { createApp, defineComponent, h } from 'vue'
|
||||
|
||||
import ProxyNodeSelect from '@/features/providers/components/ProxyNodeSelect.vue'
|
||||
@@ -19,34 +19,81 @@ vi.mock('@/components/ui', async () => {
|
||||
const { defineComponent, h } = await import('vue')
|
||||
const passthrough = (name: string) => defineComponent({
|
||||
name,
|
||||
setup(_, { slots }) {
|
||||
return () => h('div', slots.default?.())
|
||||
inheritAttrs: false,
|
||||
setup(_, { attrs, slots }) {
|
||||
return () => h('div', attrs, slots.default?.())
|
||||
},
|
||||
})
|
||||
|
||||
return {
|
||||
Select: passthrough('SelectStub'),
|
||||
Select: defineComponent({
|
||||
name: 'SelectStub',
|
||||
props: {
|
||||
disabled: { type: Boolean, default: false },
|
||||
},
|
||||
setup(props, { slots }) {
|
||||
return () => h('div', {
|
||||
'data-testid': 'proxy-select',
|
||||
'data-disabled': String(props.disabled),
|
||||
}, slots.default?.())
|
||||
},
|
||||
}),
|
||||
SelectTrigger: passthrough('SelectTriggerStub'),
|
||||
SelectValue: passthrough('SelectValueStub'),
|
||||
SelectContent: passthrough('SelectContentStub'),
|
||||
SelectItem: passthrough('SelectItemStub'),
|
||||
SelectItem: defineComponent({
|
||||
name: 'SelectItemStub',
|
||||
props: {
|
||||
value: { type: String, required: true },
|
||||
},
|
||||
setup(props, { slots }) {
|
||||
return () => h('div', { 'data-select-value': props.value }, slots.default?.())
|
||||
},
|
||||
}),
|
||||
}
|
||||
})
|
||||
|
||||
function mountSelect(props: Record<string, unknown> = {}) {
|
||||
const root = document.createElement('div')
|
||||
const app = createApp(defineComponent({
|
||||
setup() {
|
||||
return () => h(ProxyNodeSelect, { modelValue: '', ...props })
|
||||
},
|
||||
}))
|
||||
app.use(createI18n())
|
||||
app.mount(root)
|
||||
return { app, root }
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
proxyNodesStore.ensureLoaded.mockClear()
|
||||
})
|
||||
|
||||
describe('ProxyNodeSelect', () => {
|
||||
it('loads proxy nodes when mounted', () => {
|
||||
const root = document.createElement('div')
|
||||
const app = createApp(defineComponent({
|
||||
setup() {
|
||||
return () => h(ProxyNodeSelect, { modelValue: '' })
|
||||
},
|
||||
}))
|
||||
|
||||
app.use(createI18n())
|
||||
app.mount(root)
|
||||
const { app } = mountSelect()
|
||||
|
||||
expect(proxyNodesStore.ensureLoaded).toHaveBeenCalledTimes(1)
|
||||
|
||||
app.unmount()
|
||||
})
|
||||
})
|
||||
|
||||
it('stays disabled when there are no proxy nodes', () => {
|
||||
const { app, root } = mountSelect()
|
||||
|
||||
expect(root.querySelector('[data-testid="proxy-select"]')
|
||||
?.getAttribute('data-disabled')).toBe('true')
|
||||
|
||||
app.unmount()
|
||||
})
|
||||
|
||||
it('applies an accessible label to the select trigger', () => {
|
||||
const { app, root } = mountSelect({
|
||||
triggerAriaLabel: 'External model catalog access',
|
||||
})
|
||||
|
||||
expect(root.querySelector('[aria-label="External model catalog access"]')).not.toBeNull()
|
||||
|
||||
app.unmount()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user