Added timesheet-calendar view (#236)

This commit is contained in:
Kevin Papst
2018-07-27 20:19:56 +02:00
committed by GitHub
parent 5ccc1c991b
commit e6f8bc8ae2
40 changed files with 1286 additions and 49 deletions

View 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());
}
}

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\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());
}
}

View 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());
}
}

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\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());
}
}

View 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));
}
}

View File

@@ -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]);
}
}

View File

@@ -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);
}
}

View 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;
}
}

View File

@@ -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');