226 lines
10 KiB
PHP
226 lines
10 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Unit\App\Services;
|
|
|
|
use App\Dto\ArcadiaIncoDataDto;
|
|
use App\Dto\ArcadiaIncoPreviewDto;
|
|
use App\Services\ArcadiaIncoService;
|
|
use Domain\Enums\Nutriscore;
|
|
use Psr\Log\LoggerInterface;
|
|
use Uwil\ArcadiaApiPhpClient\Error\ApiError;
|
|
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\Brand;
|
|
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\Inco\Allegations;
|
|
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\Inco\Allergen;
|
|
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\Inco as LibInco;
|
|
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\Inco\Ingredients;
|
|
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\Inco\Nutriscore as IncoNutriscore;
|
|
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\Inco\PortionAmount;
|
|
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 as LibIncoCompo;
|
|
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 as CompoNutriScore;
|
|
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\IncoCompo\PointsNutriScore;
|
|
use Uwil\ArcadiaApiPhpClient\Lib\ApiDto\Dto\IncoCompo\Vitamines;
|
|
use Uwil\ArcadiaApiPhpClient\Lib\ApiValueObject\BrandCode;
|
|
use Uwil\ArcadiaApiPhpClient\Lib\ApiValueObject\IncoCompoId;
|
|
use Uwil\ArcadiaApiPhpClient\Lib\ApiValueObject\IncoId;
|
|
use Uwil\ArcadiaApiPhpClient\Service\IncoService as LibIncoService;
|
|
|
|
describe('ArcadiaIncoService', function (): void {
|
|
it('throws RuntimeException when API returns an ApiError', function (): void {
|
|
// GIVEN
|
|
$incoService = \Mockery::mock(LibIncoService::class);
|
|
$logger = \Mockery::mock(LoggerInterface::class);
|
|
$logger->shouldReceive('debug');
|
|
$logger->shouldReceive('error');
|
|
|
|
$apiError = \Mockery::mock(ApiError::class);
|
|
$apiError->shouldReceive('message')->andReturn('Unauthorized');
|
|
|
|
$incoService->shouldReceive('findBy')
|
|
->once()
|
|
->with(\Mockery::type(IncoId::class))
|
|
->andReturn($apiError);
|
|
|
|
$service = new ArcadiaIncoService($incoService, $logger);
|
|
|
|
// WHEN & THEN
|
|
expect(fn () => $service->fetchInco(27996))->toThrow(\RuntimeException::class, 'Unauthorized');
|
|
});
|
|
|
|
it('returns null when INCO sheet is not found (404)', function (): void {
|
|
// GIVEN
|
|
$incoService = \Mockery::mock(LibIncoService::class);
|
|
$logger = \Mockery::mock(LoggerInterface::class);
|
|
$logger->shouldReceive('debug');
|
|
$logger->shouldReceive('info');
|
|
|
|
$incoService->shouldReceive('findBy')
|
|
->once()
|
|
->with(\Mockery::type(IncoId::class))
|
|
->andReturnNull();
|
|
|
|
$service = new ArcadiaIncoService($incoService, $logger);
|
|
|
|
// WHEN
|
|
$result = $service->fetchInco(99999);
|
|
|
|
// THEN
|
|
expect($result)->toBeNull();
|
|
});
|
|
|
|
it('fetches and maps complete INCO and composition data', function (): void {
|
|
// GIVEN
|
|
$incoService = \Mockery::mock(LibIncoService::class);
|
|
$logger = \Mockery::mock(LoggerInterface::class);
|
|
$logger->shouldReceive('debug');
|
|
$logger->shouldReceive('warning');
|
|
|
|
$incoId = new IncoId('27996');
|
|
$libInco = new LibInco(
|
|
id: $incoId,
|
|
name: 'POULET JAUNE FERMIER',
|
|
libelle: 'Poulet Jaune PAC Le Gaulois',
|
|
description: 'Volaille fermière de qualité.',
|
|
allegations: new Allegations([]),
|
|
sellArguments: 'Un poulet savoureux.',
|
|
preparationAdvices: 'Cuire à 200°C pendant 1h30.',
|
|
tips: 'Arroser régulièrement.',
|
|
sellFamilly: 'VOLAILLES',
|
|
ingredients: new Ingredients([
|
|
'Ingrédients' => ['Poulet Jaune (100%)'],
|
|
]),
|
|
portions: new PortionAmount(4, 5, true),
|
|
allergens: [
|
|
new Allergen(1, 'Aucun allergène'),
|
|
],
|
|
brand: new Brand(new BrandCode('LGL01'), 'Le Gaulois'),
|
|
isSeasonal: false,
|
|
weight: null,
|
|
nutriscore: new IncoNutriscore('A', null),
|
|
storageCondition: null,
|
|
additives: [],
|
|
compo: new IncoCompoId('88888'),
|
|
createdAt: new \DateTimeImmutable('2025-01-01T00:00:00Z'),
|
|
updatedAt: new \DateTimeImmutable('2025-01-01T00:00:00Z'),
|
|
);
|
|
|
|
$libCompo = new LibIncoCompo(
|
|
id: new IncoCompoId('88888'),
|
|
idInco: $incoId,
|
|
identification: new Identification('Poulet Jaune', '27996', 'SNV'),
|
|
energie: new Energie('100', '623', '149', '150', '935', '224'),
|
|
macronutrimentsRef: new MacronutrimentsRef(
|
|
'7.2', '=', '2.0', '=', '0.0', '=', '0.0', '=', '0.0', '=', '21.0', '=', '0.16', '=', '64'
|
|
),
|
|
macronutrimentsPortion: new MacronutrimentsPortion(
|
|
'10.8', '=', '3.0', '=', '0.0', '=', '0.0', '=', '0.0', '=', '31.5', '=', '0.24', '=', '96'
|
|
),
|
|
fnl: new FruitLegumeNoix('0', '0', '0', '0', '0', '0', '0', '0'),
|
|
apportsReference: new ApportsReference(
|
|
'11', '11', '15', '15', '0', '0', '63', '4', '150g', '2.9'
|
|
),
|
|
nutriScore: new CompoNutriScore(
|
|
'2', '2', '5', '5', '-3', '-3', 'A', 'A', '1', '0'
|
|
),
|
|
pointsNutriScore: new PointsNutriScore('0', '0', '0', '0', '0', '0', '0'),
|
|
mineraux: new Mineraux('0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
|
|
vitamines: new Vitamines('0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
|
|
glucidesDetail: new GlucidesDetail('0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'),
|
|
acideGras: new AcideGras(
|
|
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
|
|
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
|
|
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
|
|
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
|
|
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
|
|
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
|
|
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'
|
|
),
|
|
acidesAmines: new AcidesAmines('0', '0', '0'),
|
|
composesSpeciaux: new ComposesSpeciaux('0', '0', '0', '0'),
|
|
);
|
|
|
|
$incoService->shouldReceive('findBy')->once()->andReturn($libInco);
|
|
$incoService->shouldReceive('findCompo')->once()->andReturn($libCompo);
|
|
|
|
$service = new ArcadiaIncoService($incoService, $logger);
|
|
|
|
// WHEN
|
|
$result = $service->fetchInco(27996);
|
|
|
|
// THEN
|
|
expect($result)->toBeInstanceOf(ArcadiaIncoDataDto::class)
|
|
->and($result->noArt)->toBe(27996)
|
|
->and($result->name)->toBe('POULET JAUNE FERMIER')
|
|
->and($result->brand)->toBe('Le Gaulois')
|
|
->and($result->nutriscore)->toBe(Nutriscore::A)
|
|
->and($result->allergens)->toBe('Aucun allergène')
|
|
->and($result->servings)->toBe('entre 4 et 5')
|
|
->and($result->preparation)->toContain('Cuire à 200°C')
|
|
->and($result->ingredients)->toContain('Poulet Jaune (100%)')
|
|
->and($result->nutrition->kj)->toBe(623.0)
|
|
->and($result->nutrition->kcal)->toBe(149.0)
|
|
->and($result->nutrition->fatG)->toBe(7.2)
|
|
->and($result->nutrition->proteinG)->toBe(21.0);
|
|
});
|
|
|
|
it('returns preview DTO correctly', function (): void {
|
|
// GIVEN
|
|
$incoService = \Mockery::mock(LibIncoService::class);
|
|
$logger = \Mockery::mock(LoggerInterface::class);
|
|
$logger->shouldReceive('debug');
|
|
|
|
$incoId = new IncoId('27996');
|
|
$libInco = new LibInco(
|
|
id: $incoId,
|
|
name: 'POULET JAUNE FERMIER',
|
|
libelle: 'Poulet Jaune PAC Le Gaulois',
|
|
description: 'Volaille fermière.',
|
|
allegations: new Allegations([]),
|
|
sellArguments: 'Savoureux.',
|
|
preparationAdvices: 'Four.',
|
|
tips: null,
|
|
sellFamilly: null,
|
|
ingredients: new Ingredients([
|
|
['Poulet'],
|
|
]),
|
|
portions: null,
|
|
allergens: [],
|
|
brand: new Brand(new BrandCode('LGL01'), 'Le Gaulois'),
|
|
isSeasonal: false,
|
|
weight: null,
|
|
nutriscore: new IncoNutriscore('A', null),
|
|
storageCondition: null,
|
|
additives: [],
|
|
compo: null,
|
|
createdAt: null,
|
|
updatedAt: null,
|
|
);
|
|
|
|
$incoService->shouldReceive('findBy')->once()->andReturn($libInco);
|
|
$incoService->shouldReceive('findCompo')->once()->andReturnNull();
|
|
|
|
$service = new ArcadiaIncoService($incoService, $logger);
|
|
|
|
// WHEN
|
|
$preview = $service->getPreview(27996);
|
|
|
|
// THEN
|
|
expect($preview)->toBeInstanceOf(ArcadiaIncoPreviewDto::class)
|
|
->and($preview->noArt)->toBe(27996)
|
|
->and($preview->name)->toBe('POULET JAUNE FERMIER')
|
|
->and($preview->brand)->toBe('Le Gaulois')
|
|
->and($preview->nutriscore)->toBe('A');
|
|
});
|
|
});
|