userOrganizationApp service test

This commit is contained in:
Charles 2025-12-09 15:45:35 +01:00
parent 0df623ba17
commit 30901335d9
1 changed files with 320 additions and 0 deletions

View File

@ -0,0 +1,320 @@
<?php
namespace App\Tests\Service;
use App\Entity\Apps;
use App\Entity\Organizations;
use App\Entity\Roles;
use App\Entity\User;
use App\Entity\UserOrganizatonApp;
use App\Entity\UsersOrganizations;
use App\Service\ActionService;
use App\Service\LoggerService;
use App\Service\UserOrganizationAppService;
use App\Service\UserService;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\SecurityBundle\Security;
class UserOrganizationAppServiceTest extends TestCase
{
private UserOrganizationAppService $service;
// Mocks
private MockObject|EntityManagerInterface $entityManager;
private MockObject|ActionService $actionService;
private MockObject|Security $security;
private MockObject|UserService $userService;
private MockObject|LoggerInterface $psrLogger;
private MockObject|LoggerService $loggerService;
protected function setUp(): void
{
$this->entityManager = $this->createMock(EntityManagerInterface::class);
$this->actionService = $this->createMock(ActionService::class);
$this->security = $this->createMock(Security::class);
$this->userService = $this->createMock(UserService::class);
$this->psrLogger = $this->createMock(LoggerInterface::class);
$this->loggerService = $this->createMock(LoggerService::class);
$this->service = new UserOrganizationAppService(
$this->entityManager,
$this->actionService,
$this->security,
$this->userService,
$this->psrLogger,
$this->loggerService
);
}
/**
* Helper to set private ID property on entities.
*/
private function setEntityId(object $entity, int $id): void
{
$reflection = new \ReflectionClass($entity);
if ($reflection->hasProperty('id')) {
$property = $reflection->getProperty('id');
// $property->setAccessible(true); // Needed for PHP < 8.1
$property->setValue($entity, $id);
}
}
// ==========================================
// TEST: groupUserOrganizationAppsByApplication
// ==========================================
public function testGroupUserOrganizationAppsByApplication(): void
{
// 1. Setup Apps
$app1 = new Apps(); $this->setEntityId($app1, 1);
$app2 = new Apps(); $this->setEntityId($app2, 2); // No roles for this one
// 2. Setup Existing Link
$role = new Roles(); $this->setEntityId($role, 10);
$uo = new UsersOrganizations(); $this->setEntityId($uo, 99);
$uoa = new UserOrganizatonApp();
$this->setEntityId($uoa, 500);
$uoa->setApplication($app1);
$uoa->setRole($role);
$uoa->setUserOrganization($uo);
// 3. Run
$result = $this->service->groupUserOrganizationAppsByApplication(
[$uoa],
[$app1, $app2],
null
);
// 4. Assert
$this->assertArrayHasKey(1, $result);
$this->assertArrayHasKey(2, $result);
// Check App 1 (Has existing link)
$this->assertEquals(99, $result[1]['uoId']);
$this->assertEquals([10], $result[1]['selectedRoleIds']);
// Check App 2 (Empty default)
$this->assertNull($result[2]['uoId']);
$this->assertEmpty($result[2]['selectedRoleIds']);
}
// ==========================================
// TEST: deactivateAllUserOrganizationsAppLinks
// ==========================================
public function testDeactivateAllLinksSuccess(): void
{
$uo = new UsersOrganizations();
$user = new User();
$org = new Organizations();
$uo->setUsers($user);
$uo->setOrganization($org);
$app = new Apps();
$this->setEntityId($app, 1);
$role = new Roles();
$this->setEntityId($role, 10);
$uoa = new UserOrganizatonApp();
$this->setEntityId($uoa, 555);
$uoa->setApplication($app);
$uoa->setRole($role);
$uoa->setIsActive(true);
// Mock Repository
$repo = $this->createMock(EntityRepository::class);
$repo->method('findBy')->willReturn([$uoa]);
$this->entityManager->method('getRepository')->willReturn($repo);
// Expectations
$this->actionService->expects($this->once())->method('createAction');
$this->entityManager->expects($this->once())->method('persist')->with($uoa);
$this->loggerService->expects($this->once())->method('logUOALinkDeactivated');
$this->service->deactivateAllUserOrganizationsAppLinks($uo, null);
$this->assertFalse($uoa->isActive());
}
public function testDeactivateHandlesException(): void
{
$uo = new UsersOrganizations();
// The service needs a User to create an Action log
$user = new User();
$this->setEntityId($user, 99);
$uo->setUsers($user); // <--- Assign the user!
// Also needs an Org for the Action log
$org = new Organizations();
$this->setEntityId($org, 88);
$uo->setOrganization($org);
$app = new Apps(); $this->setEntityId($app, 1);
$role = new Roles(); $this->setEntityId($role, 1);
$realUoa = new UserOrganizatonApp();
$this->setEntityId($realUoa, 100);
$realUoa->setApplication($app);
$realUoa->setRole($role);
$realUoa->setIsActive(true);
$repo = $this->createMock(EntityRepository::class);
$repo->method('findBy')->willReturn([$realUoa]);
$this->entityManager->method('getRepository')->willReturn($repo);
// Throw exception on persist
$this->entityManager->method('persist')->willThrowException(new \Exception('DB Error'));
// Expect Logger Critical
$this->loggerService->expects($this->once())->method('logCritical');
$this->service->deactivateAllUserOrganizationsAppLinks($uo);
}
// ==========================================
// TEST: syncRolesForUserOrganizationApp
// ==========================================
public function testSyncRolesAddsNewRole(): void
{
// Setup
$actingUser = new User(); $this->setEntityId($actingUser, 1);
$targetUser = new User(); $this->setEntityId($targetUser, 2);
$org = new Organizations(); $this->setEntityId($org, 10);
$uo = new UsersOrganizations();
$uo->setOrganization($org);
$uo->setUsers($targetUser);
$app = new Apps(); $this->setEntityId($app, 5);
$app->setName('App1');
$roleId = 20;
$role = new Roles();
$role->setName('EDITOR');
$this->setEntityId($role, $roleId);
// Mock Repositories
$uoaRepo = $this->createMock(EntityRepository::class);
$uoaRepo->method('findBy')->willReturn([]); // No existing roles
$roleRepo = $this->createMock(EntityRepository::class);
$roleRepo->method('find')->with($roleId)->willReturn($role);
$this->entityManager->method('getRepository')->willReturnMap([
[UserOrganizatonApp::class, $uoaRepo],
[Roles::class, $roleRepo],
]);
// Expect creation
$this->entityManager->expects($this->once())->method('persist')->with($this->isInstanceOf(UserOrganizatonApp::class));
$this->entityManager->expects($this->once())->method('flush');
$this->actionService->expects($this->once())->method('createAction');
// Run
$this->service->syncRolesForUserOrganizationApp($uo, $app, [(string)$roleId], $actingUser);
}
public function testSyncRolesDeactivatesUnselectedRole(): void
{
$actingUser = new User(); $this->setEntityId($actingUser, 1);
$targetUser = new User(); $this->setEntityId($targetUser, 2);
$org = new Organizations(); $this->setEntityId($org, 10);
$uo = new UsersOrganizations();
$uo->setOrganization($org);
$uo->setUsers($targetUser);
$app = new Apps(); $this->setEntityId($app, 5);
$app->setName('App1');
// Existing active role
$role = new Roles(); $this->setEntityId($role, 30);
$role->setName('VIEWER');
$existingUoa = new UserOrganizatonApp();
$this->setEntityId($existingUoa, 999);
$existingUoa->setRole($role);
$existingUoa->setApplication($app);
$existingUoa->setUserOrganization($uo);
$existingUoa->setIsActive(true);
// Repos
$uoaRepo = $this->createMock(EntityRepository::class);
$uoaRepo->method('findBy')->willReturn([$existingUoa]);
$this->entityManager->method('getRepository')->willReturnMap([
[UserOrganizatonApp::class, $uoaRepo],
]);
// We pass empty array [] as selected roles -> expect deactivation
$this->service->syncRolesForUserOrganizationApp($uo, $app, [], $actingUser);
$this->assertFalse($existingUoa->isActive());
}
public function testSyncRolesHandlesSuperAdminLogic(): void
{
// Setup
$actingUser = new User(); $this->setEntityId($actingUser, 1);
$targetUser = new User(); $this->setEntityId($targetUser, 2);
$uo = new UsersOrganizations();
$uo->setUsers($targetUser);
$org = new Organizations();
$this->setEntityId($org, 500); // <--- Give the Org an ID!
$uo->setOrganization($org);
$app = new Apps(); $this->setEntityId($app, 1);
$app->setName('Portal');
// Roles
$superAdminRole = new Roles();
$superAdminRole->setName('SUPER ADMIN');
$this->setEntityId($superAdminRole, 100);
$adminRole = new Roles();
$adminRole->setName('ADMIN');
$this->setEntityId($adminRole, 101);
// Repositories Configuration
$uoaRepo = $this->createMock(EntityRepository::class);
// 1. findBy (initial check) -> returns empty
// 2. findOneBy (inside ensureAdminRoleForSuperAdmin) -> returns null (Admin link doesn't exist yet)
$uoaRepo->method('findBy')->willReturn([]);
$uoaRepo->method('findOneBy')->willReturn(null);
$roleRepo = $this->createMock(EntityRepository::class);
$roleRepo->method('find')->with(100)->willReturn($superAdminRole);
$roleRepo->method('findOneBy')->with(['name' => 'ADMIN'])->willReturn($adminRole);
$this->entityManager->method('getRepository')->willReturnMap([
[UserOrganizatonApp::class, $uoaRepo],
[Roles::class, $roleRepo],
]);
// Expectations
// 1. UserService should be called to sync SUPER ADMIN
$this->userService->expects($this->once())
->method('syncUserRoles')
->with($targetUser, 'SUPER ADMIN', true);
// 2. EntityManager should persist:
// - The new SUPER ADMIN link
// - The new ADMIN link (automatically created)
$this->entityManager->expects($this->exactly(2))
->method('persist')
->with($this->isInstanceOf(UserOrganizatonApp::class));
// Run
$this->service->syncRolesForUserOrganizationApp($uo, $app, ['100'], $actingUser);
}
}