From 6175c55f3579963b1d68b77e18a0273a026cb5d2 Mon Sep 17 00:00:00 2001 From: Arjunlal B Date: Thu, 4 Mar 2021 21:21:06 +0530 Subject: [PATCH 1/3] feat: validator for emails and a string formatter --- projects/common/src/public-api.ts | 3 +++ .../string/string-formatter.test.ts | 15 +++++++++++++- .../formatters/string/string-formatter.ts | 7 +++++++ .../validators/email-validator.test.ts | 20 +++++++++++++++++++ .../utilities/validators/email-validator.ts | 10 ++++++++++ 5 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 projects/common/src/utilities/validators/email-validator.test.ts create mode 100644 projects/common/src/utilities/validators/email-validator.ts diff --git a/projects/common/src/public-api.ts b/projects/common/src/public-api.ts index 17d68cda5..ea1e52820 100644 --- a/projects/common/src/public-api.ts +++ b/projects/common/src/public-api.ts @@ -106,3 +106,6 @@ export * from './time/time-range.service'; export * from './time/time-range.type'; export * from './time/time-unit.type'; export * from './time/time'; + +// Validators +export * from './utilities/validators/email-validator'; diff --git a/projects/common/src/utilities/formatters/string/string-formatter.test.ts b/projects/common/src/utilities/formatters/string/string-formatter.test.ts index 29dcd0446..538edfd76 100644 --- a/projects/common/src/utilities/formatters/string/string-formatter.test.ts +++ b/projects/common/src/utilities/formatters/string/string-formatter.test.ts @@ -1,4 +1,9 @@ -import { displayString, titleCaseFromKebabCase, titleCaseFromSnakeCase } from './string-formatter'; +import { + displayString, + getStringsFromCommaSeparatedList, + titleCaseFromKebabCase, + titleCaseFromSnakeCase +} from './string-formatter'; describe('String formatter', () => { test('can convert from kebab case to title case', () => { @@ -26,4 +31,12 @@ describe('String formatter', () => { expect(displayString(Symbol('test symbol'))).toBe('Symbol(test symbol)'); expect(displayString(false)).toBe('false'); }); + + test('creates string array correctly from comma separated list', () => { + expect(getStringsFromCommaSeparatedList('first,second, third ')).toEqual( + expect.arrayContaining(['first', 'second', 'third']) + ); + expect(getStringsFromCommaSeparatedList('first,second, ')).toEqual(expect.arrayContaining(['first', 'second'])); + expect(getStringsFromCommaSeparatedList('first')).toEqual(expect.arrayContaining(['first'])); + }); }); diff --git a/projects/common/src/utilities/formatters/string/string-formatter.ts b/projects/common/src/utilities/formatters/string/string-formatter.ts index f0b046e1c..4abe2380f 100644 --- a/projects/common/src/utilities/formatters/string/string-formatter.ts +++ b/projects/common/src/utilities/formatters/string/string-formatter.ts @@ -42,3 +42,10 @@ export const displayString = (provided?: unknown): string => { export const collapseWhitespace = (str: string): string => // Replace all whitespace with a single space str.replace(/\s\s+/g, ' '); + +export const getStringsFromCommaSeparatedList = (text: string): string[] => + text + .trim() + .split(',') + .map(part => part.trim()) + .filter(part => part !== ''); diff --git a/projects/common/src/utilities/validators/email-validator.test.ts b/projects/common/src/utilities/validators/email-validator.test.ts new file mode 100644 index 000000000..7ef0eae8f --- /dev/null +++ b/projects/common/src/utilities/validators/email-validator.test.ts @@ -0,0 +1,20 @@ +import { areEmailAddressesValid, isEmailAddressValid } from '@hypertrace/common'; + +describe('Email validator', () => { + test('can validate email correctly', () => { + expect(isEmailAddressValid('test@traceable.ai')).toBe(true); + expect(isEmailAddressValid('test.email@traceable.ai')).toBe(true); + expect(isEmailAddressValid('test+983tonq@traceable.ai')).toBe(true); + expect(isEmailAddressValid('test@traceable.')).toBe(false); + expect(isEmailAddressValid('test')).toBe(false); + expect(isEmailAddressValid('test@traceable-')).toBe(false); + expect(isEmailAddressValid('tes\t@traceable-')).toBe(false); + expect(isEmailAddressValid('test@@traceable.ai')).toBe(false); + expect(isEmailAddressValid('test@@traceable.ai')).toBe(false); + }); + + test('can validate email lists correctly', () => { + expect(areEmailAddressesValid(['test@traceable.ai', 'test.email@traceable.ai'])).toBe(true); + expect(areEmailAddressesValid(['test@traceable.ai', 'test.email@@traceable.ai'])).toBe(false); + }); +}); diff --git a/projects/common/src/utilities/validators/email-validator.ts b/projects/common/src/utilities/validators/email-validator.ts new file mode 100644 index 000000000..9e6054aff --- /dev/null +++ b/projects/common/src/utilities/validators/email-validator.ts @@ -0,0 +1,10 @@ +export const isEmailAddressValid = (emailAddress: string) => { + // Regex as per W3C spec for email field + // Source: https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address + const regex: RegExp = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/; + + return regex.test(emailAddress); +}; + +export const areEmailAddressesValid = (emailAddresses: string[]) => + emailAddresses.filter(emailAddress => !isEmailAddressValid(emailAddress)).length === 0; From e8dae5b628c8838475aec876b490c24858275295 Mon Sep 17 00:00:00 2001 From: Arjunlal B Date: Thu, 4 Mar 2021 21:21:50 +0530 Subject: [PATCH 2/3] fix: update test strings --- .../validators/email-validator.test.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/projects/common/src/utilities/validators/email-validator.test.ts b/projects/common/src/utilities/validators/email-validator.test.ts index 7ef0eae8f..81a8b63f5 100644 --- a/projects/common/src/utilities/validators/email-validator.test.ts +++ b/projects/common/src/utilities/validators/email-validator.test.ts @@ -2,19 +2,19 @@ import { areEmailAddressesValid, isEmailAddressValid } from '@hypertrace/common' describe('Email validator', () => { test('can validate email correctly', () => { - expect(isEmailAddressValid('test@traceable.ai')).toBe(true); - expect(isEmailAddressValid('test.email@traceable.ai')).toBe(true); - expect(isEmailAddressValid('test+983tonq@traceable.ai')).toBe(true); - expect(isEmailAddressValid('test@traceable.')).toBe(false); + expect(isEmailAddressValid('test@test.ai')).toBe(true); + expect(isEmailAddressValid('test.email@test.ai')).toBe(true); + expect(isEmailAddressValid('test+983tonq@test.ai')).toBe(true); + expect(isEmailAddressValid('test@test.')).toBe(false); expect(isEmailAddressValid('test')).toBe(false); - expect(isEmailAddressValid('test@traceable-')).toBe(false); - expect(isEmailAddressValid('tes\t@traceable-')).toBe(false); - expect(isEmailAddressValid('test@@traceable.ai')).toBe(false); - expect(isEmailAddressValid('test@@traceable.ai')).toBe(false); + expect(isEmailAddressValid('test@test-')).toBe(false); + expect(isEmailAddressValid('tes\t@test-')).toBe(false); + expect(isEmailAddressValid('test@@test.ai')).toBe(false); + expect(isEmailAddressValid('test@@test.ai')).toBe(false); }); test('can validate email lists correctly', () => { - expect(areEmailAddressesValid(['test@traceable.ai', 'test.email@traceable.ai'])).toBe(true); - expect(areEmailAddressesValid(['test@traceable.ai', 'test.email@@traceable.ai'])).toBe(false); + expect(areEmailAddressesValid(['test@test.ai', 'test.email@test.ai'])).toBe(true); + expect(areEmailAddressesValid(['test@test.ai', 'test.email@@test.ai'])).toBe(false); }); }); From 9f819bb2f1dd335f983c8ce424fc6bd05422514d Mon Sep 17 00:00:00 2001 From: Arjunlal B Date: Thu, 4 Mar 2021 22:41:30 +0530 Subject: [PATCH 3/3] fix: address comments --- .../src/utilities/formatters/string/string-formatter.test.ts | 4 ++-- .../src/utilities/formatters/string/string-formatter.ts | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/projects/common/src/utilities/formatters/string/string-formatter.test.ts b/projects/common/src/utilities/formatters/string/string-formatter.test.ts index 538edfd76..597ba126d 100644 --- a/projects/common/src/utilities/formatters/string/string-formatter.test.ts +++ b/projects/common/src/utilities/formatters/string/string-formatter.test.ts @@ -36,7 +36,7 @@ describe('String formatter', () => { expect(getStringsFromCommaSeparatedList('first,second, third ')).toEqual( expect.arrayContaining(['first', 'second', 'third']) ); - expect(getStringsFromCommaSeparatedList('first,second, ')).toEqual(expect.arrayContaining(['first', 'second'])); - expect(getStringsFromCommaSeparatedList('first')).toEqual(expect.arrayContaining(['first'])); + expect(getStringsFromCommaSeparatedList('first,second, ')).toEqual(['first', 'second']); + expect(getStringsFromCommaSeparatedList('first')).toEqual(['first']); }); }); diff --git a/projects/common/src/utilities/formatters/string/string-formatter.ts b/projects/common/src/utilities/formatters/string/string-formatter.ts index 4abe2380f..70e57a80f 100644 --- a/projects/common/src/utilities/formatters/string/string-formatter.ts +++ b/projects/common/src/utilities/formatters/string/string-formatter.ts @@ -45,7 +45,6 @@ export const collapseWhitespace = (str: string): string => export const getStringsFromCommaSeparatedList = (text: string): string[] => text - .trim() .split(',') .map(part => part.trim()) .filter(part => part !== '');