assertEquals('test-correlation-id-123', $id->toString()); $this->assertEquals('test-correlation-id-123', (string) $id); } public function test_generates_uuid_format(): void { $id = CorrelationId::generate(); $this->assertTrue($id->isUuid()); $this->assertFalse($id->isUlid()); $this->assertMatchesRegularExpression( '/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i', $id->toString() ); } public function test_generates_ulid_format(): void { $id = CorrelationId::generateUlid(); $this->assertTrue($id->isUlid()); $this->assertFalse($id->isUuid()); $this->assertEquals(26, strlen($id->toString())); } public function test_rejects_empty_string(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('cannot be empty'); CorrelationId::fromString(''); } public function test_rejects_too_long_string(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('too long'); CorrelationId::fromString(str_repeat('a', 256)); } public function test_rejects_invalid_characters(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('invalid characters'); CorrelationId::fromString('test-id-with-invalid-chars-äöü'); } public function test_allows_valid_characters(): void { $validIds = [ 'simple-id-123', 'UPPERCASE-ID-456', 'mixed_Case-ID_789', '12345-67890', 'a_b-c_d-e_f', ]; foreach ($validIds as $validId) { $id = CorrelationId::fromString($validId); $this->assertEquals($validId, $id->toString()); } } public function test_to_short_string(): void { $id = CorrelationId::fromString('very-long-correlation-id-123456789'); $this->assertEquals('very-lon', $id->toShortString()); } public function test_equals(): void { $id1 = CorrelationId::fromString('test-123'); $id2 = CorrelationId::fromString('test-123'); $id3 = CorrelationId::fromString('test-456'); $this->assertTrue($id1->equals($id2)); $this->assertFalse($id1->equals($id3)); } public function test_json_serializable(): void { $id = CorrelationId::fromString('test-json-123'); $json = json_encode(['id' => $id]); $this->assertEquals('{"id":"test-json-123"}', $json); } public function test_from_globals_with_correlation_header(): void { $_SERVER['HTTP_X_CORRELATION_ID'] = 'header-correlation-123'; $id = CorrelationId::fromGlobals(); $this->assertEquals('header-correlation-123', $id->toString()); unset($_SERVER['HTTP_X_CORRELATION_ID']); } public function test_from_globals_fallback_to_request_id(): void { $_SERVER['HTTP_X_REQUEST_ID'] = 'request-id-456'; $id = CorrelationId::fromGlobals('X-Correlation-ID'); $this->assertEquals('request-id-456', $id->toString()); unset($_SERVER['HTTP_X_REQUEST_ID']); } public function test_from_globals_generates_when_no_header(): void { unset($_SERVER['HTTP_X_CORRELATION_ID'], $_SERVER['HTTP_X_REQUEST_ID']); $id = CorrelationId::fromGlobals(); $this->assertTrue($id->isUuid()); } public function test_from_globals_generates_when_invalid_header(): void { $_SERVER['HTTP_X_CORRELATION_ID'] = 'invalid-chars-äöü'; $id = CorrelationId::fromGlobals(); // Should generate new valid ID instead of using invalid one $this->assertTrue($id->isUuid()); $this->assertNotEquals('invalid-chars-äöü', $id->toString()); unset($_SERVER['HTTP_X_CORRELATION_ID']); } public function test_creates_from_uuid(): void { $uuid = \Ramsey\Uuid\Uuid::uuid4(); $id = CorrelationId::fromUuid($uuid); $this->assertEquals($uuid->toString(), $id->toString()); $this->assertTrue($id->isUuid()); } public function test_creates_from_ulid(): void { $ulid = \App\Framework\Ulid\Ulid::generate(); $id = CorrelationId::fromUlid($ulid); $this->assertEquals((string) $ulid, $id->toString()); $this->assertTrue($id->isUlid()); } }