From 845ebc58b3abb9f935270d850427a5ad53432c08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Tue, 30 Jun 2026 13:28:33 +0200 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=94=A8=20Eliminate=20ternary=20state?= =?UTF-8?q?=20and=20make=20passwordIsVisible=20a=20real=20bool?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/TextInput.vue | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/components/TextInput.vue b/src/components/TextInput.vue index dd0db98..4758707 100644 --- a/src/components/TextInput.vue +++ b/src/components/TextInput.vue @@ -105,16 +105,12 @@ const isPasswordField = props.type === 'password'; // The current inputType, this will swap between text and password. const inputType = ref(props.type); // false: hide password, true: show password -const passwordIsVisible = ref(isPasswordField ? false : null); +const passwordIsVisible = ref(false); const togglePasswordVisibility = () => { inputType.value = passwordIsVisible.value ? 'password' : 'text'; passwordIsVisible.value = !passwordIsVisible.value; - if (passwordIsVisible.value === true) { - passwordIndicatorText.value = hidePasswordText; - } else if (passwordIsVisible.value === false) { - passwordIndicatorText.value = showPasswordText; - } + passwordIndicatorText.value = passwordIsVisible.value ? hidePasswordText : showPasswordText }; @@ -154,10 +150,10 @@ const togglePasswordVisibility = () => { :title="passwordIndicatorText" @keyup.space="togglePasswordVisibility" @click="togglePasswordVisibility" - v-if="passwordIsVisible !== null" + v-if="isPasswordField" > - - + + Date: Tue, 30 Jun 2026 13:29:03 +0200 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=94=A8=20Prevent=20text=20selection?= =?UTF-8?q?=20on=20password=20visibility=20toggle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/TextInput.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/TextInput.vue b/src/components/TextInput.vue index 4758707..32ef85d 100644 --- a/src/components/TextInput.vue +++ b/src/components/TextInput.vue @@ -149,7 +149,7 @@ const togglePasswordVisibility = () => { tabindex="0" :title="passwordIndicatorText" @keyup.space="togglePasswordVisibility" - @click="togglePasswordVisibility" + @click.prevent="togglePasswordVisibility" v-if="isPasswordField" > From 90d935f2b93208ed6658a7af2c16232c9b2f899e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Tue, 30 Jun 2026 13:52:15 +0200 Subject: [PATCH 3/4] =?UTF-8?q?=E2=9E=95=20Add=20test=20for=20password=20i?= =?UTF-8?q?nputs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/components/TextInput.test.js | 36 +++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/components/TextInput.test.js b/test/components/TextInput.test.js index 9823845..4eb43e2 100644 --- a/test/components/TextInput.test.js +++ b/test/components/TextInput.test.js @@ -1,5 +1,6 @@ import { describe, it, expect, afterEach } from 'vitest'; import { mount } from '@vue/test-utils'; +import { t } from '@/composable/i18n'; import TextInput from '@/components/TextInput.vue'; @@ -346,6 +347,41 @@ describe('TextInput', () => { expect(wrapper.emitted()['blur'][0][0].target.value).toBe(inputText); }); + it('renders password inputs and toggles visibility', async () => { + const ourProps = { + name: 'password-input-test', + label: 'The Password input label', + help: null, + error: null, + prefix: null, + outerPrefix: null, + smallText: false, + smallInput: false, + maxLength: null, + modelValue: null, + dataTestid: 'password-input-test', + type: 'password', + }; + + wrapper = mount(TextInput, { + propsData: ourProps, + }); + + const textInputSel = `[data-testid=${ourProps['dataTestid']}]`; + const textInput = wrapper.find(textInputSel); + expect(textInput.exists()).toBe(true); + expect(textInput.attributes().type).toBe('password'); + + const passwordToggle = wrapper.find('span.tbpro-input-suffix'); + expect(passwordToggle.exists()).toBe(true); + expect(passwordToggle.isVisible()).toBe(true); + expect(passwordToggle.attributes().title).toBe(t('textInput.passwordIndicator.show')); + + await passwordToggle.trigger('click'); + expect(textInput.attributes().type).toBe('text'); + expect(passwordToggle.attributes().title).toBe(t('textInput.passwordIndicator.hide')); + }); + it('able to reset the text input using exposed reset method', async () => { const ourProps = { name: 'text-input-test', From b1f0c40a2d9bb53d3ed425e2a281ef06ffcdc300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Tue, 30 Jun 2026 13:53:36 +0200 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=94=A8=20Improve=20test=20labels?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/components/TextInput.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/components/TextInput.test.js b/test/components/TextInput.test.js index 4eb43e2..4a1bf53 100644 --- a/test/components/TextInput.test.js +++ b/test/components/TextInput.test.js @@ -304,7 +304,7 @@ describe('TextInput', () => { } }); - it('able to enter text', async () => { + it('renders text inputs', async () => { const ourProps = { name: 'text-input-test', label: 'This is the TextInput label!', @@ -382,7 +382,7 @@ describe('TextInput', () => { expect(passwordToggle.attributes().title).toBe(t('textInput.passwordIndicator.hide')); }); - it('able to reset the text input using exposed reset method', async () => { + it('resets the text input using exposed reset method', async () => { const ourProps = { name: 'text-input-test', label: 'This is the TextInput label!',