From 5ea5494bde1c8ec89e038737ae5f212c2ded71b1 Mon Sep 17 00:00:00 2001 From: Jose Andres Tejerina Date: Mon, 23 Feb 2026 14:16:52 -0300 Subject: [PATCH] fix: add otlp test changes --- tests/OpenTelemetry/AuditEventTypesTest.php | 79 +++++++++++++---- tests/OpenTelemetry/AuditOtlpStrategyTest.php | 85 +++++++++++++------ ...mmitAttendeeBadgeAuditLogFormatterTest.php | 11 ++- ...ummitAttendeeNoteAuditLogFormatterTest.php | 8 +- ...mitAttendeeTicketAuditLogFormatterTest.php | 13 +-- 5 files changed, 143 insertions(+), 53 deletions(-) diff --git a/tests/OpenTelemetry/AuditEventTypesTest.php b/tests/OpenTelemetry/AuditEventTypesTest.php index d7886ac2f..2f35a806b 100644 --- a/tests/OpenTelemetry/AuditEventTypesTest.php +++ b/tests/OpenTelemetry/AuditEventTypesTest.php @@ -3,10 +3,36 @@ namespace Tests\OpenTelemetry; use App\Audit\AuditLogOtlpStrategy; +use App\Audit\AuditContext; use OpenTelemetry\API\Trace\StatusCode; class AuditEventTypesTest extends OpenTelemetryTestCase { + private const MOCK_ENTITY_ID = 999; + private const MOCK_ENTITY_TITLE = 'Test Entity'; + private const NEW_ENTITY_TITLE = 'New Entity'; + private const TEST_TYPE = 'test'; + private const OLD_TITLE = 'Old Title'; + private const NEW_TITLE = 'New Title'; + private const DELETED_ID = 999; + private const CLEANUP_REASON = 'Test cleanup'; + private const USER_ID = 999; + private const USER_EMAIL = 'test@example.com'; + private const USER_FIRST_NAME = 'Test'; + private const USER_LAST_NAME = 'User'; + private const TEST_APP = 'test-app'; + private const TEST_FLOW = 'test-flow'; + private const TEST_ROUTE = 'api.test'; + private const TEST_HTTP_METHOD = 'POST'; + private const TEST_CLIENT_IP = '127.0.0.1'; + private const TEST_USER_AGENT = 'Test-Agent/1.0'; + private const SPAN_CREATION = 'test.audit.creation'; + private const SPAN_UPDATE = 'test.audit.update'; + private const SPAN_DELETION = 'test.audit.deletion'; + private const CREATION_COMPLETED = 'Creation audit completed'; + private const UPDATE_COMPLETED = 'Update audit completed'; + private const DELETION_COMPLETED = 'Deletion audit completed'; + private AuditLogOtlpStrategy $auditStrategy; protected function setUp(): void @@ -23,20 +49,22 @@ public function testEntityCreationAudit(): void } $tracer = $this->app->make(\OpenTelemetry\API\Trace\TracerInterface::class); - $span = $tracer->spanBuilder('test.audit.creation')->startSpan(); + $span = $tracer->spanBuilder(self::SPAN_CREATION)->startSpan(); $spanScope = $span->activate(); try { - $mockEntity = (object) ['id' => 999, 'title' => 'Test Entity']; - $data = ['title' => 'New Entity', 'type' => 'test']; + $mockEntity = (object) ['id' => self::MOCK_ENTITY_ID, 'title' => self::MOCK_ENTITY_TITLE]; + $data = ['title' => self::NEW_ENTITY_TITLE, 'type' => self::TEST_TYPE]; + $ctx = $this->createAuditContext(); $this->auditStrategy->audit( $mockEntity, $data, - AuditLogOtlpStrategy::EVENT_ENTITY_CREATION + AuditLogOtlpStrategy::EVENT_ENTITY_CREATION, + $ctx ); - $span->setStatus(StatusCode::STATUS_OK, 'Creation audit completed'); + $span->setStatus(StatusCode::STATUS_OK, self::CREATION_COMPLETED); $this->assertTrue(true); } catch (\Exception $e) { $span->recordException($e); @@ -54,20 +82,22 @@ public function testEntityUpdateAudit(): void } $tracer = $this->app->make(\OpenTelemetry\API\Trace\TracerInterface::class); - $span = $tracer->spanBuilder('test.audit.update')->startSpan(); + $span = $tracer->spanBuilder(self::SPAN_UPDATE)->startSpan(); $spanScope = $span->activate(); try { - $mockEntity = (object) ['id' => 999, 'title' => 'Test Entity']; - $data = ['title' => ['Old Title', 'New Title']]; + $mockEntity = (object) ['id' => self::MOCK_ENTITY_ID, 'title' => self::MOCK_ENTITY_TITLE]; + $data = ['title' => [self::OLD_TITLE, self::NEW_TITLE]]; + $ctx = $this->createAuditContext(); $this->auditStrategy->audit( $mockEntity, $data, - AuditLogOtlpStrategy::EVENT_ENTITY_UPDATE + AuditLogOtlpStrategy::EVENT_ENTITY_UPDATE, + $ctx ); - $span->setStatus(StatusCode::STATUS_OK, 'Update audit completed'); + $span->setStatus(StatusCode::STATUS_OK, self::UPDATE_COMPLETED); $this->assertTrue(true); } catch (\Exception $e) { $span->recordException($e); @@ -85,20 +115,22 @@ public function testEntityDeletionAudit(): void } $tracer = $this->app->make(\OpenTelemetry\API\Trace\TracerInterface::class); - $span = $tracer->spanBuilder('test.audit.deletion')->startSpan(); + $span = $tracer->spanBuilder(self::SPAN_DELETION)->startSpan(); $spanScope = $span->activate(); try { - $mockEntity = (object) ['id' => 999, 'title' => 'Test Entity']; - $data = ['deleted_id' => 999, 'reason' => 'Test cleanup']; + $mockEntity = (object) ['id' => self::MOCK_ENTITY_ID, 'title' => self::MOCK_ENTITY_TITLE]; + $data = ['deleted_id' => self::DELETED_ID, 'reason' => self::CLEANUP_REASON]; + $ctx = $this->createAuditContext(); $this->auditStrategy->audit( $mockEntity, $data, - AuditLogOtlpStrategy::EVENT_ENTITY_DELETION + AuditLogOtlpStrategy::EVENT_ENTITY_DELETION, + $ctx ); - $span->setStatus(StatusCode::STATUS_OK, 'Deletion audit completed'); + $span->setStatus(StatusCode::STATUS_OK, self::DELETION_COMPLETED); $this->assertTrue(true); } catch (\Exception $e) { $span->recordException($e); @@ -116,4 +148,21 @@ private function isOpenTelemetryEnabled(): bool { return getenv('OTEL_SERVICE_ENABLED') === 'true'; } + + private function createAuditContext(): AuditContext + { + return new AuditContext( + userId: self::USER_ID, + userEmail: self::USER_EMAIL, + userFirstName: self::USER_FIRST_NAME, + userLastName: self::USER_LAST_NAME, + uiApp: self::TEST_APP, + uiFlow: self::TEST_FLOW, + route: self::TEST_ROUTE, + rawRoute: self::TEST_ROUTE, + httpMethod: self::TEST_HTTP_METHOD, + clientIp: self::TEST_CLIENT_IP, + userAgent: self::TEST_USER_AGENT, + ); + } } diff --git a/tests/OpenTelemetry/AuditOtlpStrategyTest.php b/tests/OpenTelemetry/AuditOtlpStrategyTest.php index a80d245cb..8bf855353 100644 --- a/tests/OpenTelemetry/AuditOtlpStrategyTest.php +++ b/tests/OpenTelemetry/AuditOtlpStrategyTest.php @@ -26,6 +26,23 @@ class AuditOtlpStrategyTest extends OpenTelemetryTestCase use InsertSummitTestData; use InsertMemberTestData; + private const TEST_APP = 'test-app'; + private const TEST_FLOW = 'test-flow'; + private const TEST_ROUTE = 'api.summits.update'; + private const TEST_HTTP_METHOD = 'PUT'; + private const TEST_CLIENT_IP = '127.0.0.1'; + private const TEST_USER_AGENT = 'Test-Agent/1.0'; + private const SPAN_SUMMIT_CHANGE = 'test.audit.summit_change'; + private const SPAN_SUMMIT_EVENT_CHANGE = 'test.audit.summit_event_change'; + private const SPAN_NO_ACTIVE_SPAN = 'test.audit.no_span'; + private const SPAN_EMPTY_CHANGESET = 'test.audit.empty_changeset'; + private const SUFFIX_TEST = '[TEST]'; + private const SUFFIX_UPDATED = '[UPDATED]'; + private const SPAN_EVENT_STARTED = 'test.started'; + private const EVENT_COMPLETED = 'Summit audit completed'; + private const EVENT_CHANGE_COMPLETED = 'SummitEvent audit completed'; + private const EVENT_EMPTY_COMPLETED = 'Empty changeset audit completed'; + private AuditLogOtlpStrategy $auditStrategy; protected function setUp(): void @@ -51,24 +68,26 @@ public function testAuditSummitChangeWithOtlp(): void $this->skipIfOpenTelemetryDisabled(); $tracer = $this->app->make(TracerInterface::class); - $span = $tracer->spanBuilder('test.audit.summit_change')->startSpan(); + $span = $tracer->spanBuilder(self::SPAN_SUMMIT_CHANGE)->startSpan(); $spanScope = $span->activate(); try { - $span->addEvent('test.started', [ + $span->addEvent(self::SPAN_EVENT_STARTED, [ 'summit_id' => self::$summit->getId(), 'summit_name' => self::$summit->getName() ]); $simulatedChangeSet = $this->createSummitChangeSet(); + $ctx = $this->createAuditContext(); $this->auditStrategy->audit( self::$summit, $simulatedChangeSet, - AuditLogOtlpStrategy::EVENT_ENTITY_UPDATE + AuditLogOtlpStrategy::EVENT_ENTITY_UPDATE, + $ctx ); - $span->setStatus(StatusCode::STATUS_OK, 'Summit audit completed'); + $span->setStatus(StatusCode::STATUS_OK, self::EVENT_COMPLETED); $this->assertTrue(true); } catch (\Exception $e) { @@ -86,20 +105,22 @@ public function testAuditSummitEventChangeWithOtlp(): void $this->skipIfOpenTelemetryDisabled(); $tracer = $this->app->make(TracerInterface::class); - $span = $tracer->spanBuilder('test.audit.summit_event_change')->startSpan(); + $span = $tracer->spanBuilder(self::SPAN_SUMMIT_EVENT_CHANGE)->startSpan(); $spanScope = $span->activate(); try { $summitEvent = self::$summit->getEvents()[0]; $simulatedChangeSet = $this->createSummitEventChangeSet($summitEvent); + $ctx = $this->createAuditContext(); $this->auditStrategy->audit( $summitEvent, $simulatedChangeSet, - AuditLogOtlpStrategy::EVENT_ENTITY_UPDATE + AuditLogOtlpStrategy::EVENT_ENTITY_UPDATE, + $ctx ); - $span->setStatus(StatusCode::STATUS_OK, 'SummitEvent audit completed'); + $span->setStatus(StatusCode::STATUS_OK, self::EVENT_CHANGE_COMPLETED); $this->assertTrue(true); } catch (\Exception $e) { @@ -117,11 +138,13 @@ public function testAuditStrategyWithoutActiveSpan(): void $this->skipIfOpenTelemetryDisabled(); $simulatedChangeSet = ['name' => ['Old Name', 'New Name']]; + $ctx = $this->createAuditContext(); $this->auditStrategy->audit( self::$summit, $simulatedChangeSet, - AuditLogOtlpStrategy::EVENT_ENTITY_UPDATE + AuditLogOtlpStrategy::EVENT_ENTITY_UPDATE, + $ctx ); $this->assertTrue(true); @@ -132,17 +155,19 @@ public function testAuditStrategyWithEmptyChangeSet(): void $this->skipIfOpenTelemetryDisabled(); $tracer = $this->app->make(TracerInterface::class); - $span = $tracer->spanBuilder('test.audit.empty_changeset')->startSpan(); + $span = $tracer->spanBuilder(self::SPAN_EMPTY_CHANGESET)->startSpan(); $spanScope = $span->activate(); try { + $ctx = $this->createAuditContext(); $this->auditStrategy->audit( self::$summit, [], - AuditLogOtlpStrategy::EVENT_ENTITY_UPDATE + AuditLogOtlpStrategy::EVENT_ENTITY_UPDATE, + $ctx ); - $span->setStatus(StatusCode::STATUS_OK, 'Empty changeset audit completed'); + $span->setStatus(StatusCode::STATUS_OK, self::EVENT_EMPTY_COMPLETED); $this->assertTrue(true); } catch (\Exception $e) { @@ -165,7 +190,7 @@ private function skipIfOpenTelemetryDisabled(): void private function createSummitChangeSet(): array { return [ - 'name' => [self::$summit->getName(), self::$summit->getName() . ' [TEST]'], + 'name' => [self::$summit->getName(), self::$summit->getName() . self::SUFFIX_TEST], 'description' => ['Original', 'Updated for test'] ]; } @@ -173,7 +198,7 @@ private function createSummitChangeSet(): array private function createSummitEventChangeSet(object $summitEvent): array { return [ - 'title' => [$summitEvent->getTitle(), $summitEvent->getTitle() . ' [TEST]'] + 'title' => [$summitEvent->getTitle(), $summitEvent->getTitle() . self::SUFFIX_TEST] ]; } @@ -182,6 +207,23 @@ private function isOpenTelemetryEnabled(): bool return getenv('OTEL_SERVICE_ENABLED') === 'true'; } + private function createAuditContext(): AuditContext + { + return new AuditContext( + userId: self::$member->getId(), + userEmail: self::$member->getEmail(), + userFirstName: self::$member->getFirstName(), + userLastName: self::$member->getLastName(), + uiApp: self::TEST_APP, + uiFlow: self::TEST_FLOW, + route: self::TEST_ROUTE, + rawRoute: self::TEST_ROUTE, + httpMethod: self::TEST_HTTP_METHOD, + clientIp: self::TEST_CLIENT_IP, + userAgent: self::TEST_USER_AGENT, + ); + } + public function testAuditSummitEntityPopulatesSummitIdCorrectly(): void { @@ -189,20 +231,9 @@ public function testAuditSummitEntityPopulatesSummitIdCorrectly(): void Queue::fake(); - $ctx = new AuditContext(); - $ctx->userId = self::$member->getId(); - $ctx->userEmail = self::$member->getEmail(); - $ctx->userFirstName = self::$member->getFirstName(); - $ctx->userLastName = self::$member->getLastName(); - $ctx->uiApp = 'test-app'; - $ctx->uiFlow = 'test-flow'; - $ctx->route = 'api.summits.update'; - $ctx->httpMethod = 'PUT'; - $ctx->clientIp = '127.0.0.1'; - $ctx->userAgent = 'Test-Agent/1.0'; - + $ctx = $this->createAuditContext(); $simulatedChangeSet = [ - 'name' => [self::$summit->getName(), self::$summit->getName() . ' [UPDATED]'] + 'name' => [self::$summit->getName(), self::$summit->getName() . self::SUFFIX_UPDATED] ]; $this->auditStrategy->audit( @@ -215,9 +246,7 @@ public function testAuditSummitEntityPopulatesSummitIdCorrectly(): void Queue::assertPushed(EmitAuditLogJob::class, function ($job) { $this->assertArrayHasKey('audit.summit_id', $job->auditData); $this->assertEquals((string)self::$summit->getId(), $job->auditData['audit.summit_id']); - $this->assertEquals('Summit', $job->auditData['audit.entity']); - return true; }); } diff --git a/tests/OpenTelemetry/Formatters/SummitAttendeeBadgeAuditLogFormatterTest.php b/tests/OpenTelemetry/Formatters/SummitAttendeeBadgeAuditLogFormatterTest.php index 553845c36..5d98b7f9d 100644 --- a/tests/OpenTelemetry/Formatters/SummitAttendeeBadgeAuditLogFormatterTest.php +++ b/tests/OpenTelemetry/Formatters/SummitAttendeeBadgeAuditLogFormatterTest.php @@ -14,6 +14,8 @@ class SummitAttendeeBadgeAuditLogFormatterTest extends TestCase private const TICKET_ID = 789; private const TICKET_NUMBER = 'TICKET-2024-001'; private const SUMMIT_NAME = 'OpenStack Summit 2024'; + private const OWNER_FIRST_NAME = 'John'; + private const OWNER_LAST_NAME = 'Doe'; private mixed $mockSubject; @@ -37,10 +39,15 @@ private function createMockSubject(): mixed $mockOrder = Mockery::mock('models\summit\SummitOrder'); $mockOrder->shouldReceive('getSummit')->andReturn($mockSummit); + $mockOwner = Mockery::mock('models\summit\SummitAttendee'); + $mockOwner->shouldReceive('getFirstName')->andReturn(self::OWNER_FIRST_NAME); + $mockOwner->shouldReceive('getSurname')->andReturn(self::OWNER_LAST_NAME); + $mockTicket = Mockery::mock('models\summit\SummitAttendeeTicket'); $mockTicket->shouldReceive('getId')->andReturn(self::TICKET_ID); $mockTicket->shouldReceive('getNumber')->andReturn(self::TICKET_NUMBER); $mockTicket->shouldReceive('getOrder')->andReturn($mockOrder); + $mockTicket->shouldReceive('getOwner')->andReturn($mockOwner); $mock = Mockery::mock('models\summit\SummitAttendeeBadge'); $mock->shouldReceive('getId')->andReturn(self::BADGE_ID); @@ -58,8 +65,8 @@ public function testSubjectCreationAuditMessage(): void $this->assertNotNull($result); $this->assertStringContainsString('created', $result); - $this->assertStringContainsString(self::TICKET_NUMBER, $result); - $this->assertStringContainsString((string)self::TICKET_ID, $result); + $this->assertStringContainsString(self::OWNER_FIRST_NAME . ' ' . self::OWNER_LAST_NAME, $result); + $this->assertStringContainsString((string)self::BADGE_ID, $result); } public function testSubjectUpdateAuditMessage(): void diff --git a/tests/OpenTelemetry/Formatters/SummitAttendeeNoteAuditLogFormatterTest.php b/tests/OpenTelemetry/Formatters/SummitAttendeeNoteAuditLogFormatterTest.php index a00196d02..8a045faf1 100644 --- a/tests/OpenTelemetry/Formatters/SummitAttendeeNoteAuditLogFormatterTest.php +++ b/tests/OpenTelemetry/Formatters/SummitAttendeeNoteAuditLogFormatterTest.php @@ -15,6 +15,8 @@ class SummitAttendeeNoteAuditLogFormatterTest extends TestCase private const ATTENDEE_EMAIL = 'attendee@example.com'; private const NOTE_CONTENT = 'This is a test note content'; private const SUMMIT_NAME = 'OpenStack Summit 2024'; + private const ATTENDEE_FIRST_NAME = 'Jane'; + private const ATTENDEE_LAST_NAME = 'Smith'; private mixed $mockSubject; @@ -39,6 +41,8 @@ private function createMockSubject(): mixed $mockAttendee->shouldReceive('getId')->andReturn(self::ATTENDEE_ID); $mockAttendee->shouldReceive('getEmail')->andReturn(self::ATTENDEE_EMAIL); $mockAttendee->shouldReceive('getSummit')->andReturn($mockSummit); + $mockAttendee->shouldReceive('getFirstName')->andReturn(self::ATTENDEE_FIRST_NAME); + $mockAttendee->shouldReceive('getSurname')->andReturn(self::ATTENDEE_LAST_NAME); $mock = Mockery::mock('models\summit\SummitAttendeeNote'); $mock->shouldReceive('getId')->andReturn(self::NOTE_ID); @@ -56,8 +60,8 @@ public function testSubjectCreationAuditMessage(): void $this->assertNotNull($result); $this->assertStringContainsString('created', $result); - $this->assertStringContainsString(self::ATTENDEE_EMAIL, $result); - $this->assertStringContainsString((string)self::ATTENDEE_ID, $result); + $this->assertStringContainsString(self::ATTENDEE_FIRST_NAME . ' ' . self::ATTENDEE_LAST_NAME, $result); + $this->assertStringContainsString((string)self::NOTE_ID, $result); } public function testSubjectUpdateAuditMessage(): void diff --git a/tests/OpenTelemetry/Formatters/SummitAttendeeTicketAuditLogFormatterTest.php b/tests/OpenTelemetry/Formatters/SummitAttendeeTicketAuditLogFormatterTest.php index 30b634f74..00b8dd80a 100644 --- a/tests/OpenTelemetry/Formatters/SummitAttendeeTicketAuditLogFormatterTest.php +++ b/tests/OpenTelemetry/Formatters/SummitAttendeeTicketAuditLogFormatterTest.php @@ -19,6 +19,8 @@ class SummitAttendeeTicketAuditLogFormatterTest extends TestCase private const OWNER_EMAIL = 'owner@example.com'; private const SUMMIT_NAME = 'OpenStack Summit 2024'; private const NEW_STATUS = 'Cancelled'; + private const OWNER_FIRST_NAME = 'John'; + private const OWNER_LAST_NAME = 'Doe'; private mixed $mockSubject; @@ -39,14 +41,14 @@ private function createMockSubject(): mixed $mockSummit = Mockery::mock('models\summit\Summit'); $mockSummit->shouldReceive('getName')->andReturn(self::SUMMIT_NAME); - $mockOwner = Mockery::mock('models\main\Member'); - $mockOwner->shouldReceive('getEmail')->andReturn(self::OWNER_EMAIL); + $mockOwner = Mockery::mock('models\summit\SummitAttendee'); + $mockOwner->shouldReceive('getFirstName')->andReturn(self::OWNER_FIRST_NAME); + $mockOwner->shouldReceive('getSurname')->andReturn(self::OWNER_LAST_NAME); $mockOrder = Mockery::mock('models\summit\SummitOrder'); $mockOrder->shouldReceive('getId')->andReturn(self::ORDER_ID); $mockOrder->shouldReceive('getNumber')->andReturn(self::ORDER_NUMBER); $mockOrder->shouldReceive('getSummit')->andReturn($mockSummit); - $mockOrder->shouldReceive('getOwner')->andReturn($mockOwner); $mockTicketType = Mockery::mock('models\summit\SummitTicketType'); $mockTicketType->shouldReceive('getName')->andReturn(self::TICKET_TYPE); @@ -57,6 +59,7 @@ private function createMockSubject(): mixed $mock->shouldReceive('getOrder')->andReturn($mockOrder); $mock->shouldReceive('getTicketType')->andReturn($mockTicketType); $mock->shouldReceive('getStatus')->andReturn(self::TICKET_STATUS); + $mock->shouldReceive('getOwner')->andReturn($mockOwner); return $mock; } @@ -69,10 +72,8 @@ public function testSubjectCreationAuditMessage(): void $this->assertNotNull($result); $this->assertStringContainsString('created', $result); - $this->assertStringContainsString(self::TICKET_NUMBER, $result); + $this->assertStringContainsString(self::OWNER_FIRST_NAME . ' ' . self::OWNER_LAST_NAME, $result); $this->assertStringContainsString((string)self::TICKET_ID, $result); - $this->assertStringContainsString(self::TICKET_TYPE, $result); - $this->assertStringContainsString(self::ORDER_NUMBER, $result); } public function testSubjectUpdateAuditMessage(): void