value)->toBe('abcdefghijklmnopqrstuvwxyz'); expect($alpha2->value)->toBe('ABCDEFGHIJKLMNOPQRSTUVWXYZ'); expect($alpha3->value)->toBe('HelloWorld'); }); it('rejects strings with digits', function () { PosixAlphaString::fromString('abc123'); })->throws(\InvalidArgumentException::class, 'String must contain only POSIX alphabetic characters'); it('rejects strings with punctuation', function () { PosixAlphaString::fromString('hello!world'); })->throws(\InvalidArgumentException::class, 'String must contain only POSIX alphabetic characters'); it('rejects strings with whitespace', function () { PosixAlphaString::fromString('hello world'); })->throws(\InvalidArgumentException::class, 'String must contain only POSIX alphabetic characters'); it('rejects strings with hyphens', function () { PosixAlphaString::fromString('hello-world'); })->throws(\InvalidArgumentException::class, 'String must contain only POSIX alphabetic characters'); it('rejects strings with underscores', function () { PosixAlphaString::fromString('hello_world'); })->throws(\InvalidArgumentException::class, 'String must contain only POSIX alphabetic characters'); it('rejects empty strings', function () { PosixAlphaString::fromString(''); })->throws(\InvalidArgumentException::class, 'String must not be empty'); it('rejects strings with special characters', function () { PosixAlphaString::fromString('hello@world'); })->throws(\InvalidArgumentException::class, 'String must contain only POSIX alphabetic characters'); }); describe('International Character Support', function () { it('validates German characters with locale', function () { // Note: Requires locale to be set // setlocale(LC_CTYPE, 'de_DE.UTF-8'); $german1 = PosixAlphaString::fromString('Müller'); $german2 = PosixAlphaString::fromString('Schön'); $german3 = PosixAlphaString::fromString('Größe'); expect($german1->value)->toBe('Müller'); expect($german2->value)->toBe('Schön'); expect($german3->value)->toBe('Größe'); })->skip('Requires locale configuration'); it('validates French characters with locale', function () { // Note: Requires locale to be set // setlocale(LC_CTYPE, 'fr_FR.UTF-8'); $french1 = PosixAlphaString::fromString('Dupré'); $french2 = PosixAlphaString::fromString('Château'); $french3 = PosixAlphaString::fromString('Garçon'); expect($french1->value)->toBe('Dupré'); expect($french2->value)->toBe('Château'); expect($french3->value)->toBe('Garçon'); })->skip('Requires locale configuration'); it('validates Spanish characters with locale', function () { // Note: Requires locale to be set // setlocale(LC_CTYPE, 'es_ES.UTF-8'); $spanish1 = PosixAlphaString::fromString('Señor'); $spanish2 = PosixAlphaString::fromString('Niño'); $spanish3 = PosixAlphaString::fromString('José'); expect($spanish1->value)->toBe('Señor'); expect($spanish2->value)->toBe('Niño'); expect($spanish3->value)->toBe('José'); })->skip('Requires locale configuration'); }); describe('Conversion Methods', function () { it('converts to TypedString', function () { $alpha = PosixAlphaString::fromString('Hello'); $typed = $alpha->toTypedString(); expect($typed)->toBeInstanceOf(TypedString::class); expect($typed->value)->toBe('Hello'); expect($typed->isAlphabetic())->toBeTrue(); }); it('converts to PosixString', function () { $alpha = PosixAlphaString::fromString('World'); $posix = $alpha->toPosixString(); expect($posix)->toBeInstanceOf(PosixString::class); expect($posix->value)->toBe('World'); expect($posix->isAlpha())->toBeTrue(); }); it('converts to string', function () { $alpha = PosixAlphaString::fromString('Test'); expect($alpha->toString())->toBe('Test'); expect((string) $alpha)->toBe('Test'); }); }); describe('Comparison Methods', function () { it('checks equality', function () { $alpha1 = PosixAlphaString::fromString('Hello'); $alpha2 = PosixAlphaString::fromString('Hello'); $alpha3 = PosixAlphaString::fromString('World'); expect($alpha1->equals($alpha2))->toBeTrue(); expect($alpha1->equals($alpha3))->toBeFalse(); }); it('compares case-sensitive', function () { $lower = PosixAlphaString::fromString('hello'); $upper = PosixAlphaString::fromString('HELLO'); expect($lower->equals($upper))->toBeFalse(); }); }); describe('Real World Use Cases', function () { it('validates first names', function () { $firstName1 = PosixAlphaString::fromString('John'); $firstName2 = PosixAlphaString::fromString('Mary'); $firstName3 = PosixAlphaString::fromString('Alexander'); expect($firstName1->value)->toBe('John'); expect($firstName2->value)->toBe('Mary'); expect($firstName3->value)->toBe('Alexander'); }); it('validates last names', function () { $lastName1 = PosixAlphaString::fromString('Smith'); $lastName2 = PosixAlphaString::fromString('Johnson'); $lastName3 = PosixAlphaString::fromString('Williams'); expect($lastName1->value)->toBe('Smith'); expect($lastName2->value)->toBe('Johnson'); expect($lastName3->value)->toBe('Williams'); }); it('rejects names with numbers', function () { PosixAlphaString::fromString('John123'); })->throws(\InvalidArgumentException::class); it('rejects compound names with hyphens', function () { // Note: Real-world compound names like "Jean-Pierre" would need // a different validation strategy or preprocessing PosixAlphaString::fromString('Jean-Pierre'); })->throws(\InvalidArgumentException::class); it('rejects names with titles', function () { PosixAlphaString::fromString('Dr. Smith'); })->throws(\InvalidArgumentException::class); }); describe('Single Character Strings', function () { it('accepts single letter', function () { $a = PosixAlphaString::fromString('A'); $z = PosixAlphaString::fromString('z'); expect($a->value)->toBe('A'); expect($z->value)->toBe('z'); }); it('rejects single digit', function () { PosixAlphaString::fromString('5'); })->throws(\InvalidArgumentException::class); it('rejects single special character', function () { PosixAlphaString::fromString('!'); })->throws(\InvalidArgumentException::class); }); describe('Edge Cases', function () { it('handles very long alphabetic strings', function () { $longString = str_repeat('abcdefghijklmnopqrstuvwxyz', 100); $alpha = PosixAlphaString::fromString($longString); expect($alpha->value)->toBe($longString); expect(strlen($alpha->value))->toBe(2600); }); it('handles mixed case correctly', function () { $mixed = PosixAlphaString::fromString('AbCdEfGhIjKlMnOpQrStUvWxYz'); expect($mixed->value)->toBe('AbCdEfGhIjKlMnOpQrStUvWxYz'); }); it('rejects numeric-looking strings', function () { PosixAlphaString::fromString('one23'); })->throws(\InvalidArgumentException::class); }); });