Files
michaelschiemer/tests/Unit/Framework/Database/ValueObjects/DatabaseNameTest.php
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
2025-10-25 19:18:37 +02:00

271 lines
9.8 KiB
PHP

<?php
declare(strict_types=1);
use App\Framework\Database\ValueObjects\DatabaseName;
describe('DatabaseName', function () {
it('creates database name from string', function () {
$dbName = DatabaseName::fromString('myapp_production');
expect($dbName->value)->toBe('myapp_production');
expect($dbName->toString())->toBe('myapp_production');
});
it('validates database name format', function () {
// Valid names - should not throw
DatabaseName::fromString('myapp');
DatabaseName::fromString('my_app_db');
DatabaseName::fromString('_temp_db');
DatabaseName::fromString('db123');
expect(true)->toBeTrue(); // Validation passed
// Invalid names - should throw
try {
DatabaseName::fromString('');
expect(false)->toBeTrue('Should have thrown for empty name');
} catch (\InvalidArgumentException $e) {
expect($e->getMessage())->toContain('cannot be empty');
}
try {
DatabaseName::fromString('123invalid');
expect(false)->toBeTrue('Should have thrown for name starting with number');
} catch (\InvalidArgumentException $e) {
expect($e->getMessage())->toContain('must start with a letter or underscore');
}
try {
DatabaseName::fromString('invalid-name');
expect(false)->toBeTrue('Should have thrown for name with hyphen');
} catch (\InvalidArgumentException $e) {
expect($e->getMessage())->toContain('can only contain letters, numbers, and underscores');
}
try {
DatabaseName::fromString('invalid name');
expect(false)->toBeTrue('Should have thrown for name with space');
} catch (\InvalidArgumentException $e) {
expect($e->getMessage())->toContain('can only contain letters, numbers, and underscores');
}
});
it('validates maximum length', function () {
// Valid length
$validName = str_repeat('a', 64);
DatabaseName::fromString($validName); // Should not throw
// Too long
$tooLong = str_repeat('a', 65);
try {
DatabaseName::fromString($tooLong);
expect(false)->toBeTrue('Should have thrown for name exceeding max length');
} catch (\InvalidArgumentException $e) {
expect($e->getMessage())->toContain('exceeds maximum length');
}
});
it('detects SQL injection attempts', function () {
// Note: SQL injection attempts are caught by format validation
// since they contain invalid characters (quotes, hyphens, spaces, etc.)
try {
DatabaseName::fromString("myapp'; DROP DATABASE--");
expect(false)->toBeTrue('Should have thrown for SQL injection attempt');
} catch (\InvalidArgumentException $e) {
expect($e->getMessage())->toBeString();
}
try {
DatabaseName::fromString('myapp UNION SELECT');
expect(false)->toBeTrue('Should have thrown for SQL injection attempt');
} catch (\InvalidArgumentException $e) {
expect($e->getMessage())->toBeString();
}
try {
DatabaseName::fromString('myapp/*comment*/');
expect(false)->toBeTrue('Should have thrown for SQL injection attempt');
} catch (\InvalidArgumentException $e) {
expect($e->getMessage())->toBeString();
}
});
it('quotes database names for different platforms', function () {
$dbName = DatabaseName::fromString('myapp');
expect($dbName->quoted('mysql'))->toBe('`myapp`');
expect($dbName->quoted('postgresql'))->toBe('"myapp"');
expect($dbName->quoted('postgres'))->toBe('"myapp"');
expect($dbName->quoted('pgsql'))->toBe('"myapp"');
expect($dbName->quoted('sqlite'))->toBe('"myapp"');
expect($dbName->quoted())->toBe('`myapp`'); // Default MySQL
expect($dbName->quoted('unknown'))->toBe('`myapp`'); // Fallback to MySQL
});
it('compares database names for equality', function () {
$db1 = DatabaseName::fromString('myapp');
$db2 = DatabaseName::fromString('myapp');
$db3 = DatabaseName::fromString('MYAPP'); // Different case
$db4 = DatabaseName::fromString('other_db');
expect($db1->equals($db2))->toBeTrue();
expect($db1->equals($db3))->toBeTrue(); // Case-insensitive
expect($db1->equals($db4))->toBeFalse();
});
it('matches database name patterns', function () {
$dbName = DatabaseName::fromString('myapp_production');
expect($dbName->matches('myapp_*'))->toBeTrue();
expect($dbName->matches('*_production'))->toBeTrue();
expect($dbName->matches('myapp_production'))->toBeTrue();
expect($dbName->matches('other_*'))->toBeFalse();
});
it('detects reserved SQL keywords', function () {
$dbName = DatabaseName::fromString('myapp');
expect($dbName->isReservedKeyword())->toBeFalse();
});
it('converts to lowercase', function () {
$dbName = DatabaseName::fromString('MyApp_Production');
expect($dbName->toLower())->toBe('myapp_production');
});
it('converts to uppercase', function () {
$dbName = DatabaseName::fromString('myapp_production');
expect($dbName->toUpper())->toBe('MYAPP_PRODUCTION');
});
it('checks for database name prefix', function () {
$dbName = DatabaseName::fromString('myapp_production');
expect($dbName->hasPrefix('myapp_'))->toBeTrue();
expect($dbName->hasPrefix('other_'))->toBeFalse();
});
it('checks for database name suffix', function () {
$dbName = DatabaseName::fromString('myapp_production');
expect($dbName->hasSuffix('_production'))->toBeTrue();
expect($dbName->hasSuffix('_staging'))->toBeFalse();
});
it('adds prefix to database name', function () {
$dbName = DatabaseName::fromString('myapp');
$prefixed = $dbName->withPrefix('dev_');
expect($prefixed->value)->toBe('dev_myapp');
expect($prefixed->toString())->toBe('dev_myapp');
// Original unchanged (immutable)
expect($dbName->value)->toBe('myapp');
});
it('removes prefix from database name', function () {
$dbName = DatabaseName::fromString('dev_myapp');
$unprefixed = $dbName->withoutPrefix('dev_');
expect($unprefixed->value)->toBe('myapp');
// Removing non-existent prefix returns same instance
$same = $unprefixed->withoutPrefix('prod_');
expect($same->value)->toBe('myapp');
});
it('adds suffix to database name', function () {
$dbName = DatabaseName::fromString('myapp');
$suffixed = $dbName->withSuffix('_production');
expect($suffixed->value)->toBe('myapp_production');
// Original unchanged (immutable)
expect($dbName->value)->toBe('myapp');
});
it('removes suffix from database name', function () {
$dbName = DatabaseName::fromString('myapp_production');
$unsuffixed = $dbName->withoutSuffix('_production');
expect($unsuffixed->value)->toBe('myapp');
// Removing non-existent suffix returns same instance
$same = $unsuffixed->withoutSuffix('_staging');
expect($same->value)->toBe('myapp');
});
it('detects environment suffixes', function () {
$prodDb = DatabaseName::fromString('myapp_production');
expect($prodDb->getEnvironmentSuffix())->toBe('production');
$stagingDb = DatabaseName::fromString('myapp_staging');
expect($stagingDb->getEnvironmentSuffix())->toBe('staging');
$testDb = DatabaseName::fromString('myapp_test');
expect($testDb->getEnvironmentSuffix())->toBe('test');
$devDb = DatabaseName::fromString('myapp_development');
expect($devDb->getEnvironmentSuffix())->toBe('development');
$localDb = DatabaseName::fromString('myapp_local');
expect($localDb->getEnvironmentSuffix())->toBe('local');
$noEnvDb = DatabaseName::fromString('myapp');
expect($noEnvDb->getEnvironmentSuffix())->toBeNull();
});
it('detects test databases', function () {
$testDb1 = DatabaseName::fromString('myapp_test');
expect($testDb1->isTestDatabase())->toBeTrue();
$testDb2 = DatabaseName::fromString('test_myapp');
expect($testDb2->isTestDatabase())->toBeTrue();
$prodDb = DatabaseName::fromString('myapp_production');
expect($prodDb->isTestDatabase())->toBeFalse();
});
it('converts to string via magic method', function () {
$dbName = DatabaseName::fromString('myapp');
expect((string) $dbName)->toBe('myapp');
});
it('is immutable', function () {
$original = DatabaseName::fromString('myapp');
$prefixed = $original->withPrefix('dev_');
$suffixed = $original->withSuffix('_prod');
// Original remains unchanged
expect($original->value)->toBe('myapp');
// New instances created - values should differ
expect($prefixed->value)->toBe('dev_myapp');
expect($suffixed->value)->toBe('myapp_prod');
// Verify immutability by checking original hasn't changed
expect($original->value)->toBe('myapp');
});
it('handles edge cases correctly', function () {
// Single character (valid if letter or underscore)
$a = DatabaseName::fromString('a');
expect($a->value)->toBe('a');
$underscore = DatabaseName::fromString('_');
expect($underscore->value)->toBe('_');
// Underscore-only prefix
$dbName = DatabaseName::fromString('_temp_myapp');
expect($dbName->value)->toBe('_temp_myapp');
// Numbers in name (but not at start)
$dbName = DatabaseName::fromString('myapp_123_db');
expect($dbName->value)->toBe('myapp_123_db');
});
});