userOrganizationApp service test
This commit is contained in:
parent
0df623ba17
commit
30901335d9
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue