toBeInstanceOf(Brand::class) ->and($brand)->toBeInstanceOf(Dto::class) ->and($brand->code)->toBeInstanceOf(BrandCode::class) ->and($brand->code->value)->toBe('LGL39') ->and($brand->label)->toBe('Le Gaulois') ->and($brand->arcadiaId)->toBe('arc-brand-001') ->and($brand->createdAt)->toBe($createdAt); }); it('can jsonSerialize complete Brand object graph', function (): void { // GIVEN $createdAt = new DateTimeImmutable('2024-01-15T10:30:00+00:00'); $brand = createCompleteBrand(createdAt: $createdAt); // WHEN $serialized = $brand->jsonSerialize(); // THEN expect($serialized)->toBe([ 'code' => 'LGL39', 'label' => 'Le Gaulois', 'arcadiaId' => 'arc-brand-001', 'createdAt' => '2024-01-15T10:30:00+00:00', ]); $jsonEncoded = json_encode($brand); expect($jsonEncoded)->toBeString(); expect(json_decode((string) $jsonEncoded, true))->toBe($serialized); }); it('can instantiate Brand with minimal nullable fields', function (): void { // GIVEN / WHEN $brand = new Brand( code: new BrandCode('MAI01'), label: 'Maître CoQ', ); // THEN expect($brand->code->value)->toBe('MAI01') ->and($brand->label)->toBe('Maître CoQ') ->and($brand->arcadiaId)->toBeNull() ->and($brand->createdAt)->toBeNull(); $serialized = $brand->jsonSerialize(); expect($serialized)->toBe([ 'code' => 'MAI01', 'label' => 'Maître CoQ', 'arcadiaId' => null, 'createdAt' => null, ]); }); it('throws DomainException on empty or whitespace-only label', function (string $invalidLabel): void { // GIVEN $code = new BrandCode('LGL39'); // THEN $this->expectException(DomainException::class); $this->expectExceptionMessage("Invalid label '{$invalidLabel}' should not be empty"); // WHEN new Brand($code, $invalidLabel); })->with([ [''], [' '], ["\t"], ["\n"], ]); });