added drag and drop for new records via calendar (#1962)

This commit is contained in:
Kevin Papst
2020-09-17 01:13:48 +02:00
committed by GitHub
parent 14b3de4300
commit 9ef32e75c5
82 changed files with 2808 additions and 385 deletions

View File

@@ -67,7 +67,15 @@ abstract class APIControllerBaseTest extends ControllerBaseTest
*/
protected function createUrl($url, $json = true)
{
return '/' . ltrim($url, '/') . ($json ? '.json' : '');
if ($json) {
if (stripos($url, '?') !== false) {
$url = str_replace('?', '.json?', $url);
} else {
$url .= '.json';
}
}
return '/' . ltrim($url, '/');
}
protected function assertRequestIsSecured(HttpKernelBrowser $client, string $url, $method = 'GET')
@@ -453,6 +461,15 @@ abstract class APIControllerBaseTest extends ControllerBaseTest
'color' => '@string',
];
case 'ActivityExpanded':
return [
'id' => 'int',
'name' => 'string',
'visible' => 'bool',
'project' => ['result' => 'object', 'type' => '@ProjectExpanded'],
'color' => '@string',
];
// collection of activities
case 'ActivityCollection':
return [
@@ -502,6 +519,26 @@ abstract class APIControllerBaseTest extends ControllerBaseTest
// TODO new fields: billable, category
];
case 'TimesheetEntityFull':
return [
'id' => 'int',
'begin' => 'DateTime',
'end' => '@DateTime',
'duration' => '@int',
'description' => '@string',
'rate' => 'float',
'activity' => ['result' => 'object', 'type' => 'ActivityExpanded'],
'project' => ['result' => 'object', 'type' => 'ProjectExpanded'],
'tags' => ['result' => 'array', 'type' => 'string'],
'user' => 'int',
'metaFields' => ['result' => 'array', 'type' => 'TimesheetMeta'],
'internalRate' => 'float',
'exported' => 'bool',
'fixedRate' => '@float',
'hourlyRate' => '@float',
// TODO new fields: billable, category
];
case 'TimesheetCollection':
return [
'id' => 'int',
@@ -586,8 +623,6 @@ abstract class APIControllerBaseTest extends ControllerBaseTest
break;
case 'object':
self::assertIsArray($result[$key], sprintf('Key "%s" in type "%s" is not an array', $key, $type));
if ($value['type'][0] === '@') {
if (empty($result[$key])) {
break;
@@ -595,6 +630,8 @@ abstract class APIControllerBaseTest extends ControllerBaseTest
$value['type'] = substr($value['type'], 1);
}
self::assertIsArray($result[$key], sprintf('Key "%s" in type "%s" is not an array', $key, $type));
self::assertApiResponseTypeStructure($value['type'], $result[$key]);
break;

View File

@@ -0,0 +1,89 @@
<?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\API\Serializer;
use App\API\Serializer\ValidationFailedExceptionErrorHandler;
use App\Validator\ValidationFailedException;
use JMS\Serializer\GraphNavigatorInterface;
use JMS\Serializer\Visitor\SerializationVisitorInterface;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* @covers \App\API\Serializer\ValidationFailedExceptionErrorHandler
*/
class ValidationFailedExceptionErrorHandlerTest extends TestCase
{
public function testSubscribingMethods()
{
self::assertEquals([[
'direction' => GraphNavigatorInterface::DIRECTION_SERIALIZATION,
'type' => 'App\Validator\ValidationFailedException',
'format' => 'json',
'method' => 'serializeExceptionToJson',
]], ValidationFailedExceptionErrorHandler::getSubscribingMethods());
}
public function testWithEmptyConstraintsList()
{
$translator = $this->createMock(TranslatorInterface::class);
$sut = new ValidationFailedExceptionErrorHandler($translator);
$constraints = new ConstraintViolationList();
$validations = new ValidationFailedException($constraints, 'Uuups, that is broken');
$serialization = $this->createMock(SerializationVisitorInterface::class);
$expected = [
'code' => '400',
'message' => null,
'errors' => [
'children' => []
]
];
self::assertEquals($expected, $sut->serializeExceptionToJson($serialization, $validations, []));
}
public function testWithConstraintsList()
{
$translator = $this->createMock(TranslatorInterface::class);
$sut = new ValidationFailedExceptionErrorHandler($translator);
$translator->method('trans')->willReturnArgument(0);
$constraints = new ConstraintViolationList();
$constraints->add(new ConstraintViolation('toooo many tests', 'abc.def', [], '$root', 'begin', 4, null, null, null, '$cause'));
$constraints->add(new ConstraintViolation('missing tests', 'abc.def', [], '$root', 'begin', 4, null, null, null, '$cause'));
$constraints->add(new ConstraintViolation('missing tests', 'test %wuuf% 123', ['%wuuf%' => 'xcv'], '$root', 'end', 4, 3, null, null, '$cause'));
$validations = new ValidationFailedException($constraints, 'Uuups, that is broken');
$serialization = $this->createMock(SerializationVisitorInterface::class);
$expected = [
'code' => '400',
'message' => 'Uuups, that is broken',
'errors' => [
'children' => [
'begin' => [
'errors' => [
0 => 'abc.def',
1 => 'abc.def',
],
],
'end' => [
'errors' => [
0 => 'test %wuuf% 123',
],
]
]
]
];
self::assertEquals($expected, $sut->serializeExceptionToJson($serialization, $validations, []));
}
}

View File

@@ -9,6 +9,7 @@
namespace App\Tests\API;
use App\API\BaseApiController;
use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\Project;
@@ -381,6 +382,30 @@ class TimesheetControllerTest extends APIControllerBaseTest
$this->assertEquals(2016, $result['rate']);
}
public function testPostActionWithFullExpandedResponse()
{
$dateTime = (new UserDateTimeFactoryFactory($this))->create(self::TEST_TIMEZONE);
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
$data = [
'activity' => 1,
'project' => 1,
'begin' => ($dateTime->createDateTime('- 16 hours'))->format('Y-m-d H:m:0'),
'end' => ($dateTime->createDateTime())->format('Y-m-d H:m:0'),
'description' => 'foo',
'fixedRate' => 2016,
'hourlyRate' => 127
];
$this->request($client, '/api/timesheets?full=true', 'POST', [], json_encode($data));
$this->assertTrue($client->getResponse()->isSuccessful());
$result = json_decode($client->getResponse()->getContent(), true);
$this->assertIsArray($result);
self::assertApiResponseTypeStructure('TimesheetEntityFull', $result);
$this->assertNotEmpty($result['id']);
$this->assertTrue($result['duration'] == 57600 || $result['duration'] == 57660); // 1 minute rounding might be applied
$this->assertEquals(2016, $result['rate']);
}
public function testPostActionForDifferentUser()
{
$dateTime = (new UserDateTimeFactoryFactory($this))->create(self::TEST_TIMEZONE);
@@ -833,6 +858,38 @@ class TimesheetControllerTest extends APIControllerBaseTest
$this->assertEmpty($timesheet->getTags());
}
public function testRestartActionWithBegin()
{
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
$this->importFixtureForUser(User::ROLE_USER);
$data = [
'description' => 'foo',
'tags' => 'another,testing,bar'
];
$this->request($client, '/api/timesheets/1', 'PATCH', [], json_encode($data));
$begin = new \DateTime('2019-11-27 13:55:00');
$this->request($client, '/api/timesheets/1/restart', 'PATCH', ['begin' => $begin->format(BaseApiController::DATE_FORMAT_PHP)]);
$this->assertTrue($client->getResponse()->isSuccessful());
$result = json_decode($client->getResponse()->getContent(), true);
self::assertApiResponseTypeStructure('TimesheetEntity', $result);
$this->assertEmpty($result['description']);
$this->assertEmpty($result['tags']);
$em = $this->getEntityManager();
/** @var Timesheet $timesheet */
$timesheet = $em->getRepository(Timesheet::class)->find($result['id']);
$this->assertInstanceOf(\DateTime::class, $timesheet->getBegin());
$this->assertEquals($begin->format(BaseApiController::DATE_FORMAT_PHP), $timesheet->getBegin()->format(BaseApiController::DATE_FORMAT_PHP));
$this->assertNull($timesheet->getEnd());
$this->assertEquals(1, $timesheet->getActivity()->getId());
$this->assertEquals(1, $timesheet->getProject()->getId());
$this->assertEmpty($timesheet->getDescription());
$this->assertEmpty($timesheet->getTags());
}
public function testRestartActionWithCopyData()
{
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);

View File

@@ -9,28 +9,26 @@
namespace App\Tests\Calendar;
use App\Calendar\Source;
use App\Calendar\GoogleSource;
use PHPUnit\Framework\TestCase;
/**
* @covers \App\Calendar\Source
* @covers \App\Calendar\GoogleSource
*/
class SourceTest extends TestCase
class GoogleSourceTest extends TestCase
{
public function testConstruct()
{
$sut = new Source();
$this->assertNull($sut->getId());
$this->assertNull($sut->getColor());
$this->assertNull($sut->getUri());
$this->assertInstanceOf(Source::class, $sut->setId('0815'));
$this->assertInstanceOf(Source::class, $sut->setColor('#fffccc'));
$this->assertInstanceOf(Source::class, $sut->setUri('askdjfhlaksjdhflaksjhdflkjasdlkfjh'));
$sut = new GoogleSource('0815', 'askdjfhlaksjdhflaksjhdflkjasdlkfjh', '#fffccc');
$this->assertEquals('0815', $sut->getId());
$this->assertEquals('#fffccc', $sut->getColor());
$this->assertEquals('askdjfhlaksjdhflaksjhdflkjasdlkfjh', $sut->getUri());
$this->assertEquals('#fffccc', $sut->getColor());
$sut = new GoogleSource('0815', 'askdjfhlaksjdhflaksjhdflkjasdlkfjh', null);
$this->assertEquals('0815', $sut->getId());
$this->assertEquals('askdjfhlaksjdhflaksjhdflkjasdlkfjh', $sut->getUri());
$this->assertNull($sut->getColor());
}
}

View File

@@ -10,7 +10,7 @@
namespace App\Tests\Calendar;
use App\Calendar\Google;
use App\Calendar\Source;
use App\Calendar\GoogleSource;
use PHPUnit\Framework\TestCase;
/**
@@ -21,8 +21,8 @@ class GoogleTest extends TestCase
public function testConstruct()
{
$sources = [
(new Source())->setId('foo')->setColor('#ccc'),
(new Source())->setId('bar')->setUri('sdsdfsdfsdfsdffd'),
new GoogleSource('foo', '', '#ccc'),
new GoogleSource('bar', 'sdsdfsdfsdfsdffd'),
];
$sut = new Google('qwertzuiop1234567890');

View File

@@ -0,0 +1,36 @@
<?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\Calendar;
use App\Calendar\RecentActivitiesSource;
use App\Calendar\TimesheetEntry;
use App\Entity\Timesheet;
use PHPUnit\Framework\TestCase;
/**
* @covers \App\Calendar\RecentActivitiesSource
*/
class RecentActivitiesSourceTest extends TestCase
{
public function testConstruct()
{
$entries = [new TimesheetEntry(new Timesheet(), '#cccccc')];
$sut = new RecentActivitiesSource($entries);
$this->assertEquals('calendar/drag-drop.html.twig', $sut->getBlockInclude());
$this->assertSame($entries, $sut->getEntries());
$this->assertEquals('POST', $sut->getMethod());
$this->assertEquals('post_timesheet', $sut->getRoute());
$this->assertEquals(['full' => 'true'], $sut->getRouteParams());
$this->assertEquals([], $sut->getRouteReplacer());
$this->assertEquals('recent.activities', $sut->getTitle());
}
}

View File

@@ -0,0 +1,99 @@
<?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\Calendar;
use App\Calendar\TimesheetEntry;
use App\Entity\Activity;
use App\Entity\Project;
use App\Entity\Tag;
use App\Entity\Timesheet;
use PHPUnit\Framework\TestCase;
/**
* @covers \App\Calendar\TimesheetEntry
*/
class TimesheetEntryTest extends TestCase
{
public function testConstruct()
{
$project = new Project();
$activity = new Activity();
$activity->setName('a wonderful activity!!');
$activity->setProject($project);
$timesheet = new Timesheet();
$timesheet->setActivity($activity);
$timesheet->setProject($project);
$timesheet->setDescription('hello foo bar');
$timesheet->addTag((new Tag())->setName('bulb'));
$timesheet->addTag((new Tag())->setName('action test'));
$expectedData = [
'description' => 'hello foo bar',
'activity' => null,
'project' => null,
'tags' => 'bulb,action test',
];
$sut = new TimesheetEntry($timesheet, '#cccccc');
$this->assertEquals('a wonderful activity!!', $sut->getTitle());
$this->assertEquals('#cccccc', $sut->getColor());
$this->assertSame($project, $sut->getProject());
$this->assertSame($activity, $sut->getActivity());
$this->assertEquals('dd_timesheet', $sut->getBlockName());
$this->assertEquals($expectedData, $sut->getData());
}
public function testEmpty()
{
$timesheet = new Timesheet();
$expectedData = [
'description' => null,
'activity' => null,
'project' => null,
'tags' => '',
];
$sut = new TimesheetEntry($timesheet, '#ddd');
$this->assertEquals('', $sut->getTitle());
$this->assertEquals('#ddd', $sut->getColor());
$this->assertNull($sut->getProject());
$this->assertNull($sut->getActivity());
$this->assertEquals($expectedData, $sut->getData());
}
public function testGetTitle()
{
$project = new Project();
$project->setName('sdfsdf');
$timesheet = new Timesheet();
$timesheet->setProject($project);
$sut = new TimesheetEntry($timesheet, '#ddd');
self::assertEquals('sdfsdf', $sut->getTitle());
$project = new Project();
$timesheet = new Timesheet();
$timesheet->setProject($project);
$sut = new TimesheetEntry($timesheet, '#ddd');
self::assertEquals('', $sut->getTitle());
$project = new Project();
$timesheet = new Timesheet();
$timesheet->setDescription('fooooo');
$timesheet->setProject($project);
$sut = new TimesheetEntry($timesheet, '#ddd');
self::assertEquals('fooooo', $sut->getTitle());
}
}

View File

@@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase;
/**
* @covers \App\Configuration\CalendarConfiguration
* @covers \App\Configuration\StringAccessibleConfigTrait
* @group legacy
*/
class CalendarConfigurationTest extends TestCase
{
@@ -41,6 +42,10 @@ class CalendarConfigurationTest extends TestCase
'begin' => '07:49',
'end' => '19:27'
],
'visibleHours' => [
'begin' => '09:00',
'end' => '21:34',
],
'day_limit' => 20,
'slot_duration' => '01:11:00',
'week_numbers' => false,
@@ -80,5 +85,9 @@ class CalendarConfigurationTest extends TestCase
$this->assertEquals('wertwertwegsdfbdf243w567fg8ihuon', $sut->getGoogleApiKey());
$sources = $sut->getGoogleSources();
$this->assertEquals(2, \count($sources));
self::assertTrue($sut->isShowWeekends());
self::assertEquals('09:00', $sut->getTimeframeBegin());
self::assertEquals('21:34', $sut->getTimeframeEnd());
}
}

View File

@@ -52,6 +52,34 @@ class SystemConfigurationTest extends TestCase
'country' => 'FR',
],
],
'calendar' => [
'businessHours' => [
'days' => [2, 4, 6],
'begin' => '07:49',
'end' => '19:27'
],
'day_limit' => 20,
'slot_duration' => '01:11:00',
'week_numbers' => false,
'visibleHours' => [
'begin' => '06:00:00',
'end' => '21:00:43',
],
'google' => [
'api_key' => 'wertwertwegsdfbdf243w567fg8ihuon',
'sources' => [
'holidays' => [
'id' => 'de.german#holiday@group.v.calendar.google.com',
'color' => '#ccc',
],
'holidays_en' => [
'id' => 'en.german#holiday@group.v.calendar.google.com',
'color' => '#fff',
],
]
],
'weekends' => true,
]
];
}
@@ -65,6 +93,7 @@ class SystemConfigurationTest extends TestCase
(new Configuration())->setName('timesheet.markdown_content')->setValue('1'),
(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'),
];
}
@@ -110,4 +139,30 @@ class SystemConfigurationTest extends TestCase
]);
$this->assertEquals('hello', $sut->find('foo'));
}
public function testCalendarWithoutLoader()
{
$sut = $this->getSut($this->getDefaultSettings(), []);
$this->assertEquals([2, 4, 6], $sut->getCalendarBusinessDays());
$this->assertEquals('07:49', $sut->getCalendarBusinessTimeBegin());
$this->assertEquals('19:27', $sut->getCalendarBusinessTimeEnd());
$this->assertEquals('06:00:00', $sut->getCalendarTimeframeBegin());
$this->assertEquals('21:00:43', $sut->getCalendarTimeframeEnd());
$this->assertEquals('01:11:00', $sut->getCalendarSlotDuration());
$this->assertEquals(20, $sut->getCalendarDayLimit());
$this->assertFalse($sut->isCalendarShowWeekNumbers());
$this->assertTrue($sut->isCalendarShowWeekends());
$this->assertEquals('wertwertwegsdfbdf243w567fg8ihuon', $sut->getCalendarGoogleApiKey());
$sources = $sut->getCalendarGoogleSources();
$this->assertEquals(2, \count($sources));
}
public function testCalendarWithLoader()
{
$sut = $this->getSut($this->getDefaultSettings(), $this->getDefaultLoaderSettings());
$this->assertEquals('00:30:00', $sut->getCalendarSlotDuration());
$sources = $sut->getCalendarGoogleSources();
$this->assertEquals(2, \count($sources));
}
}

View File

@@ -9,8 +9,9 @@
namespace App\Tests\Controller;
use App\Configuration\CalendarConfiguration;
use App\Configuration\SystemConfiguration;
use App\Tests\Configuration\TestConfigLoader;
use App\Tests\DataFixtures\TimesheetFixtures;
/**
* @group integration
@@ -25,21 +26,27 @@ class CalendarControllerTest extends ControllerBaseTest
public function testCalendarAction()
{
$client = $this->getClientForAuthenticatedUser();
$fixtures = new TimesheetFixtures($this->getUserByRole(), 10);
$fixtures->setStartDate(new \DateTime('-6 month'));
$this->importFixture($fixtures);
$this->request($client, '/calendar/');
$this->assertTrue($client->getResponse()->isSuccessful());
$crawler = $client->getCrawler();
$calendar = $crawler->filter('div#timesheet_calendar');
$this->assertEquals(1, $calendar->count());
$dragAndDropBoxes = $crawler->filter('div.box-body.drag-and-drop-source');
$this->assertEquals(1, $dragAndDropBoxes->count());
}
public function testCalendarActionWithGoogleSource()
{
$loader = new TestConfigLoader([]);
$config = new CalendarConfiguration($loader, $this->getDefaultSettings());
$config = new SystemConfiguration($loader, $this->getDefaultSettings());
$client = $this->getClientForAuthenticatedUser();
static::$kernel->getContainer()->set(CalendarConfiguration::class, $config);
static::$kernel->getContainer()->set(SystemConfiguration::class, $config);
$this->request($client, '/calendar/');
$this->assertTrue($client->getResponse()->isSuccessful());
@@ -57,32 +64,37 @@ class CalendarControllerTest extends ControllerBaseTest
protected function getDefaultSettings()
{
return [
'businessHours' => [
'days' => [2, 4, 6],
'begin' => '07:49',
'end' => '19:27'
'timesheet' => [
'default_begin' => '08:30:00',
],
'visibleHours' => [
'begin' => '07:49',
'end' => '19:27'
'calendar' => [
'businessHours' => [
'days' => [2, 4, 6],
'begin' => '07:49',
'end' => '19:27'
],
'visibleHours' => [
'begin' => '07:49',
'end' => '19:27'
],
'day_limit' => 20,
'week_numbers' => false,
'slot_duration' => '00:15:00',
'google' => [
'api_key' => 'wertwertwegsdfbdf243w567fg8ihuon',
'sources' => [
'holidays' => [
'id' => 'de.german#holiday@group.v.calendar.google.com',
'color' => '#ccc',
],
'holidays_en' => [
'id' => 'en.german#holiday@group.v.calendar.google.com',
'color' => '#fff',
],
]
],
'weekends' => true,
],
'day_limit' => 20,
'week_numbers' => false,
'slot_duration' => '00:15:00',
'google' => [
'api_key' => 'wertwertwegsdfbdf243w567fg8ihuon',
'sources' => [
'holidays' => [
'id' => 'de.german#holiday@group.v.calendar.google.com',
'color' => '#ccc',
],
'holidays_en' => [
'id' => 'en.german#holiday@group.v.calendar.google.com',
'color' => '#fff',
],
]
],
'weekends' => true,
];
}
}

View File

@@ -78,6 +78,16 @@ final class TimesheetFixtures extends Fixture
*/
private $tags = [];
public function __construct(?User $user = null, ?int $amount = null)
{
if ($user !== null) {
$this->setUser($user);
}
if ($amount !== null) {
$this->setAmount($amount);
}
}
public function setAllowEmptyDescriptions(bool $allowEmptyDescriptions): TimesheetFixtures
{
$this->allowEmptyDescriptions = $allowEmptyDescriptions;

View File

@@ -158,7 +158,7 @@ class AppExtensionTest extends TestCase
'select_type' => 'selectpicker',
'show_about' => true,
'chart' => [
'background_color' => 'rgba(0,115,183,0.7)',
'background_color' => '#3c8dbc',
'border_color' => '#3b8bba',
'grid_color' => 'rgba(0,0,0,.05)',
'height' => '200'
@@ -173,6 +173,9 @@ class AppExtensionTest extends TestCase
'auto_reload_datatable' => false,
'autocomplete_chars' => 3,
'tags_create' => true,
'calendar' => [
'background_color' => '#d2d6de',
],
],
'kimai.theme.select_type' => 'selectpicker',
'kimai.theme.show_about' => true,

View File

@@ -340,7 +340,7 @@ class ConfigurationTest extends TestCase
'auto_reload_datatable' => false,
'show_about' => true,
'chart' => [
'background_color' => 'rgba(0,115,183,0.7)',
'background_color' => '#3c8dbc',
'border_color' => '#3b8bba',
'grid_color' => 'rgba(0,0,0,.05)',
'height' => '200',
@@ -354,6 +354,9 @@ class ConfigurationTest extends TestCase
],
'autocomplete_chars' => 3,
'tags_create' => true,
'calendar' => [
'background_color' => '#d2d6de'
]
],
'industry' => [
'translation' => null,

View File

@@ -35,6 +35,7 @@ class ActivityTest extends TestCase
$this->assertTrue($sut->isVisible());
$this->assertTrue($sut->isGlobal());
$this->assertNull($sut->getColor());
self::assertFalse($sut->hasColor());
$this->assertEquals(0.0, $sut->getBudget());
$this->assertEquals(0, $sut->getTimeBudget());
$this->assertInstanceOf(Collection::class, $sut->getMetaFields());
@@ -56,11 +57,14 @@ class ActivityTest extends TestCase
$this->assertInstanceOf(Activity::class, $sut->setComment('hello world'));
$this->assertEquals('hello world', $sut->getComment());
self::assertFalse($sut->hasColor());
$this->assertInstanceOf(Activity::class, $sut->setColor('#fffccc'));
$this->assertEquals('#fffccc', $sut->getColor());
self::assertTrue($sut->hasColor());
$this->assertInstanceOf(Activity::class, $sut->setColor(Constants::DEFAULT_COLOR));
$this->assertNull($sut->getColor());
self::assertFalse($sut->hasColor());
$this->assertInstanceOf(Activity::class, $sut->setBudget(12345.67));
$this->assertEquals(12345.67, $sut->getBudget());

View File

@@ -48,6 +48,7 @@ class CustomerTest extends TestCase
self::assertNull($sut->getTimezone());
self::assertNull($sut->getColor());
self::assertFalse($sut->hasColor());
self::assertEquals(0.0, $sut->getBudget());
self::assertEquals(0, $sut->getTimeBudget());
self::assertInstanceOf(Collection::class, $sut->getMetaFields());
@@ -70,11 +71,14 @@ class CustomerTest extends TestCase
self::assertInstanceOf(Customer::class, $sut->setComment('hello world'));
self::assertEquals('hello world', $sut->getComment());
self::assertFalse($sut->hasColor());
self::assertInstanceOf(Customer::class, $sut->setColor('#fffccc'));
self::assertEquals('#fffccc', $sut->getColor());
self::assertTrue($sut->hasColor());
self::assertInstanceOf(Customer::class, $sut->setColor(Constants::DEFAULT_COLOR));
self::assertNull($sut->getColor());
self::assertFalse($sut->hasColor());
self::assertInstanceOf(Customer::class, $sut->setCompany('test company'));
self::assertEquals('test company', $sut->getCompany());

View File

@@ -38,6 +38,7 @@ class ProjectTest extends TestCase
self::assertNull($sut->getComment());
self::assertTrue($sut->isVisible());
self::assertNull($sut->getColor());
self::assertFalse($sut->hasColor());
self::assertEquals(0.0, $sut->getBudget());
self::assertEquals(0, $sut->getTimeBudget());
self::assertInstanceOf(Collection::class, $sut->getMetaFields());
@@ -80,11 +81,14 @@ class ProjectTest extends TestCase
self::assertInstanceOf(Project::class, $sut->setComment('a comment'));
self::assertEquals('a comment', $sut->getComment());
self::assertFalse($sut->hasColor());
self::assertInstanceOf(Project::class, $sut->setColor('#fffccc'));
self::assertEquals('#fffccc', $sut->getColor());
self::assertTrue($sut->hasColor());
self::assertInstanceOf(Project::class, $sut->setColor(Constants::DEFAULT_COLOR));
self::assertNull($sut->getColor());
self::assertFalse($sut->hasColor());
self::assertInstanceOf(Project::class, $sut->setVisible(false));
self::assertFalse($sut->isVisible());

View File

@@ -0,0 +1,73 @@
<?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\Event;
use App\Calendar\DragAndDropSource;
use App\Entity\User;
use App\Event\CalendarDragAndDropSourceEvent;
use PHPUnit\Framework\TestCase;
/**
* @covers \App\Event\CalendarDragAndDropSourceEvent
*/
class CalendarDragAndDropSourceEventTest extends TestCase
{
public function testGetterAndSetter()
{
$user = new User();
$user->setAlias('foo');
$sut = new CalendarDragAndDropSourceEvent($user);
self::assertSame($user, $sut->getUser());
self::assertIsArray($sut->getSources());
self::assertEmpty($sut->getSources());
self::assertInstanceOf(CalendarDragAndDropSourceEvent::class, $sut->addSource(new TestDragAndDropSource()));
self::assertCount(1, $sut->getSources());
}
}
class TestDragAndDropSource implements DragAndDropSource
{
public function getTitle(): string
{
return '';
}
public function getRoute(): string
{
return '';
}
public function getRouteParams(): array
{
return [];
}
public function getRouteReplacer(): array
{
return [];
}
public function getMethod(): string
{
return '';
}
public function getEntries(): array
{
return [];
}
public function getBlockInclude(): ?string
{
return null;
}
}

View File

@@ -0,0 +1,35 @@
<?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\Event;
use App\Calendar\GoogleSource;
use App\Entity\User;
use App\Event\CalendarGoogleSourceEvent;
use PHPUnit\Framework\TestCase;
/**
* @covers \App\Event\CalendarGoogleSourceEvent
*/
class CalendarGoogleSourceEventTest extends TestCase
{
public function testGetterAndSetter()
{
$user = new User();
$user->setAlias('foo');
$sut = new CalendarGoogleSourceEvent($user);
self::assertSame($user, $sut->getUser());
self::assertIsArray($sut->getSources());
self::assertEmpty($sut->getSources());
self::assertInstanceOf(CalendarGoogleSourceEvent::class, $sut->addSource(new GoogleSource('', '')));
self::assertCount(1, $sut->getSources());
}
}

View File

@@ -0,0 +1,35 @@
<?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\Event;
use App\Entity\Timesheet;
use App\Event\AbstractTimesheetEvent;
use App\Event\TimesheetRestartPostEvent;
/**
* @covers \App\Event\TimesheetRestartPostEvent
*/
class TimesheetRestartPostEventTest extends AbstractTimesheetEventTest
{
protected function createTimesheetEvent(Timesheet $timesheet): AbstractTimesheetEvent
{
return new TimesheetRestartPostEvent($timesheet, new Timesheet());
}
public function testGetOriginalTimesheet()
{
$newTimesheet = new Timesheet();
$originalTimesheet = new Timesheet();
$sut = new TimesheetRestartPostEvent($newTimesheet, $originalTimesheet);
self::assertSame($newTimesheet, $sut->getTimesheet());
self::assertSame($originalTimesheet, $sut->getOriginalTimesheet());
}
}

View File

@@ -0,0 +1,35 @@
<?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\Event;
use App\Entity\Timesheet;
use App\Event\AbstractTimesheetEvent;
use App\Event\TimesheetRestartPreEvent;
/**
* @covers \App\Event\TimesheetRestartPreEvent
*/
class TimesheetRestartPreEventTest extends AbstractTimesheetEventTest
{
protected function createTimesheetEvent(Timesheet $timesheet): AbstractTimesheetEvent
{
return new TimesheetRestartPreEvent($timesheet, new Timesheet());
}
public function testGetOriginalTimesheet()
{
$newTimesheet = new Timesheet();
$originalTimesheet = new Timesheet();
$sut = new TimesheetRestartPreEvent($newTimesheet, $originalTimesheet);
self::assertSame($newTimesheet, $sut->getTimesheet());
self::assertSame($originalTimesheet, $sut->getOriginalTimesheet());
}
}

View File

@@ -0,0 +1,61 @@
<?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\APIDateTimeType;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\Test\TypeTestCase;
/**
* @covers \App\Form\Type\APIDateTimeType
*/
class APIDateTimeTypeTest extends TypeTestCase
{
public function testSubmitValidData()
{
$data = ['date' => '2020-09-17T13:24:56'];
$model = new TypeTestModel(['date' => new \DateTime()]);
$form = $this->factory->createBuilder(FormType::class, $model);
$form->add('date', APIDateTimeType::class);
$form = $form->getForm();
$expected = new TypeTestModel([
'date' => new \DateTime('2020-09-17T13:24:56')
]);
$form->submit($data);
$this->assertTrue($form->isSynchronized());
$this->assertEquals($expected, $model);
}
public function testAttributes()
{
$data = ['date' => '2020-09-17T13:24:56'];
$model = new TypeTestModel(['date' => new \DateTime()]);
$form = $this->factory->createBuilder(FormType::class, $model);
$form->add('date', APIDateTimeType::class, [
'model_timezone' => 'Pacific/Tongatapu',
'view_timezone' => 'Pacific/Tongatapu',
]);
$form = $form->getForm();
$expected = new TypeTestModel([
'date' => new \DateTime('2020-09-17T13:24:56', new \DateTimeZone('Pacific/Tongatapu'))
]);
$form->submit($data);
$this->assertTrue($form->isSynchronized());
$this->assertEquals($expected, $model);
}
}

View File

@@ -0,0 +1,38 @@
<?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;
class TypeTestModel
{
private $fields = [];
public function __construct(array $fields = [])
{
$this->fields = $fields;
}
public function __set($name, $value)
{
if (!isset($this->fields[$name])) {
throw new \InvalidArgumentException('Unknown field: ' . $name);
}
$this->fields[$name] = $value;
}
public function __get($name)
{
if (!isset($this->fields[$name])) {
throw new \InvalidArgumentException('Unknown field: ' . $name);
}
return $this->fields[$name];
}
}

View File

@@ -43,6 +43,9 @@ class TimesheetRepositoryTest extends AbstractRepositoryTest
$this->assertIsArray($result);
}
/**
* @group legacy
*/
public function testStoppedEntriesCannotBeStoppedAgain()
{
$em = $this->getEntityManager();
@@ -72,6 +75,9 @@ class TimesheetRepositoryTest extends AbstractRepositoryTest
$repository->stopRecording($entities[0]);
}
/**
* @group legacy
*/
public function testStopRecording()
{
$em = $this->getEntityManager();

View File

@@ -0,0 +1,244 @@
<?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\Timesheet;
use App\Configuration\TimesheetConfiguration;
use App\Entity\Timesheet;
use App\Event\TimesheetCreatePostEvent;
use App\Event\TimesheetCreatePreEvent;
use App\Event\TimesheetDeleteMultiplePreEvent;
use App\Event\TimesheetDeletePreEvent;
use App\Event\TimesheetRestartPostEvent;
use App\Event\TimesheetRestartPreEvent;
use App\Repository\TimesheetRepository;
use App\Timesheet\TimesheetService;
use App\Timesheet\TrackingModeService;
use App\Validator\ValidationException;
use App\Validator\ValidationFailedException;
use PHPUnit\Framework\TestCase;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\Validator\ValidatorInterface;
/**
* @covers \App\Timesheet\TimesheetService
*/
class TimesheetServiceTest extends TestCase
{
private function getSut(
?AuthorizationCheckerInterface $authorizationChecker = null,
?EventDispatcherInterface $dispatcher = null,
?ValidatorInterface $validator = null,
?TimesheetRepository $repository = null
): TimesheetService {
$configuration = $this->createMock(TimesheetConfiguration::class);
$configuration->method('getActiveEntriesHardLimit')->willReturn(1);
if ($repository === null) {
$repository = $this->createMock(TimesheetRepository::class);
$repository->method('getActiveEntries')->willReturn([]);
}
$service = new TrackingModeService($configuration, []);
if ($dispatcher === null) {
$dispatcher = $this->createMock(EventDispatcherInterface::class);
}
if ($authorizationChecker === null) {
$authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class);
}
if ($validator === null) {
$validator = $this->createMock(ValidatorInterface::class);
$validator->method('validate')->willReturn(new ConstraintViolationList());
}
$service = new TimesheetService($configuration, $repository, $service, $dispatcher, $authorizationChecker, $validator);
return $service;
}
public function testCannotSavePersistedTimesheetAsNew()
{
$timesheet = $this->createMock(Timesheet::class);
$timesheet->expects($this->once())->method('getId')->willReturn(1);
$sut = $this->getSut();
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Cannot create timesheet, already persisted');
$sut->saveNewTimesheet($timesheet);
}
public function testCannotStartTimesheet()
{
$authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class);
$authorizationChecker->expects($this->once())->method('isGranted')->willReturn(false);
$sut = $this->getSut($authorizationChecker);
$this->expectException(AccessDeniedHttpException::class);
$this->expectExceptionMessage('You are not allowed to start this timesheet record');
$sut->saveNewTimesheet(new Timesheet());
}
public function testSaveNewTimesheetHasValidationError()
{
$authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class);
$authorizationChecker->expects($this->once())->method('isGranted')->willReturn(true);
$constraints = new ConstraintViolationList();
$constraints->add(new ConstraintViolation('toooo many tests', 'abc.def', [], '$root', 'begin', 4, null, null, null, '$cause'));
$validator = $this->createMock(ValidatorInterface::class);
$validator->method('validate')->willReturn($constraints);
$sut = $this->getSut($authorizationChecker, null, $validator);
$this->expectException(ValidationFailedException::class);
$this->expectExceptionMessage('Validation Failed');
$sut->saveNewTimesheet(new Timesheet());
}
public function testSaveNewTimesheetStopsActiveRecords()
{
$authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class);
$authorizationChecker->expects($this->once())->method('isGranted')->willReturn(true);
$timesheet1 = $this->createMock(Timesheet::class);
$timesheet1->method('getId')->willReturn(1);
$timesheet1->method('getBegin')->willReturn(new \DateTime());
$timesheet1->expects($this->once())->method('setBegin');
$timesheet1->expects($this->once())->method('setEnd');
$timesheet2 = $this->createMock(Timesheet::class);
$timesheet2->method('getId')->willReturn(1);
$timesheet2->method('getBegin')->willReturn(new \DateTime());
$timesheet2->expects($this->once())->method('setBegin');
$timesheet2->expects($this->once())->method('setEnd');
$repository = $this->createMock(TimesheetRepository::class);
$repository->method('getActiveEntries')->willReturn([$timesheet1, $timesheet2]);
$sut = $this->getSut($authorizationChecker, null, null, $repository);
$sut->saveNewTimesheet(new Timesheet());
}
public function testCannotRestartedPersistedTimesheet()
{
$timesheet = $this->createMock(Timesheet::class);
$timesheet->expects($this->once())->method('getId')->willReturn(1);
$dispatcher = $this->createMock(EventDispatcherInterface::class);
$dispatcher->method('dispatch')->willReturnCallback(function ($event) {
self::assertInstanceOf(TimesheetRestartPreEvent::class, $event);
});
$sut = $this->getSut(null, $dispatcher);
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Cannot create timesheet, already persisted');
$sut->restartTimesheet($timesheet, new Timesheet());
}
public function testRestartTimesheetDispatchesTwoEvents()
{
$timesheet = $this->createMock(Timesheet::class);
$authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class);
$authorizationChecker->expects($this->once())->method('isGranted')->willReturn(true);
$dispatcher = $this->createMock(EventDispatcherInterface::class);
$dispatcher->method('dispatch')->willReturnCallback(function ($event) {
static $counter = 0;
switch ($counter++) {
case 0:
self::assertInstanceOf(TimesheetRestartPreEvent::class, $event);
break;
case 1:
self::assertInstanceOf(TimesheetCreatePreEvent::class, $event);
break;
case 2:
self::assertInstanceOf(TimesheetCreatePostEvent::class, $event);
break;
case 3:
self::assertInstanceOf(TimesheetRestartPostEvent::class, $event);
break;
}
});
$sut = $this->getSut($authorizationChecker, $dispatcher);
$sut->restartTimesheet($timesheet, new Timesheet());
}
public function testPreparePersistedTimesheetAsNew()
{
$timesheet = $this->createMock(Timesheet::class);
$timesheet->expects($this->once())->method('getId')->willReturn(1);
$sut = $this->getSut();
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Cannot prepare timesheet, already persisted');
$sut->prepareNewTimesheet($timesheet);
}
public function testStoppedEntriesCannotBeStoppedAgain()
{
$timesheet = new Timesheet();
$timesheet->setEnd(new \DateTime());
$sut = $this->getSut();
$this->expectException(ValidationException::class);
$this->expectExceptionMessage('Timesheet entry already stopped');
$sut->stopTimesheet($timesheet);
}
public function testDeleteDispatchesEvent()
{
$timesheet = new Timesheet();
$dispatcher = $this->createMock(EventDispatcherInterface::class);
$dispatcher->method('dispatch')->willReturnCallback(function ($event) use ($timesheet) {
self::assertInstanceOf(TimesheetDeletePreEvent::class, $event);
/* @var TimesheetDeletePreEvent $event */
self::assertSame($timesheet, $event->getTimesheet());
});
$sut = $this->getSut(null, $dispatcher);
$sut->deleteTimesheet($timesheet);
}
public function testDeleteMultipleDispatchesEvent()
{
$timesheets = [new Timesheet(), new Timesheet()];
$dispatcher = $this->createMock(EventDispatcherInterface::class);
$dispatcher->method('dispatch')->willReturnCallback(function ($event) use ($timesheets) {
self::assertInstanceOf(TimesheetDeleteMultiplePreEvent::class, $event);
/* @var TimesheetDeleteMultiplePreEvent $event */
self::assertSame($timesheets, $event->getTimesheets());
});
$sut = $this->getSut(null, $dispatcher);
$sut->deleteMultipleTimesheets($timesheets);
}
}

View File

@@ -9,9 +9,8 @@
namespace App\Tests\Twig;
use App\Constants;
use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\Project;
use App\Entity\User;
use App\Twig\Extensions;
use PHPUnit\Framework\TestCase;
@@ -30,7 +29,7 @@ class ExtensionsTest extends TestCase
public function testGetFilters()
{
$filters = ['docu_link', 'multiline_indent', 'color'];
$filters = ['docu_link', 'multiline_indent', 'color', 'font_contrast'];
$sut = $this->getSut();
$twigFilters = $sut->getFilters();
$this->assertCount(\count($filters), $twigFilters);
@@ -122,39 +121,30 @@ sdfsdf' . PHP_EOL . "\n" .
self::assertEquals(implode("\n", $expected), $sut->multilineIndent($string, $indent));
}
/**
* Just a very short test, as this delegates to Utils/Color
*/
public function testColor()
{
$sut = $this->getSut();
$globalActivity = new Activity();
self::assertNull($sut->color($globalActivity));
self::assertEquals(Constants::DEFAULT_COLOR, $sut->color($globalActivity, true));
$globalActivity->setColor('#000001');
self::assertEquals('#000001', $sut->color($globalActivity));
self::assertEquals('#000001', $sut->color($globalActivity, true));
}
$customer = new Customer();
self::assertNull($sut->color($customer));
/**
* Just a very short test, as this delegates to Utils/Color
*/
public function testFontContrast()
{
$sut = $this->getSut();
$customer->setColor('#000004');
self::assertEquals('#000004', $sut->color($customer));
$project = new Project();
self::assertNull($sut->color($project));
$project->setCustomer($customer);
self::assertEquals('#000004', $sut->color($project));
$project->setColor('#000003');
self::assertEquals('#000003', $sut->color($project));
$activity = new Activity();
self::assertNull($sut->color($activity));
$activity->setProject($project);
self::assertEquals('#000003', $sut->color($activity));
$activity->setColor('#000002');
self::assertEquals('#000002', $sut->color($activity));
self::assertEquals('#000000', $sut->calculateFontContrastColor('#ccc'));
}
public function testIsoDayByName()

111
tests/Utils/ColorTest.php Normal file
View File

@@ -0,0 +1,111 @@
<?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\Utils;
use App\Constants;
use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\Project;
use App\Entity\Timesheet;
use App\Utils\Color;
use PHPUnit\Framework\TestCase;
/**
* @covers \App\Utils\Color
*/
class ColorTest extends TestCase
{
public function testGetColorAndGetTimesheetColor()
{
$sut = new Color();
$globalActivity = new Activity();
self::assertNull($sut->getColor($globalActivity));
$globalActivity->setColor('#000001');
self::assertEquals('#000001', $sut->getColor($globalActivity));
$customer = new Customer();
self::assertNull($sut->getColor($customer));
$customer->setColor('#000004');
self::assertEquals('#000004', $sut->getColor($customer));
$project = new Project();
self::assertNull($sut->getColor($project));
$project->setCustomer($customer);
self::assertEquals('#000004', $sut->getColor($project));
$project->setColor('#000003');
self::assertEquals('#000003', $sut->getColor($project));
$activity = new Activity();
self::assertNull($sut->getColor($activity));
$timesheet = new Timesheet();
$timesheet->setActivity($activity);
$timesheet->setProject($project);
self::assertEquals('#000003', $sut->getColor($timesheet));
self::assertEquals('#000003', $sut->getTimesheetColor($timesheet));
$activity->setProject($project);
self::assertEquals('#000003', $sut->getColor($activity));
$timesheet = new Timesheet();
$timesheet->setActivity($activity);
$timesheet->setProject($project);
self::assertEquals('#000003', $sut->getColor($timesheet));
self::assertEquals('#000003', $sut->getTimesheetColor($timesheet));
$activity->setColor('#000002');
self::assertEquals('#000002', $sut->getColor($activity));
$timesheet = new Timesheet();
$timesheet->setActivity($activity);
$timesheet->setProject($project);
self::assertEquals('#000002', $sut->getColor($timesheet));
self::assertEquals('#000002', $sut->getTimesheetColor($timesheet));
$timesheet = new Timesheet();
self::assertEquals(Constants::DEFAULT_COLOR, $sut->getTimesheetColor($timesheet));
self::assertNull($sut->getColor($timesheet));
self::assertEquals(Constants::DEFAULT_COLOR, $sut->getColor($timesheet, true));
$timesheet = new Timesheet();
$timesheet->setActivity(new Activity());
$project = new Project();
$customer = new Customer();
$customer->setColor('#123456');
$project->setCustomer($customer);
$timesheet->setProject($project);
self::assertEquals('#123456', $sut->getColor($timesheet, true));
}
public function testGetFontContrastColor()
{
$sut = new Color();
$this->assertEquals('#ffffff', $sut->getFontContrastColor('#666'));
$this->assertEquals('#ffffff', $sut->getFontContrastColor('#666666'));
$this->assertEquals('#ffffff', $sut->getFontContrastColor('#000000'));
$this->assertEquals('#000000', $sut->getFontContrastColor('#ccc'));
$this->assertEquals('#000000', $sut->getFontContrastColor('#cccccc'));
$this->assertEquals('#000000', $sut->getFontContrastColor('#ffffff'));
}
public function testGetFontContrastColorThrowsExceptionOnNonHexadecimalColor()
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Invalid color code given, only #hexadecimal is supported.');
$sut = new Color();
$sut->getFontContrastColor('000000');
}
}

View File

@@ -0,0 +1,33 @@
<?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;
use App\Validator\ValidationException;
use PHPUnit\Framework\TestCase;
/**
* @covers \App\Validator\ValidationException
*/
class ValidationExceptionTest extends TestCase
{
public function testException()
{
$sut = new ValidationException();
self::assertEquals(400, $sut->getCode());
self::assertEquals('Validation failed', $sut->getMessage());
}
public function testConstruct()
{
$sut = new ValidationException('Something went wrong');
self::assertEquals(400, $sut->getCode());
self::assertEquals('Something went wrong', $sut->getMessage());
}
}

View File

@@ -0,0 +1,38 @@
<?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;
use App\Validator\ValidationFailedException;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Validator\ConstraintViolationList;
/**
* @covers \App\Validator\ValidationFailedException
*/
class ValidationFailedExceptionTest extends TestCase
{
public function testException()
{
$list = new ConstraintViolationList();
$sut = new ValidationFailedException($list);
self::assertEquals(400, $sut->getCode());
self::assertEquals('Validation failed', $sut->getMessage());
self::assertSame($list, $sut->getViolations());
}
public function testConstruct()
{
$list = new ConstraintViolationList();
$sut = new ValidationFailedException($list, 'Something went wrong');
self::assertEquals(400, $sut->getCode());
self::assertEquals('Something went wrong', $sut->getMessage());
self::assertSame($list, $sut->getViolations());
}
}