From 2600736695e8f2ff212a0e9fbaf253882669914c Mon Sep 17 00:00:00 2001 From: Cristian Tcaci <59696583+Chris0Jeky@users.noreply.github.com> Date: Thu, 17 Sep 2026 14:52:40 +0100 Subject: [PATCH 1/2] fix(frontend): resolve late input-assist exact matches --- .../src/components/common/InputAssistField.vue | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/frontend/taskdeck-web/src/components/common/InputAssistField.vue b/frontend/taskdeck-web/src/components/common/InputAssistField.vue index 00bedd5074..923f3674a5 100644 --- a/frontend/taskdeck-web/src/components/common/InputAssistField.vue +++ b/frontend/taskdeck-web/src/components/common/InputAssistField.vue @@ -37,7 +37,7 @@ const activeDescendant = computed(() => { return `${componentId}-option-${activeIndex.value}` }) -watch(filteredOptions, (options) => { +watch(filteredOptions, (options, previousOptions) => { if (options.length === 0) { activeIndex.value = 0 return @@ -46,6 +46,16 @@ watch(filteredOptions, (options) => { if (activeIndex.value >= options.length) { activeIndex.value = 0 } + + if (!panelOpen.value) { + return + } + + const exactMatch = findExactMatch(props.modelValue) + const previousExactMatch = findExactMatch(props.modelValue, previousOptions) + if (exactMatch && !previousExactMatch) { + selectOption(exactMatch) + } }) function openPanel() { @@ -65,18 +75,18 @@ function setModelValue(value: string) { emit('update:modelValue', value) } -function findExactMatch(value: string): InputAssistOption | null { +function findExactMatch(value: string, options: InputAssistOption[] = props.options): InputAssistOption | null { const normalizedInput = value.trim().toLowerCase() if (!normalizedInput) { return null } - const byValue = props.options.find((option) => option.value.trim().toLowerCase() === normalizedInput) + const byValue = options.find((option) => option.value.trim().toLowerCase() === normalizedInput) if (byValue) { return byValue } - return props.options.find((option) => { + return options.find((option) => { return option.label.trim().toLowerCase() === normalizedInput }) ?? null From e83166bec4c04afa41335c1cacbc96a7a4483fbc Mon Sep 17 00:00:00 2001 From: Cristian Tcaci <59696583+Chris0Jeky@users.noreply.github.com> Date: Thu, 17 Sep 2026 14:53:21 +0100 Subject: [PATCH 2/2] test(frontend): cover late-loaded input-assist options --- .../tests/components/InputAssistField.spec.ts | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/frontend/taskdeck-web/src/tests/components/InputAssistField.spec.ts b/frontend/taskdeck-web/src/tests/components/InputAssistField.spec.ts index 7a219c892a..35d1f06e2f 100644 --- a/frontend/taskdeck-web/src/tests/components/InputAssistField.spec.ts +++ b/frontend/taskdeck-web/src/tests/components/InputAssistField.spec.ts @@ -113,4 +113,26 @@ describe('InputAssistField', () => { expect(wrapper.emitted('update:modelValue')?.at(-1)).toEqual(['health.check']) expect(wrapper.emitted('select')?.at(-1)?.[0]).toMatchObject({ value: 'health.check', label: 'Health Check' }) }) + + it('selects an exact value when matching options arrive after input', async () => { + const wrapper = mount(InputAssistField, { + props: { + modelValue: '', + options: [], + }, + }) + + const input = wrapper.get('input') + await input.trigger('focus') + await input.setValue('health.check') + + expect(wrapper.find('[role="listbox"]').exists()).toBe(true) + expect(wrapper.findAll('[role="option"]')).toHaveLength(0) + + await wrapper.setProps({ options }) + + expect(wrapper.find('[role="listbox"]').exists()).toBe(false) + expect(wrapper.emitted('update:modelValue')?.at(-1)).toEqual(['health.check']) + expect(wrapper.emitted('select')?.at(-1)?.[0]).toMatchObject({ value: 'health.check', label: 'Health Check' }) + }) })