improved duration and minute selector (#2264)
* do not close modal if form is dirty * deprecated TimesheetConfiguration * inject timezone in form types * cleanup usage of UserDateTimeFactory * allow to configure increment steps for minutes * use 15 minutes step for datetimepicker in project edit form * use rounding rules for increments in minute select for begin and end * allow duration in multi user and admin timesheet forms * make dropdown values configurable
This commit is contained in:
@@ -18,8 +18,8 @@ use App\Entity\Timesheet;
|
||||
use App\Entity\TimesheetMeta;
|
||||
use App\Entity\User;
|
||||
use App\Tests\DataFixtures\TimesheetFixtures;
|
||||
use App\Tests\Mocks\Security\UserDateTimeFactoryFactory;
|
||||
use App\Tests\Mocks\TimesheetTestMetaFieldSubscriberMock;
|
||||
use App\Timesheet\DateTimeFactory;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
@@ -360,7 +360,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
|
||||
public function testPostAction()
|
||||
{
|
||||
$dateTime = (new UserDateTimeFactoryFactory($this))->create(self::TEST_TIMEZONE);
|
||||
$dateTime = new DateTimeFactory(new \DateTimeZone(self::TEST_TIMEZONE));
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$data = [
|
||||
'activity' => 1,
|
||||
@@ -384,7 +384,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
|
||||
public function testPostActionWithFullExpandedResponse()
|
||||
{
|
||||
$dateTime = (new UserDateTimeFactoryFactory($this))->create(self::TEST_TIMEZONE);
|
||||
$dateTime = new DateTimeFactory(new \DateTimeZone(self::TEST_TIMEZONE));
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$data = [
|
||||
'activity' => 1,
|
||||
@@ -408,7 +408,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
|
||||
public function testPostActionForDifferentUser()
|
||||
{
|
||||
$dateTime = (new UserDateTimeFactoryFactory($this))->create(self::TEST_TIMEZONE);
|
||||
$dateTime = new DateTimeFactory(new \DateTimeZone(self::TEST_TIMEZONE));
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$admin = $this->getUserByRole(User::ROLE_ADMIN);
|
||||
$user = $this->getUserByRole(User::ROLE_USER);
|
||||
@@ -494,7 +494,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
|
||||
public function testPatchAction()
|
||||
{
|
||||
$dateTime = (new UserDateTimeFactoryFactory($this))->create(self::TEST_TIMEZONE);
|
||||
$dateTime = new DateTimeFactory(new \DateTimeZone(self::TEST_TIMEZONE));
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD);
|
||||
$this->importFixtureForUser(User::ROLE_USER);
|
||||
$data = [
|
||||
@@ -959,7 +959,7 @@ class TimesheetControllerTest extends APIControllerBaseTest
|
||||
|
||||
public function testDuplicateAction()
|
||||
{
|
||||
$dateTime = (new UserDateTimeFactoryFactory($this))->create(self::TEST_TIMEZONE);
|
||||
$dateTime = new DateTimeFactory(new \DateTimeZone(self::TEST_TIMEZONE));
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$data = [
|
||||
'activity' => 1,
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
namespace App\Tests\Configuration;
|
||||
|
||||
use App\Configuration\CalendarConfiguration;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Configuration\CalendarConfiguration
|
||||
* @covers \App\Configuration\StringAccessibleConfigTrait
|
||||
* @group legacy
|
||||
*/
|
||||
class CalendarConfigurationTest extends TestCase
|
||||
@@ -28,7 +28,7 @@ class CalendarConfigurationTest extends TestCase
|
||||
{
|
||||
$loader = new TestConfigLoader($loaderSettings);
|
||||
|
||||
return new CalendarConfiguration($loader, $settings);
|
||||
return new CalendarConfiguration(new SystemConfiguration($loader, ['calendar' => $settings]));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,4 +90,11 @@ class CalendarConfigurationTest extends TestCase
|
||||
self::assertEquals('09:00', $sut->getTimeframeBegin());
|
||||
self::assertEquals('21:34', $sut->getTimeframeEnd());
|
||||
}
|
||||
|
||||
public function testFindByKey()
|
||||
{
|
||||
$sut = $this->getSut($this->getDefaultSettings(), []);
|
||||
$this->assertFalse($sut->find('week_numbers'));
|
||||
$this->assertFalse($sut->find('calendar.week_numbers'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
namespace App\Tests\Configuration;
|
||||
|
||||
use App\Configuration\FormConfiguration;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Entity\Configuration;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Configuration\FormConfiguration
|
||||
* @covers \App\Configuration\StringAccessibleConfigTrait
|
||||
* @group legacy
|
||||
*/
|
||||
class FormConfigurationTest extends TestCase
|
||||
@@ -24,7 +24,7 @@ class FormConfigurationTest extends TestCase
|
||||
{
|
||||
$loader = new TestConfigLoader($loaderSettings);
|
||||
|
||||
return new FormConfiguration($loader, $settings);
|
||||
return new FormConfiguration(new SystemConfiguration($loader, ['defaults' => $settings]));
|
||||
}
|
||||
|
||||
protected function getDefaultSettings()
|
||||
@@ -83,7 +83,7 @@ class FormConfigurationTest extends TestCase
|
||||
$this->assertEquals('RU', $sut->getUserDefaultLanguage());
|
||||
$this->assertEquals('black', $sut->getUserDefaultTheme());
|
||||
$this->assertEquals('Russia/Moscov', $sut->getUserDefaultTimezone());
|
||||
$this->assertEquals('Russia/Moscov', $sut->offsetGet('defaults.user.timezone'));
|
||||
$this->assertEquals('Russia/Moscov', $sut->find('defaults.user.timezone'));
|
||||
}
|
||||
|
||||
public function testDefaultWithMixedConfigs()
|
||||
@@ -109,8 +109,6 @@ class FormConfigurationTest extends TestCase
|
||||
$sut = $this->getSut($this->getDefaultSettings(), [
|
||||
(new Configuration())->setName('defaults.customer.foobar')->setValue('hello'),
|
||||
]);
|
||||
$this->assertTrue($sut->has('customer.foobar'));
|
||||
$this->assertFalse($sut->has('xxxx.foobar'));
|
||||
$this->assertEquals('hello', $sut->find('customer.foobar'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,9 @@ class SystemConfigurationTest extends TestCase
|
||||
'timesheet' => [
|
||||
'rules' => [
|
||||
'allow_future_times' => false,
|
||||
'lockdown_period_start' => null,
|
||||
'lockdown_period_end' => null,
|
||||
'lockdown_grace_period' => null,
|
||||
],
|
||||
'mode' => 'duration_only',
|
||||
'markdown_content' => false,
|
||||
@@ -44,6 +47,9 @@ class SystemConfigurationTest extends TestCase
|
||||
'hard_limit' => 99,
|
||||
'soft_limit' => 15,
|
||||
],
|
||||
'default_begin' => 'now',
|
||||
'duration_increment' => 10,
|
||||
'time_increment' => 5,
|
||||
],
|
||||
'defaults' => [
|
||||
'customer' => [
|
||||
@@ -94,12 +100,16 @@ class SystemConfigurationTest extends TestCase
|
||||
return [
|
||||
(new Configuration())->setName('defaults.customer.timezone')->setValue('Russia/Moscov'),
|
||||
(new Configuration())->setName('defaults.customer.currency')->setValue('RUB'),
|
||||
(new Configuration())->setName('calendar.slot_duration')->setValue('00:30:00'),
|
||||
(new Configuration())->setName('timesheet.rules.allow_future_times')->setValue('1'),
|
||||
(new Configuration())->setName('timesheet.rules.lockdown_period_start')->setValue('first day of last month'),
|
||||
(new Configuration())->setName('timesheet.rules.lockdown_period_end')->setValue('last day of last month'),
|
||||
(new Configuration())->setName('timesheet.rules.lockdown_grace_period')->setValue('+5 days'),
|
||||
(new Configuration())->setName('timesheet.mode')->setValue('default'),
|
||||
(new Configuration())->setName('timesheet.markdown_content')->setValue('1'),
|
||||
(new Configuration())->setName('timesheet.default_begin')->setValue('07:00'),
|
||||
(new Configuration())->setName('timesheet.active_entries.hard_limit')->setValue('7'),
|
||||
(new Configuration())->setName('timesheet.active_entries.soft_limit')->setValue('3'),
|
||||
(new Configuration())->setName('calendar.slot_duration')->setValue('00:30:00'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -114,7 +124,7 @@ class SystemConfigurationTest extends TestCase
|
||||
$sut = $this->getSut($this->getDefaultSettings(), []);
|
||||
$this->assertEquals('Europe/London', $sut->find('defaults.customer.timezone'));
|
||||
$this->assertEquals('GBP', $sut->find('defaults.customer.currency'));
|
||||
$this->assertEquals(false, $sut->find('timesheet.rules.allow_future_times'));
|
||||
$this->assertFalse($sut->find('timesheet.rules.allow_future_times'));
|
||||
$this->assertEquals(99, $sut->find('timesheet.active_entries.hard_limit'));
|
||||
}
|
||||
|
||||
@@ -123,7 +133,7 @@ class SystemConfigurationTest extends TestCase
|
||||
$sut = $this->getSut($this->getDefaultSettings(), $this->getDefaultLoaderSettings());
|
||||
$this->assertEquals('Russia/Moscov', $sut->find('defaults.customer.timezone'));
|
||||
$this->assertEquals('RUB', $sut->find('defaults.customer.currency'));
|
||||
$this->assertEquals(true, $sut->find('timesheet.rules.allow_future_times'));
|
||||
$this->assertTrue($sut->find('timesheet.rules.allow_future_times'));
|
||||
$this->assertEquals(7, $sut->find('timesheet.active_entries.hard_limit'));
|
||||
}
|
||||
|
||||
@@ -132,7 +142,7 @@ class SystemConfigurationTest extends TestCase
|
||||
$sut = $this->getSut($this->getDefaultSettings(), [
|
||||
(new Configuration())->setName('timesheet.rules.allow_future_times')->setValue(''),
|
||||
]);
|
||||
$this->assertEquals(false, $sut->find('timesheet.rules.allow_future_times'));
|
||||
$this->assertFalse($sut->find('timesheet.rules.allow_future_times'));
|
||||
}
|
||||
|
||||
public function testUnknownConfigs()
|
||||
@@ -194,4 +204,52 @@ class SystemConfigurationTest extends TestCase
|
||||
$this->assertEquals('IT', $sut->getUserDefaultLanguage());
|
||||
$this->assertEquals('USD', $sut->getUserDefaultCurrency());
|
||||
}
|
||||
|
||||
public function testTimesheetWithoutLoader()
|
||||
{
|
||||
$sut = $this->getSut($this->getDefaultSettings(), []);
|
||||
$this->assertEquals(99, $sut->getTimesheetActiveEntriesHardLimit());
|
||||
$this->assertEquals(15, $sut->getTimesheetActiveEntriesSoftLimit());
|
||||
$this->assertFalse($sut->isTimesheetAllowFutureTimes());
|
||||
$this->assertFalse($sut->isTimesheetMarkdownEnabled());
|
||||
$this->assertEquals('duration_only', $sut->getTimesheetTrackingMode());
|
||||
$this->assertEquals('now', $sut->getTimesheetDefaultBeginTime());
|
||||
$this->assertFalse($sut->isTimesheetLockdownActive());
|
||||
$this->assertEquals('', $sut->getTimesheetLockdownPeriodStart());
|
||||
$this->assertEquals('', $sut->getTimesheetLockdownPeriodEnd());
|
||||
$this->assertEquals('', $sut->getTimesheetLockdownGracePeriod());
|
||||
$this->assertEquals('', $sut->isTimesheetAllowOverlappingRecords());
|
||||
$this->assertEquals('', $sut->getTimesheetDefaultRoundingDays());
|
||||
$this->assertEquals('', $sut->getTimesheetDefaultRoundingMode());
|
||||
$this->assertEquals(0, $sut->getTimesheetDefaultRoundingDuration());
|
||||
$this->assertEquals(0, $sut->getTimesheetDefaultRoundingEnd());
|
||||
$this->assertEquals(0, $sut->getTimesheetDefaultRoundingBegin());
|
||||
$this->assertEquals(10, $sut->getTimesheetIncrementDuration());
|
||||
$this->assertEquals(5, $sut->getTimesheetIncrementBegin());
|
||||
$this->assertEquals(5, $sut->getTimesheetIncrementEnd());
|
||||
}
|
||||
|
||||
public function testTimesheetWithLoader()
|
||||
{
|
||||
$sut = $this->getSut($this->getDefaultSettings(), $this->getDefaultLoaderSettings());
|
||||
$this->assertEquals(7, $sut->getTimesheetActiveEntriesHardLimit());
|
||||
$this->assertEquals(3, $sut->getTimesheetActiveEntriesSoftLimit());
|
||||
$this->assertTrue($sut->isTimesheetAllowFutureTimes());
|
||||
$this->assertTrue($sut->isTimesheetMarkdownEnabled());
|
||||
$this->assertEquals('default', $sut->getTimesheetTrackingMode());
|
||||
$this->assertEquals('07:00', $sut->getTimesheetDefaultBeginTime());
|
||||
$this->assertTrue($sut->isTimesheetLockdownActive());
|
||||
$this->assertEquals('first day of last month', $sut->getTimesheetLockdownPeriodStart());
|
||||
$this->assertEquals('last day of last month', $sut->getTimesheetLockdownPeriodEnd());
|
||||
$this->assertEquals('+5 days', $sut->getTimesheetLockdownGracePeriod());
|
||||
$this->assertEquals('', $sut->isTimesheetAllowOverlappingRecords());
|
||||
$this->assertEquals('', $sut->getTimesheetDefaultRoundingDays());
|
||||
$this->assertEquals('', $sut->getTimesheetDefaultRoundingMode());
|
||||
$this->assertEquals(0, $sut->getTimesheetDefaultRoundingDuration());
|
||||
$this->assertEquals(0, $sut->getTimesheetDefaultRoundingEnd());
|
||||
$this->assertEquals(0, $sut->getTimesheetDefaultRoundingBegin());
|
||||
$this->assertEquals(10, $sut->getTimesheetIncrementDuration());
|
||||
$this->assertEquals(5, $sut->getTimesheetIncrementBegin());
|
||||
$this->assertEquals(5, $sut->getTimesheetIncrementEnd());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,13 +9,14 @@
|
||||
|
||||
namespace App\Tests\Configuration;
|
||||
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Configuration\TimesheetConfiguration;
|
||||
use App\Entity\Configuration;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Configuration\TimesheetConfiguration
|
||||
* @covers \App\Configuration\StringAccessibleConfigTrait
|
||||
* @group legacy
|
||||
*/
|
||||
class TimesheetConfigurationTest extends TestCase
|
||||
{
|
||||
@@ -28,7 +29,9 @@ class TimesheetConfigurationTest extends TestCase
|
||||
{
|
||||
$loader = new TestConfigLoader($loaderSettings);
|
||||
|
||||
return new TimesheetConfiguration($loader, $settings);
|
||||
$config = new SystemConfiguration($loader, ['timesheet' => $settings]);
|
||||
|
||||
return new TimesheetConfiguration($config);
|
||||
}
|
||||
|
||||
protected function getDefaultSettings()
|
||||
@@ -74,6 +77,7 @@ class TimesheetConfigurationTest extends TestCase
|
||||
public function testDefaultWithoutLoader()
|
||||
{
|
||||
$sut = $this->getSut($this->getDefaultSettings(), []);
|
||||
|
||||
$this->assertEquals(99, $sut->getActiveEntriesHardLimit());
|
||||
$this->assertEquals(15, $sut->getActiveEntriesSoftLimit());
|
||||
$this->assertFalse($sut->isAllowFutureTimes());
|
||||
@@ -84,6 +88,12 @@ class TimesheetConfigurationTest extends TestCase
|
||||
$this->assertEquals('', $sut->getLockdownPeriodStart());
|
||||
$this->assertEquals('', $sut->getLockdownPeriodEnd());
|
||||
$this->assertEquals('', $sut->getLockdownGracePeriod());
|
||||
$this->assertEquals('', $sut->isAllowOverlappingRecords());
|
||||
$this->assertEquals('', $sut->getDefaultRoundingDays());
|
||||
$this->assertEquals('', $sut->getDefaultRoundingMode());
|
||||
$this->assertEquals(0, $sut->getDefaultRoundingBegin());
|
||||
$this->assertEquals(0, $sut->getDefaultRoundingEnd());
|
||||
$this->assertEquals(0, $sut->getDefaultRoundingDuration());
|
||||
}
|
||||
|
||||
public function testDefaultWithLoader()
|
||||
@@ -91,8 +101,8 @@ class TimesheetConfigurationTest extends TestCase
|
||||
$sut = $this->getSut($this->getDefaultSettings(), $this->getDefaultLoaderSettings());
|
||||
$this->assertEquals(7, $sut->getActiveEntriesHardLimit());
|
||||
$this->assertEquals(3, $sut->getActiveEntriesSoftLimit());
|
||||
$this->assertEquals(true, $sut->isAllowFutureTimes());
|
||||
$this->assertEquals(true, $sut->isMarkdownEnabled());
|
||||
$this->assertTrue($sut->isAllowFutureTimes());
|
||||
$this->assertTrue($sut->isMarkdownEnabled());
|
||||
$this->assertEquals('default', $sut->getTrackingMode());
|
||||
$this->assertEquals('07:00', $sut->getDefaultBeginTime());
|
||||
$this->assertTrue($sut->isLockdownActive());
|
||||
@@ -112,8 +122,8 @@ class TimesheetConfigurationTest extends TestCase
|
||||
public function testFindByKey()
|
||||
{
|
||||
$sut = $this->getSut($this->getDefaultSettings(), []);
|
||||
$this->assertEquals(false, $sut->find('rules.allow_future_times'));
|
||||
$this->assertEquals(false, $sut->find('timesheet.rules.allow_future_times'));
|
||||
$this->assertFalse($sut->find('rules.allow_future_times'));
|
||||
$this->assertFalse($sut->find('timesheet.rules.allow_future_times'));
|
||||
}
|
||||
|
||||
public function testUnknownConfigAreImported()
|
||||
@@ -121,7 +131,6 @@ class TimesheetConfigurationTest extends TestCase
|
||||
$sut = $this->getSut($this->getDefaultSettings(), [
|
||||
(new Configuration())->setName('timesheet.foo')->setValue('hello'),
|
||||
]);
|
||||
$this->assertTrue($sut->has('foo'));
|
||||
$this->assertEquals('hello', $sut->find('foo'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ class CalendarControllerTest extends ControllerBaseTest
|
||||
],
|
||||
'timesheet' => [
|
||||
'default_begin' => '08:30:00',
|
||||
'mode' => 'default'
|
||||
],
|
||||
'calendar' => [
|
||||
'businessHours' => [
|
||||
|
||||
@@ -89,7 +89,7 @@ class SystemConfigurationControllerTest extends ControllerBaseTest
|
||||
|
||||
$configService = static::$kernel->getContainer()->get(SystemConfiguration::class);
|
||||
$this->assertEquals('default', $configService->find('timesheet.mode'));
|
||||
$this->assertEquals(true, $configService->find('timesheet.rules.allow_future_times'));
|
||||
$this->assertTrue($configService->find('timesheet.rules.allow_future_times'));
|
||||
$this->assertEquals(1, $configService->find('timesheet.active_entries.hard_limit'));
|
||||
$this->assertEquals(1, $configService->find('timesheet.active_entries.soft_limit'));
|
||||
|
||||
@@ -117,8 +117,8 @@ class SystemConfigurationControllerTest extends ControllerBaseTest
|
||||
|
||||
$configService = static::$kernel->getContainer()->get(SystemConfiguration::class);
|
||||
$this->assertEquals('duration_only', $configService->find('timesheet.mode'));
|
||||
$this->assertEquals(false, $configService->find('timesheet.rules.allow_future_times'));
|
||||
$this->assertEquals(false, $configService->find('timesheet.rules.allow_overlapping_records'));
|
||||
$this->assertFalse($configService->find('timesheet.rules.allow_future_times'));
|
||||
$this->assertFalse($configService->find('timesheet.rules.allow_overlapping_records'));
|
||||
$this->assertEquals(99, $configService->find('timesheet.active_entries.hard_limit'));
|
||||
$this->assertEquals(77, $configService->find('timesheet.active_entries.soft_limit'));
|
||||
}
|
||||
@@ -247,7 +247,7 @@ class SystemConfigurationControllerTest extends ControllerBaseTest
|
||||
$this->assertAccessIsGranted($client, '/admin/system-config/');
|
||||
|
||||
$configService = static::$kernel->getContainer()->get(SystemConfiguration::class);
|
||||
$this->assertEquals(false, $configService->find('timesheet.markdown_content'));
|
||||
$this->assertFalse($configService->find('timesheet.markdown_content'));
|
||||
$this->assertEquals('selectpicker', $configService->find('theme.select_type'));
|
||||
|
||||
$form = $client->getCrawler()->filter('form[name=system_configuration_form_theme]')->form();
|
||||
@@ -267,7 +267,7 @@ class SystemConfigurationControllerTest extends ControllerBaseTest
|
||||
|
||||
$configService = static::$kernel->getContainer()->get(SystemConfiguration::class);
|
||||
$this->assertEquals('selectpicker', $configService->find('theme.select_type'));
|
||||
$this->assertEquals(true, $configService->find('timesheet.markdown_content'));
|
||||
$this->assertTrue($configService->find('timesheet.markdown_content'));
|
||||
}
|
||||
|
||||
public function testUpdateThemeConfigValidation()
|
||||
|
||||
@@ -190,6 +190,64 @@ class TimesheetControllerTest extends ControllerBaseTest
|
||||
$this->assertNull($timesheet->getFixedRate());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getTestDataForDurationValues
|
||||
*/
|
||||
public function testCreateActionWithDurationValues($begin, $end, $duration, $expectedDuration, $expectedEnd)
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser();
|
||||
$this->request($client, '/timesheet/create');
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
|
||||
$form = $client->getCrawler()->filter('form[name=timesheet_edit_form]')->form();
|
||||
$client->submit($form, [
|
||||
'timesheet_edit_form' => [
|
||||
'description' => 'Testing is fun!',
|
||||
'begin' => $begin,
|
||||
'end' => $end,
|
||||
'duration' => $duration,
|
||||
'project' => 1,
|
||||
'activity' => 1,
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertIsRedirect($client, $this->createUrl('/timesheet/'));
|
||||
$client->followRedirect();
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
$this->assertHasFlashSuccess($client);
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
/** @var Timesheet $timesheet */
|
||||
$timesheet = $em->getRepository(Timesheet::class)->find(1);
|
||||
$this->assertInstanceOf(\DateTime::class, $timesheet->getBegin());
|
||||
$this->assertInstanceOf(\DateTime::class, $timesheet->getEnd());
|
||||
$this->assertEquals($expectedDuration, $timesheet->getDuration());
|
||||
$this->assertEquals($expectedEnd, $timesheet->getEnd()->format('Y-m-d H:i:s'));
|
||||
$this->assertEquals('Testing is fun!', $timesheet->getDescription());
|
||||
}
|
||||
|
||||
public function getTestDataForDurationValues()
|
||||
{
|
||||
// duration is ignored, because end is set and the duration might come from a rounding rule (by default seconds are rounded down with 1)
|
||||
yield ['2018-12-31 00:00:00', '2018-12-31 02:10:10', '01:00', 7800, '2018-12-31 02:10:00'];
|
||||
yield ['2018-12-31 00:00:00', '2018-12-31 02:09:59', '01:00', 7740, '2018-12-31 02:09:00'];
|
||||
// if seconds are given, they are first rounded up (default for duration rounding is 1)
|
||||
yield ['2018-12-31 00:00:00', null, '01:00', 3600, '2018-12-31 01:00:00'];
|
||||
yield ['2018-12-31 00:00:00', null, '01:00:10', 3660, '2018-12-31 01:01:00'];
|
||||
yield ['2018-12-31 00:00:00', null, '1h', 3600, '2018-12-31 01:00:00'];
|
||||
yield ['2018-12-31 00:00:00', null, '1h10m', 4200, '2018-12-31 01:10:00'];
|
||||
yield ['2018-12-31 00:00:00', null, '1h10s', 3660, '2018-12-31 01:01:00'];
|
||||
yield ['2018-12-31 00:00:00', null, '60m', 3600, '2018-12-31 01:00:00'];
|
||||
yield ['2018-12-31 00:00:00', null, '60M1s', 3660, '2018-12-31 01:01:00'];
|
||||
yield ['2018-12-31 00:00:00', null, '3600s', 3600, '2018-12-31 01:00:00'];
|
||||
yield ['2018-12-31 00:00:00', null, '59m60s', 3600, '2018-12-31 01:00:00'];
|
||||
yield ['2018-12-31 00:00:00', null, '1', 3600, '2018-12-31 01:00:00'];
|
||||
yield ['2018-12-31 00:00:00', null, '1,0', 3600, '2018-12-31 01:00:00'];
|
||||
yield ['2018-12-31 00:00:00', null, '1.0', 3600, '2018-12-31 01:00:00'];
|
||||
yield ['2018-12-31 00:00:00', null, '1.5', 5400, '2018-12-31 01:30:00'];
|
||||
yield ['2018-12-31 00:00:00', null, '1,25', 4500, '2018-12-31 01:15:00'];
|
||||
}
|
||||
|
||||
public function testCreateActionShowsMetaFields()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser();
|
||||
|
||||
@@ -207,6 +207,8 @@ class AppExtensionTest extends TestCase
|
||||
'lockdown_grace_period' => null,
|
||||
],
|
||||
'default_begin' => 'now',
|
||||
'duration_increment' => null,
|
||||
'time_increment' => null,
|
||||
],
|
||||
'kimai.timesheet.rates' => [],
|
||||
'kimai.timesheet.rounding' => [
|
||||
|
||||
@@ -286,6 +286,8 @@ class ConfigurationTest extends TestCase
|
||||
'lockdown_period_end' => null,
|
||||
'lockdown_grace_period' => null,
|
||||
],
|
||||
'duration_increment' => null,
|
||||
'time_increment' => null,
|
||||
],
|
||||
'user' => [
|
||||
'registration' => true,
|
||||
|
||||
@@ -21,7 +21,7 @@ class ThemeJavascriptTranslationsEventTest extends TestCase
|
||||
{
|
||||
$sut = new ThemeJavascriptTranslationsEvent();
|
||||
|
||||
$this->assertCount(23, $sut->getTranslations());
|
||||
$this->assertCount(24, $sut->getTranslations());
|
||||
}
|
||||
|
||||
public function testGetterAndSetter()
|
||||
@@ -31,7 +31,7 @@ class ThemeJavascriptTranslationsEventTest extends TestCase
|
||||
$sut->setTranslation('hello', 'world', 'testing');
|
||||
|
||||
$result = $sut->getTranslations();
|
||||
self::assertCount(25, $result);
|
||||
self::assertCount(26, $result);
|
||||
self::assertArrayHasKey('foo', $result);
|
||||
self::assertEquals(['bar', 'messages'], $result['foo']);
|
||||
self::assertArrayHasKey('hello', $result);
|
||||
|
||||
54
tests/Form/FormTraitTest.php
Normal file
54
tests/Form/FormTraitTest.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?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\Form;
|
||||
|
||||
use App\Form\FormTrait;
|
||||
use App\Tests\Form\Type\TypeTestModel;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||
use Symfony\Component\Form\Test\TypeTestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Form\FormTrait
|
||||
*/
|
||||
class FormTraitTest extends TypeTestCase
|
||||
{
|
||||
use FormTrait;
|
||||
|
||||
/**
|
||||
* @expectedDeprecation FormTrait::addDescription() is deprecated and will be removed with 2.0, use DescriptionType instead
|
||||
* @group legacy
|
||||
*/
|
||||
public function testAddDescription()
|
||||
{
|
||||
$data = ['description' => 'foo'];
|
||||
$model = new TypeTestModel(['description' => 'bar']);
|
||||
|
||||
$form = $this->factory->createBuilder(FormType::class, $model);
|
||||
$this->addDescription($form);
|
||||
|
||||
$desc = $form->get('description');
|
||||
self::assertArrayHasKey('autofocus', $desc->getOption('attr'));
|
||||
self::assertEquals('autofocus', $desc->getOption('attr')['autofocus']);
|
||||
|
||||
$form = $form->getForm();
|
||||
|
||||
$desc = $form->get('description');
|
||||
self::assertFalse($desc->isRequired());
|
||||
|
||||
$expected = new TypeTestModel([
|
||||
'description' => 'foo'
|
||||
]);
|
||||
|
||||
$form->submit($data);
|
||||
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
$this->assertEquals($expected, $model);
|
||||
}
|
||||
}
|
||||
101
tests/Form/Type/DurationTypeTest.php
Normal file
101
tests/Form/Type/DurationTypeTest.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?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\Form\Type;
|
||||
|
||||
use App\Form\Type\DurationType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||
use Symfony\Component\Form\Test\TypeTestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Form\Type\DurationType
|
||||
*/
|
||||
class DurationTypeTest extends TypeTestCase
|
||||
{
|
||||
public function getTestData()
|
||||
{
|
||||
yield [4.5, 16200];
|
||||
yield ['4,5', 16200];
|
||||
yield ['4:30', 16200];
|
||||
yield ['4h30m', 16200];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getTestData
|
||||
*/
|
||||
public function testSubmitValidData($value, $expected)
|
||||
{
|
||||
$data = ['duration' => $value];
|
||||
$model = new TypeTestModel(['duration' => 3600]);
|
||||
|
||||
$form = $this->factory->createBuilder(FormType::class, $model);
|
||||
$form->add('duration', DurationType::class);
|
||||
$form = $form->getForm();
|
||||
|
||||
$expected = new TypeTestModel([
|
||||
'duration' => $expected
|
||||
]);
|
||||
|
||||
$form->submit($data);
|
||||
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
$this->assertEquals($expected, $model);
|
||||
}
|
||||
|
||||
public function testPresetPopulatesView()
|
||||
{
|
||||
$view = $this->factory->create(DurationType::class, 3600, [
|
||||
'preset_minutes' => 15,
|
||||
'preset_hours' => 5,
|
||||
])->createView();
|
||||
|
||||
self::assertArrayHasKey('duration_presets', $view->vars);
|
||||
self::assertCount(20, $view->vars['duration_presets']);
|
||||
self::assertEquals('0:30', $view->vars['duration_presets'][1]);
|
||||
self::assertEquals('4:45', $view->vars['duration_presets'][18]);
|
||||
}
|
||||
|
||||
public function testPresetsAreNotGeneratedOnMissingHours()
|
||||
{
|
||||
$view = $this->factory->create(DurationType::class, 3600, [
|
||||
'preset_minutes' => 5,
|
||||
])->createView();
|
||||
|
||||
self::assertArrayNotHasKey('duration_presets', $view->vars);
|
||||
}
|
||||
|
||||
public function testPresetsAreNotGeneratedOnMissingMinutes()
|
||||
{
|
||||
$view = $this->factory->create(DurationType::class, 3600, [
|
||||
'preset_hours' => 5,
|
||||
])->createView();
|
||||
|
||||
self::assertArrayNotHasKey('duration_presets', $view->vars);
|
||||
}
|
||||
|
||||
public function testPresetsAreNotGeneratedOnNegativeMinutes()
|
||||
{
|
||||
$view = $this->factory->create(DurationType::class, 3600, [
|
||||
'preset_minutes' => -1,
|
||||
'preset_hours' => 5,
|
||||
])->createView();
|
||||
|
||||
self::assertArrayNotHasKey('duration_presets', $view->vars);
|
||||
}
|
||||
|
||||
public function testPresetsAreNotGeneratedOnNegativeHours()
|
||||
{
|
||||
$view = $this->factory->create(DurationType::class, 3600, [
|
||||
'preset_minutes' => 5,
|
||||
'preset_hours' => -1,
|
||||
])->createView();
|
||||
|
||||
self::assertArrayNotHasKey('duration_presets', $view->vars);
|
||||
}
|
||||
}
|
||||
78
tests/Form/Type/MinuteIncrementTypeTest.php
Normal file
78
tests/Form/Type/MinuteIncrementTypeTest.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?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\Form\Type;
|
||||
|
||||
use App\Form\Type\MinuteIncrementType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||
use Symfony\Component\Form\Test\TypeTestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Form\Type\MinuteIncrementType
|
||||
*/
|
||||
class MinuteIncrementTypeTest extends TypeTestCase
|
||||
{
|
||||
public function testSubmitValidData()
|
||||
{
|
||||
$data = ['increment' => 4];
|
||||
$model = new TypeTestModel(['increment' => 5]);
|
||||
|
||||
$form = $this->factory->createBuilder(FormType::class, $model);
|
||||
$form->add('increment', MinuteIncrementType::class);
|
||||
$form = $form->getForm();
|
||||
|
||||
$expected = new TypeTestModel([
|
||||
'increment' => '3'
|
||||
]);
|
||||
|
||||
$form->submit($data);
|
||||
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
$this->assertEquals($expected, $model);
|
||||
}
|
||||
|
||||
public function testSubmitValidDataWithoutDeactivate()
|
||||
{
|
||||
$data = ['increment' => 4];
|
||||
$model = new TypeTestModel(['increment' => 5]);
|
||||
|
||||
$form = $this->factory->createBuilder(FormType::class, $model);
|
||||
$form->add('increment', MinuteIncrementType::class, ['deactivate' => false]);
|
||||
$form = $form->getForm();
|
||||
|
||||
$expected = new TypeTestModel([
|
||||
'increment' => '4'
|
||||
]);
|
||||
|
||||
$form->submit($data);
|
||||
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
$this->assertEquals($expected, $model);
|
||||
}
|
||||
|
||||
public function testPresetPopulatesView()
|
||||
{
|
||||
$view = $this->factory->create(MinuteIncrementType::class, 3600, [])->createView();
|
||||
self::assertArrayHasKey('choices', $view->vars);
|
||||
self::assertCount(16, $view->vars['choices']);
|
||||
self::assertEquals(null, $view->vars['choices'][0]->data);
|
||||
self::assertEquals(0, $view->vars['choices'][1]->data);
|
||||
self::assertEquals(1, $view->vars['choices'][2]->data);
|
||||
}
|
||||
|
||||
public function testPresetPopulatesViewWithoutDeactivate()
|
||||
{
|
||||
$view = $this->factory->create(MinuteIncrementType::class, 3600, ['deactivate' => false])->createView();
|
||||
self::assertArrayHasKey('choices', $view->vars);
|
||||
self::assertCount(15, $view->vars['choices']);
|
||||
self::assertEquals(null, $view->vars['choices'][0]->data);
|
||||
self::assertEquals(1, $view->vars['choices'][1]->data);
|
||||
self::assertEquals(2, $view->vars['choices'][2]->data);
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace App\Tests\Mocks;
|
||||
|
||||
use App\Configuration\TimesheetConfiguration;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Tests\Configuration\TestConfigLoader;
|
||||
use App\Timesheet\Rounding\CeilRounding;
|
||||
use App\Timesheet\Rounding\ClosestRounding;
|
||||
@@ -35,8 +35,8 @@ class RoundingServiceFactory extends AbstractMockFactory
|
||||
];
|
||||
}
|
||||
|
||||
$configuration = new TimesheetConfiguration($loader, [
|
||||
'rounding' => $rules
|
||||
$configuration = new SystemConfiguration($loader, [
|
||||
'timesheet' => ['rounding' => $rules]
|
||||
]);
|
||||
|
||||
$modes = [
|
||||
|
||||
@@ -1,25 +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\Mocks\Security;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Tests\Mocks\AbstractMockFactory;
|
||||
use App\Timesheet\UserDateTimeFactory;
|
||||
|
||||
class UserDateTimeFactoryFactory extends AbstractMockFactory
|
||||
{
|
||||
public function create(?string $timezone = null): UserDateTimeFactory
|
||||
{
|
||||
$userFactory = new CurrentUserFactory($this->getTestCase());
|
||||
$currentUser = $userFactory->create(new User(), $timezone);
|
||||
|
||||
return new UserDateTimeFactory($currentUser);
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,8 @@
|
||||
|
||||
namespace App\Tests\Mocks;
|
||||
|
||||
use App\Configuration\TimesheetConfiguration;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Tests\Configuration\TestConfigLoader;
|
||||
use App\Tests\Mocks\Security\UserDateTimeFactoryFactory;
|
||||
use App\Timesheet\TrackingMode\DefaultMode;
|
||||
use App\Timesheet\TrackingMode\DurationFixedBeginMode;
|
||||
use App\Timesheet\TrackingMode\DurationOnlyMode;
|
||||
@@ -26,17 +25,16 @@ class TrackingModeServiceFactory extends AbstractMockFactory
|
||||
$mode = 'default';
|
||||
}
|
||||
|
||||
$dateTime = (new UserDateTimeFactoryFactory($this->getTestCase()))->create();
|
||||
$loader = new TestConfigLoader([]);
|
||||
|
||||
$configuration = new TimesheetConfiguration($loader, ['mode' => $mode]);
|
||||
$configuration = new SystemConfiguration($loader, ['timesheet' => ['mode' => $mode]]);
|
||||
|
||||
if (null === $modes) {
|
||||
$modes = [
|
||||
new DefaultMode($dateTime, $configuration, (new RoundingServiceFactory($this->getTestCase()))->create()),
|
||||
new PunchInOutMode($dateTime),
|
||||
new DurationOnlyMode($dateTime, $configuration),
|
||||
new DurationFixedBeginMode($dateTime, $configuration),
|
||||
new DefaultMode((new RoundingServiceFactory($this->getTestCase()))->create()),
|
||||
new PunchInOutMode(),
|
||||
new DurationOnlyMode($configuration),
|
||||
new DurationFixedBeginMode($configuration),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ class SamlLogoutHandlerTest extends TestCase
|
||||
$auth->expects($this->once())->method('getSLOurl')->willReturn('/logout');
|
||||
$auth->expects($this->once())->method('logout')->willReturnCallback(function () {
|
||||
$args = \func_get_args();
|
||||
self::assertEquals(null, $args[0]);
|
||||
self::assertNull($args[0]);
|
||||
self::assertEquals([], $args[1]);
|
||||
self::assertEquals('tony', $args[2]);
|
||||
self::assertEquals('foo-bar', $args[3]);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace App\Tests\Timesheet;
|
||||
|
||||
use App\Configuration\TimesheetConfiguration;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Entity\Timesheet;
|
||||
use App\Entity\User;
|
||||
use App\Event\TimesheetCreatePostEvent;
|
||||
@@ -42,8 +42,8 @@ class TimesheetServiceTest extends TestCase
|
||||
?ValidatorInterface $validator = null,
|
||||
?TimesheetRepository $repository = null
|
||||
): TimesheetService {
|
||||
$configuration = $this->createMock(TimesheetConfiguration::class);
|
||||
$configuration->method('getActiveEntriesHardLimit')->willReturn(1);
|
||||
$configuration = $this->createMock(SystemConfiguration::class);
|
||||
$configuration->method('getTimesheetActiveEntriesHardLimit')->willReturn(1);
|
||||
|
||||
if ($repository === null) {
|
||||
$repository = $this->createMock(TimesheetRepository::class);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
namespace App\Tests\Timesheet\TrackingMode;
|
||||
|
||||
use App\Entity\Timesheet;
|
||||
use App\Entity\User;
|
||||
use App\Timesheet\TrackingMode\AbstractTrackingMode;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -24,6 +25,14 @@ abstract class AbstractTrackingModeTest extends TestCase
|
||||
*/
|
||||
abstract protected function createSut();
|
||||
|
||||
protected function createTimesheet(): Timesheet
|
||||
{
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet->setUser(new User());
|
||||
|
||||
return $timesheet;
|
||||
}
|
||||
|
||||
protected function assertDefaultBegin(Timesheet $timesheet)
|
||||
{
|
||||
self::assertNull($timesheet->getBegin());
|
||||
@@ -33,7 +42,7 @@ abstract class AbstractTrackingModeTest extends TestCase
|
||||
{
|
||||
$sut = $this->createSut();
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet = $this->createTimesheet();
|
||||
|
||||
self::assertNull($timesheet->getBegin());
|
||||
self::assertNull($timesheet->getEnd());
|
||||
@@ -48,7 +57,7 @@ abstract class AbstractTrackingModeTest extends TestCase
|
||||
{
|
||||
$sut = $this->createSut();
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet = $this->createTimesheet();
|
||||
$request = new Request([
|
||||
'begin' => '2017-07-23',
|
||||
]);
|
||||
@@ -65,7 +74,7 @@ abstract class AbstractTrackingModeTest extends TestCase
|
||||
{
|
||||
$sut = $this->createSut();
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet = $this->createTimesheet();
|
||||
$request = new Request([
|
||||
'begin' => '2017-07-23',
|
||||
'end' => '2017-07-23',
|
||||
@@ -85,7 +94,7 @@ abstract class AbstractTrackingModeTest extends TestCase
|
||||
{
|
||||
$sut = $this->createSut();
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet = $this->createTimesheet();
|
||||
$request = new Request([
|
||||
'begin' => '10x0-99-99',
|
||||
'end' => '2017-07-23',
|
||||
@@ -102,7 +111,7 @@ abstract class AbstractTrackingModeTest extends TestCase
|
||||
{
|
||||
$sut = $this->createSut();
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet = $this->createTimesheet();
|
||||
$request = new Request([
|
||||
'begin' => '2017-07-23',
|
||||
'end' => '20xx-07-23',
|
||||
@@ -120,7 +129,7 @@ abstract class AbstractTrackingModeTest extends TestCase
|
||||
{
|
||||
$sut = $this->createSut();
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet = $this->createTimesheet();
|
||||
$request = new Request([
|
||||
'from' => '2018-05-23 21:47:55',
|
||||
]);
|
||||
@@ -136,7 +145,7 @@ abstract class AbstractTrackingModeTest extends TestCase
|
||||
{
|
||||
$sut = $this->createSut();
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet = $this->createTimesheet();
|
||||
$request = new Request([
|
||||
'from' => '2018-05-23 21:47:55',
|
||||
'to' => '2018-05-24 01:11:11',
|
||||
@@ -156,7 +165,7 @@ abstract class AbstractTrackingModeTest extends TestCase
|
||||
{
|
||||
$sut = $this->createSut();
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet = $this->createTimesheet();
|
||||
$request = new Request([
|
||||
'begin' => '2017-07-23',
|
||||
'end' => '2017-07-23',
|
||||
@@ -178,7 +187,7 @@ abstract class AbstractTrackingModeTest extends TestCase
|
||||
{
|
||||
$sut = $this->createSut();
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet = $this->createTimesheet();
|
||||
$request = new Request([
|
||||
'from' => '2018-xx-23 21:47:55',
|
||||
'to' => '2018-05-24 01:11:11',
|
||||
@@ -195,7 +204,7 @@ abstract class AbstractTrackingModeTest extends TestCase
|
||||
{
|
||||
$sut = $this->createSut();
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet = $this->createTimesheet();
|
||||
$request = new Request([
|
||||
'from' => '2018-05-23 21:47:55',
|
||||
'to' => '2018-xx-24 01:11:11',
|
||||
|
||||
@@ -9,11 +9,8 @@
|
||||
|
||||
namespace App\Tests\Timesheet\TrackingMode;
|
||||
|
||||
use App\Configuration\TimesheetConfiguration;
|
||||
use App\Entity\Timesheet;
|
||||
use App\Tests\Configuration\TestConfigLoader;
|
||||
use App\Tests\Mocks\RoundingServiceFactory;
|
||||
use App\Tests\Mocks\Security\UserDateTimeFactoryFactory;
|
||||
use App\Timesheet\TrackingMode\DefaultMode;
|
||||
|
||||
/**
|
||||
@@ -32,11 +29,7 @@ class DefaultModeTest extends AbstractTrackingModeTest
|
||||
*/
|
||||
protected function createSut()
|
||||
{
|
||||
$loader = new TestConfigLoader([]);
|
||||
$dateTime = (new UserDateTimeFactoryFactory($this))->create();
|
||||
$configuration = new TimesheetConfiguration($loader, ['default_begin' => '13:47']);
|
||||
|
||||
return new DefaultMode($dateTime, $configuration, (new RoundingServiceFactory($this))->create());
|
||||
return new DefaultMode((new RoundingServiceFactory($this))->create());
|
||||
}
|
||||
|
||||
public function testDefaultValues()
|
||||
@@ -45,7 +38,7 @@ class DefaultModeTest extends AbstractTrackingModeTest
|
||||
|
||||
self::assertTrue($sut->canEditBegin());
|
||||
self::assertTrue($sut->canEditEnd());
|
||||
self::assertFalse($sut->canEditDuration());
|
||||
self::assertTrue($sut->canEditDuration());
|
||||
self::assertTrue($sut->canUpdateTimesWithAPI());
|
||||
self::assertTrue($sut->canSeeBeginAndEndTimes());
|
||||
self::assertEquals('default', $sut->getId());
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
|
||||
namespace App\Tests\Timesheet\TrackingMode;
|
||||
|
||||
use App\Configuration\TimesheetConfiguration;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Entity\Timesheet;
|
||||
use App\Entity\User;
|
||||
use App\Tests\Configuration\TestConfigLoader;
|
||||
use App\Tests\Mocks\Security\UserDateTimeFactoryFactory;
|
||||
use App\Timesheet\TrackingMode\DurationFixedBeginMode;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -25,10 +25,9 @@ class DurationFixedBeginModeTest extends TestCase
|
||||
protected function createSut()
|
||||
{
|
||||
$loader = new TestConfigLoader([]);
|
||||
$dateTime = (new UserDateTimeFactoryFactory($this))->create();
|
||||
$configuration = new TimesheetConfiguration($loader, ['default_begin' => '13:47']);
|
||||
$configuration = new SystemConfiguration($loader, ['timesheet' => ['default_begin' => '13:47']]);
|
||||
|
||||
return new DurationFixedBeginMode($dateTime, $configuration);
|
||||
return new DurationFixedBeginMode($configuration);
|
||||
}
|
||||
|
||||
public function testDefaultValues()
|
||||
@@ -57,7 +56,7 @@ class DurationFixedBeginModeTest extends TestCase
|
||||
|
||||
public function testCreateWithoutBeginInjectsBegin()
|
||||
{
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet = (new Timesheet())->setUser(new User());
|
||||
$request = new Request();
|
||||
|
||||
$sut = $this->createSut();
|
||||
|
||||
@@ -9,10 +9,9 @@
|
||||
|
||||
namespace App\Tests\Timesheet\TrackingMode;
|
||||
|
||||
use App\Configuration\TimesheetConfiguration;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Entity\Timesheet;
|
||||
use App\Tests\Configuration\TestConfigLoader;
|
||||
use App\Tests\Mocks\Security\UserDateTimeFactoryFactory;
|
||||
use App\Timesheet\TrackingMode\DurationOnlyMode;
|
||||
|
||||
/**
|
||||
@@ -29,10 +28,9 @@ class DurationOnlyModeTest extends AbstractTrackingModeTest
|
||||
protected function createSut()
|
||||
{
|
||||
$loader = new TestConfigLoader([]);
|
||||
$dateTime = (new UserDateTimeFactoryFactory($this))->create();
|
||||
$configuration = new TimesheetConfiguration($loader, ['default_begin' => '13:45:37']);
|
||||
$configuration = new SystemConfiguration($loader, ['timesheet' => ['default_begin' => '13:45:37']]);
|
||||
|
||||
return new DurationOnlyMode($dateTime, $configuration);
|
||||
return new DurationOnlyMode($configuration);
|
||||
}
|
||||
|
||||
public function testDefaultValues()
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace App\Tests\Timesheet\TrackingMode;
|
||||
|
||||
use App\Entity\Timesheet;
|
||||
use App\Tests\Mocks\Security\UserDateTimeFactoryFactory;
|
||||
use App\Entity\User;
|
||||
use App\Timesheet\TrackingMode\PunchInOutMode;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -22,8 +22,7 @@ class PunchInOutModeTest extends TestCase
|
||||
{
|
||||
public function testDefaultValues()
|
||||
{
|
||||
$dateTime = (new UserDateTimeFactoryFactory($this))->create();
|
||||
$sut = new PunchInOutMode($dateTime);
|
||||
$sut = new PunchInOutMode();
|
||||
|
||||
self::assertFalse($sut->canEditBegin());
|
||||
self::assertFalse($sut->canEditEnd());
|
||||
@@ -40,19 +39,17 @@ class PunchInOutModeTest extends TestCase
|
||||
$timesheet->setBegin($startingTime);
|
||||
$request = new Request();
|
||||
|
||||
$dateTime = (new UserDateTimeFactoryFactory($this))->create();
|
||||
$sut = new PunchInOutMode($dateTime);
|
||||
$sut = new PunchInOutMode();
|
||||
$sut->create($timesheet, $request);
|
||||
self::assertEquals($timesheet->getBegin(), $startingTime);
|
||||
}
|
||||
|
||||
public function testCreateWithoutBegin()
|
||||
{
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet = (new Timesheet())->setUser(new User());
|
||||
$request = new Request();
|
||||
|
||||
$dateTime = (new UserDateTimeFactoryFactory($this))->create();
|
||||
$sut = new PunchInOutMode($dateTime);
|
||||
$sut = new PunchInOutMode();
|
||||
$sut->create($timesheet, $request);
|
||||
self::assertInstanceOf(\DateTime::class, $timesheet->getBegin());
|
||||
}
|
||||
|
||||
@@ -9,13 +9,15 @@
|
||||
|
||||
namespace App\Tests\Timesheet;
|
||||
|
||||
use App\Tests\Mocks\Security\UserDateTimeFactoryFactory;
|
||||
use App\Entity\User;
|
||||
use App\Tests\Mocks\Security\CurrentUserFactory;
|
||||
use App\Timesheet\UserDateTimeFactory;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Timesheet\DateTimeFactory
|
||||
* @covers \App\Timesheet\UserDateTimeFactory
|
||||
* @group legacy
|
||||
*/
|
||||
class UserDateTimeFactoryTest extends TestCase
|
||||
{
|
||||
@@ -23,7 +25,10 @@ class UserDateTimeFactoryTest extends TestCase
|
||||
|
||||
protected function createUserDateTimeFactory(?string $timezone = null): UserDateTimeFactory
|
||||
{
|
||||
return (new UserDateTimeFactoryFactory($this))->create($timezone);
|
||||
$userFactory = new CurrentUserFactory($this);
|
||||
$currentUser = $userFactory->create(new User(), $timezone);
|
||||
|
||||
return new UserDateTimeFactory($currentUser);
|
||||
}
|
||||
|
||||
public function testGetTimezone()
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace App\Tests\Twig;
|
||||
|
||||
use App\Configuration\ConfigLoaderInterface;
|
||||
use App\Configuration\TimesheetConfiguration;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Twig\MarkdownExtension;
|
||||
use App\Utils\Markdown;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
@@ -24,7 +24,7 @@ class MarkdownExtensionTest extends TestCase
|
||||
public function testGetFilters()
|
||||
{
|
||||
$loader = $this->createMock(ConfigLoaderInterface::class);
|
||||
$config = new TimesheetConfiguration($loader, ['markdown_content' => true]);
|
||||
$config = new SystemConfiguration($loader, ['timesheet' => ['markdown_content' => true]]);
|
||||
$sut = new MarkdownExtension(new Markdown(), $config);
|
||||
$filters = $sut->getFilters();
|
||||
$this->assertCount(3, $filters);
|
||||
@@ -48,7 +48,7 @@ class MarkdownExtensionTest extends TestCase
|
||||
public function testMarkdownToHtml()
|
||||
{
|
||||
$loader = $this->createMock(ConfigLoaderInterface::class);
|
||||
$config = new TimesheetConfiguration($loader, ['markdown_content' => true]);
|
||||
$config = new SystemConfiguration($loader, ['timesheet' => ['markdown_content' => true]]);
|
||||
$sut = new MarkdownExtension(new Markdown(), $config);
|
||||
$this->assertEquals('<p><em>test</em></p>', $sut->markdownToHtml('*test*'));
|
||||
$this->assertEquals('<p># foobar</p>', $sut->markdownToHtml('# foobar'));
|
||||
@@ -57,7 +57,7 @@ class MarkdownExtensionTest extends TestCase
|
||||
public function testTimesheetContent()
|
||||
{
|
||||
$loader = $this->createMock(ConfigLoaderInterface::class);
|
||||
$config = new TimesheetConfiguration($loader, ['markdown_content' => false]);
|
||||
$config = new SystemConfiguration($loader, ['timesheet' => ['markdown_content' => false]]);
|
||||
$sut = new MarkdownExtension(new Markdown(), $config);
|
||||
$this->assertEquals(
|
||||
"- test<br />\n- foo",
|
||||
@@ -66,7 +66,7 @@ class MarkdownExtensionTest extends TestCase
|
||||
$this->assertEquals('', $sut->timesheetContent(null));
|
||||
$this->assertEquals('', $sut->timesheetContent(''));
|
||||
|
||||
$config = new TimesheetConfiguration($loader, ['markdown_content' => true]);
|
||||
$config = new SystemConfiguration($loader, ['timesheet' => ['markdown_content' => true]]);
|
||||
$sut = new MarkdownExtension(new Markdown(), $config);
|
||||
$this->assertEquals(
|
||||
"<ul>\n<li>test</li>\n<li>foo</li>\n</ul>\n<p>foo <strong>bar</strong></p>",
|
||||
@@ -77,7 +77,7 @@ class MarkdownExtensionTest extends TestCase
|
||||
public function testCommentContent()
|
||||
{
|
||||
$loader = $this->createMock(ConfigLoaderInterface::class);
|
||||
$config = new TimesheetConfiguration($loader, ['markdown_content' => false]);
|
||||
$config = new SystemConfiguration($loader, ['timesheet' => ['markdown_content' => false]]);
|
||||
$sut = new MarkdownExtension(new Markdown(), $config);
|
||||
$this->assertEquals(
|
||||
"<p>- test<br />\n- foo</p>",
|
||||
@@ -95,7 +95,7 @@ class MarkdownExtensionTest extends TestCase
|
||||
$this->assertEquals('<p>' . $loremIpsum . '</p>', $sut->commentContent($loremIpsum, true));
|
||||
$this->assertEquals('Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut l …', $sut->commentContent($loremIpsum));
|
||||
|
||||
$config = new TimesheetConfiguration($loader, ['markdown_content' => true]);
|
||||
$config = new SystemConfiguration($loader, ['timesheet' => ['markdown_content' => true]]);
|
||||
$sut = new MarkdownExtension(new Markdown(), $config);
|
||||
$this->assertEquals(
|
||||
"<ul>\n<li>test</li>\n<li>foo</li>\n</ul>\n<p>foo <strong>bar</strong></p>",
|
||||
|
||||
@@ -50,6 +50,6 @@ class ThemeEventExtensionTest extends TestCase
|
||||
{
|
||||
$sut = $this->getSut();
|
||||
$values = $sut->getJavascriptTranslations();
|
||||
self::assertCount(23, $values);
|
||||
self::assertCount(24, $values);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,19 @@ class DurationTest extends TestCase
|
||||
$this->assertEquals('02:38:14', $sut->format(9494, Duration::FORMAT_WITH_SECONDS));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testParseDurationStringSpecials()
|
||||
{
|
||||
$sut = new Duration();
|
||||
$this->assertEquals(0, $sut->parseDuration('-1', Duration::FORMAT_SECONDS));
|
||||
$this->assertEquals(0, $sut->parseDuration('0', Duration::FORMAT_SECONDS));
|
||||
$this->assertEquals(3600, $sut->parseDuration('3600', Duration::FORMAT_SECONDS));
|
||||
$this->assertEquals(0, $sut->parseDuration('', Duration::FORMAT_SECONDS));
|
||||
$this->assertEquals(0, $sut->parseDuration('-12', Duration::FORMAT_SECONDS));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getParseDurationTestData
|
||||
*/
|
||||
@@ -47,13 +60,15 @@ class DurationTest extends TestCase
|
||||
public function getParseDurationTestData()
|
||||
{
|
||||
return [
|
||||
[0, '', Duration::FORMAT_SECONDS],
|
||||
[0, 0, Duration::FORMAT_SECONDS],
|
||||
[0, -12, Duration::FORMAT_SECONDS],
|
||||
[3600, 3600, Duration::FORMAT_SECONDS],
|
||||
[3600, 1, Duration::FORMAT_DECIMAL],
|
||||
[5400, 1.5, Duration::FORMAT_DECIMAL],
|
||||
[3600, '1', Duration::FORMAT_DECIMAL],
|
||||
[5400, '1.5', Duration::FORMAT_DECIMAL],
|
||||
[5400, '1,5', Duration::FORMAT_DECIMAL],
|
||||
|
||||
[0, '', Duration::FORMAT_NATURAL],
|
||||
[0, 0, Duration::FORMAT_NATURAL],
|
||||
|
||||
[99, '99s', Duration::FORMAT_NATURAL],
|
||||
[7200, '2h', Duration::FORMAT_NATURAL],
|
||||
[2280, '38m', Duration::FORMAT_NATURAL],
|
||||
@@ -63,6 +78,10 @@ class DurationTest extends TestCase
|
||||
|
||||
[0, '', Duration::FORMAT_COLON],
|
||||
[0, 0, Duration::FORMAT_COLON],
|
||||
|
||||
[12420, '3:27', Duration::FORMAT_COLON],
|
||||
[12420, '3h27m', Duration::FORMAT_NATURAL],
|
||||
|
||||
[48420, '13:27', Duration::FORMAT_COLON],
|
||||
[48474, '13:27:54', Duration::FORMAT_COLON],
|
||||
[48474, '12:87:54', Duration::FORMAT_COLON],
|
||||
|
||||
@@ -29,14 +29,18 @@ class DurationValidatorTest extends ConstraintValidatorTestCase
|
||||
public function getValidData()
|
||||
{
|
||||
return [
|
||||
['99s'],
|
||||
['2h'],
|
||||
['38m'],
|
||||
['99s'],
|
||||
['2h38m'],
|
||||
['2h38s'],
|
||||
['2m38s'],
|
||||
['2h38m17s'],
|
||||
['1h96m137s'],
|
||||
[''],
|
||||
['0'],
|
||||
['1.2'],
|
||||
['2,3'],
|
||||
[null],
|
||||
[0],
|
||||
[11257200],
|
||||
@@ -64,6 +68,7 @@ class DurationValidatorTest extends ConstraintValidatorTestCase
|
||||
{
|
||||
$constraint = new Duration();
|
||||
$this->validator->validate($input, $constraint);
|
||||
$this->validator->validate(strtoupper($input), $constraint);
|
||||
$this->assertNoViolation();
|
||||
}
|
||||
|
||||
@@ -71,7 +76,12 @@ class DurationValidatorTest extends ConstraintValidatorTestCase
|
||||
{
|
||||
return [
|
||||
['13-13'],
|
||||
['13.13'],
|
||||
['2m3m'],
|
||||
['2s3s'],
|
||||
['2h3h'],
|
||||
['2m3h'],
|
||||
['2s3h'],
|
||||
['2s3m'],
|
||||
['3127::00'],
|
||||
['3127:00:'],
|
||||
[':3127:00'],
|
||||
@@ -92,10 +102,27 @@ class DurationValidatorTest extends ConstraintValidatorTestCase
|
||||
|
||||
$this->validator->validate($input, $constraint);
|
||||
|
||||
$expectedFormat = \is_string($input) ? '"' . $input . '"' : $input;
|
||||
$this->buildViolation('myMessage')
|
||||
->setParameter('{{ value }}', '"' . $input . '"')
|
||||
->setCode(Regex::REGEX_FAILED_ERROR)
|
||||
->assertRaised();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getInvalidData
|
||||
* @param mixed $input
|
||||
*/
|
||||
public function testValidationErrorUpperCase($input)
|
||||
{
|
||||
$input = strtoupper($input);
|
||||
$constraint = new Duration([
|
||||
'message' => 'myMessage',
|
||||
]);
|
||||
|
||||
$this->validator->validate($input, $constraint);
|
||||
|
||||
$this->buildViolation('myMessage')
|
||||
->setParameter('{{ value }}', $expectedFormat)
|
||||
->setParameter('{{ value }}', '"' . $input . '"')
|
||||
->setCode(Regex::REGEX_FAILED_ERROR)
|
||||
->assertRaised();
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace App\Tests\Validator\Constraints;
|
||||
|
||||
use App\Configuration\ConfigLoaderInterface;
|
||||
use App\Configuration\TimesheetConfiguration;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Entity\Timesheet;
|
||||
use App\Validator\Constraints\TimesheetFutureTimes;
|
||||
use App\Validator\Constraints\TimesheetFutureTimesValidator;
|
||||
@@ -31,13 +31,15 @@ class TimesheetFutureTimesValidatorTest extends ConstraintValidatorTestCase
|
||||
protected function createMyValidator(bool $allowFutureTimes = false)
|
||||
{
|
||||
$loader = $this->createMock(ConfigLoaderInterface::class);
|
||||
$config = new TimesheetConfiguration($loader, [
|
||||
'rules' => [
|
||||
'allow_future_times' => $allowFutureTimes,
|
||||
],
|
||||
'rounding' => [
|
||||
'default' => [
|
||||
'begin' => 1
|
||||
$config = new SystemConfiguration($loader, [
|
||||
'timesheet' => [
|
||||
'rules' => [
|
||||
'allow_future_times' => $allowFutureTimes,
|
||||
],
|
||||
'rounding' => [
|
||||
'default' => [
|
||||
'begin' => 1
|
||||
]
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace App\Tests\Validator\Constraints;
|
||||
|
||||
use App\Configuration\ConfigLoaderInterface;
|
||||
use App\Configuration\TimesheetConfiguration;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Entity\Timesheet;
|
||||
use App\Validator\Constraints\TimesheetLockdown;
|
||||
use App\Validator\Constraints\TimesheetLockdownValidator;
|
||||
@@ -46,12 +46,14 @@ class TimesheetLockdownValidatorTest extends ConstraintValidatorTestCase
|
||||
);
|
||||
|
||||
$loader = $this->createMock(ConfigLoaderInterface::class);
|
||||
$config = new TimesheetConfiguration($loader, [
|
||||
'rules' => [
|
||||
'lockdown_period_start' => $start,
|
||||
'lockdown_period_end' => $end,
|
||||
'lockdown_grace_period' => $grace,
|
||||
],
|
||||
$config = new SystemConfiguration($loader, [
|
||||
'timesheet' => [
|
||||
'rules' => [
|
||||
'lockdown_period_start' => $start,
|
||||
'lockdown_period_end' => $end,
|
||||
'lockdown_grace_period' => $grace,
|
||||
],
|
||||
]
|
||||
]);
|
||||
|
||||
return new TimesheetLockdownValidator($auth, $config);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace App\Tests\Validator\Constraints;
|
||||
|
||||
use App\Configuration\ConfigLoaderInterface;
|
||||
use App\Configuration\TimesheetConfiguration;
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Entity\Timesheet;
|
||||
use App\Repository\TimesheetRepository;
|
||||
use App\Validator\Constraints\TimesheetOverlapping;
|
||||
@@ -32,9 +32,11 @@ class TimesheetOverlappingValidatorTest extends ConstraintValidatorTestCase
|
||||
protected function createMyValidator(bool $allowOverlappingRecords = false, bool $hasRecords = true)
|
||||
{
|
||||
$loader = $this->createMock(ConfigLoaderInterface::class);
|
||||
$config = new TimesheetConfiguration($loader, [
|
||||
'rules' => [
|
||||
'allow_overlapping_records' => $allowOverlappingRecords,
|
||||
$config = new SystemConfiguration($loader, [
|
||||
'timesheet' => [
|
||||
'rules' => [
|
||||
'allow_overlapping_records' => $allowOverlappingRecords,
|
||||
],
|
||||
],
|
||||
]);
|
||||
$repository = $this->createMock(TimesheetRepository::class);
|
||||
|
||||
Reference in New Issue
Block a user