ldc-arcadia-genesis-php-client/tests/Unit/Lib/ApiDto/IncoCompoTest.php

452 lines
18 KiB
PHP
Raw Permalink Normal View History

<?php
declare(strict_types=1);
namespace Tests\Unit\Lib\ApiDto;
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto;
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\IncoCompo;
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\IncoCompo\AbstractIncoCompoPartDto;
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\IncoCompo\AcideGras;
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\IncoCompo\AcidesAmines;
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\IncoCompo\ApportsReference;
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\IncoCompo\ComposesSpeciaux;
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\IncoCompo\Energie;
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\IncoCompo\FruitLegumeNoix;
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\IncoCompo\GlucidesDetail;
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\IncoCompo\Identification;
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\IncoCompo\MacronutrimentsPortion;
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\IncoCompo\MacronutrimentsRef;
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\IncoCompo\Mineraux;
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\IncoCompo\NutriScore;
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\IncoCompo\PointsNutriScore;
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\IncoCompo\Vitamines;
use Uwil\ArcadiaApiPhpClient\Lib\ApiValueObject\IncoCompoId;
use Uwil\ArcadiaApiPhpClient\Lib\ApiValueObject\IncoId;
/**
* Creates an AcideGras instance with all 60 fields populated.
*/
function createCompleteAcideGras(): AcideGras
{
return new AcideGras(
nutFd: '10.5',
nutChol: '60',
nutAgt: '0.1',
nutFformiq: '0',
nutFacetiq: '0',
nutFpropioniq: '0',
nutFbutyriq: '0',
nutFvaleriq: '0',
nutFcaproiq: '0',
nutFenatiq: '0',
nutFcapryliq: '0',
nutFpelargoniq: '0',
nutFcapriq: '0',
nutFundecyliq: '0',
nutFlauriq: '0.05',
nutFtridecyliq: '0',
nutFmyristiq: '0.1',
nutFpentadecyliq: '0',
nutF16d0: '2.5',
nutFmargariq: '0',
nutFsteariq: '1.2',
nutFarachidiq: '0.05',
nutFheneicosyliq: '0',
nutFbeheniq: '0',
nutFtricosiliq: '0',
nutFlignoceriq: '0',
nutFcarboceriq: '0',
nutFcerotiq: '0',
nutFceroplastiq: '0',
nutFmontaniq: '0',
nutFnonacosyliq: '0',
nutFmelissiq: '0',
nutFlaceroiq: '0',
nutFhentriacontyliq: '0',
nutFhextriacontyliq: '0',
nutFheptatriacontyliq: '0',
nutFoctatriacontyliq: '0',
nutFnonadylique: '0',
nutFpsylliq: '0',
nutFpalm: '0.3',
nutFoleiq: '3.8',
nutF18d: '0',
nutF19d: '0',
nutF11eico: '0.1',
nutFgeddiq: '0',
nutFeruciq: '0',
nutFnervoniq: '0',
nutFhyeniq: '0',
nutFamscis: '4.2',
nutF18d2cn6: '1.8',
nutF18d3n3: '0.2',
nutF20d4: '0.05',
nutF20d5n3: '0.02',
nutF22d6n3: '0.03',
nutFapun3: '0.25',
nutFapun6: '1.85',
nutFapun9: '0',
nutFapucis: '2.1',
nutFapulc: '0.1',
);
}
/**
* Creates a complete IncoCompo object graph with all 14 nutritional parts.
*/
function createCompleteIncoCompo(
string $id = '10',
string $idInco = '20',
): IncoCompo {
return new IncoCompo(
id: new IncoCompoId($id),
idInco: new IncoId($idInco),
identification: new Identification(
nom: 'Composition Poulet',
numero: 'COMP-001',
source: 'Laboratoire LDC',
),
energie: new Energie(
tailleReference: '100g',
valEnergKjReference: '650',
valEnergKcalReference: '155',
taillePortion: '150g',
valEnergKjPortion: '975',
valEnergKcalPortion: '232.5',
),
macronutrimentsRef: new MacronutrimentsRef(
matGrassReference: '10.5',
matGrassReferencePrec: '=',
acideGrasSatureReference: '2.5',
acideGrasSatureReferencePrec: '=',
glucidesReference: '1.0',
glucidesReferencePrec: '<',
sucreReference: '0.5',
sucreReferencePrec: '<',
fibAlimReference: '0.8',
fibAlimReferencePrec: '=',
proteineReference: '22.0',
proteineReferencePrec: '=',
selReference: '1.2',
selReferencePrec: '=',
sodiumReference: '0.48',
),
macronutrimentsPortion: new MacronutrimentsPortion(
matGrassPortion: '15.75',
matGrassPortionPrec: '=',
acideGrasSaturePortion: '3.75',
acideGrasSaturePortionPrec: '=',
glucidesPortion: '1.5',
glucidesPortionPrec: '<',
sucrePortion: '0.75',
sucrePortionPrec: '<',
fibAlimPortion: '1.2',
fibAlimPortionPrec: '=',
proteinePortion: '33.0',
proteinePortionPrec: '=',
selPortion: '1.8',
selPortionPrec: '=',
sodiumPortion: '0.72',
),
fnl: new FruitLegumeNoix(
fruitsReference: '0',
fruitsCoqueSechReference: '0',
fruitsPortion: '0',
fruitsCoqueSechPortion: '0',
fruitLegumeNoixFrais: '0',
fruitLegumeNoixFraisPortion: '0',
pourcentFruitsLegumesNoixFrais: '0',
pourcentFruits: '0',
),
apportsReference: new ApportsReference(
pourcentApportRefE14P: '12%',
pourcentApportRefKjoP: '12%',
pourcentApportRefFatP: '15%',
pourcentApportRefFatsatP: '13%',
pourcentApportRefChovalP: '1%',
pourcentApportRefSugarP: '1%',
pourcentApportRefProP: '44%',
pourcentApportRefSalteqP: '20%',
apportPort: '150g',
pSurL: '2.1',
),
nutriScore: new NutriScore(
composanteN: '5',
composanteN2022: '5',
composanteP: '2',
composanteP2022: '2',
scoreNutri: '3',
scoreNutri2022: '3',
classement: 'B',
nutriScore2022: 'B',
nutriAArt: 'Non',
viandeRouge: 'Non',
),
pointsNutriScore: new PointsNutriScore(
pointsEnergie: '1',
pointsAcideGrasSature: '1',
pointsSucres: '0',
pointsSel: '1',
pointsFibres: '0',
pointsProteines: '4',
pointsFruitsLegumesNoixFrais: '0',
),
mineraux: new Mineraux(
nutCa: '12',
nutMg: '25',
nutK: '300',
nutP: '200',
nutCld: '50',
nutFe: '1.5',
nutZn: '2.0',
nutCu: '0.1',
nutMn: '0.05',
nutSe: '15',
nutId: '10',
nutCr: '5',
nutMo: '8',
nutS6: '2',
nutNitra: '0',
),
vitamines: new Vitamines(
nutVita: '20',
nutVitb6: '0.4',
nutVitb12: '1.2',
nutVitc: '5',
nutVitd: '0.2',
nutVite: '1.0',
nutVitk: '10',
nutChocal: '0.1',
nutNia: '8.0',
nutRibf: '0.2',
nutThia: '0.1',
nutPantac: '0.8',
nutBiot: '5',
nutFoldfe: '25',
),
glucidesDetail: new GlucidesDetail(
nutStarch: '0.5',
nutMaltdex: '0',
nutSucs: '0.1',
nutGlus: '0.1',
nutLacs: '0',
nutMals: '0',
nutGalfb: '0',
nutGHc: '0',
nutFrufb: '0',
nutFrus: '0.1',
nutOlsac: '0',
nutPolyl: '0',
nutFibsol: '0.3',
nutInotl: '0',
),
acideGras: createCompleteAcideGras(),
acidesAmines: new AcidesAmines(
nutAae: '15',
nutCasn: '0',
nutWhey: '0',
),
composesSpeciaux: new ComposesSpeciaux(
nutCholn: '30',
nutCarnitine: '10',
nutTau: '5',
nutNucleotide: '2',
),
);
}
describe('IncoCompo DTO test', function (): void {
it('can instantiate IncoCompo with complete 14-part nutrition graph', function (): void {
// GIVEN
$compo = createCompleteIncoCompo('10', '20');
// THEN
expect($compo)->toBeInstanceOf(IncoCompo::class)
->and($compo)->toBeInstanceOf(Dto::class)
->and($compo->id)->toBeInstanceOf(IncoCompoId::class)
->and($compo->id->value)->toBe('10')
->and($compo->idInco)->toBeInstanceOf(IncoId::class)
->and($compo->idInco->value)->toBe('20');
// Verify all 14 parts are instances of AbstractIncoCompoPartDto
expect($compo->identification)->toBeInstanceOf(Identification::class)
->and($compo->identification)->toBeInstanceOf(AbstractIncoCompoPartDto::class)
->and($compo->identification->nom)->toBe('Composition Poulet')
->and($compo->identification->numero)->toBe('COMP-001')
->and($compo->identification->source)->toBe('Laboratoire LDC');
expect($compo->energie)->toBeInstanceOf(Energie::class)
->and($compo->energie)->toBeInstanceOf(AbstractIncoCompoPartDto::class)
->and($compo->energie->valEnergKcalReference)->toBe('155')
->and($compo->energie->valEnergKcalPortion)->toBe('232.5');
expect($compo->macronutrimentsRef)->toBeInstanceOf(MacronutrimentsRef::class)
->and($compo->macronutrimentsRef)->toBeInstanceOf(AbstractIncoCompoPartDto::class)
->and($compo->macronutrimentsRef->proteineReference)->toBe('22.0');
expect($compo->macronutrimentsPortion)->toBeInstanceOf(MacronutrimentsPortion::class)
->and($compo->macronutrimentsPortion)->toBeInstanceOf(AbstractIncoCompoPartDto::class)
->and($compo->macronutrimentsPortion->proteinePortion)->toBe('33.0');
expect($compo->fnl)->toBeInstanceOf(FruitLegumeNoix::class)
->and($compo->fnl)->toBeInstanceOf(AbstractIncoCompoPartDto::class);
expect($compo->apportsReference)->toBeInstanceOf(ApportsReference::class)
->and($compo->apportsReference)->toBeInstanceOf(AbstractIncoCompoPartDto::class)
->and($compo->apportsReference->pSurL)->toBe('2.1');
expect($compo->nutriScore)->toBeInstanceOf(NutriScore::class)
->and($compo->nutriScore)->toBeInstanceOf(AbstractIncoCompoPartDto::class)
->and($compo->nutriScore->classement)->toBe('B');
expect($compo->pointsNutriScore)->toBeInstanceOf(PointsNutriScore::class)
->and($compo->pointsNutriScore)->toBeInstanceOf(AbstractIncoCompoPartDto::class)
->and($compo->pointsNutriScore->pointsProteines)->toBe('4');
expect($compo->mineraux)->toBeInstanceOf(Mineraux::class)
->and($compo->mineraux)->toBeInstanceOf(AbstractIncoCompoPartDto::class)
->and($compo->mineraux->nutCa)->toBe('12');
expect($compo->vitamines)->toBeInstanceOf(Vitamines::class)
->and($compo->vitamines)->toBeInstanceOf(AbstractIncoCompoPartDto::class)
->and($compo->vitamines->nutVita)->toBe('20');
expect($compo->glucidesDetail)->toBeInstanceOf(GlucidesDetail::class)
->and($compo->glucidesDetail)->toBeInstanceOf(AbstractIncoCompoPartDto::class)
->and($compo->glucidesDetail->nutStarch)->toBe('0.5');
expect($compo->acideGras)->toBeInstanceOf(AcideGras::class)
->and($compo->acideGras)->toBeInstanceOf(AbstractIncoCompoPartDto::class)
->and($compo->acideGras->nutFd)->toBe('10.5')
->and($compo->acideGras->nutChol)->toBe('60');
expect($compo->acidesAmines)->toBeInstanceOf(AcidesAmines::class)
->and($compo->acidesAmines)->toBeInstanceOf(AbstractIncoCompoPartDto::class)
->and($compo->acidesAmines->nutAae)->toBe('15');
expect($compo->composesSpeciaux)->toBeInstanceOf(ComposesSpeciaux::class)
->and($compo->composesSpeciaux)->toBeInstanceOf(AbstractIncoCompoPartDto::class)
->and($compo->composesSpeciaux->nutCholn)->toBe('30');
});
it('can jsonSerialize complete IncoCompo graph recursively', function (): void {
// GIVEN
$compo = createCompleteIncoCompo('10', '20');
// WHEN
$serialized = $compo->jsonSerialize();
// THEN
expect($serialized)->toBeArray()
->and($serialized['id'])->toBe('10')
->and($serialized['idInco'])->toBe('20')
->and($serialized['identification'])->toBe($compo->identification)
->and($serialized['energie'])->toBe($compo->energie)
->and($serialized['macronutrimentsRef'])->toBe($compo->macronutrimentsRef)
->and($serialized['macronutrimentsPortion'])->toBe($compo->macronutrimentsPortion)
->and($serialized['fnl'])->toBe($compo->fnl)
->and($serialized['apportsReference'])->toBe($compo->apportsReference)
->and($serialized['nutriScore'])->toBe($compo->nutriScore)
->and($serialized['pointsNutriScore'])->toBe($compo->pointsNutriScore)
->and($serialized['mineraux'])->toBe($compo->mineraux)
->and($serialized['vitamines'])->toBe($compo->vitamines)
->and($serialized['glucidesDetail'])->toBe($compo->glucidesDetail)
->and($serialized['acideGras'])->toBe($compo->acideGras)
->and($serialized['acidesAmines'])->toBe($compo->acidesAmines)
->and($serialized['composesSpeciaux'])->toBe($compo->composesSpeciaux);
// Recursive json_encode check
$jsonString = json_encode($compo);
expect($jsonString)->toBeString();
$decoded = json_decode((string) $jsonString, true);
expect($decoded)->toBeArray()
->and($decoded['id'])->toBe('10')
->and($decoded['idInco'])->toBe('20')
->and($decoded['identification']['nom'])->toBe('Composition Poulet')
->and($decoded['energie']['valEnergKcalReference'])->toBe('155')
->and($decoded['macronutrimentsRef']['proteineReference'])->toBe('22.0')
->and($decoded['nutriScore']['classement'])->toBe('B')
->and($decoded['mineraux']['nutCa'])->toBe('12')
->and($decoded['vitamines']['nutVita'])->toBe('20')
->and($decoded['acideGras']['nutChol'])->toBe('60')
->and($decoded['acidesAmines']['nutAae'])->toBe('15')
->and($decoded['composesSpeciaux']['nutCholn'])->toBe('30');
});
it('exercises humanReadableValues and units across compo parts', function (): void {
// GIVEN
$compo = createCompleteIncoCompo();
// WHEN & THEN: Energie
$energyValues = $compo->energie->humanReadableValues();
expect($energyValues)->toBeArray()
->and($energyValues['Taille de référence'])->toBe('100g')
->and($energyValues['Énergie (kJ) / 100g'])->toBe('650')
->and($energyValues['Énergie (kcal) / 100g'])->toBe('155');
$energyUnits = Energie::units();
expect($energyUnits['valEnergKjReference'])->toBe('kJ')
->and($energyUnits['valEnergKcalReference'])->toBe('kcal');
// Energie string cast
$energyString = (string) $compo->energie;
expect($energyString)->toContain('Taille de référence : 100g')
->and($energyString)->toContain('Énergie (kcal) / 100g : 155 kcal');
// Identification human readable
$identValues = $compo->identification->humanReadableValues();
expect($identValues['Nom'])->toBe('Composition Poulet')
->and($identValues['Numéro'])->toBe('COMP-001')
->and($identValues['Source'])->toBe('Laboratoire LDC');
// NutriScore human readable
$nsValues = $compo->nutriScore->humanReadableValues();
expect($nsValues['Classement (A-E)'])->toBe('B');
// AcideGras units
$agUnits = AcideGras::units();
expect($agUnits['nutChol'])->toBe('mg')
->and($agUnits['nutFd'])->toBe('g');
});
it('covers fieldLabels, fieldUnits, humanReadableValues, units, humanReadableUnits, and string cast for all 14 nutritional parts', function (
string $partClass,
string $property
): void {
// GIVEN
$compo = createCompleteIncoCompo();
/** @var AbstractIncoCompoPartDto $part */
$part = $compo->{$property};
// WHEN
$humanValues = $part->humanReadableValues();
$arrayValues = $part->toArray();
$units = $partClass::units();
$humanUnits = $partClass::humanReadableUnits();
$asString = (string) $part;
// THEN
expect($humanValues)->toBeArray()->not->toBeEmpty()
->and($arrayValues)->toBeArray()->not->toBeEmpty()
->and($units)->toBeArray()->not->toBeEmpty()
->and($humanUnits)->toBeArray()->not->toBeEmpty()
->and($asString)->toBeString()->not->toBeEmpty();
})->with([
'Identification' => [Identification::class, 'identification'],
'Energie' => [Energie::class, 'energie'],
'MacronutrimentsRef' => [MacronutrimentsRef::class, 'macronutrimentsRef'],
'MacronutrimentsPortion' => [MacronutrimentsPortion::class, 'macronutrimentsPortion'],
'FruitLegumeNoix' => [FruitLegumeNoix::class, 'fnl'],
'ApportsReference' => [ApportsReference::class, 'apportsReference'],
'NutriScore' => [NutriScore::class, 'nutriScore'],
'PointsNutriScore' => [PointsNutriScore::class, 'pointsNutriScore'],
'Mineraux' => [Mineraux::class, 'mineraux'],
'Vitamines' => [Vitamines::class, 'vitamines'],
'GlucidesDetail' => [GlucidesDetail::class, 'glucidesDetail'],
'AcideGras' => [AcideGras::class, 'acideGras'],
'AcidesAmines' => [AcidesAmines::class, 'acidesAmines'],
'ComposesSpeciaux' => [ComposesSpeciaux::class, 'composesSpeciaux'],
]);
});