- 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.
222 lines
6.4 KiB
PHP
222 lines
6.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/../../vendor/autoload.php';
|
|
|
|
use App\Framework\LiveComponents\ValueObjects\EventPayload;
|
|
|
|
echo "Testing EventPayload Value Object\n";
|
|
echo "==================================\n\n";
|
|
|
|
$testsPassed = 0;
|
|
$testsFailed = 0;
|
|
|
|
function test(string $name, callable $fn): void
|
|
{
|
|
global $testsPassed, $testsFailed;
|
|
|
|
try {
|
|
$fn();
|
|
echo "✅ {$name}\n";
|
|
$testsPassed++;
|
|
} catch (Throwable $e) {
|
|
echo "❌ {$name}\n";
|
|
echo " Error: {$e->getMessage()}\n";
|
|
$testsFailed++;
|
|
}
|
|
}
|
|
|
|
// Test 1: Create from array
|
|
test('Create from array', function () {
|
|
$payload = EventPayload::fromArray(['key' => 'value', 'number' => 42]);
|
|
assert($payload->get('key') === 'value');
|
|
assert($payload->get('number') === 42);
|
|
});
|
|
|
|
// Test 2: Create empty
|
|
test('Create empty', function () {
|
|
$payload = EventPayload::empty();
|
|
assert($payload->isEmpty() === true);
|
|
assert($payload->size() === 0);
|
|
});
|
|
|
|
// Test 3: Get with default
|
|
test('Get with default', function () {
|
|
$payload = EventPayload::fromArray(['key' => 'value']);
|
|
assert($payload->get('missing', 'default') === 'default');
|
|
});
|
|
|
|
// Test 4: Has key
|
|
test('Has key', function () {
|
|
$payload = EventPayload::fromArray(['key' => 'value']);
|
|
assert($payload->has('key') === true);
|
|
assert($payload->has('missing') === false);
|
|
});
|
|
|
|
// Test 5: Get string
|
|
test('Get string', function () {
|
|
$payload = EventPayload::fromArray(['name' => 'John', 'age' => 30]);
|
|
assert($payload->getString('name') === 'John');
|
|
assert($payload->getString('age') === '30'); // Type coercion
|
|
});
|
|
|
|
// Test 6: Require string
|
|
test('Require string', function () {
|
|
$payload = EventPayload::fromArray(['name' => 'John']);
|
|
assert($payload->requireString('name') === 'John');
|
|
});
|
|
|
|
// Test 7: Require string throws on missing
|
|
test('Require string throws on missing', function () {
|
|
$payload = EventPayload::empty();
|
|
|
|
try {
|
|
$payload->requireString('missing');
|
|
assert(false, 'Should have thrown exception');
|
|
} catch (InvalidArgumentException $e) {
|
|
assert(str_contains($e->getMessage(), 'missing'));
|
|
}
|
|
});
|
|
|
|
// Test 8: Get int
|
|
test('Get int', function () {
|
|
$payload = EventPayload::fromArray(['count' => 42, 'string_num' => '100']);
|
|
assert($payload->getInt('count') === 42);
|
|
assert($payload->getInt('string_num') === 100); // Type coercion
|
|
});
|
|
|
|
// Test 9: Get float
|
|
test('Get float', function () {
|
|
$payload = EventPayload::fromArray(['price' => 19.99, 'integer' => 42]);
|
|
assert($payload->getFloat('price') === 19.99);
|
|
assert($payload->getFloat('integer') === 42.0); // Type coercion
|
|
});
|
|
|
|
// Test 10: Get bool
|
|
test('Get bool', function () {
|
|
$payload = EventPayload::fromArray(['active' => true, 'inactive' => false]);
|
|
assert($payload->getBool('active') === true);
|
|
assert($payload->getBool('inactive') === false);
|
|
});
|
|
|
|
// Test 11: Get array
|
|
test('Get array', function () {
|
|
$payload = EventPayload::fromArray(['items' => ['a', 'b', 'c']]);
|
|
assert($payload->getArray('items') === ['a', 'b', 'c']);
|
|
});
|
|
|
|
// Test 12: With (immutable update)
|
|
test('With (immutable update)', function () {
|
|
$payload1 = EventPayload::fromArray(['key' => 'value']);
|
|
$payload2 = $payload1->with('new', 'data');
|
|
|
|
assert($payload1->has('new') === false); // Original unchanged
|
|
assert($payload2->has('new') === true);
|
|
assert($payload2->get('key') === 'value'); // Old data preserved
|
|
});
|
|
|
|
// Test 13: WithMany
|
|
test('WithMany', function () {
|
|
$payload1 = EventPayload::fromArray(['a' => 1]);
|
|
$payload2 = $payload1->withMany(['b' => 2, 'c' => 3]);
|
|
|
|
assert($payload2->get('a') === 1);
|
|
assert($payload2->get('b') === 2);
|
|
assert($payload2->get('c') === 3);
|
|
});
|
|
|
|
// Test 14: Without
|
|
test('Without', function () {
|
|
$payload1 = EventPayload::fromArray(['a' => 1, 'b' => 2, 'c' => 3]);
|
|
$payload2 = $payload1->without('b');
|
|
|
|
assert($payload1->has('b') === true); // Original unchanged
|
|
assert($payload2->has('b') === false);
|
|
assert($payload2->get('a') === 1);
|
|
});
|
|
|
|
// Test 15: Only
|
|
test('Only', function () {
|
|
$payload1 = EventPayload::fromArray(['a' => 1, 'b' => 2, 'c' => 3]);
|
|
$payload2 = $payload1->only(['a', 'c']);
|
|
|
|
assert($payload2->size() === 2);
|
|
assert($payload2->has('a') === true);
|
|
assert($payload2->has('b') === false);
|
|
assert($payload2->has('c') === true);
|
|
});
|
|
|
|
// Test 16: Except
|
|
test('Except', function () {
|
|
$payload1 = EventPayload::fromArray(['a' => 1, 'b' => 2, 'c' => 3]);
|
|
$payload2 = $payload1->except(['b']);
|
|
|
|
assert($payload2->size() === 2);
|
|
assert($payload2->has('a') === true);
|
|
assert($payload2->has('b') === false);
|
|
assert($payload2->has('c') === true);
|
|
});
|
|
|
|
// Test 17: Merge
|
|
test('Merge', function () {
|
|
$payload1 = EventPayload::fromArray(['a' => 1, 'b' => 2]);
|
|
$payload2 = EventPayload::fromArray(['c' => 3, 'd' => 4]);
|
|
$merged = $payload1->merge($payload2);
|
|
|
|
assert($merged->size() === 4);
|
|
assert($merged->get('a') === 1);
|
|
assert($merged->get('d') === 4);
|
|
});
|
|
|
|
// Test 18: Equals
|
|
test('Equals', function () {
|
|
$payload1 = EventPayload::fromArray(['a' => 1, 'b' => 2]);
|
|
$payload2 = EventPayload::fromArray(['a' => 1, 'b' => 2]);
|
|
$payload3 = EventPayload::fromArray(['a' => 1, 'b' => 3]);
|
|
|
|
assert($payload1->equals($payload2) === true);
|
|
assert($payload1->equals($payload3) === false);
|
|
});
|
|
|
|
// Test 19: Keys
|
|
test('Keys', function () {
|
|
$payload = EventPayload::fromArray(['a' => 1, 'b' => 2, 'c' => 3]);
|
|
$keys = $payload->keys();
|
|
|
|
assert(count($keys) === 3);
|
|
assert(in_array('a', $keys));
|
|
assert(in_array('b', $keys));
|
|
assert(in_array('c', $keys));
|
|
});
|
|
|
|
// Test 20: ToArray
|
|
test('ToArray', function () {
|
|
$data = ['key' => 'value', 'number' => 42];
|
|
$payload = EventPayload::fromArray($data);
|
|
|
|
assert($payload->toArray() === $data);
|
|
});
|
|
|
|
// Test 21: Validation - non-string keys
|
|
test('Validation rejects non-string keys', function () {
|
|
try {
|
|
EventPayload::fromArray([0 => 'value', 'key' => 'data']);
|
|
assert(false, 'Should have thrown exception');
|
|
} catch (InvalidArgumentException $e) {
|
|
assert(str_contains($e->getMessage(), 'must be strings'));
|
|
}
|
|
});
|
|
|
|
echo "\n";
|
|
echo "==================================\n";
|
|
echo "Tests passed: {$testsPassed}\n";
|
|
echo "Tests failed: {$testsFailed}\n";
|
|
echo "==================================\n";
|
|
|
|
if ($testsFailed > 0) {
|
|
exit(1);
|
|
}
|
|
|
|
echo "\n✅ All EventPayload tests passed!\n";
|