Added timesheet-calendar view (#236)
This commit is contained in:
40
tests/Calendar/ConfigTest.php
Normal file
40
tests/Calendar/ConfigTest.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?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\Config;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \App\Calendar\Config
|
||||
*/
|
||||
class ConfigTest extends TestCase
|
||||
{
|
||||
public function testConstruct()
|
||||
{
|
||||
$config = [
|
||||
'businessHours' => [
|
||||
'days' => [0, 99, 127],
|
||||
'begin' => '07:49',
|
||||
'end' => '19:27'
|
||||
],
|
||||
'day_limit' => 20,
|
||||
'week_numbers' => false,
|
||||
];
|
||||
|
||||
$sut = new Config($config);
|
||||
|
||||
$this->assertEquals([0, 99, 127], $sut->getBusinessDays());
|
||||
$this->assertEquals('07:49', $sut->getBusinessTimeBegin());
|
||||
$this->assertEquals('19:27', $sut->getBusinessTimeEnd());
|
||||
$this->assertEquals(20, $sut->getDayLimit());
|
||||
$this->assertFalse($sut->isShowWeekNumbers());
|
||||
}
|
||||
}
|
||||
38
tests/Calendar/GoogleTest.php
Normal file
38
tests/Calendar/GoogleTest.php
Normal 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\Calendar;
|
||||
|
||||
use App\Calendar\Google;
|
||||
use App\Calendar\Source;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \App\Calendar\Google
|
||||
*/
|
||||
class GoogleTest extends TestCase
|
||||
{
|
||||
public function testConstruct()
|
||||
{
|
||||
$sources = [
|
||||
(new Source())->setId('foo')->setColor('#ccc'),
|
||||
(new Source())->setId('bar')->setUri('sdsdfsdfsdfsdffd'),
|
||||
];
|
||||
|
||||
$sut = new Google('qwertzuiop1234567890');
|
||||
|
||||
$this->assertEquals([], $sut->getSources());
|
||||
$this->assertEquals('qwertzuiop1234567890', $sut->getApiKey());
|
||||
|
||||
$sut = new Google('ewa6347865fg908ouhpoihui7f56', $sources);
|
||||
|
||||
$this->assertEquals($sources, $sut->getSources());
|
||||
$this->assertEquals('ewa6347865fg908ouhpoihui7f56', $sut->getApiKey());
|
||||
}
|
||||
}
|
||||
64
tests/Calendar/ServiceTest.php
Normal file
64
tests/Calendar/ServiceTest.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?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\Config;
|
||||
use App\Calendar\Google;
|
||||
use App\Calendar\Service;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \App\Calendar\Service
|
||||
*/
|
||||
class ServiceTest extends TestCase
|
||||
{
|
||||
public function testConstruct()
|
||||
{
|
||||
$config = [
|
||||
'businessHours' => [
|
||||
'days' => [2, 4, 6],
|
||||
'begin' => '07:49',
|
||||
'end' => '19:27'
|
||||
],
|
||||
'day_limit' => 20,
|
||||
'week_numbers' => false,
|
||||
'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',
|
||||
],
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$sut = new Service($config);
|
||||
|
||||
$config = $sut->getConfig();
|
||||
$this->assertInstanceOf(Config::class, $config);
|
||||
$this->assertEquals([2, 4, 6], $config->getBusinessDays());
|
||||
|
||||
$google = $sut->getGoogle();
|
||||
$this->assertInstanceOf(Google::class, $google);
|
||||
$this->assertEquals('wertwertwegsdfbdf243w567fg8ihuon', $google->getApiKey());
|
||||
|
||||
$sources = $google->getSources();
|
||||
$this->assertEquals(2, count($sources));
|
||||
$this->assertEquals('holidays', $sources[0]->getId());
|
||||
$this->assertEquals('#ccc', $sources[0]->getColor());
|
||||
$this->assertEquals('holidays_en', $sources[1]->getId());
|
||||
$this->assertEquals('#fff', $sources[1]->getColor());
|
||||
}
|
||||
}
|
||||
36
tests/Calendar/SourceTest.php
Normal file
36
tests/Calendar/SourceTest.php
Normal 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\Source;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \App\Calendar\Source
|
||||
*/
|
||||
class SourceTest 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'));
|
||||
|
||||
$this->assertEquals('0815', $sut->getId());
|
||||
$this->assertEquals('#fffccc', $sut->getColor());
|
||||
$this->assertEquals('askdjfhlaksjdhflaksjhdflkjasdlkfjh', $sut->getUri());
|
||||
}
|
||||
}
|
||||
76
tests/Controller/CalendarControllerTest.php
Normal file
76
tests/Controller/CalendarControllerTest.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?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\Controller;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Tests\DataFixtures\TimesheetFixtures;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \App\Controller\CalendarController
|
||||
* @group integration
|
||||
* @group legacy
|
||||
*/
|
||||
class CalendarControllerTest extends ControllerBaseTest
|
||||
{
|
||||
public function testIsSecure()
|
||||
{
|
||||
$this->assertUrlIsSecured('/calendar/');
|
||||
}
|
||||
|
||||
public function testCalendarAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser();
|
||||
$this->request($client, '/calendar/');
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
|
||||
$crawler = $client->getCrawler();
|
||||
$calendar = $crawler->filter('div#calendar');
|
||||
}
|
||||
|
||||
public function testCalendarEntriesAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
|
||||
$em = $client->getContainer()->get('doctrine.orm.entity_manager');
|
||||
|
||||
$fixture = new TimesheetFixtures();
|
||||
$fixture->setAmount(10);
|
||||
$fixture->setUser($this->getUserByRole($em, User::ROLE_USER));
|
||||
$fixture->setStartDate('2017-05-01');
|
||||
$this->importFixture($em, $fixture);
|
||||
|
||||
$this->request($client, '/calendar/user');
|
||||
$response = $client->getResponse();
|
||||
$this->assertTrue($response->isSuccessful());
|
||||
$json = json_decode($response->getContent(), true);
|
||||
$this->assertInternalType('array', $json);
|
||||
$this->assertEmpty($json);
|
||||
}
|
||||
|
||||
public function testCalendarEntriesActionWithStartAndEndDate()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
|
||||
$em = $client->getContainer()->get('doctrine.orm.entity_manager');
|
||||
|
||||
$fixture = new TimesheetFixtures();
|
||||
$fixture->setAmount(10);
|
||||
$fixture->setUser($this->getUserByRole($em, User::ROLE_USER));
|
||||
$fixture->setStartDate('2017-05-01');
|
||||
$this->importFixture($em, $fixture);
|
||||
|
||||
$client = $this->getClientForAuthenticatedUser();
|
||||
$this->request($client, '/calendar/user?start=2017-05-01&end=2017-05-30');
|
||||
$response = $client->getResponse();
|
||||
$this->assertTrue($response->isSuccessful());
|
||||
$json = json_decode($response->getContent(), true);
|
||||
$this->assertInternalType('array', $json);
|
||||
$this->assertNotEmpty($json);
|
||||
$this->assertEquals(10, count($json));
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,10 @@ namespace App\Tests\Controller;
|
||||
|
||||
use App\DataFixtures\UserFixtures;
|
||||
use App\Entity\User;
|
||||
use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||
use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
|
||||
use Doctrine\Common\DataFixtures\Loader;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Symfony\Bundle\FrameworkBundle\Client;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
@@ -208,4 +212,50 @@ abstract class ControllerBaseTest extends WebTestCase
|
||||
$this->assertGreaterThanOrEqual(1, count($validation), 'Form field has no validation message: ' . $name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EntityManager $em
|
||||
* @param Fixture $fixture
|
||||
*/
|
||||
protected function importFixture(EntityManager $em, Fixture $fixture)
|
||||
{
|
||||
$loader = new Loader();
|
||||
$loader->addFixture($fixture);
|
||||
|
||||
$executor = new ORMExecutor($em, null);
|
||||
$executor->execute($loader->getFixtures(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EntityManager $em
|
||||
* @param string $role
|
||||
* @return User|null
|
||||
*/
|
||||
protected function getUserByRole(EntityManager $em, string $role = User::ROLE_USER)
|
||||
{
|
||||
$name = null;
|
||||
|
||||
switch ($role) {
|
||||
case User::ROLE_SUPER_ADMIN:
|
||||
$name = UserFixtures::USERNAME_SUPER_ADMIN;
|
||||
break;
|
||||
|
||||
case User::ROLE_ADMIN:
|
||||
$name = UserFixtures::USERNAME_ADMIN;
|
||||
break;
|
||||
|
||||
case User::ROLE_TEAMLEAD:
|
||||
$name = UserFixtures::USERNAME_TEAMLEAD;
|
||||
break;
|
||||
|
||||
case User::ROLE_USER:
|
||||
$name = UserFixtures::USERNAME_USER;
|
||||
break;
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
return $em->getRepository(User::class)->findOneBy(['username' => $name]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace App\Tests\Controller;
|
||||
/**
|
||||
* @coversDefaultClass \App\Controller\TimesheetController
|
||||
* @group integration
|
||||
* @group legacy
|
||||
*/
|
||||
class TimesheetControllerTest extends ControllerBaseTest
|
||||
{
|
||||
@@ -25,5 +26,6 @@ class TimesheetControllerTest extends ControllerBaseTest
|
||||
$client = $this->getClientForAuthenticatedUser();
|
||||
$this->request($client, '/timesheet/');
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
$this->assertHasDataTable($client);
|
||||
}
|
||||
}
|
||||
|
||||
171
tests/DataFixtures/TimesheetFixtures.php
Normal file
171
tests/DataFixtures/TimesheetFixtures.php
Normal file
@@ -0,0 +1,171 @@
|
||||
<?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\DataFixtures;
|
||||
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\Timesheet;
|
||||
use App\Entity\User;
|
||||
use App\Entity\UserPreference;
|
||||
use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Faker\Factory;
|
||||
|
||||
/**
|
||||
* Defines the sample data to load in during controller tests.
|
||||
*/
|
||||
class TimesheetFixtures extends Fixture
|
||||
{
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $amount = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $running = 0;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $startDate = '2018-04-01';
|
||||
|
||||
/**
|
||||
* @param string $date
|
||||
*/
|
||||
public function setStartDate($date)
|
||||
{
|
||||
$this->startDate = $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $amount
|
||||
*/
|
||||
public function setAmountRunning($amount)
|
||||
{
|
||||
$this->running = $amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $amount
|
||||
*/
|
||||
public function setAmount($amount)
|
||||
{
|
||||
$this->amount = $amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*/
|
||||
public function setUser(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
$activities = $this->getAllActivities($manager);
|
||||
$faker = Factory::create();
|
||||
$user = $this->user;
|
||||
|
||||
// random amount of timesheet entries for every user
|
||||
for ($i = 0; $i < $this->amount; $i++) {
|
||||
$entry = $this->createTimesheetEntry(
|
||||
$user,
|
||||
$activities[array_rand($activities)],
|
||||
($i % 3 == 0 ? $faker->text : ''),
|
||||
$this->getDateTime($i)
|
||||
);
|
||||
|
||||
$manager->persist($entry);
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $this->running; $i++) {
|
||||
$entry = $this->createTimesheetEntry(
|
||||
$user,
|
||||
$activities[array_rand($activities)],
|
||||
$faker->text,
|
||||
$this->getDateTime($i)
|
||||
);
|
||||
$manager->persist($entry);
|
||||
}
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $i
|
||||
* @return bool|\DateTime
|
||||
*/
|
||||
protected function getDateTime($i)
|
||||
{
|
||||
$start = \DateTime::createFromFormat('Y-m-d', $this->startDate);
|
||||
$start->modify("+ $i days");
|
||||
$start->modify('+ ' . rand(1, 172.800) . ' seconds'); // up to 2 days
|
||||
return $start;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ObjectManager $manager
|
||||
* @return Activity[]
|
||||
*/
|
||||
protected function getAllActivities(ObjectManager $manager)
|
||||
{
|
||||
$all = [];
|
||||
/* @var User[] $entries */
|
||||
$entries = $manager->getRepository(Activity::class)->findAll();
|
||||
foreach ($entries as $temp) {
|
||||
$all[$temp->getId()] = $temp;
|
||||
}
|
||||
|
||||
return $all;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param Activity $activity
|
||||
* @param $description
|
||||
* @param \DateTime $start
|
||||
* @param bool $setEndDate
|
||||
* @return Timesheet
|
||||
*/
|
||||
private function createTimesheetEntry(User $user, Activity $activity, $description, \DateTime $start, $setEndDate = true)
|
||||
{
|
||||
$end = clone $start;
|
||||
$end = $end->modify('+ ' . (rand(1, 172800)) . ' seconds');
|
||||
|
||||
$duration = $end->getTimestamp() - $start->getTimestamp();
|
||||
$rate = $user->getPreferenceValue(UserPreference::HOURLY_RATE);
|
||||
|
||||
$entry = new Timesheet();
|
||||
$entry
|
||||
->setActivity($activity)
|
||||
->setDescription($description)
|
||||
->setUser($user)
|
||||
->setRate(round(($duration / 3600) * $rate))
|
||||
->setBegin($start);
|
||||
|
||||
if ($setEndDate) {
|
||||
$entry
|
||||
->setEnd($end)
|
||||
->setDuration($duration);
|
||||
}
|
||||
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
@@ -185,6 +185,7 @@ class ExtensionsTest extends TestCase
|
||||
'list' => 'fas fa-list',
|
||||
'print' => 'fas fa-print',
|
||||
'visibility' => 'far fa-eye',
|
||||
'calendar' => 'far fa-calendar-alt',
|
||||
];
|
||||
|
||||
$sut = $this->getSut('en');
|
||||
|
||||
Reference in New Issue
Block a user