Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions website/modules/asset/ui/src/js/formValidator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const TEST_CONSTANTS = {
EMAIL_INVALID: 'Enter a valid email address',
EMAIL_DOMAIN_INVALID: 'Check the domain part of the email',
PHONE_REQUIRED: 'Phone number is required',
PHONE_INVALID: 'Enter a valid phone number (e.g., +1 (234) 567-8900)',
PHONE_INVALID: 'Enter a valid phone number',
TEXT_TOO_LONG: 'Maximum 50 characters',
TEXT_TOO_SHORT: 'Minimum 2 characters',
TEXTAREA_TOO_LONG: 'Maximum 200 characters',
Expand Down Expand Up @@ -199,12 +199,12 @@ const testPhoneNumber = () =>
{
description: 'rejects too short phone number',
value: TEST_CONSTANTS.INVALID_SAMPLES.PHONE_SHORT,
message: TEST_CONSTANTS.MESSAGES.PHONE_INVALID,
message: 'Phone number is too short',
},
{
description: 'rejects invalid international format',
value: TEST_CONSTANTS.INVALID_SAMPLES.PHONE_INVALID,
message: TEST_CONSTANTS.MESSAGES.PHONE_INVALID,
message: 'Phone number is too short',
},
],
});
Expand Down
16 changes: 13 additions & 3 deletions website/modules/asset/ui/src/js/phoneNumberValidator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const {

describe('Phone Number Validator', () => {
let phoneInput = null;
const ERROR_MESSAGE = 'Enter a valid phone number (e.g., +1 (234) 567-8900)';
const ERROR_MESSAGE = 'Phone number is too short';

beforeEach(() => {
phoneInput = document.createElement('input');
Expand Down Expand Up @@ -33,11 +33,21 @@ describe('Phone Number Validator', () => {
});

it('rejects invalid international format', async () => {
await expectInvalidPhone('+123456789');
phoneInput.value = '+123';
const result = await validateField(phoneInput);
expect(result).toEqual({
isValid: false,
message: 'Phone number is too short',
});
});

it('rejects phone number with letters', async () => {
await expectInvalidPhone('+1 (234) ABC-1234');
phoneInput.value = '+1 (234) ABC-1234';
const result = await validateField(phoneInput);
expect(result).toEqual({
isValid: false,
message: 'Enter a valid phone number',
});
});

it('accepts valid phone number with country code', async () => {
Expand Down
41 changes: 10 additions & 31 deletions website/modules/asset/ui/src/js/validationSchemas.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const { formatPhoneNumber } = require('./phoneFormat');
const {
STANDARD_FORM_FIELD_NAMES,
} = require('../../../../@apostrophecms/shared-constants/ui/src/index');
Expand Down Expand Up @@ -34,37 +35,15 @@ const fieldSpecificSchemas = {
[STANDARD_FORM_FIELD_NAMES.PHONE_NUMBER]: yup
.string()
.required('Phone number is required')
.max(20, 'Phone number is too long')
.test(
'phone-format',
'Enter a valid phone number (e.g., +1 (234) 567-8900)',
(value) => {
if (!value) return false;

// First check for letters - reject immediately if found
if (/[A-Za-z]/u.test(value)) return false;

// Remove all non-digit characters except leading +
const digits = value.replace(/\D/gu, '');

// Check for minimum length (10 digits typical for phone numbers)
if (digits.length < 10) return false;

// International format: +1 (234) 567-8900 or +1 234 567 8900 or +1.234.567.8900
const internationalPattern =
/^\+?\d{1,3}[\s.-]?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$/u;
// Local format: (234) 567-8900 or 234 567 8900
const localPattern = /^\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$/u;

// If it starts with +, it must match international pattern
if (value.startsWith('+')) {
return internationalPattern.test(value);
}

// Otherwise check both patterns
return internationalPattern.test(value) || localPattern.test(value);
},
),
.min(10, 'Phone number is too short')
.max(19, 'Phone number is too long')
.test('phone-format', 'Enter a valid phone number', (value) => {
if (!value) return false;
if (/[A-Za-z]/u.test(value)) return false;
Comment thread
VitalyyP marked this conversation as resolved.

const formatted = formatPhoneNumber(value);
return Boolean(formatted);
}),
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

'g-recaptcha-response': yup
.string()
Expand Down
6 changes: 3 additions & 3 deletions website/modules/asset/ui/src/js/validationSchemas.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ describe('Phone Number Schema', () => {

test('rejects too short phone number', async () => {
await expect(schema.validate('123')).rejects.toThrow(
'Enter a valid phone number (e.g., +1 (234) 567-8900)',
'Phone number is too short',
);
});

Expand All @@ -122,13 +122,13 @@ describe('Phone Number Schema', () => {

test('rejects invalid format', async () => {
await expect(schema.validate('abc')).rejects.toThrow(
'Enter a valid phone number (e.g., +1 (234) 567-8900)',
'Phone number is too short',
);
});

test('rejects phone number with letters', async () => {
await expect(schema.validate('123-ABC-4567')).rejects.toThrow(
'Enter a valid phone number (e.g., +1 (234) 567-8900)',
'Enter a valid phone number',
);
});
});
Expand Down
Loading