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 abe24686..4e4210a5 100644
--- a/app/components/new-signup/input.js
+++ b/app/components/new-signup/input.js
@@ -9,8 +9,31 @@ export default class SignupComponent extends Component {
return LABEL_TEXT[currentStep];
}
- @action inputFieldChanged({ target: { value } }) {
+ @action inputFieldChanged(event) {
const { onChange, currentStep } = this.args;
- onChange(currentStep, value);
+
+ const rawValue = event.target.value;
+
+ if (/\s/.test(rawValue)) {
+ const cursorPosition = event.target.selectionStart;
+ const sanitizedInput = rawValue.replace(/\s/g, '');
+
+ const textBeforeCursor = rawValue.substring(0, cursorPosition);
+ const spacesBeforeCursor = (textBeforeCursor.match(/\s/g) || []).length;
+ const newCursorPosition = cursorPosition - spacesBeforeCursor;
+
+ event.target.value = sanitizedInput;
+ event.target.setSelectionRange(newCursorPosition, newCursorPosition);
+
+ onChange(currentStep, sanitizedInput);
+ } else {
+ onChange(currentStep, rawValue);
+ }
+ }
+
+ @action handleKeydown(event) {
+ if (/\s/.test(event.key)) {
+ event.preventDefault();
+ }
}
}
diff --git a/tests/integration/components/new-signup/input-test.js b/tests/integration/components/new-signup/input-test.js
index e993372b..d9212b88 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, typeIn } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
import { NEW_SIGNUP_STEPS } from 'website-www/constants/new-signup';
@@ -136,4 +136,183 @@ module('Integration | Component | new-signup/input', function (hooks) {
assert.dom('[data-test-button="signup"]').isDisabled();
});
+
+ module('whitespace handling', function (hooks) {
+ hooks.beforeEach(function () {
+ 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');
+ });
+
+ test('should remove multiple consecutive spaces 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', 'Multiple consecutive spaces should be removed');
+ });
+
+ 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');
+ });
+
+ 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');
+ });
+
+ 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('');
+ });
+
+ 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');
+ });
+
+ 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');
+ });
+ });
});