@open3cl/engine 1.8.8 → 1.8.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/13.2_generateur_combustion.js +116 -31
- package/13.2_generateur_combustion.spec.js +286 -2
- package/13.2_generateur_combustion_pn.js +248 -0
- package/13.2_generateur_combustion_pn.spec.js +476 -0
- package/9_besoin_ch.js +26 -1
- package/9_besoin_ch.spec.js +151 -2
- package/9_generateur_ch.js +46 -0
- package/9_generateur_ch.spec.js +67 -0
- package/README.md +24 -24
- package/conso.js +178 -4
- package/conso.spec.js +187 -1
- package/engine.js +7 -4
- package/features/engine/domain/apport_et_besoin/ch/perte-ch-recup.service.js +54 -8
- package/features/engine/domain/apport_et_besoin/ch/perte-ch-recup.service.spec.js +185 -0
- package/package.json +1 -1
- package/utils.js +5 -0
- package/utils.spec.js +53 -0
package/engine.js
CHANGED
|
@@ -33,7 +33,7 @@ import getFicheTechnique from './ficheTechnique.js';
|
|
|
33
33
|
import { ProductionENR } from './16.2_production_enr.js';
|
|
34
34
|
import DpeSanitizerService from './dpe-sanitizer.service.js';
|
|
35
35
|
|
|
36
|
-
const LIB_VERSION = '1.8.
|
|
36
|
+
const LIB_VERSION = '1.8.10';
|
|
37
37
|
|
|
38
38
|
const dpeSanitizerService = new DpeSanitizerService();
|
|
39
39
|
|
|
@@ -573,7 +573,8 @@ export function calcul_3cl(inputDpe, options) {
|
|
|
573
573
|
prorataECS,
|
|
574
574
|
prorataChauffage,
|
|
575
575
|
dateDpe,
|
|
576
|
-
coef_ep
|
|
576
|
+
coef_ep,
|
|
577
|
+
th === 'immeuble' ? Nb_lgt : 1
|
|
577
578
|
);
|
|
578
579
|
|
|
579
580
|
const production_electricite = productionENR.calculateEnr(
|
|
@@ -595,7 +596,8 @@ export function calcul_3cl(inputDpe, options) {
|
|
|
595
596
|
prorataECS,
|
|
596
597
|
prorataChauffage,
|
|
597
598
|
dateDpe,
|
|
598
|
-
coef_ep_1_7
|
|
599
|
+
coef_ep_1_7,
|
|
600
|
+
th === 'immeuble' ? Nb_lgt : 1
|
|
599
601
|
);
|
|
600
602
|
|
|
601
603
|
productionENR.calculateEnr(
|
|
@@ -618,7 +620,8 @@ export function calcul_3cl(inputDpe, options) {
|
|
|
618
620
|
prorataECS,
|
|
619
621
|
prorataChauffage,
|
|
620
622
|
dateDpe,
|
|
621
|
-
coef_ep_2_3
|
|
623
|
+
coef_ep_2_3,
|
|
624
|
+
th === 'immeuble' ? Nb_lgt : 1
|
|
622
625
|
);
|
|
623
626
|
|
|
624
627
|
productionENR.calculateEnr(
|
|
@@ -52,27 +52,73 @@ export class PerteChRecupService {
|
|
|
52
52
|
*/
|
|
53
53
|
pertesGenerateurChRecup(ctx, logement, depensier) {
|
|
54
54
|
const generateursWithPertesGeneration = this.generateursWithPertesGeneration(logement);
|
|
55
|
+
const generateursEcsSeulsWithPertesGeneration =
|
|
56
|
+
this.generateursEcsSeulsWithPertesGeneration(logement);
|
|
55
57
|
|
|
56
58
|
return mois_liste.reduce((acc, mois) => {
|
|
59
|
+
const nref = this.#tvStore.getData(
|
|
60
|
+
depensier ? 'nref21' : 'nref19',
|
|
61
|
+
ctx.altitude.value,
|
|
62
|
+
ctx.zoneClimatique.value,
|
|
63
|
+
mois,
|
|
64
|
+
ctx.inertie.ilpa
|
|
65
|
+
);
|
|
57
66
|
return (
|
|
58
67
|
acc +
|
|
59
68
|
this.Qrec(
|
|
60
69
|
generateursWithPertesGeneration,
|
|
61
|
-
|
|
62
|
-
depensier ? 'nref21' : 'nref19',
|
|
63
|
-
ctx.altitude.value,
|
|
64
|
-
ctx.zoneClimatique.value,
|
|
65
|
-
mois,
|
|
66
|
-
ctx.inertie.ilpa
|
|
67
|
-
),
|
|
70
|
+
nref,
|
|
68
71
|
depensier
|
|
69
72
|
? logement.donnees_de_calcul.besoinChauffageDepensierHP[mois]
|
|
70
73
|
: logement.donnees_de_calcul.besoinChauffageHP[mois]
|
|
71
|
-
)
|
|
74
|
+
) +
|
|
75
|
+
this.QrecEcsSeul(generateursEcsSeulsWithPertesGeneration, nref)
|
|
72
76
|
);
|
|
73
77
|
}, 0);
|
|
74
78
|
}
|
|
75
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Générateurs de la collection ECS assurant l'ECS uniquement dont les pertes de génération sont
|
|
82
|
+
* récupérées pour le chauffage (issue #153) :
|
|
83
|
+
* — pertes à l'arrêt Qp0 > 0
|
|
84
|
+
* — situés en volume chauffé
|
|
85
|
+
* — usage ECS uniquement (enum_usage_generateur_id = 2). Les générateurs 'chauffage + ecs' sont
|
|
86
|
+
* déjà pris en compte dans la collection des générateurs de chauffage.
|
|
87
|
+
*
|
|
88
|
+
* @param logement {Logement}
|
|
89
|
+
* @return {GenerateurEcs[]}
|
|
90
|
+
*/
|
|
91
|
+
generateursEcsSeulsWithPertesGeneration(logement) {
|
|
92
|
+
const installationsEcs = logement.installation_ecs_collection?.installation_ecs || [];
|
|
93
|
+
|
|
94
|
+
return installationsEcs.flatMap((installation) =>
|
|
95
|
+
(installation.generateur_ecs_collection?.generateur_ecs || []).filter((generateurEcs) => {
|
|
96
|
+
const generateurEcsDE = generateurEcs.donnee_entree || {};
|
|
97
|
+
const generateurEcsDI = generateurEcs.donnee_intermediaire || {};
|
|
98
|
+
return (
|
|
99
|
+
Number(generateurEcsDI.qp0 || 0) > 0 &&
|
|
100
|
+
Number(generateurEcsDE.position_volume_chauffe ?? 0) === 1 &&
|
|
101
|
+
parseInt(generateurEcsDE.enum_usage_generateur_id) === 2
|
|
102
|
+
);
|
|
103
|
+
})
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Pertes récupérées de génération pour le chauffage sur le mois j (Wh) pour les générateurs
|
|
109
|
+
* assurant l'ECS uniquement : Dperj = Nrefj * 1790 / 8760
|
|
110
|
+
*
|
|
111
|
+
* @param generateurs {GenerateurEcs[]}
|
|
112
|
+
* @param nref {number}
|
|
113
|
+
* @return {number}
|
|
114
|
+
*/
|
|
115
|
+
QrecEcsSeul(generateurs, nref) {
|
|
116
|
+
return generateurs.reduce((acc, generateur) => {
|
|
117
|
+
const Cper = Number(generateur.donnee_entree.presence_ventouse || 0) === 1 ? 0.75 : 0.5;
|
|
118
|
+
return acc + 0.48 * Cper * generateur.donnee_intermediaire.qp0 * this.#pertes_gen_ecs(nref);
|
|
119
|
+
}, 0);
|
|
120
|
+
}
|
|
121
|
+
|
|
76
122
|
/**
|
|
77
123
|
* Pertes récupérées des générateurs de chauffage pour le chauffage
|
|
78
124
|
* 9.1.1 Consommation de chauffage
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
+
import { FrTvStore } from '../../../../dpe/infrastructure/froid/frTv.store.js';
|
|
3
|
+
import { PerteChRecupService } from './perte-ch-recup.service.js';
|
|
4
|
+
import { mois_liste } from '../../../../../utils.js';
|
|
5
|
+
|
|
6
|
+
/** @type {PerteChRecupService} **/
|
|
7
|
+
let service;
|
|
8
|
+
|
|
9
|
+
/** @type {FrTvStore} **/
|
|
10
|
+
let tvStore;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 9.1.1 Pertes récupérées de génération pour le chauffage
|
|
14
|
+
* Qgen_rec_j = 0,48 * Cper * Qp0 * Dperj
|
|
15
|
+
* @see : Methode_de_calcul_3CL_DPE_2021-338.pdf - §9.1.1
|
|
16
|
+
*/
|
|
17
|
+
describe('Calcul des pertes récupérées de génération pour le chauffage', () => {
|
|
18
|
+
/** @type {Contexte} */
|
|
19
|
+
const ctx = {
|
|
20
|
+
altitude: { value: '400-800m' },
|
|
21
|
+
zoneClimatique: { value: 'h1a' },
|
|
22
|
+
inertie: { ilpa: 0 }
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/** Besoins de chauffage hors pertes (kWh) : 10 kWh par mois */
|
|
26
|
+
const donneesDeCalcul = {
|
|
27
|
+
besoinChauffageHP: Object.fromEntries(mois_liste.map((m) => [m, 10])),
|
|
28
|
+
besoinChauffageDepensierHP: Object.fromEntries(mois_liste.map((m) => [m, 12]))
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/** Générateur ECS seul (usage 2), en volume chauffé, Qp0 = 100 W */
|
|
32
|
+
function generateurEcs(de = {}, di = { qp0: 100 }) {
|
|
33
|
+
return {
|
|
34
|
+
donnee_entree: {
|
|
35
|
+
enum_usage_generateur_id: 2,
|
|
36
|
+
position_volume_chauffe: 1,
|
|
37
|
+
presence_ventouse: 0,
|
|
38
|
+
...de
|
|
39
|
+
},
|
|
40
|
+
donnee_intermediaire: di
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Logement avec une installation ECS et, optionnellement, des générateurs de chauffage */
|
|
45
|
+
function logement(generateursEcs = [], generateursCh = []) {
|
|
46
|
+
return {
|
|
47
|
+
donnees_de_calcul: donneesDeCalcul,
|
|
48
|
+
installation_ecs_collection: {
|
|
49
|
+
installation_ecs: [{ generateur_ecs_collection: { generateur_ecs: generateursEcs } }]
|
|
50
|
+
},
|
|
51
|
+
installation_chauffage_collection: {
|
|
52
|
+
installation_chauffage: [
|
|
53
|
+
{ generateur_chauffage_collection: { generateur_chauffage: generateursCh } }
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
beforeEach(() => {
|
|
60
|
+
tvStore = new FrTvStore();
|
|
61
|
+
service = new PerteChRecupService(tvStore);
|
|
62
|
+
// Nref constant : 100 h (conventionnel) / 120 h (dépensier) pour chacun des 12 mois
|
|
63
|
+
vi.spyOn(tvStore, 'getData').mockImplementation((type) => (type === 'nref21' ? 120 : 100));
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('Générateurs ECS assurant l’ECS uniquement (issue #153)', () => {
|
|
67
|
+
test('ECS seul sans ventouse : 0,48 * 0,5 * Qp0 * Nref * 1790 / 8760 par mois', () => {
|
|
68
|
+
const result = service.execute(ctx, logement([generateurEcs()]));
|
|
69
|
+
|
|
70
|
+
// 12 * 0.48 * 0.5 * 100 * (100 * 1790 / 8760) / 1000 = 5.884931506... kWh
|
|
71
|
+
expect(result.pertes_generateur_ch_recup).toBeCloseTo(5.884931506849315, 9);
|
|
72
|
+
// 12 * 0.48 * 0.5 * 100 * (120 * 1790 / 8760) / 1000 = 7.061917808... kWh
|
|
73
|
+
expect(result.pertes_generateur_ch_recup_depensier).toBeCloseTo(7.061917808219178, 9);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test('ECS seul avec ventouse : Cper = 0,75', () => {
|
|
77
|
+
const result = service.execute(ctx, logement([generateurEcs({ presence_ventouse: 1 })]));
|
|
78
|
+
expect(result.pertes_generateur_ch_recup).toBeCloseTo(1.5 * 5.884931506849315, 9);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test.each([
|
|
82
|
+
{ cas: 'hors volume chauffé', de: { position_volume_chauffe: 0 }, di: { qp0: 100 } },
|
|
83
|
+
{
|
|
84
|
+
cas: 'position non renseignée',
|
|
85
|
+
de: { position_volume_chauffe: undefined },
|
|
86
|
+
di: { qp0: 100 }
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
cas: "usage 'chauffage + ecs' (déjà compté)",
|
|
90
|
+
de: { enum_usage_generateur_id: 3 },
|
|
91
|
+
di: { qp0: 100 }
|
|
92
|
+
},
|
|
93
|
+
{ cas: 'Qp0 nul', de: {}, di: { qp0: 0 } },
|
|
94
|
+
{ cas: 'Qp0 absent', de: {}, di: null }
|
|
95
|
+
])('pas de récupération pour un générateur ECS $cas', ({ de, di }) => {
|
|
96
|
+
const result = service.execute(ctx, logement([generateurEcs(de, di)]));
|
|
97
|
+
expect(result.pertes_generateur_ch_recup).toBe(0);
|
|
98
|
+
expect(result.pertes_generateur_ch_recup_depensier).toBe(0);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test('logement sans installation ECS ni chauffage : aucune récupération', () => {
|
|
102
|
+
const result = service.execute(ctx, { donnees_de_calcul: donneesDeCalcul });
|
|
103
|
+
expect(result.pertes_generateur_ch_recup).toBe(0);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test('installation ECS sans collection de générateurs : aucune récupération', () => {
|
|
107
|
+
const result = service.execute(ctx, {
|
|
108
|
+
donnees_de_calcul: donneesDeCalcul,
|
|
109
|
+
installation_ecs_collection: { installation_ecs: [{}] }
|
|
110
|
+
});
|
|
111
|
+
expect(result.pertes_generateur_ch_recup).toBe(0);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('Générateurs de chauffage', () => {
|
|
116
|
+
/** Générateur de chauffage en volume chauffé, Pn = 10 000 W, Qp0 = 100 W */
|
|
117
|
+
function generateurCh(de = {}) {
|
|
118
|
+
return {
|
|
119
|
+
donnee_entree: {
|
|
120
|
+
position_volume_chauffe: 1,
|
|
121
|
+
enum_type_generateur_ch_id: 85,
|
|
122
|
+
enum_usage_generateur_id: 1,
|
|
123
|
+
...de
|
|
124
|
+
},
|
|
125
|
+
donnee_intermediaire: { pn: 10000, qp0: 100 }
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
test('usage chauffage : Dperj = min(Nref, 1,3 * Bch / (0,3 * Pn))', () => {
|
|
130
|
+
const result = service.execute(ctx, logement([], [generateurCh()]));
|
|
131
|
+
// Dperj = min(100, 1.3 * 10 * 1000 / 3000) = 4.333.. h
|
|
132
|
+
// 12 * 0.48 * 0.5 * 100 * 4.333.. / 1000 = 1.248 kWh
|
|
133
|
+
expect(result.pertes_generateur_ch_recup).toBeCloseTo(1.248, 9);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test('usage ECS : Dperj = Nref * 1790 / 8760', () => {
|
|
137
|
+
const result = service.execute(
|
|
138
|
+
ctx,
|
|
139
|
+
logement([], [generateurCh({ enum_usage_generateur_id: 2 })])
|
|
140
|
+
);
|
|
141
|
+
expect(result.pertes_generateur_ch_recup).toBeCloseTo(5.884931506849315, 9);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test('usage chauffage + ECS avec ventouse : cumul des deux durées, Cper = 0,75', () => {
|
|
145
|
+
const result = service.execute(
|
|
146
|
+
ctx,
|
|
147
|
+
logement([], [generateurCh({ enum_usage_generateur_id: 3, presence_ventouse: 1 })])
|
|
148
|
+
);
|
|
149
|
+
// Dperj = min(100, 4.333.. + 20.4337..) ; 12 * 0.48 * 0.75 * 100 * Dperj / 1000
|
|
150
|
+
expect(result.pertes_generateur_ch_recup).toBeCloseTo(10.699397260273972, 9);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test.each([
|
|
154
|
+
{ cas: 'hors volume chauffé', de: { position_volume_chauffe: 0 } },
|
|
155
|
+
{ cas: 'à air chaud (50)', de: { enum_type_generateur_ch_id: 50 } },
|
|
156
|
+
{ cas: 'à air chaud (52)', de: { enum_type_generateur_ch_id: 52 } }
|
|
157
|
+
])('pas de récupération pour un générateur de chauffage $cas', ({ de }) => {
|
|
158
|
+
const result = service.execute(ctx, logement([], [generateurCh(de)]));
|
|
159
|
+
expect(result.pertes_generateur_ch_recup).toBe(0);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
test('installation de chauffage sans collection de générateurs : aucune récupération', () => {
|
|
163
|
+
const result = service.execute(ctx, {
|
|
164
|
+
donnees_de_calcul: donneesDeCalcul,
|
|
165
|
+
installation_chauffage_collection: { installation_chauffage: [{}] }
|
|
166
|
+
});
|
|
167
|
+
expect(result.pertes_generateur_ch_recup).toBe(0);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test('cumul générateur de chauffage + générateur ECS seul', () => {
|
|
171
|
+
const result = service.execute(ctx, logement([generateurEcs()], [generateurCh()]));
|
|
172
|
+
expect(result.pertes_generateur_ch_recup).toBeCloseTo(1.248 + 5.884931506849315, 9);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test('un générateur ECS mixte (usage 3) n’est pas compté deux fois', () => {
|
|
176
|
+
const ch = generateurCh({ enum_usage_generateur_id: 3 });
|
|
177
|
+
const seul = service.execute(ctx, logement([], [ch]));
|
|
178
|
+
const avecEcsMixte = service.execute(
|
|
179
|
+
ctx,
|
|
180
|
+
logement([generateurEcs({ enum_usage_generateur_id: 3 })], [ch])
|
|
181
|
+
);
|
|
182
|
+
expect(avecEcsMixte.pertes_generateur_ch_recup).toBe(seul.pertes_generateur_ch_recup);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
});
|
package/package.json
CHANGED
package/utils.js
CHANGED
|
@@ -277,10 +277,15 @@ export function requestInput(de, du, field, type) {
|
|
|
277
277
|
return enums[field][de[enum_name]];
|
|
278
278
|
} else {
|
|
279
279
|
// not enums
|
|
280
|
+
// `!type` couvre aussi NaN, 0 et '' (valeurs falsy)
|
|
280
281
|
if (!type) {
|
|
281
282
|
console.error(`requestInput: type is not defined for ${field}`);
|
|
282
283
|
return null;
|
|
283
284
|
}
|
|
285
|
+
if (!['string', 'number', 'boolean'].includes(typeof type)) {
|
|
286
|
+
console.error(`requestInput: type has an unexpected type (${typeof type}) for ${field}`);
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
284
289
|
du[field] = type;
|
|
285
290
|
return de[field];
|
|
286
291
|
}
|
package/utils.spec.js
CHANGED
|
@@ -287,6 +287,59 @@ describe('Utils unit tests', () => {
|
|
|
287
287
|
spy.mockRestore();
|
|
288
288
|
});
|
|
289
289
|
|
|
290
|
+
test.each([
|
|
291
|
+
['NaN', Number.NaN],
|
|
292
|
+
['0', 0],
|
|
293
|
+
['une chaîne vide', '']
|
|
294
|
+
])(
|
|
295
|
+
'requestInput : champ non enum avec %s comme type est traité comme un type absent',
|
|
296
|
+
(_libelle, type) => {
|
|
297
|
+
const spy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
298
|
+
const de = { epaisseur: 5 };
|
|
299
|
+
const du = {};
|
|
300
|
+
expect(requestInput(de, du, 'epaisseur', type)).toBeNull();
|
|
301
|
+
expect(spy).toHaveBeenCalledWith('requestInput: type is not defined for epaisseur');
|
|
302
|
+
// Le type invalide n'est pas publié dans donnee_utilisateur
|
|
303
|
+
expect(du).toStrictEqual({});
|
|
304
|
+
spy.mockRestore();
|
|
305
|
+
}
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
test.each([
|
|
309
|
+
['un objet', { a: 1 }, 'object'],
|
|
310
|
+
['un tableau', ['number'], 'object'],
|
|
311
|
+
['une fonction', () => 'number', 'function'],
|
|
312
|
+
['un symbole', Symbol('number'), 'symbol'],
|
|
313
|
+
['un bigint', 10n, 'bigint']
|
|
314
|
+
])(
|
|
315
|
+
'requestInput : champ non enum avec %s comme type journalise une erreur et retourne null',
|
|
316
|
+
(_libelle, type, typeAttendu) => {
|
|
317
|
+
const spy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
318
|
+
const de = { epaisseur: 5 };
|
|
319
|
+
const du = {};
|
|
320
|
+
expect(requestInput(de, du, 'epaisseur', type)).toBeNull();
|
|
321
|
+
expect(spy).toHaveBeenCalledWith(
|
|
322
|
+
`requestInput: type has an unexpected type (${typeAttendu}) for epaisseur`
|
|
323
|
+
);
|
|
324
|
+
expect(du).toStrictEqual({});
|
|
325
|
+
spy.mockRestore();
|
|
326
|
+
}
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
test.each([
|
|
330
|
+
['une chaîne', 'string'],
|
|
331
|
+
['un nombre', 1],
|
|
332
|
+
['un booléen', true]
|
|
333
|
+
])('requestInput : champ non enum avec %s comme type est accepté', (_libelle, type) => {
|
|
334
|
+
const spy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
335
|
+
const de = { epaisseur: 5 };
|
|
336
|
+
const du = {};
|
|
337
|
+
expect(requestInput(de, du, 'epaisseur', type)).toBe(5);
|
|
338
|
+
expect(du.epaisseur).toBe(type);
|
|
339
|
+
expect(spy).not.toHaveBeenCalled();
|
|
340
|
+
spy.mockRestore();
|
|
341
|
+
});
|
|
342
|
+
|
|
290
343
|
test('requestInputID : sans type publie les clés et retourne l identifiant', () => {
|
|
291
344
|
const de = { enum_materiaux_id: '1' };
|
|
292
345
|
const du = {};
|