Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
1 change: 1 addition & 0 deletions .docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ COPY . .
RUN chmod +x ./scripts/*.sh || true
# Set up git
RUN apk add git

ADD git-config.txt ${WORKDIR}

EXPOSE 7000
194 changes: 194 additions & 0 deletions src/__tests__/utils/validatePhoneNumber.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
const validatePhoneNumber = require('../../utils/validatePhoneNumber');

describe('validatePhoneNumber', () => {
let mockHelpers;

beforeEach(() => {
// Clear all mocks before each test
jest.clearAllMocks();

// Mock Joi helpers
mockHelpers = {
error: jest.fn((code) => ({ code, message: `Validation error: ${code}` }))
};
});

describe('Valid phone numbers', () => {
it('should accept valid US/Canada phone numbers with exactly 10 digits after +1', () => {
const validNumbers = [
'+12345678901',
'+15551234567',
'+19876543210',
'+11234567890'
];

validNumbers.forEach(number => {
const result = validatePhoneNumber(number, mockHelpers);

expect(result).toBe(number);
expect(mockHelpers.error).not.toHaveBeenCalled();
});
});

it('should reject phone numbers with less than or more than 10 digits after +1', () => {
const invalidNumbers = [
'+123456789', // 9 digits
'+123456789012', // 12 digits
'+1', // only +1
'+12', // only +1 and 1 digit
'+123', // only +1 and 2 digits
'+1234', // only +1 and 3 digits
'+12345', // only +1 and 4 digits
'+123456', // only +1 and 5 digits
'+1234567', // only +1 and 6 digits
'+12345678', // only +1 and 7 digits
'+123456789' // only +1 and 9 digits
];

invalidNumbers.forEach(number => {
const result = validatePhoneNumber(number, mockHelpers);

expect(result).toEqual({ code: 'any.invalid', message: 'Validation error: any.invalid' });
expect(mockHelpers.error).toHaveBeenCalledWith('any.invalid');
});
});
});

describe('Invalid phone numbers', () => {
it('should reject phone numbers that do not start with +', () => {
const invalidNumbers = [
'1234567890',
'1555123456',
'1987654321',
'1123456789'
];

invalidNumbers.forEach(number => {
const result = validatePhoneNumber(number, mockHelpers);

expect(result).toEqual({ code: 'any.invalid', message: 'Validation error: any.invalid' });
expect(mockHelpers.error).toHaveBeenCalledWith('any.invalid');
});
});

it('should reject phone numbers that do not start with +1', () => {
const invalidNumbers = [
'+21234567890', // +2
'+31234567890', // +3
'+41234567890', // +4
'+51234567890', // +5
'+61234567890', // +6
'+71234567890', // +7
'+81234567890', // +8
'+91234567890' // +9
];

invalidNumbers.forEach(number => {
const result = validatePhoneNumber(number, mockHelpers);

expect(result).toEqual({ code: 'any.invalid', message: 'Validation error: any.invalid' });
expect(mockHelpers.error).toHaveBeenCalledWith('any.invalid');
});
});

it('should reject phone numbers with non-digit characters after +1', () => {
const invalidNumbers = [
'+1a23456789',
'+1-234-567-8900',
'+1 (234) 567-8900',
'+1.234.567.8900',
'+1_234_567_8900',
'+1 234 567 8900'
];

invalidNumbers.forEach(number => {
const result = validatePhoneNumber(number, mockHelpers);

expect(result).toEqual({ code: 'any.invalid', message: 'Validation error: any.invalid' });
expect(mockHelpers.error).toHaveBeenCalledWith('any.invalid');
});
});

it('should reject phone numbers that are too short', () => {
const invalidNumbers = [
'+1', // Only +1, no digits
'+', // Only +
'' // Empty string
];

invalidNumbers.forEach(number => {
const result = validatePhoneNumber(number, mockHelpers);

expect(result).toEqual({ code: 'any.invalid', message: 'Validation error: any.invalid' });
expect(mockHelpers.error).toHaveBeenCalledWith('any.invalid');
});
});
});

describe('Edge cases', () => {
it('should handle null and undefined values', () => {
const invalidValues = [null, undefined];

invalidValues.forEach(value => {
const result = validatePhoneNumber(value, mockHelpers);

expect(result).toEqual({ code: 'any.invalid', message: 'Validation error: any.invalid' });
expect(mockHelpers.error).toHaveBeenCalledWith('any.invalid');
});
});

it('should handle non-string values', () => {
const invalidValues = [123, {}, [], true, false];

invalidValues.forEach(value => {
const result = validatePhoneNumber(value, mockHelpers);

expect(result).toEqual({ code: 'any.invalid', message: 'Validation error: any.invalid' });
expect(mockHelpers.error).toHaveBeenCalledWith('any.invalid');
});
});

it('should handle strings with leading/trailing whitespace', () => {
const invalidNumbers = [
' +1234567890',
'+1234567890 ',
' +1234567890 ',
'\t+1234567890',
'+1234567890\n'
];

invalidNumbers.forEach(number => {
const result = validatePhoneNumber(number, mockHelpers);

expect(result).toEqual({ code: 'any.invalid', message: 'Validation error: any.invalid' });
expect(mockHelpers.error).toHaveBeenCalledWith('any.invalid');
});
});
});

describe('Function behavior', () => {
it('should return the original value for valid phone numbers', () => {
const validNumber = '+12345678901';
const result = validatePhoneNumber(validNumber, mockHelpers);

expect(result).toBe(validNumber);
expect(typeof result).toBe('string');
});

it('should call helpers.error with correct error code for invalid numbers', () => {
const invalidNumber = '1234567890';

validatePhoneNumber(invalidNumber, mockHelpers);

expect(mockHelpers.error).toHaveBeenCalledTimes(1);
expect(mockHelpers.error).toHaveBeenCalledWith('any.invalid');
});

it('should return error object from helpers.error for invalid numbers', () => {
const invalidNumber = '1234567890';
const result = validatePhoneNumber(invalidNumber, mockHelpers);

expect(result).toEqual({ code: 'any.invalid', message: 'Validation error: any.invalid' });
});
});
});
Loading