Skip to content

Commit

Permalink
feat: allow multi email in contact field
Browse files Browse the repository at this point in the history
  • Loading branch information
abelkhay committed Mar 25, 2024
1 parent 77cef20 commit 508cadf
Show file tree
Hide file tree
Showing 18 changed files with 70 additions and 39 deletions.
19 changes: 5 additions & 14 deletions src/models/contact/contact.spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
/* eslint-disable @typescript-eslint/naming-convention, camelcase */

import { Courriel } from '../courriel';
import { Url } from '../url';
import { Contact, ContactToValidate } from './contact';
import { CourrielError, TelephoneError } from './errors';
import { TelephoneError } from './errors';

describe('contact model', (): void => {
it('should create a valid contact', (): void => {
const contactData: ContactToValidate = {
telephone: '+33145896378',
courriel: '[email protected]',
courriel: [Courriel('[email protected]')],
site_web: [Url('http://www.cartographienationale.fr')]
};

Expand All @@ -29,7 +30,7 @@ describe('contact model', (): void => {

it('should create a valid contact with only courriel property', (): void => {
const contactData: ContactToValidate = {
courriel: '[email protected]'
courriel: [Courriel('[email protected]')]
};

const contact: Contact = Contact(contactData);
Expand All @@ -40,7 +41,7 @@ describe('contact model', (): void => {
it('should create a valid contact with a phone from French Guiana', (): void => {
const contactData: ContactToValidate = {
telephone: '+594694020905',
courriel: '[email protected]',
courriel: [Courriel('[email protected]')],
site_web: [Url('https://www.facebook.com/YenkumuLutuPapaichton/')]
};

Expand All @@ -49,16 +50,6 @@ describe('contact model', (): void => {
expect(contact).toStrictEqual({ ...contactData } as Contact);
});

it('should throw CourrielError when courriel is invalid', (): void => {
const contactData: ContactToValidate = {
courriel: 'error'
};

expect((): void => {
Contact(contactData);
}).toThrow(new CourrielError('error'));
});

it('should throw TelephoneError when telephone is invalid', (): void => {
const contactData: ContactToValidate = {
telephone: 'error'
Expand Down
17 changes: 4 additions & 13 deletions src/models/contact/contact.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,29 @@
import { Courriel } from '../courriel';
import { Model } from '../model';
import { Url } from '../url';
import { CourrielError, TelephoneError } from './errors';
import { TelephoneError } from './errors';

export type Contact = Model<
'Contact',
{
telephone?: string;
courriel?: string;
/* eslint-disable-next-line @typescript-eslint/naming-convention */
courriel?: Courriel[];
site_web?: Url[];

Check failure on line 12 in src/models/contact/contact.ts

View workflow job for this annotation

GitHub Actions / validation-matrix / (lint.es)

Type Property name `site_web` must match one of the following formats: camelCase
}
>;

export type ContactToValidate = Omit<Contact, 'isContact'>;

const COURRIEL_REG_EXP: RegExp =
/^[a-zA-Z0-9_][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])+$/u;

const TELEPHONE_REG_EXP: RegExp =
/^(?:(?:\+|00)(?:33|594|262|596|269|687|689|590|508|681)[\s.-]{0,3}(?:\(0\)[\s.-]{0,3})?|0)(?:(?:[1-9](?:[\s.-]?\d{2}){4}|\d{2}(?:[\s.-]\d{3}){2})|\d{6}|\s\d{3}(?:\s\d{2}){3})$/u;

export const isValidCourriel = (courriel: string): boolean => COURRIEL_REG_EXP.test(courriel);

export const isValidTelephone = (telephone: string): boolean => TELEPHONE_REG_EXP.test(telephone);

const isValidContact = (contact: Omit<Contact, 'isContact'>): contact is Contact =>
(contact.courriel == null || isValidCourriel(contact.courriel)) &&
(contact.telephone == null || isValidTelephone(contact.telephone));
contact.telephone == null || isValidTelephone(contact.telephone);

const throwContactError = (contact: Omit<Contact, 'isContact'>): Contact => {
if (contact.courriel != null && !isValidCourriel(contact.courriel)) {
throw new CourrielError(contact.courriel);
}

if (contact.telephone != null && !isValidTelephone(contact.telephone)) {
throw new TelephoneError(contact.telephone);
}
Expand Down
1 change: 0 additions & 1 deletion src/models/contact/errors/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export * from './courriel.error';
export * from './telephone.error';
20 changes: 20 additions & 0 deletions src/models/courriel/courriel.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Courriel } from './courriel';
import { CourrielError } from './errors';

describe('courriel model', (): void => {
it('should create a valid courriel', (): void => {
const courrielData: string = '[email protected]';

const courriel: Courriel = Courriel(courrielData);

expect(courriel).toStrictEqual(courrielData as Courriel);
});

it('should throw CourrielError when email do not have at symbole or domain extension', (): void => {
const courrielData: string = 'test@gmail';

expect((): void => {
Courriel(courrielData);
}).toThrow(new CourrielError(courrielData));
});
});
16 changes: 16 additions & 0 deletions src/models/courriel/courriel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Model } from '../model';
import { CourrielError } from './errors';

export type Courriel = Model<'Courriel', string>;

const COURRIEL_REG_EXP: RegExp =
/^(?:[a-zA-Z0-9_][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])+(?:;|$))+$/u;

const throwCourrielError = (courriel: string): Courriel => {
throw new CourrielError(courriel);
};

export const isValidCourriel = (courriel: string): courriel is Courriel => COURRIEL_REG_EXP.test(courriel);

/* eslint-disable-next-line @typescript-eslint/naming-convention */
export const Courriel = (courriel: string): Courriel => (isValidCourriel(courriel) ? courriel : throwCourrielError(courriel));
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ModelError } from '../../../errors';
import { Contact } from '../contact';

export class CourrielError extends ModelError<Contact> {
export class CourrielError extends ModelError<{ courriel: string }> {
constructor(courriel: string) {
super('courriel', `Le courriel ${courriel} n'est pas valide`);
}
Expand Down
1 change: 1 addition & 0 deletions src/models/courriel/errors/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './courriel.error'
2 changes: 2 additions & 0 deletions src/models/courriel/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './errors';
export * from './courriel';
1 change: 1 addition & 0 deletions src/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ export * from './url';
export * from './lieu-mediation-numerique';
export * from './model';
export * from './presentation';
export * from './courriel';
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ConditionAcces,
ConditionsAcces,
Contact,
Courriel,
LabelNational,
LabelsNationaux,
Localisation,
Expand Down Expand Up @@ -172,7 +173,7 @@ export const contactFromDataInclusion = (courriel?: string, telephone?: string,
? {}
: {
contact: Contact({
...(courriel == null ? {} : { courriel }),
...(courriel == null ? {} : { courriel: courriel.split(';').map(Courriel) }),
...(telephone == null ? {} : { telephone }),
...(site_web == null ? {} : { site_web: site_web.split(';').map(Url) })
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
ConditionAcces,
ConditionsAcces,
Contact,
Courriel,
Id,
LabelNational,
LabelsNationaux,
Expand Down Expand Up @@ -170,7 +171,7 @@ describe('from schema data inclusion', (): void => {
typologies: Typologies([Typologie.TIERS_LIEUX]),
contact: Contact({
telephone: '+33180059880',
courriel: '[email protected]',
courriel: [Courriel('[email protected]')],
site_web: [Url('https://www.laquincaillerie.tl/'), Url('https://m.facebook.com/laquincaillerienumerique/')]
}),
horaires: 'Mo-Fr 09:00-12:00,14:00-18:30; Sa 08:30-12:00',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import {
SchemaStructureDataInclusionPresentationFields,
SchemaStructureDataInclusionStructureGeneralFields
} from '../schema-data-inclusion';
import { isValidCourriel, isValidTelephone } from '../../../models';
import { isValidTelephone } from '../../../models';
import { isValidCourriel } from '../../../models/courriel';

export const isServiceWithAdresse = (
service: Partial<SchemaStructureDataInclusionAdresseFields> & SchemaServiceDataInclusion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ const typologyIfExist = (typologie?: string): { typologie?: string } => (typolog

const siteWebIfExist = (site_web?: string): { site_web?: string } => (site_web == null ? {} : { site_web });

const courrielIfExist = (courriel?: string): { courriel?: string } => (courriel == null ? {} : { courriel });

const fraisIfExist = (frais?: string): { frais?: string[] } => (frais == null ? {} : { frais: [frais] });

const fraisFromConditionAcces = (conditionAcces?: ConditionAcces): { frais?: string[] } =>
Expand Down Expand Up @@ -131,7 +133,9 @@ export const localisationFields = (

export const contactFields = (lieuMediationNumerique: LieuMediationNumerique): SchemaStructureDataInclusionContactFields => ({
...(lieuMediationNumerique.contact?.telephone == null ? {} : { telephone: lieuMediationNumerique.contact.telephone }),
...(lieuMediationNumerique.contact?.courriel == null ? {} : { courriel: lieuMediationNumerique.contact.courriel }),
...(lieuMediationNumerique.contact?.courriel != null && lieuMediationNumerique.contact.courriel.length > 0
? courrielIfExist(lieuMediationNumerique.contact.courriel.at(0)?.toString())
: {}),
...(lieuMediationNumerique.contact?.site_web != null && lieuMediationNumerique.contact.site_web.length > 0
? siteWebIfExist(lieuMediationNumerique.contact.site_web.at(0)?.toString())
: {})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
ConditionAcces,
ConditionsAcces,
Contact,
Courriel,
Id,
LabelNational,
LabelsNationaux,
Expand Down Expand Up @@ -100,7 +101,7 @@ describe('to schema data.inclusion', (): void => {
contact: Contact({
site_web: [Url('https://www.asso-gonzalez.net/'), Url('https://www.facebook.com/asso-gonzalez.net/')],
telephone: '0102030405',
courriel: '[email protected]'
courriel: [Courriel('[email protected]')]
}),
horaires: 'Mo-Fr 10:00-20:00 "sur rendez-vous"; PH off',
presentation: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
CleBan,
ConditionsAcces,
Contact,
Courriel,
LabelsNationaux,
Localisation,
ModalitesAccompagnement,
Expand Down Expand Up @@ -45,7 +46,7 @@ export const typologiesIfAny = (typologies?: string): { typologies?: Typologies

const telephoneIfAny = (telephone?: string): { telephone?: string } => (telephone == null ? {} : { telephone });

const courrielIfAny = (courriel?: string): { courriel?: string } => (courriel == null ? {} : { courriel });
const courrielIfAny = (courriel?: string): { courriel?: Courriel[] } => (courriel == null ? {} : { courriel: listFromString(courriel) });

const siteWebIfAny = (siteWeb?: string): { site_web?: Url[] } => (siteWeb == null ? {} : { site_web: listFromString(siteWeb) });

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ConditionAcces,
ConditionsAcces,
Contact,
Courriel,
Id,
LabelNational,
LabelsNationaux,
Expand Down Expand Up @@ -140,7 +141,7 @@ describe('from schema lieux de mediation numerique', (): void => {
typologies: Typologies([Typologie.TIERS_LIEUX]),
contact: Contact({
telephone: '+33180059880',
courriel: '[email protected]',
courriel: [Courriel('[email protected]')],
site_web: [Url('https://www.laquincaillerie.tl/'), Url('https://m.facebook.com/laquincaillerienumerique/')]
}),
horaires: 'Mo-Fr 09:00-12:00,14:00-18:30; Sa 08:30-12:00',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const localisationFields = (

export const contactFields = (lieuMediationNumerique: LieuMediationNumerique): SchemaLieuMediationNumeriqueContactFields => ({
...(lieuMediationNumerique.contact?.telephone == null ? {} : { telephone: lieuMediationNumerique.contact.telephone }),
...(lieuMediationNumerique.contact?.courriel == null ? {} : { courriel: lieuMediationNumerique.contact.courriel }),
...(lieuMediationNumerique.contact?.courriel == null ? {} : { courriel: lieuMediationNumerique.contact.courriel.join(';') }),
...(lieuMediationNumerique.contact?.site_web == null ? {} : { site_web: lieuMediationNumerique.contact.site_web.join(';') })
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ConditionAcces,
ConditionsAcces,
Contact,
Courriel,
Id,
LabelNational,
LabelsNationaux,
Expand Down Expand Up @@ -97,7 +98,7 @@ describe('to schema lieux de mediation numerique', (): void => {
typologies: Typologies([Typologie.TIERS_LIEUX]),
contact: Contact({
telephone: '+33180059880',
courriel: '[email protected]',
courriel: [Courriel('[email protected]')],
site_web: [Url('https://www.laquincaillerie.tl/'), Url('https://m.facebook.com/laquincaillerienumerique/')]
}),
horaires: 'Mo-Fr 09:00-12:00,14:00-18:30; Sa 08:30-12:00',
Expand Down

0 comments on commit 508cadf

Please sign in to comment.