Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
- Remove middleware reference from Gitea Traefik labels (caused routing issues) - Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s) - Add explicit service reference in Traefik labels - Fix intermittent 504 timeouts by improving PostgreSQL connection handling Fixes Gitea unreachability via git.michaelschiemer.de
297 lines
12 KiB
PHP
297 lines
12 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Framework\String\ValueObjects\PosixWordString;
|
|
use App\Framework\String\ValueObjects\TypedString;
|
|
use App\Framework\String\ValueObjects\PosixString;
|
|
|
|
describe('PosixWordString', function () {
|
|
describe('Validation', function () {
|
|
it('accepts valid word strings', function () {
|
|
$word1 = PosixWordString::fromString('hello');
|
|
$word2 = PosixWordString::fromString('Hello123');
|
|
$word3 = PosixWordString::fromString('user_name');
|
|
$word4 = PosixWordString::fromString('MAX_VALUE');
|
|
$word5 = PosixWordString::fromString('_private');
|
|
|
|
expect($word1->value)->toBe('hello');
|
|
expect($word2->value)->toBe('Hello123');
|
|
expect($word3->value)->toBe('user_name');
|
|
expect($word4->value)->toBe('MAX_VALUE');
|
|
expect($word5->value)->toBe('_private');
|
|
});
|
|
|
|
it('rejects strings with hyphens', function () {
|
|
PosixWordString::fromString('user-name');
|
|
})->throws(\InvalidArgumentException::class, 'String must contain only POSIX word characters');
|
|
|
|
it('rejects strings with spaces', function () {
|
|
PosixWordString::fromString('hello world');
|
|
})->throws(\InvalidArgumentException::class, 'String must contain only POSIX word characters');
|
|
|
|
it('rejects strings with special characters', function () {
|
|
PosixWordString::fromString('hello@world');
|
|
})->throws(\InvalidArgumentException::class, 'String must contain only POSIX word characters');
|
|
|
|
it('rejects strings with punctuation', function () {
|
|
PosixWordString::fromString('hello.world');
|
|
})->throws(\InvalidArgumentException::class, 'String must contain only POSIX word characters');
|
|
|
|
it('rejects strings with operators', function () {
|
|
PosixWordString::fromString('a+b');
|
|
})->throws(\InvalidArgumentException::class, 'String must contain only POSIX word characters');
|
|
|
|
it('rejects empty strings', function () {
|
|
PosixWordString::fromString('');
|
|
})->throws(\InvalidArgumentException::class, 'String must not be empty');
|
|
|
|
it('rejects strings with parentheses', function () {
|
|
PosixWordString::fromString('function()');
|
|
})->throws(\InvalidArgumentException::class, 'String must contain only POSIX word characters');
|
|
|
|
it('rejects strings with brackets', function () {
|
|
PosixWordString::fromString('array[0]');
|
|
})->throws(\InvalidArgumentException::class, 'String must contain only POSIX word characters');
|
|
});
|
|
|
|
describe('Conversion Methods', function () {
|
|
it('converts to TypedString', function () {
|
|
$word = PosixWordString::fromString('user_id');
|
|
$typed = $word->toTypedString();
|
|
|
|
expect($typed)->toBeInstanceOf(TypedString::class);
|
|
expect($typed->value)->toBe('user_id');
|
|
expect($typed->isAlphanumeric())->toBeFalse(); // Contains underscore
|
|
});
|
|
|
|
it('converts to PosixString', function () {
|
|
$word = PosixWordString::fromString('MAX_VALUE');
|
|
$posix = $word->toPosixString();
|
|
|
|
expect($posix)->toBeInstanceOf(PosixString::class);
|
|
expect($posix->value)->toBe('MAX_VALUE');
|
|
expect($posix->isWord())->toBeTrue();
|
|
});
|
|
|
|
it('converts to string', function () {
|
|
$word = PosixWordString::fromString('username');
|
|
|
|
expect($word->toString())->toBe('username');
|
|
expect((string) $word)->toBe('username');
|
|
});
|
|
});
|
|
|
|
describe('Comparison Methods', function () {
|
|
it('checks equality', function () {
|
|
$word1 = PosixWordString::fromString('user_id');
|
|
$word2 = PosixWordString::fromString('user_id');
|
|
$word3 = PosixWordString::fromString('user_name');
|
|
|
|
expect($word1->equals($word2))->toBeTrue();
|
|
expect($word1->equals($word3))->toBeFalse();
|
|
});
|
|
|
|
it('compares case-sensitive', function () {
|
|
$lower = PosixWordString::fromString('username');
|
|
$upper = PosixWordString::fromString('USERNAME');
|
|
|
|
expect($lower->equals($upper))->toBeFalse();
|
|
});
|
|
});
|
|
|
|
describe('Real World Use Cases', function () {
|
|
describe('PHP Identifiers', function () {
|
|
it('validates variable names', function () {
|
|
$var1 = PosixWordString::fromString('userName');
|
|
$var2 = PosixWordString::fromString('user_id');
|
|
$var3 = PosixWordString::fromString('_privateVar');
|
|
|
|
expect($var1->value)->toBe('userName');
|
|
expect($var2->value)->toBe('user_id');
|
|
expect($var3->value)->toBe('_privateVar');
|
|
});
|
|
|
|
it('validates constant names', function () {
|
|
$const1 = PosixWordString::fromString('MAX_SIZE');
|
|
$const2 = PosixWordString::fromString('API_KEY');
|
|
$const3 = PosixWordString::fromString('DEFAULT_TIMEOUT');
|
|
|
|
expect($const1->value)->toBe('MAX_SIZE');
|
|
expect($const2->value)->toBe('API_KEY');
|
|
expect($const3->value)->toBe('DEFAULT_TIMEOUT');
|
|
});
|
|
|
|
it('validates function names', function () {
|
|
$func1 = PosixWordString::fromString('calculateTotal');
|
|
$func2 = PosixWordString::fromString('get_user_by_id');
|
|
$func3 = PosixWordString::fromString('__construct');
|
|
|
|
expect($func1->value)->toBe('calculateTotal');
|
|
expect($func2->value)->toBe('get_user_by_id');
|
|
expect($func3->value)->toBe('__construct');
|
|
});
|
|
|
|
it('rejects invalid PHP identifiers', function () {
|
|
PosixWordString::fromString('my-function');
|
|
})->throws(\InvalidArgumentException::class);
|
|
});
|
|
|
|
describe('Database Column Names', function () {
|
|
it('validates snake_case column names', function () {
|
|
$col1 = PosixWordString::fromString('user_id');
|
|
$col2 = PosixWordString::fromString('created_at');
|
|
$col3 = PosixWordString::fromString('email_verified_at');
|
|
|
|
expect($col1->value)->toBe('user_id');
|
|
expect($col2->value)->toBe('created_at');
|
|
expect($col3->value)->toBe('email_verified_at');
|
|
});
|
|
|
|
it('rejects kebab-case column names', function () {
|
|
PosixWordString::fromString('user-id');
|
|
})->throws(\InvalidArgumentException::class);
|
|
});
|
|
|
|
describe('Usernames', function () {
|
|
it('validates valid usernames', function () {
|
|
$user1 = PosixWordString::fromString('john_doe');
|
|
$user2 = PosixWordString::fromString('user123');
|
|
$user3 = PosixWordString::fromString('admin_user');
|
|
|
|
expect($user1->value)->toBe('john_doe');
|
|
expect($user2->value)->toBe('user123');
|
|
expect($user3->value)->toBe('admin_user');
|
|
});
|
|
|
|
it('rejects usernames with special characters', function () {
|
|
PosixWordString::fromString('john@doe');
|
|
})->throws(\InvalidArgumentException::class);
|
|
|
|
it('rejects usernames with hyphens', function () {
|
|
PosixWordString::fromString('john-doe');
|
|
})->throws(\InvalidArgumentException::class);
|
|
|
|
it('rejects usernames with spaces', function () {
|
|
PosixWordString::fromString('john doe');
|
|
})->throws(\InvalidArgumentException::class);
|
|
});
|
|
|
|
describe('URL Slugs (with underscore)', function () {
|
|
it('validates underscore slugs', function () {
|
|
$slug1 = PosixWordString::fromString('my_blog_post');
|
|
$slug2 = PosixWordString::fromString('product_category_1');
|
|
$slug3 = PosixWordString::fromString('about_us');
|
|
|
|
expect($slug1->value)->toBe('my_blog_post');
|
|
expect($slug2->value)->toBe('product_category_1');
|
|
expect($slug3->value)->toBe('about_us');
|
|
});
|
|
|
|
it('rejects hyphenated slugs', function () {
|
|
// Note: Hyphenated slugs need different validation
|
|
PosixWordString::fromString('my-blog-post');
|
|
})->throws(\InvalidArgumentException::class);
|
|
});
|
|
});
|
|
|
|
describe('Single Character Strings', function () {
|
|
it('accepts single letter', function () {
|
|
$a = PosixWordString::fromString('a');
|
|
$Z = PosixWordString::fromString('Z');
|
|
|
|
expect($a->value)->toBe('a');
|
|
expect($Z->value)->toBe('Z');
|
|
});
|
|
|
|
it('accepts single digit', function () {
|
|
$five = PosixWordString::fromString('5');
|
|
|
|
expect($five->value)->toBe('5');
|
|
});
|
|
|
|
it('accepts single underscore', function () {
|
|
$underscore = PosixWordString::fromString('_');
|
|
|
|
expect($underscore->value)->toBe('_');
|
|
});
|
|
|
|
it('rejects single special character', function () {
|
|
PosixWordString::fromString('!');
|
|
})->throws(\InvalidArgumentException::class);
|
|
|
|
it('rejects single hyphen', function () {
|
|
PosixWordString::fromString('-');
|
|
})->throws(\InvalidArgumentException::class);
|
|
});
|
|
|
|
describe('Edge Cases', function () {
|
|
it('handles very long word strings', function () {
|
|
$longString = str_repeat('abc123_', 100);
|
|
$word = PosixWordString::fromString($longString);
|
|
|
|
expect($word->value)->toBe($longString);
|
|
expect(strlen($word->value))->toBe(700);
|
|
});
|
|
|
|
it('handles mixed case correctly', function () {
|
|
$mixed = PosixWordString::fromString('CamelCase_With_Underscore123');
|
|
|
|
expect($mixed->value)->toBe('CamelCase_With_Underscore123');
|
|
});
|
|
|
|
it('accepts strings starting with underscore', function () {
|
|
$leading = PosixWordString::fromString('_privateMethod');
|
|
|
|
expect($leading->value)->toBe('_privateMethod');
|
|
});
|
|
|
|
it('accepts strings starting with digit', function () {
|
|
// Note: Valid for word class, but not valid PHP identifiers
|
|
$digit = PosixWordString::fromString('123abc');
|
|
|
|
expect($digit->value)->toBe('123abc');
|
|
});
|
|
|
|
it('accepts strings with only digits', function () {
|
|
$digits = PosixWordString::fromString('123456');
|
|
|
|
expect($digits->value)->toBe('123456');
|
|
});
|
|
|
|
it('accepts strings with only underscores', function () {
|
|
$underscores = PosixWordString::fromString('___');
|
|
|
|
expect($underscores->value)->toBe('___');
|
|
});
|
|
});
|
|
|
|
describe('Boundary Cases', function () {
|
|
it('handles maximum practical length', function () {
|
|
// 255 characters - typical database VARCHAR limit
|
|
$longIdentifier = str_repeat('a', 255);
|
|
$word = PosixWordString::fromString($longIdentifier);
|
|
|
|
expect(strlen($word->value))->toBe(255);
|
|
});
|
|
|
|
it('handles alphanumeric only', function () {
|
|
$alnum = PosixWordString::fromString('abc123XYZ789');
|
|
|
|
expect($alnum->value)->toBe('abc123XYZ789');
|
|
});
|
|
|
|
it('handles underscores only', function () {
|
|
$underscores = PosixWordString::fromString('_____');
|
|
|
|
expect($underscores->value)->toBe('_____');
|
|
});
|
|
|
|
it('handles mixed content', function () {
|
|
$mixed = PosixWordString::fromString('a1_B2_c3_D4');
|
|
|
|
expect($mixed->value)->toBe('a1_B2_c3_D4');
|
|
});
|
|
});
|
|
});
|