entityManager = $this->createMock(EntityManagerInterface::class); $this->service = new ActionService($this->entityManager); } /** * Helper to set private ID properties on entities without setters */ private function setEntityId(object $entity, int $id): void { $reflection = new \ReflectionClass($entity); if ($reflection->hasProperty('id')) { $property = $reflection->getProperty('id'); // $property->setAccessible(true); // Uncomment for PHP < 8.1 $property->setValue($entity, $id); } } // ========================================== // TEST: getActivityColor // ========================================== public function testGetActivityColorRecent(): void { // Less than 15 minutes ago $date = new \DateTimeImmutable('-10 minutes'); $color = $this->service->getActivityColor($date); $this->assertEquals('#086572', $color); } public function testGetActivityColorMedium(): void { // Between 15 and 60 minutes ago $date = new \DateTimeImmutable('-30 minutes'); $color = $this->service->getActivityColor($date); $this->assertEquals('#247208', $color); } public function testGetActivityColorOld(): void { // Older than 1 hour $date = new \DateTimeImmutable('-2 hours'); $color = $this->service->getActivityColor($date); $this->assertEquals('#cc664c', $color); } // ========================================== // TEST: formatActivities // ========================================== public function testFormatActivities(): void { $user = new User(); $org = new Organizations(); $action1 = new Actions(); $action1->setDate(new \DateTimeImmutable('-5 minutes')); // Recent $action1->setActionType('LOGIN'); $action1->setUsers($user); $action1->setOrganization($org); $action1->setDescription('User logged in'); $action2 = new Actions(); $action2->setDate(new \DateTimeImmutable('-2 hours')); // Old $action2->setUsers($user); $action2->setActionType('LOGOUT'); $activities = [$action1, $action2]; $result = $this->service->formatActivities($activities); $this->assertCount(2, $result); // Check first activity (Recent) $this->assertEquals('#086572', $result[0]['color']); $this->assertEquals('LOGIN', $result[0]['actionType']); $this->assertSame($user->getName(), $result[0]['userName']); // Check second activity (Old) $this->assertEquals('#cc664c', $result[1]['color']); $this->assertEquals('LOGOUT', $result[1]['actionType']); } // ========================================== // TEST: createAction // ========================================== public function testCreateActionBasic(): void { $user = new User(); $user->setEmail('user@test.com'); $this->entityManager->expects($this->once()) ->method('persist') ->with($this->callback(function (Actions $action) use ($user) { return $action->getActionType() === 'LOGIN' && $action->getUsers() === $user && $action->getOrganization() === null && $action->getDescription() === null; })); $this->entityManager->expects($this->once())->method('flush'); $this->service->createAction('LOGIN', $user); } public function testCreateActionWithOrganizationAndTarget(): void { $user = new User(); $user->setEmail('admin@test.com'); $org = new Organizations(); $this->setEntityId($org, 99); // Expect persist with full details $this->entityManager->expects($this->once()) ->method('persist') ->with($this->callback(function (Actions $action) use ($user, $org) { return $action->getActionType() === 'UPDATE' && $action->getUsers() === $user && $action->getOrganization() === $org // Check description generated by descriptionAction && str_contains($action->getDescription(), 'UPDATE by admin@test.com onto Settings'); })); $this->entityManager->expects($this->once())->method('flush'); $this->service->createAction('UPDATE', $user, $org, 'Settings'); } // ========================================== // TEST: descriptionAction // ========================================== public function testDescriptionActionSuccess(): void { $user = new User(); $user->setEmail('jane@doe.com'); $action = new Actions(); $action->setActionType('DELETE'); $action->setUsers($user); // Pass by reference $this->service->descriptionAction($action, 'Document.pdf'); $this->assertEquals( 'DELETE by jane@doe.com onto Document.pdf', $action->getDescription() ); } public function testDescriptionActionThrowsIfNoUser(): void { $action = new Actions(); $action->setActionType('DELETE'); // No user set $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Action must have a user set'); $this->service->descriptionAction($action, 'Target'); } public function testDescriptionActionThrowsIfInvalidType(): void { $invalidObject = new \stdClass(); $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Action must be an instance of Actions'); // Pass an object that is NOT an instance of Actions entity $this->service->descriptionAction($invalidObject, 'Target'); } }