From f5c0c8f1c56758fce38dac63aa56d98d746d66ae Mon Sep 17 00:00:00 2001 From: Azeemuddin Aziz Date: Mon, 15 Dec 2025 13:36:25 +0530 Subject: [PATCH 1/8] feat: restrict user to enter space in signup component input field --- app/components/new-signup/input.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/components/new-signup/input.js b/app/components/new-signup/input.js index abe24686..78343754 100644 --- a/app/components/new-signup/input.js +++ b/app/components/new-signup/input.js @@ -11,6 +11,12 @@ export default class SignupComponent extends Component { @action inputFieldChanged({ target: { value } }) { const { onChange, currentStep } = this.args; - onChange(currentStep, value); + + const sanitizedInput = value.replace(/\s/g, ''); + if (value !== sanitizedInput) { + event.target.value = sanitizedInput; + } + + onChange(currentStep, sanitizedInput); } } From f5934d056248932611bc38597dbc0ea3954498fb Mon Sep 17 00:00:00 2001 From: Azeemuddin Aziz Date: Mon, 15 Dec 2025 13:59:22 +0530 Subject: [PATCH 2/8] fix: incorrect reference to event object in Signup Comonent --- app/components/new-signup/input.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/components/new-signup/input.js b/app/components/new-signup/input.js index 78343754..e8afbe17 100644 --- a/app/components/new-signup/input.js +++ b/app/components/new-signup/input.js @@ -1,5 +1,5 @@ -import Component from '@glimmer/component'; import { action } from '@ember/object'; +import Component from '@glimmer/component'; import { LABEL_TEXT } from '../../constants/new-signup'; export default class SignupComponent extends Component { @@ -9,11 +9,14 @@ export default class SignupComponent extends Component { return LABEL_TEXT[currentStep]; } - @action inputFieldChanged({ target: { value } }) { + @action inputFieldChanged(event) { const { onChange, currentStep } = this.args; - const sanitizedInput = value.replace(/\s/g, ''); - if (value !== sanitizedInput) { + const inputValue = event.target.value; + + const sanitizedInput = inputValue.replace(/\s/g, ''); + + if (inputValue !== sanitizedInput) { event.target.value = sanitizedInput; } From 8745e4c2570b50fba75f9a7860155ab794fc4551 Mon Sep 17 00:00:00 2001 From: Azeemuddin Aziz Date: Wed, 17 Dec 2025 09:40:40 +0530 Subject: [PATCH 3/8] feat: add test for input field removes spaces as user types --- .../components/new-signup/input-test.js | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/tests/integration/components/new-signup/input-test.js b/tests/integration/components/new-signup/input-test.js index e993372b..ff37854f 100644 --- a/tests/integration/components/new-signup/input-test.js +++ b/tests/integration/components/new-signup/input-test.js @@ -1,6 +1,6 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'website-www/tests/helpers'; -import { render } from '@ember/test-helpers'; +import { render, triggerEvent } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; import { NEW_SIGNUP_STEPS } from 'website-www/constants/new-signup'; @@ -136,4 +136,34 @@ module('Integration | Component | new-signup/input', function (hooks) { assert.dom('[data-test-button="signup"]').isDisabled(); }); + + test('input field should remove spaces as user types', async function (assert) { + assert.expect(1); + + this.setProperties({ + currentStep: 'firstname', + onChange: (step, value) => { + this.inputValue = value; + }, + onClick: () => {}, + }); + + await render(hbs` + + `); + + const input = this.element.querySelector('[data-test-signup-form-input]'); + input.value = 'John Doe'; + await triggerEvent(input, 'input'); + + assert.strictEqual( + this.inputValue, + 'JohnDoe', + 'Spaces should be removed from input', + ); + }); }); From 44e56a39ee90c839e7418e8c798a0de58723c16a Mon Sep 17 00:00:00 2001 From: Azeemuddin Aziz Date: Fri, 19 Dec 2025 14:07:59 +0530 Subject: [PATCH 4/8] fix: prevent spaces in input field using keydown event - Sanitize input only when it contains a space. --- app/components/new-signup/input.hbs | 1 + app/components/new-signup/input.js | 21 ++++++++---- .../components/new-signup/input-test.js | 34 +++++++++++++++++-- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/app/components/new-signup/input.hbs b/app/components/new-signup/input.hbs index 5e5e4e56..eff2476a 100644 --- a/app/components/new-signup/input.hbs +++ b/app/components/new-signup/input.hbs @@ -13,6 +13,7 @@ placeholder="Darth" aria-labelledby="signup-form-label" {{on "input" this.inputFieldChanged}} + {{on "keydown" this.handleKeydown}} data-test-signup-form-input /> {{#if @error}} diff --git a/app/components/new-signup/input.js b/app/components/new-signup/input.js index e8afbe17..d1a27eea 100644 --- a/app/components/new-signup/input.js +++ b/app/components/new-signup/input.js @@ -1,5 +1,5 @@ -import { action } from '@ember/object'; import Component from '@glimmer/component'; +import { action } from '@ember/object'; import { LABEL_TEXT } from '../../constants/new-signup'; export default class SignupComponent extends Component { @@ -12,14 +12,23 @@ export default class SignupComponent extends Component { @action inputFieldChanged(event) { const { onChange, currentStep } = this.args; - const inputValue = event.target.value; + const rawValue = event.target.value; - const sanitizedInput = inputValue.replace(/\s/g, ''); + if (rawValue.includes(' ')) { + const sanitizedInput = rawValue.replace(/\s/g, ''); + onChange(currentStep, sanitizedInput); - if (inputValue !== sanitizedInput) { - event.target.value = sanitizedInput; + if (rawValue !== sanitizedInput) { + event.target.value = sanitizedInput; + } + } else { + onChange(currentStep, rawValue); } + } - onChange(currentStep, sanitizedInput); + @action handleKeydown(event) { + if (event.key === ' ' || event.code === 'Space') { + event.preventDefault(); + } } } diff --git a/tests/integration/components/new-signup/input-test.js b/tests/integration/components/new-signup/input-test.js index ff37854f..e5553985 100644 --- a/tests/integration/components/new-signup/input-test.js +++ b/tests/integration/components/new-signup/input-test.js @@ -1,6 +1,6 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'website-www/tests/helpers'; -import { render, triggerEvent } from '@ember/test-helpers'; +import { render, triggerEvent, typeIn } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; import { NEW_SIGNUP_STEPS } from 'website-www/constants/new-signup'; @@ -137,11 +137,11 @@ module('Integration | Component | new-signup/input', function (hooks) { assert.dom('[data-test-button="signup"]').isDisabled(); }); - test('input field should remove spaces as user types', async function (assert) { + test('input field should remove spaces if user pastes text', async function (assert) { assert.expect(1); this.setProperties({ - currentStep: 'firstname', + currentStep: 'firstName', onChange: (step, value) => { this.inputValue = value; }, @@ -166,4 +166,32 @@ module('Integration | Component | new-signup/input', function (hooks) { 'Spaces should be removed from input', ); }); + + test('input field should not accept spaces', async function (assert) { + assert.expect(1); + + this.setProperties({ + currentStep: 'firstName', + onChange: (step, value) => { + this.inputValue = value; + }, + onClick: () => {}, + }); + + await render(hbs` + + `); + + const input = this.element.querySelector('[data-test-signup-form-input]'); + + await typeIn(input, 'John Doe'); + + assert + .dom(input) + .hasValue('JohnDoe', 'Keydown prevention blocked the space'); + }); }); From 2fc4a326a367b6c7e38653aac6766be63d425e0e Mon Sep 17 00:00:00 2001 From: Azeemuddin Aziz Date: Fri, 19 Dec 2025 17:09:47 +0530 Subject: [PATCH 5/8] fix: prevent all whitespaces in input and sanitize for all whitespaces incase of copy-paste text --- app/components/new-signup/input.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app/components/new-signup/input.js b/app/components/new-signup/input.js index d1a27eea..a21b71df 100644 --- a/app/components/new-signup/input.js +++ b/app/components/new-signup/input.js @@ -14,20 +14,21 @@ export default class SignupComponent extends Component { const rawValue = event.target.value; - if (rawValue.includes(' ')) { + if (/\s/.test(rawValue)) { + const cursorPosition = event.target.selectionStart; const sanitizedInput = rawValue.replace(/\s/g, ''); - onChange(currentStep, sanitizedInput); - if (rawValue !== sanitizedInput) { - event.target.value = sanitizedInput; - } + event.target.value = sanitizedInput; + event.target.setSelectionRange(cursorPosition - 1, cursorPosition - 1); + + onChange(currentStep, sanitizedInput); } else { onChange(currentStep, rawValue); } } @action handleKeydown(event) { - if (event.key === ' ' || event.code === 'Space') { + if (/\s/.test(event.key)) { event.preventDefault(); } } From afd490842212e10caea06dfa509c591f4ef27e72 Mon Sep 17 00:00:00 2001 From: Azeemuddin Aziz Date: Fri, 19 Dec 2025 17:10:56 +0530 Subject: [PATCH 6/8] test: add missing test cases from whitespace handling - Group all whitespace related test under one module. --- .../components/new-signup/input-test.js | 209 ++++++++++++++---- 1 file changed, 165 insertions(+), 44 deletions(-) diff --git a/tests/integration/components/new-signup/input-test.js b/tests/integration/components/new-signup/input-test.js index e5553985..d9212b88 100644 --- a/tests/integration/components/new-signup/input-test.js +++ b/tests/integration/components/new-signup/input-test.js @@ -137,61 +137,182 @@ module('Integration | Component | new-signup/input', function (hooks) { assert.dom('[data-test-button="signup"]').isDisabled(); }); - test('input field should remove spaces if user pastes text', async function (assert) { - assert.expect(1); + module('whitespace handling', function (hooks) { + hooks.beforeEach(function () { + this.setProperties({ + currentStep: 'firstName', + onChange: (step, value) => { + this.inputValue = value; + }, + onClick: () => {}, + }); + }); - this.setProperties({ - currentStep: 'firstName', - onChange: (step, value) => { - this.inputValue = value; - }, - onClick: () => {}, + test('should prevent single space when typing', async function (assert) { + await render(hbs` + + `); + + const input = this.element.querySelector('[data-test-signup-form-input]'); + + await typeIn(input, 'John Doe'); + + assert + .dom(input) + .hasValue('JohnDoe', 'Single space should be prevented when typing'); }); - await render(hbs` - - `); + test('should remove multiple consecutive spaces when typing', async function (assert) { + await render(hbs` + + `); - const input = this.element.querySelector('[data-test-signup-form-input]'); - input.value = 'John Doe'; - await triggerEvent(input, 'input'); + const input = this.element.querySelector('[data-test-signup-form-input]'); - assert.strictEqual( - this.inputValue, - 'JohnDoe', - 'Spaces should be removed from input', - ); - }); + await typeIn(input, 'John Doe'); - test('input field should not accept spaces', async function (assert) { - assert.expect(1); + assert + .dom(input) + .hasValue('JohnDoe', 'Multiple consecutive spaces should be removed'); + }); - this.setProperties({ - currentStep: 'firstName', - onChange: (step, value) => { - this.inputValue = value; - }, - onClick: () => {}, + test('should remove single space when pasting', async function (assert) { + await render(hbs` + + `); + + const input = this.element.querySelector('[data-test-signup-form-input]'); + input.value = 'John Doe'; + await triggerEvent(input, 'input'); + + assert.strictEqual( + this.inputValue, + 'JohnDoe', + 'Single space should be removed when pasting', + ); + assert.dom(input).hasValue('JohnDoe'); }); - await render(hbs` - - `); + test('should remove leading and trailing spaces when pasting', async function (assert) { + await render(hbs` + + `); + + const input = this.element.querySelector('[data-test-signup-form-input]'); + input.value = ' John Doe '; + await triggerEvent(input, 'input'); + + assert.strictEqual( + this.inputValue, + 'JohnDoe', + 'Leading and trailing spaces should be removed', + ); + assert.dom(input).hasValue('JohnDoe'); + }); - const input = this.element.querySelector('[data-test-signup-form-input]'); + test('should handle input with only spaces', async function (assert) { + await render(hbs` + + `); + + const input = this.element.querySelector('[data-test-signup-form-input]'); + input.value = ' '; + await triggerEvent(input, 'input'); + + assert.strictEqual( + this.inputValue, + '', + 'Input with only spaces should result in empty string', + ); + assert.dom(input).hasValue(''); + }); - await typeIn(input, 'John Doe'); + test('should remove mixed whitespace characters when pasting', async function (assert) { + await render(hbs` + + `); + + const input = this.element.querySelector('[data-test-signup-form-input]'); + input.value = 'John\t\nDoe'; + await triggerEvent(input, 'input'); + + assert.strictEqual( + this.inputValue, + 'JohnDoe', + 'Tabs and newlines should be removed', + ); + assert.dom(input).hasValue('JohnDoe'); + }); - assert - .dom(input) - .hasValue('JohnDoe', 'Keydown prevention blocked the space'); + test('should accept text without whitespace', async function (assert) { + await render(hbs` + + `); + + const input = this.element.querySelector('[data-test-signup-form-input]'); + + await typeIn(input, 'JohnDoe'); + + assert.strictEqual( + this.inputValue, + 'JohnDoe', + 'Text without whitespace should be accepted as-is', + ); + assert.dom(input).hasValue('JohnDoe'); + }); + + test('should handle combination of typing and pasting with whitespace', async function (assert) { + await render(hbs` + + `); + + const input = this.element.querySelector('[data-test-signup-form-input]'); + + // First type some text + await typeIn(input, 'John '); + + // Then paste text with spaces + input.value = input.value + ' Doe Smith'; + await triggerEvent(input, 'input'); + + assert.strictEqual( + this.inputValue, + 'JohnDoeSmith', + 'Combination of typing and pasting should remove all spaces', + ); + assert.dom(input).hasValue('JohnDoeSmith'); + }); }); }); From 218123ee644304188d06bc8a227967d40c6e7b47 Mon Sep 17 00:00:00 2001 From: Azeemuddin Aziz Date: Sun, 21 Dec 2025 01:58:03 +0530 Subject: [PATCH 7/8] fix: cursor position logic to handle cases with multiple spaces and multiple positions --- app/components/new-signup/input.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/app/components/new-signup/input.js b/app/components/new-signup/input.js index a21b71df..1a246e43 100644 --- a/app/components/new-signup/input.js +++ b/app/components/new-signup/input.js @@ -18,8 +18,18 @@ export default class SignupComponent extends Component { const cursorPosition = event.target.selectionStart; const sanitizedInput = rawValue.replace(/\s/g, ''); + const textBeforeCursor = rawValue.substring(0, cursorPosition); + const nonWhitespaceBeforeCursor = textBeforeCursor.replace( + /\s/g, + '', + ).length; + const newCursorPosition = Math.min( + nonWhitespaceBeforeCursor, + sanitizedInput.length, + ); + event.target.value = sanitizedInput; - event.target.setSelectionRange(cursorPosition - 1, cursorPosition - 1); + event.target.setSelectionRange(newCursorPosition, newCursorPosition); onChange(currentStep, sanitizedInput); } else { From b1615b11dbc86f6832c7dc573b5739d7d81cb916 Mon Sep 17 00:00:00 2001 From: Azeemuddin Aziz Date: Thu, 25 Dec 2025 18:47:49 +0530 Subject: [PATCH 8/8] fix: cursor calculation logic based on whitespaces proposed by Tejas --- app/components/new-signup/input.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/app/components/new-signup/input.js b/app/components/new-signup/input.js index 1a246e43..4e4210a5 100644 --- a/app/components/new-signup/input.js +++ b/app/components/new-signup/input.js @@ -19,14 +19,8 @@ export default class SignupComponent extends Component { const sanitizedInput = rawValue.replace(/\s/g, ''); const textBeforeCursor = rawValue.substring(0, cursorPosition); - const nonWhitespaceBeforeCursor = textBeforeCursor.replace( - /\s/g, - '', - ).length; - const newCursorPosition = Math.min( - nonWhitespaceBeforeCursor, - sanitizedInput.length, - ); + const spacesBeforeCursor = (textBeforeCursor.match(/\s/g) || []).length; + const newCursorPosition = cursorPosition - spacesBeforeCursor; event.target.value = sanitizedInput; event.target.setSelectionRange(newCursorPosition, newCursorPosition);