Next major version 2 with PHP 8.1, Symfony 6, Tabler UI, 2FA ... (#2902)

This commit is contained in:
Kevin Papst
2022-12-31 21:19:55 +01:00
committed by GitHub
parent 95e06746bd
commit 90a0fd8a22
2164 changed files with 83700 additions and 86426 deletions

View File

@@ -1,101 +0,0 @@
<?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\Validator\Constraints\AllowedHtmlTags;
use App\Validator\Constraints\AllowedHtmlTagsValidator;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
/**
* @covers \App\Validator\Constraints\AllowedHtmlTags
* @covers \App\Validator\Constraints\AllowedHtmlTagsValidator
*/
class AllowedHtmlTagsTest extends ConstraintValidatorTestCase
{
protected function createValidator()
{
return new AllowedHtmlTagsValidator();
}
public function testConstraintIsInvalid()
{
$this->expectException(UnexpectedTypeException::class);
$this->validator->validate('foo', new NotBlank());
}
public function testConstraintIsInvalidObject()
{
$this->expectException(UnexpectedTypeException::class);
$constraint = new AllowedHtmlTags(['tags' => '']);
$this->validator->validate(new \stdClass(), $constraint);
}
/**
* @dataProvider getValidValues
* @param string $allowedTags
* @param string $testString
*/
public function testConstraintWithValidValue(string $allowedTags, string $testString)
{
$constraint = new AllowedHtmlTags(['tags' => $allowedTags]);
$this->validator->validate($testString, $constraint);
$this->assertNoViolation();
}
public function testNullIsInvalid()
{
$this->validator->validate(null, new AllowedHtmlTags(['tags' => '<i>', 'message' => 'myMessage']));
$this->assertNoViolation();
}
public function getValidValues()
{
return [
['', 'foo'],
['', ''],
['<i>', 'foo<i>kjhg</i>'],
['<i>', 'foo<I>kjhg</I>'],
['<u><i>', 'foo<i>kj<u>h</u>g</i><u>kjhgk</u>'],
];
}
public function getInvalidValues()
{
return [
['', 'foo<i>kjhg</i>'],
['<u>', 'foo<i>kjhg</i>'],
['<i>', 'foo<u>kjhg</u>'],
];
}
/**
* @dataProvider getInvalidValues
* @param string $allowedTags
* @param string $testString
*/
public function testValidationError(string $allowedTags, string $testString)
{
$constraint = new AllowedHtmlTags([
'tags' => $allowedTags,
]);
$this->validator->validate($testString, $constraint);
$this->buildViolation('This string contains invalid HTML tags.')
->setParameter('{{ value }}', '"' . $testString . '"')
->setCode(AllowedHtmlTags::DISALLOWED_TAGS_FOUND)
->assertRaised();
}
}

View File

@@ -63,16 +63,14 @@ class DurationValidatorTest extends ConstraintValidatorTestCase
/**
* @dataProvider getValidData
* @param string $input
*/
public function testConstraintWithValidData($input)
public function testConstraintWithValidData(string|int|null $input)
{
$constraint = new Duration();
$this->validator->validate($input, $constraint);
if ($input !== null) {
$input = strtoupper($input);
$this->validator->validate(strtoupper($input), $constraint);
}
$this->validator->validate($input, $constraint);
$this->assertNoViolation();
}
@@ -96,9 +94,8 @@ class DurationValidatorTest extends ConstraintValidatorTestCase
/**
* @dataProvider getInvalidData
* @param mixed $input
*/
public function testValidationError($input)
public function testValidationError(string $input)
{
$constraint = new Duration([
'message' => 'myMessage',
@@ -114,9 +111,8 @@ class DurationValidatorTest extends ConstraintValidatorTestCase
/**
* @dataProvider getInvalidData
* @param mixed $input
*/
public function testValidationErrorUpperCase($input)
public function testValidationErrorUpperCase(string $input)
{
$input = strtoupper($input);
$constraint = new Duration([

View File

@@ -0,0 +1,117 @@
<?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\User;
use App\Tests\Mocks\Security\RoleServiceFactory;
use App\Validator\Constraints\RoleName;
use App\Validator\Constraints\RoleNameValidator;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
/**
* @covers \App\Validator\Constraints\RoleName
* @covers \App\Validator\Constraints\RoleNameValidator
*/
class RoleNameValidatorTest extends ConstraintValidatorTestCase
{
protected function createValidator(): RoleNameValidator
{
$factory = new RoleServiceFactory($this);
return new RoleNameValidator($factory->create());
}
/**
* @return array<array<int, string>>
*/
public function getValidRoleNames(): array
{
return [
['FOOBAR'],
['ROLE_CUSTOMER'],
['ANONYMOUS'],
['TESTA'],
['TE_ST'],
];
}
public function testConstraintIsInvalid(): void
{
$this->expectException(UnexpectedTypeException::class);
$this->validator->validate('foo', new NotBlank());
}
/**
* @dataProvider getValidRoleNames
* @param string $role
*/
public function testConstraintWithValidRole(string $role): void
{
$constraint = new RoleName();
$this->validator->validate($role, $constraint);
$this->assertNoViolation();
}
public function testNullIsInvalid(): void
{
$this->validator->validate(null, new RoleName(['message' => 'myMessage']));
$this->buildViolation('myMessage')
->setParameter('{{ value }}', 'null')
->setCode(RoleName::ROLE_NAME_ERROR)
->assertRaised();
}
/**
* @return array<array<string|int>>
*/
public function getInvalidRoleNames(): array
{
return [
['foo'],
['foobar'],
[0],
['role_user'],
['ROLE-CUSTOMER'],
['anonymous'],
[''],
['_TESTA'],
['TESTA_'],
['TE__ST'],
['_______'],
[User::ROLE_USER],
[User::ROLE_TEAMLEAD],
[User::ROLE_ADMIN],
[User::ROLE_SUPER_ADMIN],
];
}
/**
* @dataProvider getInvalidRoleNames
*/
public function testValidationError(string|int $role): void
{
$constraint = new RoleName([
'message' => 'myMessage',
]);
$this->validator->validate($role, $constraint);
$expectedFormat = \is_string($role) ? '"' . $role . '"' : (string) $role;
$this->buildViolation('myMessage')
->setParameter('{{ value }}', $expectedFormat)
->setCode(RoleName::ROLE_NAME_ERROR)
->assertRaised();
}
}

View File

@@ -93,7 +93,7 @@ class RoleValidatorTest extends ConstraintValidatorTestCase
$this->validator->validate($role, $constraint);
$expectedFormat = \is_string($role) ? '"' . $role . '"' : $role;
$expectedFormat = \is_string($role) ? '"' . $role . '"' : (string) $role;
$this->buildViolation('myMessage')
->setParameter('{{ value }}', $expectedFormat)

View File

@@ -42,13 +42,13 @@ class TeamValidatorTest extends ConstraintValidatorTestCase
$member->setTeamlead(false);
$member->setUser(new User());
$team = new Team();
$team = new Team('foo');
$team->addMember($member);
$this->validator->validate($team, new TeamConstraint());
$this->buildViolation('At least one team leader must be assigned to the team.')
->atPath('property.path.teamleads')
->atPath('property.path.members')
->setCode(TeamConstraint::MISSING_TEAMLEAD)
->assertRaised();
}

View File

@@ -13,6 +13,7 @@ use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\Project;
use App\Entity\Timesheet;
use App\Tests\Mocks\SystemConfigurationFactory;
use App\Validator\Constraints\TimesheetBasic;
use App\Validator\Constraints\TimesheetBasicValidator;
use Symfony\Component\Validator\Constraints\NotBlank;
@@ -32,7 +33,9 @@ class TimesheetBasicValidatorTest extends ConstraintValidatorTestCase
protected function createMyValidator()
{
return new TimesheetBasicValidator();
$configuration = SystemConfigurationFactory::createStub(['timesheet' => ['rules' => ['require_activity' => true]]]);
return new TimesheetBasicValidator($configuration);
}
public function testConstraintIsInvalid()
@@ -55,7 +58,7 @@ class TimesheetBasicValidatorTest extends ConstraintValidatorTestCase
$this->validator->validate($timesheet, new TimesheetBasic(['message' => 'myMessage']));
$this->buildViolation('You must submit a begin date.')
->atPath('property.path.begin')
->atPath('property.path.begin_date')
->setCode(TimesheetBasic::MISSING_BEGIN_ERROR)
->buildNextViolation('An activity needs to be selected.')
->atPath('property.path.activity')
@@ -85,7 +88,7 @@ class TimesheetBasicValidatorTest extends ConstraintValidatorTestCase
// therefor sub-constraints will not be executed :-(
/*
->buildNextViolation('The begin date cannot be in the future.')
->atPath('property.path.begin')
->atPath('property.path.begin_date')
->setCode(TimesheetFutureTimes::BEGIN_IN_FUTURE_ERROR)
*/
->assertRaised();
@@ -102,7 +105,7 @@ class TimesheetBasicValidatorTest extends ConstraintValidatorTestCase
$this->validator->validate($timesheet, new TimesheetBasic(['message' => 'myMessage']));
$this->buildViolation('End date must not be earlier then start date.')
->atPath('property.path.end')
->atPath('property.path.end_date')
->setCode(TimesheetBasic::END_BEFORE_BEGIN_ERROR)
->buildNextViolation('An activity needs to be selected.')
->atPath('property.path.activity')
@@ -120,7 +123,7 @@ class TimesheetBasicValidatorTest extends ConstraintValidatorTestCase
$activity = new Activity();
$project1 = new Project();
$project2 = new Project();
$project2->setCustomer(new Customer());
$project2->setCustomer(new Customer('foo'));
$activity->setProject($project1);
$timesheet = new Timesheet();
@@ -142,7 +145,7 @@ class TimesheetBasicValidatorTest extends ConstraintValidatorTestCase
public function testDisabledValuesDuringStart()
{
$begin = new \DateTime('-10 hour');
$customer = new Customer();
$customer = new Customer('foo');
$customer->setVisible(false);
$activity = new Activity();
$activity->setVisible(false);
@@ -175,26 +178,26 @@ class TimesheetBasicValidatorTest extends ConstraintValidatorTestCase
public function getProjectStartEndTestData()
{
yield [new \DateTime(), new \DateTime(), [
['begin', TimesheetBasic::PROJECT_NOT_STARTED, 'The project has not started at that time.'],
['end', TimesheetBasic::PROJECT_NOT_STARTED, 'The project has not started at that time.'],
['begin_date', TimesheetBasic::PROJECT_NOT_STARTED, 'The project has not started at that time.'],
['end_date', TimesheetBasic::PROJECT_NOT_STARTED, 'The project has not started at that time.'],
]];
yield [new \DateTime('-9 hour'), new \DateTime('-2 hour'), [
['begin', TimesheetBasic::PROJECT_NOT_STARTED, 'The project has not started at that time.'],
['end', TimesheetBasic::PROJECT_ALREADY_ENDED, 'The project is finished at that time.'],
['begin_date', TimesheetBasic::PROJECT_NOT_STARTED, 'The project has not started at that time.'],
['end_date', TimesheetBasic::PROJECT_ALREADY_ENDED, 'The project is finished at that time.'],
]];
yield [new \DateTime('-19 hour'), new \DateTime('-12 hour'), [
['begin', TimesheetBasic::PROJECT_ALREADY_ENDED, 'The project is finished at that time.'],
['end', TimesheetBasic::PROJECT_ALREADY_ENDED, 'The project is finished at that time.'],
['begin_date', TimesheetBasic::PROJECT_ALREADY_ENDED, 'The project is finished at that time.'],
['end_date', TimesheetBasic::PROJECT_ALREADY_ENDED, 'The project is finished at that time.'],
]];
yield [new \DateTime('-19 hour'), new \DateTime('-2 hour'), [
['end', TimesheetBasic::PROJECT_ALREADY_ENDED, 'The project is finished at that time.'],
['end_date', TimesheetBasic::PROJECT_ALREADY_ENDED, 'The project is finished at that time.'],
]];
yield [new \DateTime('-9 hour'), new \DateTime(), [
['begin', TimesheetBasic::PROJECT_NOT_STARTED, 'The project has not started at that time.'],
['begin_date', TimesheetBasic::PROJECT_NOT_STARTED, 'The project has not started at that time.'],
]];
}
@@ -207,7 +210,7 @@ class TimesheetBasicValidatorTest extends ConstraintValidatorTestCase
$timesheet->setBegin(new \DateTime('-10 hour'));
$timesheet->setEnd(new \DateTime('-1 hour'));
$customer = new Customer();
$customer = new Customer('foo');
$project = new Project();
$project->setStart($start);
$project->setEnd($end);
@@ -224,7 +227,7 @@ class TimesheetBasicValidatorTest extends ConstraintValidatorTestCase
$assertion = $this->buildViolation($violation[2])
->atPath('property.path.' . $violation[0])
->setCode($violation[1])
;
;
} else {
$assertion = $assertion->buildNextViolation($violation[2])
->atPath('property.path.' . $violation[0])

View File

@@ -10,7 +10,7 @@
namespace App\Tests\Validator\Constraints;
use App\Activity\ActivityStatisticService;
use App\Configuration\SystemConfiguration;
use App\Configuration\LocaleService;
use App\Customer\CustomerStatisticService;
use App\Entity\Activity;
use App\Entity\Customer;
@@ -25,6 +25,7 @@ use App\Model\ProjectBudgetStatisticModel;
use App\Model\ProjectStatistic;
use App\Project\ProjectStatisticService;
use App\Repository\TimesheetRepository;
use App\Tests\Mocks\SystemConfigurationFactory;
use App\Timesheet\Rate;
use App\Timesheet\RateService;
use App\Timesheet\RateServiceInterface;
@@ -44,11 +45,10 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
{
protected function createValidator(bool $isAllowed = false, ?ActivityBudgetStatisticModel $activityStatisticModel = null, ?ProjectBudgetStatisticModel $projectStatisticModel = null, ?CustomerBudgetStatisticModel $customerStatisticModel = null, ?array $rawData = null, ?Rate $rate = null)
{
$configuration = $this->createMock(SystemConfiguration::class);
$configuration->method('isTimesheetAllowOverbookingBudget')->willReturn($isAllowed);
$configuration = SystemConfigurationFactory::createStub(['timesheet' => ['rules' => ['allow_overbooking_budget' => $isAllowed]]]);
if ($customerStatisticModel === null) {
$customerStatisticModel = new CustomerBudgetStatisticModel(new Customer());
$customerStatisticModel = new CustomerBudgetStatisticModel(new Customer('foo'));
$customerStatistic = new CustomerStatistic();
$customerStatisticModel->setStatisticTotal($customerStatistic);
$customerStatisticModel->setStatistic($customerStatistic);
@@ -91,7 +91,9 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
$auth = $this->createMock(AuthorizationCheckerInterface::class);
return new TimesheetBudgetUsedValidator($configuration, $customerRepository, $projectRepository, $activityRepository, $timesheetRepository, $rateService, $auth);
$localeService = new LocaleService([]);
return new TimesheetBudgetUsedValidator($configuration, $customerRepository, $projectRepository, $activityRepository, $timesheetRepository, $rateService, $auth, $localeService);
}
public function testConstraintIsInvalid()
@@ -151,7 +153,7 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
public function testWithoutBudget()
{
$project = new Project();
$project->setCustomer(new Customer());
$project->setCustomer(new Customer('foo'));
$timesheet = new Timesheet();
$timesheet->setBegin(new DateTime());
@@ -176,7 +178,7 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
$end->modify('+3601 seconds');
$project = new Project();
$project->setCustomer(new Customer());
$project->setCustomer(new Customer('foo'));
$timesheet = new Timesheet();
$timesheet->setBegin($begin);
@@ -194,7 +196,7 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
return [
// activity: violations ----------------------------------------------------------------------
// previously logged available budgets expected violation duration entry currently in database
'a_a' => [1230, null, null, null, null, null, null, 3600, null, null, null, null, null, null, null, '00:20', '00:39', '01:00', 'activity', '+3600 seconds'],
'a_a' => [1230, null, null, null, null, null, null, 3600, null, null, null, null, null, null, null, '0:20', '0:39', '1:00', 'activity', '+3600 seconds'],
'a_b' => [null, 1001.0, null, null, null, null, null, null, 1000.0, null, null, null, null, null, null, '€1,001.00', '€0.00', '€1,000.00', 'activity', '+3600 seconds'],
// activity: no violations
@@ -203,29 +205,29 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
'a_e' => [1230, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
// previously logged available budgets expected violation duration entry currently in database
'a_f1' => [1320, null, null, null, null, null, null, 3600, null, null, null, null, null, null, null, '00:22', '00:38', '01:00', 'activity', '+3600 seconds', ['rate' => 1.0, 'duration' => 1000]],
'a_h1' => [7200, null, null, null, null, null, null, 7200, null, null, null, null, null, null, null, '02:00', '00:00', '02:00', 'activity', '+3601 seconds', ['rate' => 1.0, 'duration' => 3600]],
'a_f1' => [1320, null, null, null, null, null, null, 3600, null, null, null, null, null, null, null, '0:22', '0:38', '1:00', 'activity', '+3600 seconds', ['rate' => 1.0, 'duration' => 1000]],
'a_h1' => [7200, null, null, null, null, null, null, 7200, null, null, null, null, null, null, null, '2:00', '0:00', '2:00', 'activity', '+3601 seconds', ['rate' => 1.0, 'duration' => 3600]],
'a_h2' => [3601, null, null, null, null, null, null, 3600, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 1.0, 'duration' => 3601]],
'a_g0' => [null, 1002.0, null, null, null, null, null, null, 1000.0, null, null, null, null, null, null, '1,002.00', '0.00', '1,000.00', 'activity', '+3600 seconds', ['rate' => 1.0, 'duration' => 1010]],
'a_g0' => [null, 1002.0, null, null, null, null, null, null, 1000.0, null, null, null, null, null, null, '1,002.00', '0.00', '1,000.00', 'activity', '+3600 seconds', ['rate' => 1.0, 'duration' => 1010]],
'a_g1' => [null, 1002.0, null, null, null, null, null, null, 1000.0, null, null, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 2.0, 'duration' => 0]],
// nothing changed => no violation
'a_x1' => [3600, 1000.0, null, null, null, null, null, 3600, 1000.0, null, null, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 1000.0, 'duration' => 3600], new Rate(1000.0, 0.00)],
// date changed => violation
'a_x2' => [3600, 1000.0, null, null, null, null, 'month', 3600, 1000.0, null, null, null, null, null, null, '1,000.00', '0.00', '1,000.00', 'activity', '+3600 seconds', ['rate' => 999.0, 'duration' => 3599, 'begin' => new DateTime('2021-03-17 16:15:00'), 'end' => new DateTime('2021-03-17 17:15:01'), 'billable' => true], new Rate(1000.0, 0.00)],
'a_x2' => [3600, 1000.0, null, null, null, null, 'month', 3600, 1000.0, null, null, null, null, null, null, '1,000.00', '0.00', '1,000.00', 'activity', '+3600 seconds', ['rate' => 999.0, 'duration' => 3599, 'begin' => new DateTime('2021-03-17 16:15:00'), 'end' => new DateTime('2021-03-17 17:15:01'), 'billable' => true], new Rate(1000.0, 0.00)],
// date changed but not violation was raised
'a_x3' => [3600, 1000.0, null, null, null, null, 'month', 3600, 1000.0, null, null, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 999.0, 'duration' => 3599, 'begin' => new DateTime('2021-03-17 16:15:00'), 'end' => new DateTime('2021-03-17 17:15:01'), 'billable' => false], new Rate(1000.0, 0.00)],
'a_x4' => [3600, 1000.0, null, null, null, null, 'month', 3600, 1000.0, null, null, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 1000.0, 'duration' => 3600, 'begin' => new DateTime('2021-03-17 16:15:00'), 'end' => new DateTime('2021-03-17 17:15:01'), 'billable' => true], new Rate(1000.0, 0.00)],
'a_x5' => [3600, 1000.0, null, null, null, null, 'month', 3600, 1000.0, null, null, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 1000.0, 'duration' => 3600, 'begin' => new DateTime('2021-03-17 16:15:00'), 'end' => new DateTime('2021-03-17 17:15:01'), 'billable' => false], new Rate(1000.0, 0.00)],
// project: violations ----------------------------------------------------------------------
'p_j' => [null, null, 1230, null, null, null, null, null, null, null, 3600, null, null, null, null, '00:20', '00:39', '01:00', 'project', '+3600 seconds'],
'p_j' => [null, null, 1230, null, null, null, null, null, null, null, 3600, null, null, null, null, '0:20', '0:39', '1:00', 'project', '+3600 seconds'],
'p_k' => [null, null, null, 1001.0, null, null, null, null, null, null, null, 1000.0, null, null, null, '€1,001.00', '€0.00', '€1,000.00', 'project', '+3600 seconds'],
// previously logged available budgets expected violation duration entry currently in database
'p_f1' => [null, null, 1320, null, null, null, null, null, null, null, 3600, null, null, null, null, '00:22', '00:38', '01:00', 'project', '+3600 seconds', ['rate' => 1.0, 'duration' => 1000]],
'p_h1' => [null, null, 7200, null, null, null, null, null, null, null, 7200, null, null, null, null, '02:00', '00:00', '02:00', 'project', '+3601 seconds', ['rate' => 1.0, 'duration' => 3600]],
'p_f1' => [null, null, 1320, null, null, null, null, null, null, null, 3600, null, null, null, null, '0:22', '0:38', '1:00', 'project', '+3600 seconds', ['rate' => 1.0, 'duration' => 1000]],
'p_h1' => [null, null, 7200, null, null, null, null, null, null, null, 7200, null, null, null, null, '2:00', '0:00', '2:00', 'project', '+3601 seconds', ['rate' => 1.0, 'duration' => 3600]],
'p_h2' => [null, null, 3601, null, null, null, null, null, null, null, 3600, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 1.0, 'duration' => 3601]],
'p_g0' => [null, null, null, 1002.0, null, null, null, null, null, null, null, 1000.0, null, null, null, '1,002.00', '0.00', '1,000.00', 'project', '+3600 seconds', ['rate' => 1.0, 'duration' => 1010]],
'p_g0' => [null, null, null, 1002.0, null, null, null, null, null, null, null, 1000.0, null, null, null, '1,002.00', '0.00', '1,000.00', 'project', '+3600 seconds', ['rate' => 1.0, 'duration' => 1010]],
'p_g1' => [null, null, null, 1002.0, null, null, null, null, null, null, null, 1000.0, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 2.0, 'duration' => 0]],
// project: no violations
@@ -240,14 +242,14 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
'p_u' => [1230, 1001.0, 1230, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
// customer: violations ----------------------------------------------------------------------
'c_v' => [null, null, null, null, 1230, null, null, null, null, null, null, null, null, 3600, null, '00:20', '00:39', '01:00', 'customer', '+3600 seconds'],
'c_v' => [null, null, null, null, 1230, null, null, null, null, null, null, null, null, 3600, null, '0:20', '0:39', '1:00', 'customer', '+3600 seconds'],
'c_w' => [null, null, null, null, null, 1001.0, null, null, null, null, null, null, null, null, 1000.0, '€1,001.00', '€0.00', '€1,000.00', 'customer', '+3600 seconds'],
// previously logged available budgets expected violation duration entry currently in database
'c_f1' => [null, null, null, null, 1320, null, null, null, null, null, null, null, null, 3600, null, '00:22', '00:38', '01:00', 'customer', '+3600 seconds', ['rate' => 1.0, 'duration' => 1000]],
'c_h1' => [null, null, null, null, 7200, null, null, null, null, null, null, null, null, 7200, null, '02:00', '00:00', '02:00', 'customer', '+3601 seconds', ['rate' => 1.0, 'duration' => 3600]],
'c_f1' => [null, null, null, null, 1320, null, null, null, null, null, null, null, null, 3600, null, '0:22', '0:38', '1:00', 'customer', '+3600 seconds', ['rate' => 1.0, 'duration' => 1000]],
'c_h1' => [null, null, null, null, 7200, null, null, null, null, null, null, null, null, 7200, null, '2:00', '0:00', '2:00', 'customer', '+3601 seconds', ['rate' => 1.0, 'duration' => 3600]],
'c_h2' => [null, null, null, null, 3601, null, null, null, null, null, null, null, null, 3600, null, null, null, null, null, '+3600 seconds', ['rate' => 1.0, 'duration' => 3601]],
'c_g0' => [null, null, null, null, null, 1002.0, null, null, null, null, null, null, null, null, 1000.0, '1,002.00', '0.00', '1,000.00', 'customer', '+3600 seconds', ['rate' => 1.0, 'duration' => 1010]],
'c_g0' => [null, null, null, null, null, 1002.0, null, null, null, null, null, null, null, null, 1000.0, '1,002.00', '0.00', '1,000.00', 'customer', '+3600 seconds', ['rate' => 1.0, 'duration' => 1010]],
'c_g1' => [null, null, null, null, null, 1002.0, null, null, null, null, null, null, null, null, 1000.0, null, null, null, null, '+3600 seconds', ['rate' => 2.0, 'duration' => 0]],
// customer: no violations
@@ -371,6 +373,7 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
}
$customer = $this->createMock(Customer::class);
$customer->method('getCurrency')->willReturn('EUR');
$customer->method('getId')->willReturn($rawData['customer']);
$customer->method('isMonthlyBudget')->willReturn(false);
if ($customerBudgetType !== null) {
@@ -425,7 +428,7 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
$activity->setBudget($activityBudget);
}
$customer = new Customer();
$customer = new Customer('foo');
if ($customerTimeBudget !== null) {
$customer->setTimeBudget($customerTimeBudget);
}

View File

@@ -10,8 +10,8 @@
namespace App\Tests\Validator\Constraints;
use App\Configuration\ConfigLoaderInterface;
use App\Configuration\SystemConfiguration;
use App\Entity\Timesheet;
use App\Tests\Mocks\SystemConfigurationFactory;
use App\Validator\Constraints\TimesheetFutureTimes;
use App\Validator\Constraints\TimesheetFutureTimesValidator;
use Symfony\Component\Validator\Constraints\NotBlank;
@@ -32,7 +32,7 @@ class TimesheetFutureTimesValidatorTest extends ConstraintValidatorTestCase
protected function createMyValidator(bool $allowFutureTimes = false)
{
$loader = $this->createMock(ConfigLoaderInterface::class);
$config = new SystemConfiguration($loader, [
$config = SystemConfigurationFactory::create($loader, [
'timesheet' => [
'rules' => [
'allow_future_times' => $allowFutureTimes,
@@ -71,7 +71,7 @@ class TimesheetFutureTimesValidatorTest extends ConstraintValidatorTestCase
$this->validator->validate($timesheet, new TimesheetFutureTimes(['message' => 'myMessage']));
$this->buildViolation('The begin date cannot be in the future.')
->atPath('property.path.begin')
->atPath('property.path.begin_date')
->setCode(TimesheetFutureTimes::BEGIN_IN_FUTURE_ERROR)
->assertRaised();
}

View File

@@ -10,9 +10,9 @@
namespace App\Tests\Validator\Constraints;
use App\Configuration\ConfigLoaderInterface;
use App\Configuration\SystemConfiguration;
use App\Entity\Timesheet;
use App\Entity\User;
use App\Tests\Mocks\SystemConfigurationFactory;
use App\Timesheet\LockdownService;
use App\Validator\Constraints\TimesheetLockdown;
use App\Validator\Constraints\TimesheetLockdownValidator;
@@ -50,7 +50,7 @@ class TimesheetLockdownValidatorTest extends ConstraintValidatorTestCase
);
$loader = $this->createMock(ConfigLoaderInterface::class);
$config = new SystemConfiguration($loader, [
$config = SystemConfigurationFactory::create($loader, [
'timesheet' => [
'rules' => [
'lockdown_period_start' => $start,
@@ -92,7 +92,7 @@ class TimesheetLockdownValidatorTest extends ConstraintValidatorTestCase
$this->validator->validate($timesheet, $constraint);
$this->buildViolation('This period is locked, please choose a later date.')
->atPath('property.path.begin')
->atPath('property.path.begin_date')
->setCode(TimesheetLockdown::PERIOD_LOCKED)
->assertRaised();
}
@@ -162,7 +162,7 @@ class TimesheetLockdownValidatorTest extends ConstraintValidatorTestCase
if ($isViolation) {
$this->buildViolation('This period is locked, please choose a later date.')
->atPath('property.path.begin')
->atPath('property.path.begin_date')
->setCode(TimesheetLockdown::PERIOD_LOCKED)
->assertRaised();
} else {

View File

@@ -10,8 +10,8 @@
namespace App\Tests\Validator\Constraints;
use App\Configuration\ConfigLoaderInterface;
use App\Configuration\SystemConfiguration;
use App\Entity\Timesheet;
use App\Tests\Mocks\SystemConfigurationFactory;
use App\Validator\Constraints\TimesheetLongRunning;
use App\Validator\Constraints\TimesheetLongRunningValidator;
use Symfony\Component\Validator\Constraints\NotBlank;
@@ -32,7 +32,7 @@ class TimesheetLongRunningValidatorTest extends ConstraintValidatorTestCase
protected function createMyValidator(int $minutes)
{
$loader = $this->createMock(ConfigLoaderInterface::class);
$config = new SystemConfiguration($loader, [
$config = SystemConfigurationFactory::create($loader, [
'timesheet' => [
'rules' => [
'long_running_duration' => $minutes,
@@ -69,7 +69,7 @@ class TimesheetLongRunningValidatorTest extends ConstraintValidatorTestCase
$this->buildViolation('Maximum duration of {{ value }} hours exceeded.')
->atPath('property.path.duration')
->setParameter('{{ value }}', '02:00')
->setParameter('{{ value }}', '2:00')
->setCode(TimesheetLongRunning::LONG_RUNNING)
->assertRaised();
}

View File

@@ -105,7 +105,7 @@ class TimesheetMultiUpdateValidatorTest extends ConstraintValidatorTestCase
public function testDisabledValues()
{
$customer = new Customer();
$customer = new Customer('foo');
$customer->setVisible(false);
$activity = new Activity();
$activity->setVisible(false);

View File

@@ -10,9 +10,9 @@
namespace App\Tests\Validator\Constraints;
use App\Configuration\ConfigLoaderInterface;
use App\Configuration\SystemConfiguration;
use App\Entity\Timesheet;
use App\Repository\TimesheetRepository;
use App\Tests\Mocks\SystemConfigurationFactory;
use App\Validator\Constraints\TimesheetOverlapping;
use App\Validator\Constraints\TimesheetOverlappingValidator;
use Symfony\Component\Validator\Constraints\NotBlank;
@@ -33,7 +33,7 @@ class TimesheetOverlappingValidatorTest extends ConstraintValidatorTestCase
protected function createMyValidator(bool $allowOverlappingRecords = false, bool $hasRecords = true)
{
$loader = $this->createMock(ConfigLoaderInterface::class);
$config = new SystemConfiguration($loader, [
$config = SystemConfigurationFactory::create($loader, [
'timesheet' => [
'rules' => [
'allow_overlapping_records' => $allowOverlappingRecords,
@@ -71,7 +71,7 @@ class TimesheetOverlappingValidatorTest extends ConstraintValidatorTestCase
$this->validator->validate($timesheet, new TimesheetOverlapping(['message' => 'myMessage']));
$this->buildViolation('You already have an entry for this time.')
->atPath('property.path.begin')
->atPath('property.path.begin_date')
->setCode(TimesheetOverlapping::RECORD_OVERLAPPING)
->assertRaised();
}

View File

@@ -68,7 +68,7 @@ class TimesheetRestartValidatorTest extends ConstraintValidatorTestCase
$this->validator->initialize($this->context);
$begin = new \DateTime('-10 hour');
$customer = new Customer();
$customer = new Customer('foo');
$activity = new Activity();
$project = new Project();
$project->setCustomer($customer);
@@ -95,9 +95,8 @@ class TimesheetRestartValidatorTest extends ConstraintValidatorTestCase
public function getTestData()
{
yield [false, 'end', 'default'];
yield [false, 'end_date', 'default'];
yield [true, null, 'default'];
yield [false, 'duration', 'duration_only'];
yield [false, 'start', 'punch'];
yield [false, 'start_date', 'punch'];
}
}

View File

@@ -10,8 +10,8 @@
namespace App\Tests\Validator\Constraints;
use App\Configuration\ConfigLoaderInterface;
use App\Configuration\SystemConfiguration;
use App\Entity\Timesheet;
use App\Tests\Mocks\SystemConfigurationFactory;
use App\Validator\Constraints\TimesheetZeroDuration;
use App\Validator\Constraints\TimesheetZeroDurationValidator;
use Symfony\Component\Validator\Constraints\NotBlank;
@@ -32,7 +32,7 @@ class TimesheetZeroDurationValidatorTest extends ConstraintValidatorTestCase
protected function createMyValidator(bool $allowZeroDuration = false)
{
$loader = $this->createMock(ConfigLoaderInterface::class);
$config = new SystemConfiguration($loader, [
$config = SystemConfigurationFactory::create($loader, [
'timesheet' => [
'rules' => [
'allow_zero_duration' => $allowZeroDuration,

View File

@@ -54,7 +54,10 @@ class UserValidatorTest extends ConstraintValidatorTestCase
public function testEmptyUserIsValid()
{
$this->validator->validate(new UserEntity(), new User(['message' => 'myMessage']));
$user = new UserEntity();
$user->setUserIdentifier('foo');
$user->setEmail('test');
$this->validator->validate($user, new User(['message' => 'myMessage']));
$this->assertNoViolation();
}
@@ -62,7 +65,7 @@ class UserValidatorTest extends ConstraintValidatorTestCase
public function testUserIsValidWithEmptyRepository()
{
$user = new UserEntity();
$user->setUsername('foo');
$user->setUserIdentifier('foo');
$user->setEmail('foo@example.com');
$this->validator->validate($user, new User(['message' => 'myMessage']));
@@ -83,7 +86,7 @@ class UserValidatorTest extends ConstraintValidatorTestCase
$this->validator->initialize($this->context);
$user = new UserEntity();
$user->setUsername('foo');
$user->setUserIdentifier('foo');
$user->setEmail('foo@example.com');
$this->validator->validate($user, new User());