Files
michaelschiemer/tests/Framework/Validation/Rules/UlidTest.php
Michael Schiemer 55a330b223 Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
2025-08-11 20:13:26 +02:00

151 lines
5.5 KiB
PHP

<?php
declare(strict_types=1);
use App\Framework\Validation\Rules\Ulid;
beforeEach(function () {
$this->rule = new Ulid();
});
test('validates empty values as true (handled by Required rule)', function () {
expect($this->rule->validate(null))->toBeTrue()
->and($this->rule->validate(''))->toBeTrue();
});
test('validates non-string values as false', function () {
expect($this->rule->validate(123))->toBeFalse()
->and($this->rule->validate(['not', 'a', 'ulid']))->toBeFalse()
->and($this->rule->validate(new stdClass()))->toBeFalse()
->and($this->rule->validate(true))->toBeFalse()
->and($this->rule->validate(12.34))->toBeFalse();
});
test('validates valid ULIDs', function () {
$validUlids = [
'01ARZ3NDEKTSV4RRFFQ69G5FAV', // Standard ULID format
'01BX5ZZKBKACTAV9WEVGEMMVRY', // Another valid ULID
'01CA2ZZKBKACTAV9WEVGEMMVRY', // Year 2022 timestamp
'7ZZZZZZZZZZZZZZZZZZZZZZZZZ', // Max timestamp, max random
'00000000000000000000000000', // Min ULID (all zeros)
'0123456789ABCDEFGHJKMNPQRS', // Using all valid Crockford Base32 chars
];
foreach ($validUlids as $ulid) {
expect($this->rule->validate($ulid))->toBeTrue("ULID should be valid: $ulid");
}
});
test('validates invalid ULIDs as false', function () {
$invalidUlids = [
// Wrong length
'01ARZ3NDEK', // Too short
'01ARZ3NDEKTSV4RRFFQ69G5FAVX', // Too long (27 chars)
'01ARZ3NDEKTSV4RRFFQ69G5FA', // Too short (25 chars)
// Invalid characters (not in Crockford Base32)
'01ARZ3NDEKTSV4RRFFQ69G5FI0', // Contains 'I' (invalid)
'01ARZ3NDEKTSV4RRFFQ69G5FL0', // Contains 'L' (invalid)
'01ARZ3NDEKTSV4RRFFQ69G5FO0', // Contains 'O' (invalid)
'01ARZ3NDEKTSV4RRFFQ69G5FU0', // Contains 'U' (invalid)
'01ARZ3NDEKTSV4RRFFQ69G5f@V', // Contains '@' (invalid)
'01ARZ3NDEKTSV4RRFFQ69G5f_V', // Contains '_' (invalid)
'01ARZ3NDEKTSV4RRFFQ69G5f-V', // Contains '-' (invalid)
// Lowercase (ULIDs should be uppercase)
'01arz3ndektsv4rrffq69g5fav', // All lowercase
'01ARZ3ndektsv4rrffq69g5fav', // Mixed case
// Completely invalid formats
'not-a-ulid-at-all',
'01ARZ3NDEKTSV4RRFFQ69G5F V', // Contains space
'01ARZ3NDEKTSV4RRFFQ69G5F\tV', // Contains tab
'01ARZ3NDEKTSV4RRFFQ69G5F\nV', // Contains newline
// Empty variations
' ', // Space only
'\t', // Tab only
'\n', // Newline only
// Common mistakes
'01ARZ3NDEKTSV4RRFFQ69G5FAV ', // Trailing space
' 01ARZ3NDEKTSV4RRFFQ69G5FAV', // Leading space
'01ARZ3NDEKTSV4RRFFQ69G5FAV\n', // Trailing newline
];
foreach ($invalidUlids as $ulid) {
expect($this->rule->validate($ulid))->toBeFalse("ULID should be invalid: '$ulid'");
}
});
test('validates ULIDs with edge case timestamps', function () {
// ULIDs with specific timestamp patterns that should be valid (all 26 chars)
$edgeCaseUlids = [
'00000000000000000000000000', // Min ULID (all zeros)
'7ZZZZZZZZZZZZZZZZZZZZZZZZZ', // Max timestamp (~10889 AD)
'01FXYZ0000000000000000000V', // Year 2021 with min random
'01FXYZ999999999999999999ZZ', // Year 2021 with high random
'GGGGGGGGGGGGGGGGGGGGGGGGGG', // All G's (valid in Crockford Base32)
];
foreach ($edgeCaseUlids as $ulid) {
expect($this->rule->validate($ulid))->toBeTrue("Edge case ULID should be valid: $ulid");
}
// Test Y case separately (26 characters)
$yUlid = 'YYYYYYYYYYYYYYYYYYYYYYYYYY';
expect(strlen($yUlid))->toBe(26, "Y ULID should be 26 chars");
expect($this->rule->validate($yUlid))->toBeTrue("Y ULID should be valid: $yUlid");
});
test('validates strict Crockford Base32 alphabet', function () {
// Test each valid character
$validChars = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
$baseUlid = '01ARZ3NDEKTSV4RRFFQ69G5FA';
for ($i = 0; $i < strlen($validChars); $i++) {
$char = $validChars[$i];
$testUlid = $baseUlid . $char;
expect($this->rule->validate($testUlid))->toBeTrue("ULID with char '$char' should be valid");
}
// Test invalid characters from standard Base32 that are excluded in Crockford
$invalidChars = 'ILOU'; // These are excluded in Crockford Base32
foreach (str_split($invalidChars) as $char) {
$testUlid = $baseUlid . $char;
expect($this->rule->validate($testUlid))->toBeFalse("ULID with invalid char '$char' should be invalid");
}
});
test('default error message', function () {
$messages = $this->rule->getErrorMessages();
expect($messages)->toHaveCount(1)
->and($messages[0])->toBe('Bitte geben Sie eine gültige ULID ein (26 Zeichen, Crockford Base32).');
});
test('custom error message', function () {
$customRule = new Ulid(message: 'Diese ULID ist nicht korrekt!');
$messages = $customRule->getErrorMessages();
expect($messages)->toHaveCount(1)
->and($messages[0])->toBe('Diese ULID ist nicht korrekt!');
});
test('validates performance with many ULIDs', function () {
// Performance test - should validate many ULIDs quickly
$validUlid = '01ARZ3NDEKTSV4RRFFQ69G5FAV';
$startTime = microtime(true);
for ($i = 0; $i < 1000; $i++) {
$this->rule->validate($validUlid);
}
$endTime = microtime(true);
$duration = $endTime - $startTime;
// Should complete 1000 validations in less than 100ms
expect($duration)->toBeLessThan(0.1);
});