toString())->toBe($value); expect($nanoId->getValue())->toBe($value); }); it('validates NanoId alphabet matching', function () { $nanoId = NanoId::fromString('ABC123'); expect($nanoId->matchesAlphabet('ABC123'))->toBeTrue(); expect($nanoId->matchesAlphabet('XYZ'))->toBeFalse(); }); it('checks if NanoId is default alphabet', function () { $defaultId = NanoId::fromString('abcDEF123_-'); expect($defaultId->isDefault())->toBeTrue(); $nonDefaultId = NanoId::fromString('abc!@#'); expect($nonDefaultId->isDefault())->toBeFalse(); }); it('checks if NanoId is safe alphabet', function () { $safeId = NanoId::fromString('abcDEF23456789'); expect($safeId->isSafe())->toBeTrue(); $unsafeId = NanoId::fromString('abc0O1I'); expect($unsafeId->isSafe())->toBeFalse(); }); it('checks if NanoId is numeric', function () { $numericId = NanoId::fromString('123456789'); expect($numericId->isNumeric())->toBeTrue(); $alphaId = NanoId::fromString('abc123'); expect($alphaId->isNumeric())->toBeFalse(); }); it('gets NanoId length correctly', function () { $nanoId = NanoId::fromString('12345'); expect($nanoId->getLength())->toBe(5); }); it('checks equality between NanoIds', function () { $value = 'sameId123'; $nanoId1 = NanoId::fromString($value); $nanoId2 = NanoId::fromString($value); $nanoId3 = NanoId::fromString('differentId'); expect($nanoId1->equals($nanoId2))->toBeTrue(); expect($nanoId1->equals($nanoId3))->toBeFalse(); }); it('adds prefix to NanoId', function () { $nanoId = NanoId::fromString('abc123'); $prefixed = $nanoId->withPrefix('user_'); expect($prefixed->toString())->toBe('user_abc123'); }); it('adds suffix to NanoId', function () { $nanoId = NanoId::fromString('abc123'); $suffixed = $nanoId->withSuffix('_v2'); expect($suffixed->toString())->toBe('abc123_v2'); }); it('truncates NanoId', function () { $nanoId = NanoId::fromString('verylongnanoid123456'); $truncated = $nanoId->truncate(10); expect($truncated->toString())->toBe('verylongna'); expect($truncated->getLength())->toBe(10); }); it('throws exception for empty NanoId', function () { expect(fn () => NanoId::fromString(''))->toThrow(InvalidArgumentException::class, 'NanoId cannot be empty'); }); it('throws exception for NanoId exceeding 255 characters', function () { $longString = str_repeat('a', 256); expect(fn () => NanoId::fromString($longString))->toThrow(InvalidArgumentException::class, 'NanoId cannot exceed 255 characters'); }); it('throws exception for empty prefix', function () { $nanoId = NanoId::fromString('test'); expect(fn () => $nanoId->withPrefix(''))->toThrow(InvalidArgumentException::class, 'Prefix cannot be empty'); }); it('throws exception for empty suffix', function () { $nanoId = NanoId::fromString('test'); expect(fn () => $nanoId->withSuffix(''))->toThrow(InvalidArgumentException::class, 'Suffix cannot be empty'); }); it('throws exception for invalid truncate length', function () { $nanoId = NanoId::fromString('test'); expect(fn () => $nanoId->truncate(0))->toThrow(InvalidArgumentException::class, 'Length must be positive'); }); it('converts NanoId to string using magic method', function () { $nanoId = NanoId::fromString('test123'); expect((string)$nanoId)->toBe('test123'); }); it('does not truncate when length is greater than NanoId length', function () { $nanoId = NanoId::fromString('short'); $truncated = $nanoId->truncate(10); expect($truncated->toString())->toBe('short'); expect($truncated->equals($nanoId))->toBeTrue(); }); it('validates alphabet patterns correctly', function () { $defaultId = NanoId::fromString('abc123DEF_-'); expect($defaultId->matchesAlphabet(NanoId::DEFAULT_ALPHABET))->toBeTrue(); $safeId = NanoId::fromString('abc23456789DEF'); expect($safeId->matchesAlphabet(NanoId::SAFE_ALPHABET))->toBeTrue(); $numericId = NanoId::fromString('123456789'); expect($numericId->matchesAlphabet(NanoId::NUMBERS))->toBeTrue(); $lowercaseId = NanoId::fromString('abc123def'); expect($lowercaseId->matchesAlphabet(NanoId::LOWERCASE_ALPHANUMERIC))->toBeTrue(); $uppercaseId = NanoId::fromString('ABC123DEF'); expect($uppercaseId->matchesAlphabet(NanoId::UPPERCASE_ALPHANUMERIC))->toBeTrue(); });