From f4fdd00d68a78d0cb8b1b9eaff8d6b26ab4f6ac9 Mon Sep 17 00:00:00 2001 From: lukicenturi Date: Fri, 31 May 2024 16:28:23 +0700 Subject: [PATCH] feat(AutoComplete): allow AutoComplete to accept custom value --- example/cypress/e2e/forms/autocomplete.cy.ts | 2 +- example/src/views/AutoCompleteView.vue | 32 ++++ .../auto-complete/RuiAutoComplete.spec.ts | 45 ++++-- .../forms/auto-complete/RuiAutoComplete.vue | 143 +++++++++++++++--- src/components/overlays/menu/Menu.vue | 2 +- src/composables/dropdown-menu.ts | 16 +- 6 files changed, 205 insertions(+), 35 deletions(-) diff --git a/example/cypress/e2e/forms/autocomplete.cy.ts b/example/cypress/e2e/forms/autocomplete.cy.ts index a8bf4d2..b9c478a 100644 --- a/example/cypress/e2e/forms/autocomplete.cy.ts +++ b/example/cypress/e2e/forms/autocomplete.cy.ts @@ -17,6 +17,6 @@ describe('forms/Auto Completes', () => { cy.get('div[role=menu]').should('be.visible'); cy.get('div[role=menu] button:first-child').click(); - cy.get('@firstAutoComplete').find('div[class*=_value_]').should('contain.text', 'Germany'); + cy.get('@firstAutoComplete').find('input').should('have.value', 'Germany'); }); }); diff --git a/example/src/views/AutoCompleteView.vue b/example/src/views/AutoCompleteView.vue index 4d21835..fa90d8e 100644 --- a/example/src/views/AutoCompleteView.vue +++ b/example/src/views/AutoCompleteView.vue @@ -211,6 +211,38 @@ const autoCompletePrimitive = ref[]>([ label: 'Multiple', options: primitiveOptions, }, + { + value: undefined, + variant: 'outlined', + label: 'Custom Value', + customValue: true, + options: primitiveOptions, + }, + { + value: undefined, + dense: true, + variant: 'outlined', + label: 'Custom Value', + customValue: true, + options: primitiveOptions, + }, + { + value: [], + chips: true, + dense: true, + variant: 'outlined', + label: 'Multiple With Custom Value', + customValue: true, + options: primitiveOptions, + }, + { + value: ['Lorem'], + dense: true, + variant: 'outlined', + label: 'Multiple With Custom Value', + customValue: true, + options: primitiveOptions, + }, ]); function getDisplayText(options?: Options | Options[]): string { diff --git a/src/components/forms/auto-complete/RuiAutoComplete.spec.ts b/src/components/forms/auto-complete/RuiAutoComplete.spec.ts index c89ae59..7c19ab8 100644 --- a/src/components/forms/auto-complete/RuiAutoComplete.spec.ts +++ b/src/components/forms/auto-complete/RuiAutoComplete.spec.ts @@ -56,7 +56,7 @@ describe('autocomplete', () => { }, }); expect(wrapper.find('div[data-id=activator][tabindex=-1]').exists()).toBeTruthy(); - expect(wrapper.find('div[data-id=activator][tabindex=-1]').text()).toMatch('Spain'); + expect((wrapper.find('div[data-id=activator][tabindex=-1] input').element as HTMLInputElement).value).toMatch('Spain'); }); it('works with primitive options', () => { @@ -66,11 +66,12 @@ describe('autocomplete', () => { value: options[4].label, }, }); - expect(wrapper.find('div[data-id=activator]').text()).toMatch('Spain'); + expect((wrapper.find('div[data-id=activator] input').element as HTMLInputElement).value).toMatch('Spain'); }); it('value passed and emitted properly', async () => { const wrapper = createWrapper({ + attachTo: document.body, propsData: { autoSelectFirst: true, keyAttr: 'id', @@ -104,8 +105,6 @@ describe('autocomplete', () => { expect(document.body.querySelector('div[role=menu]')).toBeTruthy(); - await nextTick(); - highlightedItemButton = document.body.querySelector(`button:nth-child(${selectedIndex})`) as HTMLButtonElement; expect(highlightedItemButton.classList).toContain('highlighted'); @@ -162,15 +161,43 @@ describe('autocomplete', () => { chips = wrapper.find('div[data-id=activator]').findAll('.rui-chip'); expect(chips).toHaveLength(3); - expect(chips.at(0).text()).toBe('India'); - expect(chips.at(1).text()).toBe('France'); - expect(chips.at(2).text()).toBe('England'); + + expect(chips.at(0).text()).toBe('France'); + expect(chips.at(1).text()).toBe('England'); + expect(chips.at(2).text()).toBe('India'); // Delete England - await chips.at(2).find('button[type="button"]').trigger('click'); + await chips.at(0).find('button[type="button"]').trigger('click'); await nextTick(); - newValue = ['6', '7']; + newValue = ['8', '6']; expect(wrapper.emitted().input!.at(-1)![0]).toEqual(newValue); }); + + it('custom value', async () => { + const wrapper = createWrapper({ + propsData: { + autoSelectFirst: true, + chips: true, + customValue: true, + keyAttr: 'id', + options, + textAttr: 'label', + value: ['custom value'], + }, + }); + + expect(wrapper.find('div[data-id=activator]').exists()).toBeTruthy(); + const chips = wrapper.find('div[data-id=activator]').findAll('.rui-chip'); + expect(chips).toHaveLength(1); + expect(chips.at(0).text()).toBe('custom value'); + + await wrapper.find('input').setValue('custom value 2'); + await wrapper.find('[data-id=activator]').trigger('keydown.enter'); + + expect(wrapper.emitted().input!.at(-1)![0]).toEqual([ + 'custom value', + 'custom value 2', + ]); + }); }); diff --git a/src/components/forms/auto-complete/RuiAutoComplete.vue b/src/components/forms/auto-complete/RuiAutoComplete.vue index 4447d93..c0ebe95 100644 --- a/src/components/forms/auto-complete/RuiAutoComplete.vue +++ b/src/components/forms/auto-complete/RuiAutoComplete.vue @@ -1,5 +1,6 @@