toBeInstanceOf(RawPicturePath::class) ->and($picture->content)->toBe($content) ->and($picture->originalName)->toBe($originalName); }); it('rejects empty binary content', function (): void { // WHEN $action = fn (): RawPicturePath => new RawPicturePath('', 'logo.png'); // THEN expect($action) ->toThrow(\DomainException::class, 'Raw picture content cannot be empty.'); }); it('rejects content that exceeds the maximum allowed size', function (): void { // GIVEN $content = str_repeat('a', RawPicturePath::MAX_SIZE_IN_BYTES + 1); // WHEN $action = fn (): RawPicturePath => new RawPicturePath($content, 'logo.png'); // THEN expect($action) ->toThrow(\DomainException::class, 'Raw picture exceeds the maximum allowed size.'); }); it('accepts content of exactly the maximum allowed size', function (): void { // GIVEN $content = str_repeat('a', RawPicturePath::MAX_SIZE_IN_BYTES); // WHEN $picture = new RawPicturePath($content, 'logo.png'); // THEN expect($picture) ->toBeInstanceOf(RawPicturePath::class) ->and(strlen($picture->content)) ->toBe(RawPicturePath::MAX_SIZE_IN_BYTES); }); it('measures size in raw bytes rather than characters', function (): void { // GIVEN $halfLimit = RawPicturePath::MAX_SIZE_IN_BYTES / 2 + 1; $content = str_repeat('é', $halfLimit); // WHEN $action = fn (): RawPicturePath => new RawPicturePath($content, 'logo.png'); // THEN expect($action) ->toThrow( \DomainException::class, 'Raw picture exceeds the maximum allowed size.' ); }); it('rejects an empty original name', function (string $originalName): void { // WHEN $action = fn (): RawPicturePath => new RawPicturePath('binary-content', $originalName); // THEN expect($action) ->toThrow( \DomainException::class, 'Raw picture original name cannot be empty.' ); })->with([ 'empty string' => '', 'spaces only' => ' ', 'whitespace only' => "\t\n ", ]); it('rejects an original name without an allowed extension', function (string $originalName): void { // WHEN $action = fn (): RawPicturePath => new RawPicturePath('binary-content', $originalName); // THEN expect($action) ->toThrow( \DomainException::class, 'Raw picture must have one of these extensions: ' . implode(', ', RawPicturePath::ALLOWED_EXTENSIONS) ); })->with([ 'no extension' => 'logo', 'forbidden extension' => 'logo.gif', 'executable extension' => 'logo.php', 'trailing dot' => 'logo.', 'double extension' => 'logo.png.exe', ]); it('accepts every allowed extension regardless of case', function (string $extension): void { // GIVEN $originalName = 'logo.' . $extension; // WHEN $picture = new RawPicturePath('binary-content', $originalName); // THEN expect($picture) ->toBeInstanceOf(RawPicturePath::class) ->and($picture->originalName) ->toBe($originalName); })->with([ 'lowercase jpg' => 'jpg', 'uppercase JPG' => 'JPG', 'mixed case Png' => 'Png', 'webp' => 'webp', ]); it('shares its allowed extensions with PicturePath', function (): void { expect(RawPicturePath::ALLOWED_EXTENSIONS) ->toBe(PicturePath::ALLOWED_EXTENSIONS); }); });