Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • pub/pnm-public/camino
1 result
Show changes
Commits on Source (2)
Showing
with 385 additions and 27 deletions
......@@ -14,6 +14,7 @@ import {
isBefore,
intervalleAnnees,
caminoDateValidator,
CaminoDate,
} from './date'
import { test, expect } from 'vitest'
......@@ -76,7 +77,9 @@ test('anneePrecedente', () => {
})
test('intervalleAnnees', () => {
expect(intervalleAnnees(toCaminoAnnee('1997'), toCaminoAnnee('1999'))).toStrictEqual([toCaminoAnnee('1997'), toCaminoAnnee('1998'), toCaminoAnnee('1999')])
expect(() => intervalleAnnees(toCaminoAnnee('1999'), toCaminoAnnee('1980'))).toThrowErrorMatchingInlineSnapshot(`[Error: L'année de départ 1999 doit être inférieure à l'année d'arrivée 1980]`)
})
test("retourne une erreur si aucune date n'est fournie", () => {
let tested = dateValidate(null)
......@@ -108,6 +111,10 @@ test.each([
expect(dateAddDays(toCaminoDate(date), days)).toBe(result)
})
test("ajoute une date qui n'en est pas une", () => {
expect(() => dateAddDays('plop' as CaminoDate, 12)).toThrowErrorMatchingInlineSnapshot(`[Error: Cette camino date plop n'est pas vraiment une caminoDate]`)
})
test.each([
['2020-01-01', 1, '2020-02-01'],
['2020-01-01', 12, '2021-01-01'],
......
......@@ -81,16 +81,11 @@ export function toCaminoAnnee(annee: string | number): CaminoAnnee {
export const dateValidate = (str: CaminoDate | string | undefined | null): { valid: true; date: CaminoDate } | { valid: false; error: 'Date manquante' | 'Date invalide' } => {
if (isNullOrUndefined(str)) return { valid: false, error: 'Date manquante' }
if (typeof str === 'string') {
try {
return { valid: true, date: toCaminoDate(str) }
} catch (e) {
return { valid: false, error: 'Date invalide' }
}
try {
return { valid: true, date: toCaminoDate(str) }
} catch (e) {
return { valid: false, error: 'Date invalide' }
}
return { valid: true, date: str }
}
export const intervalleAnnees = (anneeDepart: CaminoAnnee, anneeArrivee: CaminoAnnee): CaminoAnnee[] => {
......
/* v8 ignore next 5 */
export interface Definition<T> {
id: T
nom: string
......
......@@ -5,6 +5,7 @@ import { proprietesGeothermieForagesElementIds } from './static/titresTypes_dema
import { ETAPES_TYPES } from './static/etapesTypes'
import { toCaminoDate } from './date'
import { DEMARCHES_TYPES_IDS } from './static/demarchesTypes'
import { TITRES_TYPES_IDS, TitreTypeId } from './static/titresTypes'
test('getDemarcheContenu arm', () => {
expect(
......@@ -161,7 +162,67 @@ test('getDemarcheContenu prm', () => {
}
`)
})
test('getDemarcheContenu cxw', () => {
test('getDemarcheContenu prm edgeCasess', () => {
expect(
getDemarcheContenu(
[
{
sections_with_values: [
{
id: 'prx',
nom: 'Propriétés du permis exclusif de recherches',
elements: [
{ id: 'engagement', optionnel: true, type: 'number', value: 3201430 },
{
id: 'engagementDeviseId',
nom: "Devise de l'engagement",
description: '',
optionnel: true,
type: 'select',
options: [
{ id: 'EUR', nom: 'Euros' },
{ id: 'FRF', nom: 'Francs' },
{ id: 'XPF', nom: 'Francs Pacifique' },
],
value: 'NET',
},
],
},
{
id: 'publication',
nom: 'Références Légifrance',
elements: [
{ id: 'jorf', nom: 'Numéro JORF', description: '', optionnel: false, type: 'text', value: 'JORFTEXT000000774145' },
{ id: 'nor', nom: 'Numéro NOR', description: '', optionnel: true, type: 'text', value: 'ECOI0100462D' },
],
},
],
etape_type_id: 'dpu',
},
],
'prm'
)
).toMatchInlineSnapshot(`
{
"": "3 201 430 Euros",
}
`)
})
test.each<{ titreTypeId: TitreTypeId; result: unknown }>([
{
titreTypeId: TITRES_TYPES_IDS.CONCESSION_SOUTERRAIN,
result: {
Volume: '3 000 000 Mètre cube par an',
},
},
{
titreTypeId: TITRES_TYPES_IDS.CONCESSION_GRANULATS_MARINS,
result: {
Volume: '3 000 000 Mètre cube par an',
},
},
{ titreTypeId: TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_GRANULATS_MARINS, result: {} },
])('getDemarcheContenu %s', ({ titreTypeId, result }) => {
expect(
getDemarcheContenu(
[
......@@ -254,15 +315,97 @@ test('getDemarcheContenu cxw', () => {
etape_type_id: 'dex',
},
],
titreTypeId
)
).toStrictEqual(result)
})
test('edge cases', () => {
expect(
getDemarcheContenu(
[
{
sections_with_values: [
{
id: 'cxx',
nom: 'Propriétés de la concession',
elements: [
{ id: 'volume', optionnel: true, type: 'text', value: 'notANumber' },
{
id: 'volumeUniteId',
nom: 'Unité du volume',
description: '',
optionnel: true,
type: 'select',
options: [{ id: 'deg', nom: 'degré' }],
value: 'unknown',
},
],
},
],
etape_type_id: 'dpu',
},
],
'cxw'
)
).toMatchInlineSnapshot(`
{
"": "0 Mètre cube",
}
`)
expect(
getDemarcheContenu(
[
{
etape_type_id: 'mfr',
sections_with_values: [
{
id: 'arm',
elements: [
{ id: 'franchissements', type: 'text', value: null, optionnel: false },
{ id: 'mecanise', type: 'text', value: null, optionnel: false },
],
},
],
},
],
TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX
)
).toMatchInlineSnapshot(`
{
"Volume": "3 000 000 Mètre cube par an",
"": "Non",
}
`)
expect(
getDemarcheContenu(
[
{
etape_type_id: 'mfr',
sections_with_values: [
{
id: 'pxg',
elements: [
{ id: 'volume', type: 'number', value: 12, optionnel: false, uniteId: 'deg' },
{ id: 'debit', type: 'number', value: 13, optionnel: false, uniteId: 'deg' },
{ id: 'profondeurToitNappe', type: 'number', value: 13, optionnel: false, uniteId: 'deg' },
{ id: 'profondeurBaseNappe', type: 'number', value: 13, optionnel: false, uniteId: 'deg' },
],
},
],
},
],
TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_GEOTHERMIE
)
).toMatchInlineSnapshot(`
{
"": "13 undefined",
}
`)
})
expect(getDemarcheContenu([], TITRES_TYPES_IDS.CONCESSION_FOSSILES)).toMatchInlineSnapshot(`{}`)
})
test('getDemarcheContenu pxg', () => {
expect(
getDemarcheContenu(
......
......@@ -129,6 +129,7 @@ export const getDemarcheContenu = (etapes: (Pick<DemarcheEtapeCommon, 'sections_
if (engagementLabel !== null && engagement !== null && engagementDeviseId !== null) {
return { [engagementLabel]: `${numberFormat(engagement)} ${capitalize(Devises[engagementDeviseId].nom)}` }
}
/* v8 ignore next 2 */
}
} else if (
titreTypeId === TITRES_TYPES_IDS.CONCESSION_SOUTERRAIN ||
......
import { test, expect } from 'vitest'
import { sirenValidator } from './entreprise'
import { isEntrepriseId, sirenValidator, toEntrepriseDocumentId } from './entreprise'
import { toCaminoDate } from './date'
test('sirenValidator', () => {
expect(sirenValidator.safeParse('123456789').success).toBe(true)
......@@ -9,3 +10,11 @@ test('sirenValidator', () => {
expect(sirenValidator.safeParse('1234567').success).toBe(false)
expect(sirenValidator.safeParse('1234567890').success).toBe(false)
})
test('isEntrepriseId', () => {
expect(isEntrepriseId('id')).toBe(true)
})
test('toEntrepriseDocumentId', () => {
expect(toEntrepriseDocumentId(toCaminoDate('2023-01-01'), 'aac', 'hash')).toBe('2023-01-01-aac-hash')
})
import { test, expect } from 'vitest'
import { activitesFiltresNames } from './filters'
test('activitesFiltresNames', () => {
expect(activitesFiltresNames).toMatchInlineSnapshot(`
[
"titresIds",
"substancesIds",
"domainesIds",
"typesIds",
"statutsIds",
"annees",
"entreprisesIds",
"activiteTypesIds",
"activiteStatutsIds",
"references",
]
`)
})
/* v8 ignore next 16 */
export const HTTP_STATUS = {
// OK
OK: 200,
......
/* v8 ignore next 8 */
import { z } from 'zod'
import { titreIdValidator } from './validators/titres'
......
import { test, expect } from 'vitest'
import { crsUrnValidator, equalGeojson } from './perimetre'
import { crsUrnValidator, equalGeojson, featureMultiPolygonValidator } from './perimetre'
test('equalGeojson', () => {
expect(equalGeojson(null, null)).toBe(true)
......@@ -51,4 +51,40 @@ test('crsUrnValidator', () => {
expect(crsUrnValidator.safeParse('urn:ogc:def:crs:EPSG::PLOP').success).toBe(false)
expect(crsUrnValidator.safeParse('urn:ogc:def:crs:EPSG::').success).toBe(false)
expect(crsUrnValidator.safeParse('urn:ogc:def:crs:EPSG::27572').success).toBe(true)
expect(crsUrnValidator.safeParse(12).success).toBe(false)
})
test('nullableToEmptyObject', () => {
featureMultiPolygonValidator.parse({
type: 'Feature',
properties: null,
geometry: {
type: 'MultiPolygon',
coordinates: [
[
[
[1, 2],
[1, 2],
[1, 2],
],
],
],
},
})
featureMultiPolygonValidator.parse({
type: 'Feature',
properties: {},
geometry: {
type: 'MultiPolygon',
coordinates: [
[
[
[1, 2],
[1, 2],
[1, 2],
],
],
],
},
})
})
......@@ -88,6 +88,8 @@ export const canEditActivite = async (
const entrepriseFetched = await entreprises()
return user.entrepriseIds.some(entrepriseId => entrepriseFetched.includes(entrepriseId)) && [ACTIVITES_STATUTS_IDS.ABSENT, ACTIVITES_STATUTS_IDS.EN_CONSTRUCTION].includes(activiteStatutId)
// code unreachable due to canReadTitreActivites
/* v8 ignore next 4 */
}
return false
......
......@@ -27,6 +27,8 @@ export const canReadActivitesTypesEmails = (user: User, administrationId: Admini
administrationIds.push(user.administrationId)
return administrationIds.includes(administrationId)
// unreachable code due to canReadAdministrations
/* v8 ignore next 4 */
}
return false
......
......@@ -3,6 +3,7 @@ import {
dateTypeStepIsComplete,
entrepriseDocumentsStepIsComplete,
entrepriseDocumentsStepIsVisible,
etapeAvisStepIsComplete,
etapeAvisStepIsVisible,
etapeDocumentsStepIsComplete,
etapeDocumentsStepIsVisible,
......@@ -25,6 +26,7 @@ import { ADMINISTRATION_IDS } from '../static/administrations'
import { SUBSTANCES_FISCALES_IDS } from '../static/substancesFiscales'
import { DEMARCHES_TYPES_IDS } from '../static/demarchesTypes'
import { TITRES_TYPES_IDS } from '../static/titresTypes'
import { ETAPES_TYPES } from '../static/etapesTypes'
describe('dateTypeStepIsComplete', () => {
test.each<User>([
......@@ -599,6 +601,12 @@ test('etapeDocumentsStepIsComplete', () => {
"valid": true,
}
`)
expect(etapeDocumentsStepIsComplete({ typeId: 'pqr', contenu: {}, isBrouillon: ETAPE_IS_BROUILLON }, 'oct', 'axm', [], [])).toMatchInlineSnapshot(`
{
"valid": true,
}
`)
})
test('entrepriseDocumentsStepIsVisible', () => {
......@@ -911,6 +919,15 @@ test('getDocumentsTypes', () => {
})
test('getAvisType', () => {
expect(getAvisTypes(ETAPES_TYPES.avisDesCollectivites, 'arm', [])).toMatchInlineSnapshot(`
[
{
"id": "avisDUneCollectivite",
"nom": "Avis d'une collectivité",
"optionnel": true,
},
]
`)
expect(getAvisTypes('mfr', 'arm', [])).toMatchInlineSnapshot('[]')
expect(getAvisTypes('asc', 'arm', [])).toMatchInlineSnapshot(`
[
......@@ -1219,3 +1236,8 @@ test('etapeAvisStepIsVisible', () => {
expect(etapeAvisStepIsVisible({ typeId: 'mfr' }, 'arm', [])).toBe(false)
expect(etapeAvisStepIsVisible({ typeId: 'asc' }, 'arm', [])).toBe(true)
})
test('etapeAvisStepIsComplete', () => {
expect(etapeAvisStepIsComplete({ typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives }, [{ avis_type_id: 'autreAvis' }], 'arm', []).valid).toBe(false)
expect(etapeAvisStepIsComplete({ typeId: ETAPES_TYPES.avisDesCollectivites }, [{ avis_type_id: 'autreAvis' }], 'arm', []).valid).toBe(true)
})
import { describe, expect, test } from 'vitest'
import { AdministrationId } from '../static/administrations'
import { canEditDemarche, canCreateTravaux, canDeleteDemarche, canCreateDemarche, canPublishResultatMiseEnConcurrence } from './titres-demarches'
import { canEditDemarche, canCreateTravaux, canDeleteDemarche, canCreateDemarche, canPublishResultatMiseEnConcurrence, canCreateEtapeByDemarche } from './titres-demarches'
import { testBlankUser, TestUser } from '../tests-utils'
import { TitresStatutIds } from '../static/titresStatuts'
import { caminoDateValidator, dateAddDays, toCaminoDate } from '../date'
......@@ -218,3 +218,7 @@ describe('canPublishResultatMiseEnConcurrence', () => {
`)
})
})
test('canCreateEtapeByDemarche', () => {
canCreateEtapeByDemarche({ ...testBlankUser, role: 'super' }, 'arm', 'oct', [], 'dmi')
})
......@@ -17,6 +17,7 @@ import {
isEtapeDeposable,
InputPresence,
canEditPerimetre,
canDeposeEtape,
} from './titres-etapes'
import { AdministrationId, ADMINISTRATION_IDS } from '../static/administrations'
import { test, expect, describe, vi } from 'vitest'
......@@ -78,6 +79,7 @@ test.each<{ titreTypeId: TitreTypeId; demarcheTypeId: DemarcheTypeId; etapeTypeI
{ titreTypeId: 'prm', etapeTypeId: 'mfr', demarcheTypeId: 'dep', user: { role: 'lecteur', administrationId: ADMINISTRATION_IDS.BRGM }, canEdit: false },
{ titreTypeId: 'prm', etapeTypeId: 'mfr', demarcheTypeId: 'exp', user: { role: 'super' }, canEdit: false },
{ titreTypeId: 'prm', etapeTypeId: 'mfr', demarcheTypeId: 'mut', user: { role: 'super' }, canEdit: false },
{ titreTypeId: 'prm', etapeTypeId: 'dpu', demarcheTypeId: 'dec', user: { role: 'defaut' }, canEdit: false },
])('canEditDate $titreTypeId | $demarcheTypeId | $etapeTypeId | $user | $canEdit', ({ titreTypeId, demarcheTypeId, etapeTypeId, user, canEdit }) => {
expect(canEditDates(titreTypeId, demarcheTypeId, etapeTypeId, { ...user, ...testBlankUser }).visibility === 'present').toEqual(canEdit)
})
......@@ -312,6 +314,13 @@ test('une entreprise peut modifier sa demande mais ne peut pas la supprimer', ()
expect(canDeleteEtape(user, 'mfr', ETAPE_IS_BROUILLON, [entrepriseId], [], 'oct', { typeId: 'arm', titreStatutId: 'ind' })).toBe(false)
})
test('canDeleteEtape', () => {
const entrepriseId = entrepriseIdValidator.parse('entrepriseId')
const user: EntrepriseUserNotNull = { ...testBlankUser, role: 'entreprise', entrepriseIds: [entrepriseId] }
expect(canDeleteEtape(user, 'mfr', ETAPE_IS_BROUILLON, [entrepriseId], [], 'oct', { typeId: 'arm', titreStatutId: 'ind' })).toBe(false)
expect(canDeleteEtape({ ...testBlankUser, role: 'super' }, 'mfr', ETAPE_IS_BROUILLON, [entrepriseId], [], 'oct', { typeId: 'arm', titreStatutId: 'ind' })).toBe(true)
})
const multiPolygonWith4Points: FeatureMultiPolygon = {
type: 'Feature',
properties: {},
......@@ -581,6 +590,28 @@ test.each<[number | null, EtapeTypeId, TitreTypeId, IsEtapeCompleteDocuments, Is
}
})
describe('canDeposeEtape', () => {
test("Une demande d'ARM complète brouillon", () => {
expect(
canDeposeEtape(
{ ...testBlankUser, role: 'super' },
{
typeId: 'arm',
titreStatutId: 'dmi',
titulaires: [],
administrationsLocales: [],
},
'oct',
{ ...etapeComplete, isBrouillon: ETAPE_IS_BROUILLON, contenu: { arm: { mecanise: { value: false, etapeHeritee: null, heritee: false } } } },
[...armDocuments],
[...armEntrepriseDocuments],
[],
[],
[]
)
).toStrictEqual(true)
})
})
describe('isEtapeDeposable', () => {
test("Une demande d'ARM complète brouillon", () => {
expect(
......
import { test, expect } from 'vitest'
import { getRestRoute } from './rest'
import { getRestRoute, isCaminoRestRoute } from './rest'
import { utilisateurIdValidator } from './roles'
test('getRestRoute', () => {
......@@ -9,3 +9,8 @@ test('getRestRoute', () => {
)
expect(getRestRoute('/rest/utilisateurs/:id/newsletter', { id: utilisateurIdValidator.parse('userId') }, { toto: 'plop' })).toBe('/rest/utilisateurs/userId/newsletter?toto=plop')
})
test('isCaminoRestRoute', () => {
expect(isCaminoRestRoute('/toto')).toBe(false)
expect(isCaminoRestRoute('/rest/utilisateurs/:id/newsletter')).toBe(true)
})
......@@ -11,6 +11,11 @@ import {
isBureauDEtudes,
BaseUserNotNull,
toUtilisateurId,
isAdministrationRole,
isSuperRole,
isDefautRole,
isEntrepriseRole,
isEntrepriseOrBureauDetudeRole,
} from './roles'
import { ADMINISTRATION_IDS } from './static/administrations'
import { test, expect, describe } from 'vitest'
......@@ -105,4 +110,10 @@ test('isRole', () => {
expect(isRole('')).toBe(false)
expect(isRole(undefined)).toBe(false)
expect(isRole(null)).toBe(false)
expect(isAdministrationRole('defaut')).toBe(false)
expect(isSuperRole('defaut')).toBe(false)
expect(isDefautRole('defaut')).toBe(true)
expect(isEntrepriseRole('defaut')).toBe(false)
expect(isEntrepriseOrBureauDetudeRole('defaut')).toBe(false)
})
import { test, expect } from 'vitest'
import { isRadioElement, simpleContenuToFlattenedContenu, valeurFind } from './sections'
import { caminoDateValidator } from './date'
import { flattenContenuToSimpleContenu, isRadioElement, simpleContenuToFlattenedContenu, valeurFind } from './sections'
import { caminoDateValidator, toCaminoDate } from './date'
test('valeurFind', () => {
expect(valeurFind({ id: 'camino', type: 'text', value: null, optionnel: false })).toBe('')
......@@ -19,6 +19,15 @@ test('valeurFind', () => {
optionnel: false,
})
).toBe('A, B')
expect(
valeurFind({
id: 'camino',
type: 'checkboxes',
value: ['c'],
options: [{ id: 'a', nom: 'A' }],
optionnel: false,
})
).toBe('')
expect(
valeurFind({
id: 'camino',
......@@ -60,6 +69,7 @@ test('valeurFind', () => {
expect(valeurFind({ id: 'camino', type: 'radio', value: false, optionnel: false })).toBe('Non')
expect(valeurFind({ id: 'camino', type: 'checkbox', value: true, optionnel: false })).toBe('Oui')
expect(valeurFind({ id: 'camino', type: 'checkbox', value: false, optionnel: false })).toBe('Non')
expect(valeurFind({ id: 'camino', type: 'checkbox', value: null, optionnel: false })).toBe('')
expect(valeurFind({ id: 'camino', type: 'url', value: 'test', optionnel: false })).toBe('test')
})
......@@ -125,4 +135,64 @@ test('simpleContenuToFlattenedContenu', () => {
},
}
`)
expect(
simpleContenuToFlattenedContenu(
'arm',
'oct',
'mfr',
{ arm: {} },
{ arm: { mecanise: { actif: true, etape: { date: caminoDateValidator.parse('2023-02-02'), typeId: 'mfr', contenu: { arm: {} } } } } }
)
).toMatchInlineSnapshot(`
{
"arm": {
"franchissements": {
"etapeHeritee": null,
"heritee": false,
"value": null,
},
"mecanise": {
"etapeHeritee": {
"date": "2023-02-02",
"etapeTypeId": "mfr",
"value": null,
},
"heritee": true,
"value": null,
},
},
}
`)
})
test('flattenContenuToSimpleContenu', () => {
expect(
flattenContenuToSimpleContenu({
plop: undefined,
arm: {
franchissements: {
etapeHeritee: null,
heritee: false,
value: null,
},
mecanise: {
etapeHeritee: {
date: toCaminoDate('2023-02-02'),
etapeTypeId: 'mfr',
value: false,
},
heritee: false,
value: true,
},
},
})
).toMatchInlineSnapshot(`
{
"arm": {
"franchissements": null,
"mecanise": true,
},
"plop": {},
}
`)
})
......@@ -12,7 +12,7 @@ import {
urlElementValidator,
} from './static/titresTypes_demarchesTypes_etapesTypes/sections'
import { z } from 'zod'
import { DeepReadonly, isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty, isNullOrUndefined } from './typescript-tools'
import { DeepReadonly, isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty } from './typescript-tools'
import { TitreTypeId } from './static/titresTypes'
import { DemarcheTypeId } from './static/demarchesTypes'
import { EtapeTypeId } from './static/etapesTypes'
......@@ -93,9 +93,7 @@ export const valeurFind = (element: ElementWithValue): string | '–' => {
}
if (element.type === 'radio' || element.type === 'checkbox') {
if (isNullOrUndefined(element.value)) return ''
else if (element.value) return 'Oui'
else return 'Non'
return element.value ? 'Oui' : 'Non'
}
return element.value
......@@ -134,10 +132,10 @@ export const simpleContenuToFlattenedContenu = (
}
export const flattenContenuToSimpleContenu = (flattenContenu: FlattenEtape['contenu']): RestEtapeCreation['contenu'] => {
return Object.keys(flattenContenu).reduce<RestEtapeCreation['contenu']>((sectionsAcc, section) => {
return Object.entries(flattenContenu).reduce<RestEtapeCreation['contenu']>((sectionsAcc, [section, value]) => {
sectionsAcc = {
...sectionsAcc,
[section]: Object.keys(flattenContenu[section] ?? {}).reduce<RestEtapeCreation['contenu'][string]>((elementsAcc, element) => {
[section]: Object.keys(value ?? {}).reduce<RestEtapeCreation['contenu'][string]>((elementsAcc, element) => {
elementsAcc = { ...elementsAcc, [element]: flattenContenu[section]?.[element]?.value ?? null }
return elementsAcc
......
import { getEntriesHardcore } from '../typescript-tools'
import { getEntriesHardcore, NonEmptyArray } from '../typescript-tools'
import { EtapesStatuts, EtapeStatut, EtapeStatutId, ETAPES_STATUTS } from './etapesStatuts'
import { ETAPES_TYPES, EtapeTypeId } from './etapesTypes'
......@@ -246,7 +246,7 @@ type GetStuff<T> = T extends { [key in keyof typeof ETAPES_TYPES]: { [other in k
export type EtapeTypeEtapeStatutValidPair = GetStuff<typeof EtapesTypesEtapesStatuts>
const etapesTypeEntries = getEntriesHardcore(ETAPES_TYPES)
export const getEtapesStatuts = (etapeTypeIdToFind: EtapeTypeId): EtapeStatut[] => {
export const getEtapesStatuts = (etapeTypeIdToFind: EtapeTypeId): NonEmptyArray<EtapeStatut> => {
const entry = etapesTypeEntries.find(([_key, value]) => value === etapeTypeIdToFind)
if (!entry) {
throw new Error("Cas impossible, cet etapeTypeId n'existe pas")
......@@ -254,5 +254,5 @@ export const getEtapesStatuts = (etapeTypeIdToFind: EtapeTypeId): EtapeStatut[]
const etapesTypesEtapesStatutsKey = entry[0]
const tuple = EtapesTypesEtapesStatuts[etapesTypesEtapesStatutsKey]
return Object.values(tuple).map(({ etapeStatutId }: { etapeStatutId: EtapeStatutId }) => EtapesStatuts[etapeStatutId])
return Object.values(tuple).map(({ etapeStatutId }: { etapeStatutId: EtapeStatutId }) => EtapesStatuts[etapeStatutId]) as NonEmptyArray<EtapeStatut>
}