toBeInstanceOf(Allegations::class) ->and($vo->allegations())->toContain('Sans conservateur') ->and($vo->allegations())->not->toContain('aucun colorant') ->and($vo->health())->toContain('Riche en fer') ->and($vo->nutrition())->toContain('Faible en gras') ->and($vo->other())->toContain('100% français'); }); }); describe('toPortionAmount', function (): void { it('parses exact portion amount', function (): void { $vo = IncoParser::toPortionAmount('4', 'exact'); expect($vo)->toBeInstanceOf(PortionAmount::class) ->and($vo?->lowPart())->toBe(400) ->and($vo?->highPart())->toBe(400) ->and($vo?->approximative())->toBeFalse(); }); it('parses range portion amount like 3/4', function (): void { $vo = IncoParser::toPortionAmount('3/4'); expect($vo)->toBeInstanceOf(PortionAmount::class) ->and($vo?->lowPart())->toBe(300) ->and($vo?->highPart())->toBe(400) ->and($vo?->approximative())->toBeTrue(); }); it('returns null for null or invalid portion', function (): void { expect(IncoParser::toPortionAmount(null))->toBeNull() ->and(IncoParser::toPortionAmount(''))->toBeNull() ->and(IncoParser::toPortionAmount('non-numeric'))->toBeNull(); }); }); describe('toNutriscore', function (): void { it('parses valid nutriscore grade A to E', function (): void { expect(IncoParser::toNutriscore('A')?->grade)->toBe('A') ->and(IncoParser::toNutriscore('b')?->grade)->toBe('B') ->and(IncoParser::toNutriscore('NUTRISCORE: C')?->grade)->toBe('C'); }); it('returns null for invalid nutriscore grade', function (): void { expect(IncoParser::toNutriscore(null))->toBeNull() ->and(IncoParser::toNutriscore('Z'))->toBeNull() ->and(IncoParser::toNutriscore(''))->toBeNull(); }); }); describe('toWeight', function (): void { it('parses net, gross, and average weight', function (): void { $vo = IncoParser::toWeight(300, 320, 310); expect($vo)->toBeInstanceOf(IncoWeight::class) ->and($vo?->netWeight)->toBe(300) ->and($vo?->grossWeight)->toBe(320) ->and($vo?->theoreticalAverage)->toBe(310); }); it('returns null when all weights are null', function (): void { expect(IncoParser::toWeight(null, null, null))->toBeNull(); }); }); describe('toStorageCondition', function (): void { it('parses and cleans storage condition string', function (): void { $vo = IncoParser::toStorageCondition('

A conserver entre 0°C et +4°C

'); expect($vo)->toBeInstanceOf(StorageCondition::class) ->and($vo?->instructions)->toBe('A conserver entre 0°C et +4°C'); }); it('returns null for null or empty condition', function (): void { expect(IncoParser::toStorageCondition(null))->toBeNull() ->and(IncoParser::toStorageCondition(' '))->toBeNull(); }); }); describe('toAdditives', function (): void { it('parses string of delimited additives (code:label;code:label)', function (): void { $raw = 'E250:Nitrite de sodium;E300:Acide ascorbique'; $additives = IncoParser::toAdditives($raw); expect($additives)->toHaveCount(2) ->and($additives[0])->toBeInstanceOf(Additive::class) ->and($additives[0]->code)->toBe('E250') ->and($additives[0]->label)->toBe('Nitrite de sodium') ->and($additives[1]->code)->toBe('E300') ->and($additives[1]->label)->toBe('Acide ascorbique'); }); it('parses array of additive entries', function (): void { $raw = [ ['code' => 'E450', 'libelle' => 'Diphosphates'], ['code' => 'E330', 'libelle' => 'Acide citrique'], ]; $additives = IncoParser::toAdditives($raw); expect($additives)->toHaveCount(2) ->and($additives[0]->code)->toBe('E450') ->and($additives[1]->code)->toBe('E330'); }); }); describe('toAllergens', function (): void { it('parses string of delimited allergens (code:label;code:label)', function (): void { $raw = '1:Gluten;7:Lait'; $allergens = IncoParser::toAllergens($raw); expect($allergens)->toHaveCount(2) ->and($allergens[0])->toBeInstanceOf(Allergen::class) ->and($allergens[0]->code)->toBe(1) ->and($allergens[0]->label)->toBe('Gluten') ->and($allergens[1]->code)->toBe(7) ->and($allergens[1]->label)->toBe('Lait'); }); it('parses array of allergen entries', function (): void { $raw = [ ['code' => 3, 'libelle' => 'Œufs'], ]; $allergens = IncoParser::toAllergens($raw); expect($allergens)->toHaveCount(1) ->and($allergens[0]->code)->toBe(3) ->and($allergens[0]->label)->toBe('Œufs'); }); }); });