Release 2.57 (#5929)
This commit is contained in:
242
tests/Validator/Constraints/TimesheetTeamAccessValidatorTest.php
Normal file
242
tests/Validator/Constraints/TimesheetTeamAccessValidatorTest.php
Normal file
@@ -0,0 +1,242 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Validator\Constraints;
|
||||
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\Team;
|
||||
use App\Entity\Timesheet;
|
||||
use App\Entity\User;
|
||||
use App\Security\RolePermissionManager;
|
||||
use App\User\PermissionService;
|
||||
use App\Validator\Constraints\TimesheetTeamAccess;
|
||||
use App\Validator\Constraints\TimesheetTeamAccessValidator;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\UnitOfWork;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use Symfony\Bundle\SecurityBundle\Security;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
|
||||
|
||||
/**
|
||||
* @extends ConstraintValidatorTestCase<TimesheetTeamAccessValidator>
|
||||
*/
|
||||
#[CoversClass(TimesheetTeamAccess::class)]
|
||||
#[CoversClass(TimesheetTeamAccessValidator::class)]
|
||||
class TimesheetTeamAccessValidatorTest extends ConstraintValidatorTestCase
|
||||
{
|
||||
protected function createValidator(): TimesheetTeamAccessValidator
|
||||
{
|
||||
return $this->createMyValidator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $originalData
|
||||
*/
|
||||
protected function createMyValidator(
|
||||
array $originalData = [],
|
||||
?User $user = null
|
||||
): TimesheetTeamAccessValidator
|
||||
{
|
||||
$security = $this->createMock(Security::class);
|
||||
$security->method('getUser')->willReturn($user ?? new User());
|
||||
|
||||
$permissionService = $this->createMock(PermissionService::class);
|
||||
$permissionService->method('getPermissions')->willReturn([]);
|
||||
$permissionManager = new RolePermissionManager($permissionService, [], []);
|
||||
|
||||
$unitOfWork = $this->createMock(UnitOfWork::class);
|
||||
$unitOfWork->method('getOriginalEntityData')->willReturn($originalData);
|
||||
|
||||
$entityManager = $this->createMock(EntityManagerInterface::class);
|
||||
$entityManager->method('getUnitOfWork')->willReturn($unitOfWork);
|
||||
|
||||
$registry = $this->createMock(ManagerRegistry::class);
|
||||
$registry->method('getManagerForClass')->willReturn($entityManager);
|
||||
|
||||
return new TimesheetTeamAccessValidator($security, $permissionManager, $registry);
|
||||
}
|
||||
|
||||
public function testConstraintIsInvalid(): void
|
||||
{
|
||||
$this->expectException(UnexpectedTypeException::class);
|
||||
|
||||
$this->validator->validate(new Timesheet(), new NotBlank());
|
||||
}
|
||||
|
||||
public function testInvalidValueThrowsException(): void
|
||||
{
|
||||
$this->expectException(UnexpectedTypeException::class);
|
||||
|
||||
$this->validator->validate(new NotBlank(), new TimesheetTeamAccess(['message' => 'myMessage']));
|
||||
}
|
||||
|
||||
public function testTriggersForNewTimesheetWithInaccessibleProject(): void
|
||||
{
|
||||
$this->validator = $this->createMyValidator();
|
||||
$this->validator->initialize($this->context);
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet->setProject($this->createRestrictedProject('restricted'));
|
||||
|
||||
$this->validator->validate($timesheet, new TimesheetTeamAccess());
|
||||
|
||||
$this->buildViolation('You are not allowed to use this project.')
|
||||
->atPath('property.path.project')
|
||||
->setCode(TimesheetTeamAccess::PROJECT_ACCESS_ERROR)
|
||||
->assertRaised();
|
||||
}
|
||||
|
||||
public function testDoesNotReadOriginalDataForNewTimesheet(): void
|
||||
{
|
||||
$security = $this->createMock(Security::class);
|
||||
$security->method('getUser')->willReturn(new User());
|
||||
|
||||
$permissionService = $this->createMock(PermissionService::class);
|
||||
$permissionService->method('getPermissions')->willReturn([]);
|
||||
$permissionManager = new RolePermissionManager($permissionService, [], []);
|
||||
|
||||
$registry = $this->createMock(ManagerRegistry::class);
|
||||
$registry->expects(self::never())->method('getManagerForClass');
|
||||
|
||||
$this->validator = new TimesheetTeamAccessValidator($security, $permissionManager, $registry);
|
||||
$this->validator->initialize($this->context);
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet->setProject($this->createRestrictedProject('new-timesheet'));
|
||||
|
||||
$this->validator->validate($timesheet, new TimesheetTeamAccess());
|
||||
|
||||
$this->buildViolation('You are not allowed to use this project.')
|
||||
->atPath('property.path.project')
|
||||
->setCode(TimesheetTeamAccess::PROJECT_ACCESS_ERROR)
|
||||
->assertRaised();
|
||||
}
|
||||
|
||||
public function testDoesNotTriggerForExistingTimesheetWithUnchangedProject(): void
|
||||
{
|
||||
$originalProject = $this->createRestrictedProject('restricted');
|
||||
|
||||
$this->validator = $this->createMyValidator(['project' => $originalProject]);
|
||||
$this->validator->initialize($this->context);
|
||||
|
||||
$timesheet = $this->createPersistedTimesheet();
|
||||
$timesheet->setProject($originalProject);
|
||||
|
||||
$this->validator->validate($timesheet, new TimesheetTeamAccess());
|
||||
|
||||
$this->assertNoViolation();
|
||||
}
|
||||
|
||||
public function testTriggersForExistingTimesheetWithChangedProject(): void
|
||||
{
|
||||
$this->validator = $this->createMyValidator(['project' => $this->createProject('old')]);
|
||||
$this->validator->initialize($this->context);
|
||||
|
||||
$timesheet = $this->createPersistedTimesheet();
|
||||
$timesheet->setProject($this->createRestrictedProject('new'));
|
||||
|
||||
$this->validator->validate($timesheet, new TimesheetTeamAccess());
|
||||
|
||||
$this->buildViolation('You are not allowed to use this project.')
|
||||
->atPath('property.path.project')
|
||||
->setCode(TimesheetTeamAccess::PROJECT_ACCESS_ERROR)
|
||||
->assertRaised();
|
||||
}
|
||||
|
||||
public function testTriggersForExistingTimesheetWithChangedActivity(): void
|
||||
{
|
||||
$this->validator = $this->createMyValidator(['activity' => $this->createActivity('old')]);
|
||||
$this->validator->initialize($this->context);
|
||||
|
||||
$timesheet = $this->createPersistedTimesheet();
|
||||
$timesheet->setActivity($this->createRestrictedActivity('new'));
|
||||
|
||||
$this->validator->validate($timesheet, new TimesheetTeamAccess());
|
||||
|
||||
$this->buildViolation('You are not allowed to use this activity.')
|
||||
->atPath('property.path.activity')
|
||||
->setCode(TimesheetTeamAccess::ACTIVITY_ACCESS_ERROR)
|
||||
->assertRaised();
|
||||
}
|
||||
|
||||
public function testDoesNotTriggerForSuperAdmin(): void
|
||||
{
|
||||
$user = new User();
|
||||
$user->setRoles([User::ROLE_SUPER_ADMIN]);
|
||||
|
||||
$this->validator = $this->createMyValidator([], $user);
|
||||
$this->validator->initialize($this->context);
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setProject($this->createRestrictedProject('restricted'))
|
||||
->setActivity($this->createRestrictedActivity('restricted'))
|
||||
;
|
||||
|
||||
$this->validator->validate($timesheet, new TimesheetTeamAccess());
|
||||
|
||||
$this->assertNoViolation();
|
||||
}
|
||||
|
||||
public function testGetTargets(): void
|
||||
{
|
||||
$constraint = new TimesheetTeamAccess();
|
||||
self::assertEquals('class', $constraint->getTargets());
|
||||
}
|
||||
|
||||
private function createPersistedTimesheet(): Timesheet
|
||||
{
|
||||
$timesheet = new Timesheet();
|
||||
$reflection = new \ReflectionClass($timesheet);
|
||||
$property = $reflection->getProperty('id');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue($timesheet, 1);
|
||||
$property->setAccessible(false);
|
||||
|
||||
return $timesheet;
|
||||
}
|
||||
|
||||
private function createProject(string $name): Project
|
||||
{
|
||||
$project = new Project();
|
||||
$project->setName($name);
|
||||
$project->setCustomer(new Customer('customer-' . $name));
|
||||
|
||||
return $project;
|
||||
}
|
||||
|
||||
private function createActivity(string $name): Activity
|
||||
{
|
||||
$activity = new Activity();
|
||||
$activity->setName($name);
|
||||
|
||||
return $activity;
|
||||
}
|
||||
|
||||
private function createRestrictedProject(string $name): Project
|
||||
{
|
||||
$project = $this->createProject($name);
|
||||
$project->getCustomer()?->addTeam(new Team('customer-team-' . $name));
|
||||
|
||||
return $project;
|
||||
}
|
||||
|
||||
private function createRestrictedActivity(string $name): Activity
|
||||
{
|
||||
$activity = $this->createActivity($name);
|
||||
$activity->addTeam(new Team('activity-team-' . $name));
|
||||
|
||||
return $activity;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user