monthly budget, monthly report, unified report calculation (#2684)
This commit is contained in:
@@ -381,6 +381,7 @@ abstract class APIControllerBaseTest extends ControllerBaseTest
|
||||
'budget' => 'float',
|
||||
'timeBudget' => 'int',
|
||||
'vatId' => '@string', // since 1.10
|
||||
'budgetType' => '@string', // since 1.15
|
||||
];
|
||||
|
||||
// if a project is embedded
|
||||
@@ -436,6 +437,7 @@ abstract class APIControllerBaseTest extends ControllerBaseTest
|
||||
'timeBudget' => 'int',
|
||||
'orderNumber' => '@string',
|
||||
'orderDate' => '@datetime',
|
||||
'budgetType' => '@string', // since 1.15
|
||||
];
|
||||
|
||||
// embedded activities
|
||||
@@ -484,6 +486,7 @@ abstract class APIControllerBaseTest extends ControllerBaseTest
|
||||
'budget' => 'float',
|
||||
'timeBudget' => 'int',
|
||||
'teams' => ['result' => 'array', 'type' => 'Team'],
|
||||
'budgetType' => '@string', // since 1.15
|
||||
];
|
||||
|
||||
case 'TimesheetEntity':
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<?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\Reporting;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Tests\Controller\ControllerBaseTest;
|
||||
use App\Tests\DataFixtures\ActivityFixtures;
|
||||
use App\Tests\DataFixtures\CustomerFixtures;
|
||||
use App\Tests\DataFixtures\ProjectFixtures;
|
||||
use App\Tests\DataFixtures\TimesheetFixtures;
|
||||
|
||||
/**
|
||||
* @group integration
|
||||
*/
|
||||
class ProjectDateRangeControllerTest extends ControllerBaseTest
|
||||
{
|
||||
public function testReportIsSecure()
|
||||
{
|
||||
$this->assertUrlIsSecured('/reporting/project_daterange');
|
||||
}
|
||||
|
||||
public function testReport()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
|
||||
$customers = new CustomerFixtures();
|
||||
$customers->setIsVisible(true);
|
||||
$customers->setAmount(1);
|
||||
$customers = $this->importFixture($customers);
|
||||
|
||||
$projects = new ProjectFixtures();
|
||||
$projects->setCustomers($customers);
|
||||
$projects->setAmount(2);
|
||||
$projects->setIsVisible(true);
|
||||
$this->importFixture($projects);
|
||||
|
||||
$activities = new ActivityFixtures();
|
||||
$activities->setAmount(5);
|
||||
$activities->setIsGlobal(true);
|
||||
$activities = $this->importFixture($activities);
|
||||
|
||||
$timesheets = new TimesheetFixtures();
|
||||
$timesheets->setAmount(50);
|
||||
$timesheets->setActivities($activities);
|
||||
$timesheets->setUser($this->getUserByRole(User::ROLE_TEAMLEAD));
|
||||
$this->importFixture($timesheets);
|
||||
|
||||
$this->assertAccessIsGranted($client, '/reporting/project_daterange');
|
||||
self::assertStringContainsString('<div class="box-body project_daterange_reporting-box', $client->getResponse()->getContent());
|
||||
$rows = $client->getCrawler()->filterXPath("//table[contains(@class, 'dataTable')]/tbody/tr[not(@class='summary')]");
|
||||
self::assertGreaterThan(0, $rows->count());
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ use App\Tests\DataFixtures\TimesheetFixtures;
|
||||
/**
|
||||
* @group integration
|
||||
*/
|
||||
class InactiveProjectControllerTest extends ControllerBaseTest
|
||||
class ProjectInactiveControllerTest extends ControllerBaseTest
|
||||
{
|
||||
public function testReportIsSecure()
|
||||
{
|
||||
@@ -98,13 +98,11 @@ final class ProjectFixtures implements TestFixture
|
||||
$visible = $this->isVisible;
|
||||
}
|
||||
$project = new Project();
|
||||
$project
|
||||
->setName($faker->catchPhrase . ($visible ? '' : ' (x)'))
|
||||
->setBudget(rand(0, 10000))
|
||||
->setComment($faker->text)
|
||||
->setCustomer($customers[array_rand($customers)])
|
||||
->setVisible($visible)
|
||||
;
|
||||
$project->setName($faker->catchPhrase . ($visible ? '' : ' (x)'));
|
||||
$project->setBudget(rand(0, 10000));
|
||||
$project->setComment($faker->text);
|
||||
$project->setCustomer($customers[array_rand($customers)]);
|
||||
$project->setVisible($visible);
|
||||
|
||||
if (null !== $this->callback) {
|
||||
\call_user_func($this->callback, $project);
|
||||
|
||||
48
tests/Entity/AbstractEntityTest.php
Normal file
48
tests/Entity/AbstractEntityTest.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?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\Entity;
|
||||
|
||||
use App\Entity\EntityWithBudget;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
abstract class AbstractEntityTest extends TestCase
|
||||
{
|
||||
protected function assertBudget(EntityWithBudget $entityWithBudget)
|
||||
{
|
||||
$this->assertEquals(0.0, $entityWithBudget->getBudget());
|
||||
$this->assertEquals(0, $entityWithBudget->getTimeBudget());
|
||||
$this->assertNull($entityWithBudget->getBudgetType());
|
||||
$this->assertFalse($entityWithBudget->isMonthlyBudget());
|
||||
|
||||
self::assertFalse($entityWithBudget->hasBudget());
|
||||
self::assertFalse($entityWithBudget->hasTimeBudget());
|
||||
|
||||
$entityWithBudget->setBudget(12345.67);
|
||||
$this->assertEquals(12345.67, $entityWithBudget->getBudget());
|
||||
self::assertTrue($entityWithBudget->hasBudget());
|
||||
self::assertFalse($entityWithBudget->hasTimeBudget());
|
||||
|
||||
$entityWithBudget->setTimeBudget(937321);
|
||||
$this->assertEquals(937321, $entityWithBudget->getTimeBudget());
|
||||
self::assertTrue($entityWithBudget->hasTimeBudget());
|
||||
|
||||
$entityWithBudget->setBudgetType('month');
|
||||
$this->assertTrue($entityWithBudget->isMonthlyBudget());
|
||||
$entityWithBudget->setBudgetType(null);
|
||||
$this->assertFalse($entityWithBudget->isMonthlyBudget());
|
||||
|
||||
try {
|
||||
$entityWithBudget->setBudgetType('foo');
|
||||
$this->fail('Budget type only allows "month"');
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
self::assertEquals('Unknown budget type: foo', $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,12 +18,11 @@ use App\Export\Spreadsheet\ColumnDefinition;
|
||||
use App\Export\Spreadsheet\Extractor\AnnotationExtractor;
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Entity\Activity
|
||||
*/
|
||||
class ActivityTest extends TestCase
|
||||
class ActivityTest extends AbstractEntityTest
|
||||
{
|
||||
public function testDefaultValues()
|
||||
{
|
||||
@@ -36,16 +35,17 @@ class ActivityTest extends TestCase
|
||||
$this->assertTrue($sut->isGlobal());
|
||||
$this->assertNull($sut->getColor());
|
||||
self::assertFalse($sut->hasColor());
|
||||
$this->assertEquals(0.0, $sut->getBudget());
|
||||
$this->assertEquals(0, $sut->getTimeBudget());
|
||||
self::assertFalse($sut->hasBudget());
|
||||
self::assertFalse($sut->hasTimeBudget());
|
||||
$this->assertInstanceOf(Collection::class, $sut->getMetaFields());
|
||||
$this->assertEquals(0, $sut->getMetaFields()->count());
|
||||
$this->assertNull($sut->getMetaField('foo'));
|
||||
$this->assertInstanceOf(Collection::class, $sut->getTeams());
|
||||
}
|
||||
|
||||
public function testBudgets()
|
||||
{
|
||||
$this->assertBudget(new Activity());
|
||||
}
|
||||
|
||||
public function testSetterAndGetter()
|
||||
{
|
||||
$sut = new Activity();
|
||||
@@ -68,14 +68,6 @@ class ActivityTest extends TestCase
|
||||
$this->assertNull($sut->getColor());
|
||||
self::assertFalse($sut->hasColor());
|
||||
|
||||
$this->assertInstanceOf(Activity::class, $sut->setBudget(12345.67));
|
||||
$this->assertEquals(12345.67, $sut->getBudget());
|
||||
self::assertTrue($sut->hasBudget());
|
||||
|
||||
$this->assertInstanceOf(Activity::class, $sut->setTimeBudget(937321));
|
||||
$this->assertEquals(937321, $sut->getTimeBudget());
|
||||
self::assertTrue($sut->hasTimeBudget());
|
||||
|
||||
$this->assertTrue($sut->isGlobal());
|
||||
$this->assertInstanceOf(Activity::class, $sut->setProject(new Project()));
|
||||
$this->assertFalse($sut->isGlobal());
|
||||
|
||||
@@ -17,12 +17,11 @@ use App\Export\Spreadsheet\ColumnDefinition;
|
||||
use App\Export\Spreadsheet\Extractor\AnnotationExtractor;
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Entity\Customer
|
||||
*/
|
||||
class CustomerTest extends TestCase
|
||||
class CustomerTest extends AbstractEntityTest
|
||||
{
|
||||
public function testDefaultValues()
|
||||
{
|
||||
@@ -49,10 +48,6 @@ class CustomerTest extends TestCase
|
||||
|
||||
self::assertNull($sut->getColor());
|
||||
self::assertFalse($sut->hasColor());
|
||||
self::assertEquals(0.0, $sut->getBudget());
|
||||
self::assertEquals(0, $sut->getTimeBudget());
|
||||
self::assertFalse($sut->hasBudget());
|
||||
self::assertFalse($sut->hasTimeBudget());
|
||||
self::assertInstanceOf(Collection::class, $sut->getMetaFields());
|
||||
self::assertEquals(0, $sut->getMetaFields()->count());
|
||||
self::assertNull($sut->getMetaField('foo'));
|
||||
@@ -60,6 +55,11 @@ class CustomerTest extends TestCase
|
||||
self::assertEquals(0, $sut->getTeams()->count());
|
||||
}
|
||||
|
||||
public function testBudgets()
|
||||
{
|
||||
$this->assertBudget(new Customer());
|
||||
}
|
||||
|
||||
public function testSetterAndGetter()
|
||||
{
|
||||
$sut = new Customer();
|
||||
@@ -103,14 +103,6 @@ class CustomerTest extends TestCase
|
||||
self::assertInstanceOf(Customer::class, $sut->setHomepage('https://www.example.com'));
|
||||
self::assertEquals('https://www.example.com', $sut->getHomepage());
|
||||
|
||||
self::assertInstanceOf(Customer::class, $sut->setBudget(12345.67));
|
||||
self::assertEquals(12345.67, $sut->getBudget());
|
||||
self::assertTrue($sut->hasBudget());
|
||||
|
||||
self::assertInstanceOf(Customer::class, $sut->setTimeBudget(937321));
|
||||
self::assertEquals(937321, $sut->getTimeBudget());
|
||||
self::assertTrue($sut->hasTimeBudget());
|
||||
|
||||
self::assertInstanceOf(Customer::class, $sut->setVatId('ID 1234567890'));
|
||||
self::assertEquals('ID 1234567890', $sut->getVatId());
|
||||
|
||||
|
||||
@@ -18,12 +18,11 @@ use App\Export\Spreadsheet\ColumnDefinition;
|
||||
use App\Export\Spreadsheet\Extractor\AnnotationExtractor;
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Entity\Project
|
||||
*/
|
||||
class ProjectTest extends TestCase
|
||||
class ProjectTest extends AbstractEntityTest
|
||||
{
|
||||
public function testDefaultValues()
|
||||
{
|
||||
@@ -39,10 +38,6 @@ class ProjectTest extends TestCase
|
||||
self::assertTrue($sut->isVisible());
|
||||
self::assertNull($sut->getColor());
|
||||
self::assertFalse($sut->hasColor());
|
||||
self::assertEquals(0.0, $sut->getBudget());
|
||||
self::assertEquals(0, $sut->getTimeBudget());
|
||||
self::assertFalse($sut->hasBudget());
|
||||
self::assertFalse($sut->hasTimeBudget());
|
||||
self::assertInstanceOf(Collection::class, $sut->getMetaFields());
|
||||
self::assertEquals(0, $sut->getMetaFields()->count());
|
||||
self::assertNull($sut->getMetaField('foo'));
|
||||
@@ -51,6 +46,11 @@ class ProjectTest extends TestCase
|
||||
self::assertTrue($sut->isVisibleAtDate(new \DateTime()));
|
||||
}
|
||||
|
||||
public function testBudgets()
|
||||
{
|
||||
$this->assertBudget(new Project());
|
||||
}
|
||||
|
||||
public function testSetterAndGetter()
|
||||
{
|
||||
$sut = new Project();
|
||||
@@ -95,14 +95,6 @@ class ProjectTest extends TestCase
|
||||
|
||||
self::assertInstanceOf(Project::class, $sut->setVisible(false));
|
||||
self::assertFalse($sut->isVisible());
|
||||
|
||||
self::assertInstanceOf(Project::class, $sut->setBudget(12345.67));
|
||||
self::assertEquals(12345.67, $sut->getBudget());
|
||||
self::assertTrue($sut->hasBudget());
|
||||
|
||||
self::assertInstanceOf(Project::class, $sut->setTimeBudget(937321));
|
||||
self::assertEquals(937321, $sut->getTimeBudget());
|
||||
self::assertTrue($sut->hasTimeBudget());
|
||||
}
|
||||
|
||||
public function testMetaFields()
|
||||
|
||||
45
tests/Event/ActivityBudgetStatisticEventTest.php
Normal file
45
tests/Event/ActivityBudgetStatisticEventTest.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?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\Activity;
|
||||
use App\Event\ActivityBudgetStatisticEvent;
|
||||
use App\Model\ActivityBudgetStatisticModel;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\ActivityBudgetStatisticEvent
|
||||
*/
|
||||
class ActivityBudgetStatisticEventTest extends TestCase
|
||||
{
|
||||
public function testStatistic()
|
||||
{
|
||||
$activity = $this->createMock(Activity::class);
|
||||
$activity->expects($this->exactly(2))->method('getId')->willReturn(12);
|
||||
|
||||
$model1 = new ActivityBudgetStatisticModel($activity);
|
||||
$model2 = new ActivityBudgetStatisticModel(new Activity());
|
||||
$models = [
|
||||
$model1,
|
||||
4 => $model2,
|
||||
];
|
||||
$begin = new \DateTime('-1 years');
|
||||
$end = new \DateTime();
|
||||
|
||||
$sut = new ActivityBudgetStatisticEvent($models, $begin, $end);
|
||||
|
||||
self::assertSame($models, $sut->getModels());
|
||||
self::assertNull($sut->getModel(1));
|
||||
self::assertSame($model1, $sut->getModel(12));
|
||||
self::assertSame($model2, $sut->getModel(4));
|
||||
self::assertSame($begin, $sut->getBegin());
|
||||
self::assertSame($end, $sut->getEnd());
|
||||
}
|
||||
}
|
||||
@@ -32,5 +32,14 @@ class ActivityStatisticEventTest extends AbstractActivityEventTest
|
||||
$sut = new ActivityStatisticEvent($activity, $statistic);
|
||||
|
||||
self::assertSame($statistic, $sut->getStatistic());
|
||||
self::assertSame($activity, $sut->getActivity());
|
||||
self::assertNull($sut->getBegin());
|
||||
self::assertNull($sut->getEnd());
|
||||
|
||||
$begin = new \DateTime('2020-08-08 12:34:56');
|
||||
$end = new \DateTime('2020-09-08 12:34:56');
|
||||
$sut = new ActivityStatisticEvent($activity, $statistic, $begin, $end);
|
||||
self::assertSame($begin, $sut->getBegin());
|
||||
self::assertSame($end, $sut->getEnd());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,5 +32,14 @@ class CustomerStatisticEventTest extends AbstractCustomerEventTest
|
||||
$sut = new CustomerStatisticEvent($customer, $statistic);
|
||||
|
||||
self::assertSame($statistic, $sut->getStatistic());
|
||||
self::assertSame($customer, $sut->getCustomer());
|
||||
self::assertNull($sut->getBegin());
|
||||
self::assertNull($sut->getEnd());
|
||||
|
||||
$begin = new \DateTime('2020-08-08 12:34:56');
|
||||
$end = new \DateTime('2020-09-08 12:34:56');
|
||||
$sut = new CustomerStatisticEvent($customer, $statistic, $begin, $end);
|
||||
self::assertSame($begin, $sut->getBegin());
|
||||
self::assertSame($end, $sut->getEnd());
|
||||
}
|
||||
}
|
||||
|
||||
45
tests/Event/ProjectBudgetStatisticEventTest.php
Normal file
45
tests/Event/ProjectBudgetStatisticEventTest.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?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\Project;
|
||||
use App\Event\ProjectBudgetStatisticEvent;
|
||||
use App\Model\ProjectBudgetStatisticModel;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\ProjectBudgetStatisticEvent
|
||||
*/
|
||||
class ProjectBudgetStatisticEventTest extends TestCase
|
||||
{
|
||||
public function testStatistic()
|
||||
{
|
||||
$project = $this->createMock(Project::class);
|
||||
$project->expects($this->exactly(2))->method('getId')->willReturn(12);
|
||||
|
||||
$model1 = new ProjectBudgetStatisticModel($project);
|
||||
$model2 = new ProjectBudgetStatisticModel(new Project());
|
||||
$models = [
|
||||
$model1,
|
||||
4 => $model2,
|
||||
];
|
||||
$begin = new \DateTime('-1 years');
|
||||
$end = new \DateTime();
|
||||
|
||||
$sut = new ProjectBudgetStatisticEvent($models, $begin, $end);
|
||||
|
||||
self::assertSame($models, $sut->getModels());
|
||||
self::assertNull($sut->getModel(1));
|
||||
self::assertSame($model1, $sut->getModel(12));
|
||||
self::assertSame($model2, $sut->getModel(4));
|
||||
self::assertSame($begin, $sut->getBegin());
|
||||
self::assertSame($end, $sut->getEnd());
|
||||
}
|
||||
}
|
||||
@@ -32,5 +32,14 @@ class ProjectStatisticEventTest extends AbstractProjectEventTest
|
||||
$sut = new ProjectStatisticEvent($project, $statistic);
|
||||
|
||||
self::assertSame($statistic, $sut->getStatistic());
|
||||
self::assertSame($project, $sut->getProject());
|
||||
self::assertNull($sut->getBegin());
|
||||
self::assertNull($sut->getEnd());
|
||||
|
||||
$begin = new \DateTime('2020-08-08 12:34:56');
|
||||
$end = new \DateTime('2020-09-08 12:34:56');
|
||||
$sut = new ProjectStatisticEvent($project, $statistic, $begin, $end);
|
||||
self::assertSame($begin, $sut->getBegin());
|
||||
self::assertSame($end, $sut->getEnd());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
namespace App\Tests\Export\Renderer;
|
||||
|
||||
use App\Activity\ActivityStatisticService;
|
||||
use App\Export\Renderer\HtmlRenderer;
|
||||
use App\Export\Renderer\HtmlRendererFactory;
|
||||
use App\Project\ProjectStatisticService;
|
||||
@@ -26,7 +27,8 @@ class HtmlRendererFactoryTest extends TestCase
|
||||
$sut = new HtmlRendererFactory(
|
||||
$this->createMock(Environment::class),
|
||||
$this->createMock(EventDispatcherInterface::class),
|
||||
$this->createMock(ProjectStatisticService::class)
|
||||
$this->createMock(ProjectStatisticService::class),
|
||||
$this->createMock(ActivityStatisticService::class)
|
||||
);
|
||||
|
||||
$renderer = $sut->create('foo', 'bar.html.twig');
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
namespace App\Tests\Export\Renderer;
|
||||
|
||||
use App\Activity\ActivityStatisticService;
|
||||
use App\Export\Renderer\HtmlRenderer;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
@@ -28,7 +29,8 @@ class HtmlRendererTest extends AbstractRendererTest
|
||||
$sut = new HtmlRenderer(
|
||||
$this->createMock(Environment::class),
|
||||
new EventDispatcher(),
|
||||
$this->createMock(ProjectStatisticService::class)
|
||||
$this->createMock(ProjectStatisticService::class),
|
||||
$this->createMock(ActivityStatisticService::class)
|
||||
);
|
||||
|
||||
$this->assertEquals('html', $sut->getId());
|
||||
@@ -46,7 +48,12 @@ class HtmlRendererTest extends AbstractRendererTest
|
||||
$request->setLocale('en');
|
||||
$stack->push($request);
|
||||
|
||||
$sut = new HtmlRenderer($twig, new EventDispatcher(), $this->createMock(ProjectStatisticService::class));
|
||||
$sut = new HtmlRenderer(
|
||||
$twig,
|
||||
new EventDispatcher(),
|
||||
$this->createMock(ProjectStatisticService::class),
|
||||
$this->createMock(ActivityStatisticService::class)
|
||||
);
|
||||
|
||||
$response = $this->render($sut);
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
namespace App\Tests\Export;
|
||||
|
||||
use App\Activity\ActivityStatisticService;
|
||||
use App\Export\ExportRepositoryInterface;
|
||||
use App\Export\Renderer\HtmlRenderer;
|
||||
use App\Export\ServiceExport;
|
||||
@@ -47,7 +48,12 @@ class ServiceExportTest extends TestCase
|
||||
{
|
||||
$sut = $this->createSut();
|
||||
|
||||
$renderer = new HtmlRenderer($this->createMock(Environment::class), new EventDispatcher(), $this->createMock(ProjectStatisticService::class));
|
||||
$renderer = new HtmlRenderer(
|
||||
$this->createMock(Environment::class),
|
||||
new EventDispatcher(),
|
||||
$this->createMock(ProjectStatisticService::class),
|
||||
$this->createMock(ActivityStatisticService::class)
|
||||
);
|
||||
$sut->addRenderer($renderer);
|
||||
|
||||
self::assertEquals(1, \count($sut->getRenderer()));
|
||||
@@ -58,7 +64,7 @@ class ServiceExportTest extends TestCase
|
||||
{
|
||||
$sut = $this->createSut();
|
||||
|
||||
$exporter = new HtmlExporter($this->createMock(Environment::class), new EventDispatcher(), $this->createMock(ProjectStatisticService::class));
|
||||
$exporter = new HtmlExporter($this->createMock(Environment::class), new EventDispatcher(), $this->createMock(ProjectStatisticService::class), $this->createMock(ActivityStatisticService::class));
|
||||
$sut->addTimesheetExporter($exporter);
|
||||
|
||||
self::assertEquals(1, \count($sut->getTimesheetExporter()));
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
namespace App\Tests\Export\Timesheet;
|
||||
|
||||
use App\Activity\ActivityStatisticService;
|
||||
use App\Export\Timesheet\HtmlRenderer;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
@@ -26,7 +27,8 @@ class HtmlRendererTest extends AbstractRendererTest
|
||||
$sut = new HtmlRenderer(
|
||||
$this->createMock(Environment::class),
|
||||
new EventDispatcher(),
|
||||
$this->createMock(ProjectStatisticService::class)
|
||||
$this->createMock(ProjectStatisticService::class),
|
||||
$this->createMock(ActivityStatisticService::class)
|
||||
);
|
||||
|
||||
$this->assertEquals('print', $sut->getId());
|
||||
@@ -42,7 +44,12 @@ class HtmlRendererTest extends AbstractRendererTest
|
||||
$request->setLocale('en');
|
||||
$stack->push($request);
|
||||
|
||||
$sut = new HtmlRenderer($twig, new EventDispatcher(), $this->createMock(ProjectStatisticService::class));
|
||||
$sut = new HtmlRenderer(
|
||||
$twig,
|
||||
new EventDispatcher(),
|
||||
$this->createMock(ProjectStatisticService::class),
|
||||
$this->createMock(ActivityStatisticService::class)
|
||||
);
|
||||
|
||||
$response = $this->render($sut);
|
||||
|
||||
|
||||
@@ -20,12 +20,31 @@ abstract class AbstractTimesheetCountedStatisticTest extends TestCase
|
||||
self::assertSame(0.0, $sut->getRate());
|
||||
self::assertSame(0, $sut->getRecordDuration());
|
||||
self::assertSame(0, $sut->getDuration());
|
||||
self::assertSame(0, $sut->getRecordAmount());
|
||||
self::assertSame(0, $sut->getCounter());
|
||||
self::assertSame(0, $sut->getCounterBillable());
|
||||
self::assertSame(0.0, $sut->getRecordInternalRate());
|
||||
self::assertSame(0, $sut->getValue());
|
||||
self::assertSame(0, $sut->getDurationBillable());
|
||||
self::assertSame(0.0, $sut->getRateBillable());
|
||||
self::assertSame(0, $sut->getRecordAmountBillable());
|
||||
self::assertSame(0.0, $sut->getInternalRateBillable());
|
||||
|
||||
$json = $sut->jsonSerialize();
|
||||
|
||||
$expected = [
|
||||
'duration' => 0,
|
||||
'duration_billable' => 0,
|
||||
'rate' => 0.0,
|
||||
'rate_billable' => 0.0,
|
||||
'rate_internal' => 0.0,
|
||||
'amount' => 0,
|
||||
'amount_billable' => 0,
|
||||
];
|
||||
|
||||
foreach ($expected as $key => $value) {
|
||||
self::assertArrayHasKey($key, $json);
|
||||
self::assertSame($value, $json[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
protected function assertSetter(TimesheetCountedStatistic $sut)
|
||||
@@ -33,23 +52,34 @@ abstract class AbstractTimesheetCountedStatisticTest extends TestCase
|
||||
self::assertInstanceOf(TimesheetCountedStatistic::class, $sut->setRecordRate(23.97));
|
||||
self::assertInstanceOf(TimesheetCountedStatistic::class, $sut->setRecordDuration(21));
|
||||
self::assertInstanceOf(TimesheetCountedStatistic::class, $sut->setRecordAmount(5));
|
||||
$sut->setRecordAmountBillable(15);
|
||||
self::assertInstanceOf(TimesheetCountedStatistic::class, $sut->setRecordInternalRate(99.09));
|
||||
|
||||
self::assertSame(23.97, $sut->getRecordRate());
|
||||
self::assertSame(23.97, $sut->getRate());
|
||||
self::assertSame(21, $sut->getRecordDuration());
|
||||
self::assertSame(21, $sut->getDuration());
|
||||
self::assertSame(21, $sut->getValue());
|
||||
self::assertSame(5, $sut->getRecordAmount());
|
||||
self::assertSame(15, $sut->getRecordAmountBillable());
|
||||
self::assertSame(99.09, $sut->getRecordInternalRate());
|
||||
|
||||
self::assertSame(21, $sut->getValue());
|
||||
|
||||
$sut->setCounter(524);
|
||||
$sut->setCounterBillable(198);
|
||||
$sut->setInternalRate(567.09);
|
||||
$sut->setRate(323.97);
|
||||
$sut->setDuration(22);
|
||||
$sut->setRateBillable(123.456);
|
||||
$sut->setDurationBillable(1234);
|
||||
$sut->setRecordAmountBillable(4321);
|
||||
$sut->setInternalRateBillable(987.12);
|
||||
|
||||
self::assertSame(524, $sut->getCounter());
|
||||
self::assertSame(198, $sut->getCounterBillable());
|
||||
self::assertSame(567.09, $sut->getInternalRate());
|
||||
self::assertSame(22, $sut->getDuration());
|
||||
self::assertSame(323.97, $sut->getRate());
|
||||
self::assertSame(123.456, $sut->getRateBillable());
|
||||
self::assertSame(1234, $sut->getDurationBillable());
|
||||
self::assertSame(4321, $sut->getRecordAmountBillable());
|
||||
self::assertSame(987.12, $sut->getInternalRateBillable());
|
||||
}
|
||||
|
||||
protected function assertJsonSerialize(TimesheetCountedStatistic $sut)
|
||||
|
||||
48
tests/Model/ActivityBudgetStatisticModelTest.php
Normal file
48
tests/Model/ActivityBudgetStatisticModelTest.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?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\Model;
|
||||
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\EntityWithBudget;
|
||||
use App\Model\ActivityBudgetStatisticModel;
|
||||
use App\Model\BudgetStatisticModel;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Model\ActivityBudgetStatisticModel
|
||||
*/
|
||||
class ActivityBudgetStatisticModelTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @param EntityWithBudget $entity
|
||||
* @return ActivityBudgetStatisticModel
|
||||
*/
|
||||
protected function getSut(EntityWithBudget $entity): BudgetStatisticModel
|
||||
{
|
||||
\assert($entity instanceof Activity);
|
||||
|
||||
return new ActivityBudgetStatisticModel($entity);
|
||||
}
|
||||
|
||||
protected function getEntity(): EntityWithBudget
|
||||
{
|
||||
return new Activity();
|
||||
}
|
||||
|
||||
public function testAdditionals()
|
||||
{
|
||||
$entity = $this->getEntity();
|
||||
$sut = $this->getSut($entity);
|
||||
|
||||
self::assertInstanceOf(Activity::class, $sut->getEntity());
|
||||
self::assertSame($entity, $sut->getEntity());
|
||||
self::assertSame($entity, $sut->getActivity());
|
||||
}
|
||||
}
|
||||
169
tests/Model/BudgetStatisticModelTest.php
Normal file
169
tests/Model/BudgetStatisticModelTest.php
Normal file
@@ -0,0 +1,169 @@
|
||||
<?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\Model;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\EntityWithBudget;
|
||||
use App\Model\BudgetStatisticModel;
|
||||
use App\Model\Statistic\BudgetStatistic;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Model\BudgetStatisticModel
|
||||
*/
|
||||
class BudgetStatisticModelTest extends TestCase
|
||||
{
|
||||
protected function getSut(EntityWithBudget $entity): BudgetStatisticModel
|
||||
{
|
||||
return new BudgetStatisticModel($entity);
|
||||
}
|
||||
|
||||
protected function getEntity(): EntityWithBudget
|
||||
{
|
||||
return new Customer();
|
||||
}
|
||||
|
||||
public function testDefaults()
|
||||
{
|
||||
$this->assertDefaults();
|
||||
}
|
||||
|
||||
public function testSetter()
|
||||
{
|
||||
$this->assertSetter();
|
||||
}
|
||||
|
||||
public function testCalculation()
|
||||
{
|
||||
$this->assertCalculation();
|
||||
}
|
||||
|
||||
protected function assertCalculation()
|
||||
{
|
||||
$entity = $this->getEntity();
|
||||
$entity->setBudget(100.0);
|
||||
$entity->setTimeBudget(100);
|
||||
$entity->setBudgetType('month');
|
||||
$sut = $this->getSut($entity);
|
||||
|
||||
$statistic = new BudgetStatistic();
|
||||
$statistic->setInternalRate(147.95);
|
||||
$statistic->setRate(47.00);
|
||||
$statistic->setRateBillable(13.00);
|
||||
$statistic->setDuration(53);
|
||||
$statistic->setDurationBillable(23);
|
||||
$sut->setStatistic($statistic);
|
||||
|
||||
$statisticTotal = new BudgetStatistic();
|
||||
$statisticTotal->setInternalRate(247.95);
|
||||
$statisticTotal->setRate(247.00);
|
||||
$statisticTotal->setRateBillable(213.00);
|
||||
$statisticTotal->setDuration(253);
|
||||
$statisticTotal->setDurationBillable(223);
|
||||
$sut->setStatisticTotal($statisticTotal);
|
||||
|
||||
self::assertSame($entity, $sut->getEntity());
|
||||
self::assertSame(23, $sut->getDurationBillable());
|
||||
self::assertSame(53, $sut->getDuration());
|
||||
self::assertSame(13.00, $sut->getRateBillable());
|
||||
self::assertSame(47.00, $sut->getRate());
|
||||
self::assertSame(147.95, $sut->getInternalRate());
|
||||
|
||||
self::assertTrue($sut->isMonthlyBudget());
|
||||
|
||||
self::assertTrue($sut->hasTimeBudget());
|
||||
self::assertSame(100, $sut->getTimeBudget());
|
||||
self::assertSame(77, $sut->getTimeBudgetOpen());
|
||||
self::assertSame(23, $sut->getTimeBudgetSpent());
|
||||
|
||||
self::assertTrue($sut->hasBudget());
|
||||
self::assertSame(100.00, $sut->getBudget());
|
||||
self::assertSame(87.00, $sut->getBudgetOpen());
|
||||
self::assertSame(13.00, $sut->getBudgetSpent());
|
||||
|
||||
self::assertSame($statistic, $sut->getStatistic());
|
||||
self::assertSame($statisticTotal, $sut->getStatisticTotal());
|
||||
|
||||
$entity->setBudgetType(null);
|
||||
|
||||
self::assertSame(223, $sut->getDurationBillable());
|
||||
self::assertSame(253, $sut->getDuration());
|
||||
self::assertSame(213.00, $sut->getRateBillable());
|
||||
self::assertSame(247.00, $sut->getRate());
|
||||
self::assertSame(247.95, $sut->getInternalRate());
|
||||
|
||||
self::assertSame(100, $sut->getTimeBudget());
|
||||
self::assertSame(0, $sut->getTimeBudgetOpen());
|
||||
self::assertSame(223, $sut->getTimeBudgetSpent());
|
||||
|
||||
self::assertSame(100.00, $sut->getBudget());
|
||||
self::assertSame(0.00, $sut->getBudgetOpen());
|
||||
self::assertSame(213.00, $sut->getBudgetSpent());
|
||||
}
|
||||
|
||||
protected function assertSetter()
|
||||
{
|
||||
$entity = $this->getEntity();
|
||||
$entity->setBudget(10.0);
|
||||
$entity->setTimeBudget(10);
|
||||
$entity->setBudgetType('month');
|
||||
$sut = $this->getSut($entity);
|
||||
|
||||
self::assertSame($entity, $sut->getEntity());
|
||||
self::assertSame(0, $sut->getDurationBillable());
|
||||
self::assertSame(0, $sut->getDuration());
|
||||
self::assertSame(0.00, $sut->getRateBillable());
|
||||
self::assertSame(0.00, $sut->getRate());
|
||||
self::assertSame(0.00, $sut->getInternalRate());
|
||||
|
||||
self::assertTrue($sut->isMonthlyBudget());
|
||||
|
||||
self::assertTrue($sut->hasTimeBudget());
|
||||
self::assertSame(10, $sut->getTimeBudget());
|
||||
self::assertSame(10, $sut->getTimeBudgetOpen());
|
||||
self::assertSame(0, $sut->getTimeBudgetSpent());
|
||||
|
||||
self::assertTrue($sut->hasBudget());
|
||||
self::assertSame(10.00, $sut->getBudget());
|
||||
self::assertSame(10.00, $sut->getBudgetOpen());
|
||||
self::assertSame(0.00, $sut->getBudgetSpent());
|
||||
|
||||
self::assertNull($sut->getStatisticTotal());
|
||||
self::assertNull($sut->getStatistic());
|
||||
}
|
||||
|
||||
protected function assertDefaults()
|
||||
{
|
||||
$entity = $this->getEntity();
|
||||
$sut = $this->getSut($entity);
|
||||
|
||||
self::assertSame($entity, $sut->getEntity());
|
||||
self::assertSame(0, $sut->getDurationBillable());
|
||||
self::assertSame(0, $sut->getDuration());
|
||||
self::assertSame(0.00, $sut->getRateBillable());
|
||||
self::assertSame(0.00, $sut->getRate());
|
||||
self::assertSame(0.00, $sut->getInternalRate());
|
||||
|
||||
self::assertFalse($sut->isMonthlyBudget());
|
||||
|
||||
self::assertFalse($sut->hasTimeBudget());
|
||||
self::assertSame(0, $sut->getTimeBudget());
|
||||
self::assertSame(0, $sut->getTimeBudgetOpen());
|
||||
self::assertSame(0, $sut->getTimeBudgetSpent());
|
||||
|
||||
self::assertFalse($sut->hasBudget());
|
||||
self::assertSame(0.00, $sut->getBudget());
|
||||
self::assertSame(0.00, $sut->getBudgetOpen());
|
||||
self::assertSame(0.00, $sut->getBudgetSpent());
|
||||
|
||||
self::assertNull($sut->getStatisticTotal());
|
||||
self::assertNull($sut->getStatistic());
|
||||
}
|
||||
}
|
||||
48
tests/Model/CustomerBudgetStatisticModelTest.php
Normal file
48
tests/Model/CustomerBudgetStatisticModelTest.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?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\Model;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\EntityWithBudget;
|
||||
use App\Model\BudgetStatisticModel;
|
||||
use App\Model\CustomerBudgetStatisticModel;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Model\CustomerBudgetStatisticModel
|
||||
*/
|
||||
class CustomerBudgetStatisticModelTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @param EntityWithBudget $entity
|
||||
* @return CustomerBudgetStatisticModel
|
||||
*/
|
||||
protected function getSut(EntityWithBudget $entity): BudgetStatisticModel
|
||||
{
|
||||
\assert($entity instanceof Customer);
|
||||
|
||||
return new CustomerBudgetStatisticModel($entity);
|
||||
}
|
||||
|
||||
protected function getEntity(): EntityWithBudget
|
||||
{
|
||||
return new Customer();
|
||||
}
|
||||
|
||||
public function testAdditionals()
|
||||
{
|
||||
$entity = $this->getEntity();
|
||||
$sut = $this->getSut($entity);
|
||||
|
||||
self::assertInstanceOf(Customer::class, $sut->getEntity());
|
||||
self::assertSame($entity, $sut->getEntity());
|
||||
self::assertSame($entity, $sut->getCustomer());
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,9 @@ class CustomerStatisticTest extends AbstractTimesheetCountedStatisticTest
|
||||
$this->assertJsonSerialize(new CustomerStatistic());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testAdditionalSetter()
|
||||
{
|
||||
$sut = new CustomerStatistic();
|
||||
|
||||
69
tests/Model/DailyStatisticTest.php
Normal file
69
tests/Model/DailyStatisticTest.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?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\Model;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Model\DailyStatistic;
|
||||
use App\Model\Statistic\StatisticDate;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Model\DailyStatistic
|
||||
*/
|
||||
class DailyStatisticTest extends TestCase
|
||||
{
|
||||
public function testStatistic()
|
||||
{
|
||||
$begin = new \DateTime('2018-04-07 12:00:00');
|
||||
$end = new \DateTime('2018-04-13 18:00:00');
|
||||
$user = new User();
|
||||
$sut = new DailyStatistic($begin, $end, $user);
|
||||
|
||||
self::assertSame($user, $sut->getUser());
|
||||
$days = $sut->getDays();
|
||||
$dateTimes = $sut->getDateTimes();
|
||||
|
||||
self::assertCount(7, $days);
|
||||
self::assertCount(7, $dateTimes);
|
||||
|
||||
$expectedDateTimes = [
|
||||
new \DateTime('2018-04-07 00:00:00'),
|
||||
new \DateTime('2018-04-08 00:00:00'),
|
||||
new \DateTime('2018-04-09 00:00:00'),
|
||||
new \DateTime('2018-04-10 00:00:00'),
|
||||
new \DateTime('2018-04-11 00:00:00'),
|
||||
new \DateTime('2018-04-12 00:00:00'),
|
||||
new \DateTime('2018-04-13 00:00:00'),
|
||||
];
|
||||
|
||||
self::assertEquals($expectedDateTimes, $dateTimes);
|
||||
|
||||
foreach ($days as $day) {
|
||||
self::assertInstanceOf(StatisticDate::class, $day);
|
||||
}
|
||||
|
||||
self::assertInstanceOf(StatisticDate::class, $sut->getDayByDateTime(new \DateTime('2018-04-13 23:12:00')));
|
||||
self::assertInstanceOf(StatisticDate::class, $sut->getDay('2018', '4', '13'));
|
||||
self::assertInstanceOf(StatisticDate::class, $sut->getDay('2018', '04', '13'));
|
||||
self::assertInstanceOf(StatisticDate::class, $sut->getDay('2018', '4', '7'));
|
||||
self::assertInstanceOf(StatisticDate::class, $sut->getDay('2018', '4', '07'));
|
||||
self::assertInstanceOf(StatisticDate::class, $sut->getDay('2018', '04', '7'));
|
||||
self::assertInstanceOf(StatisticDate::class, $sut->getDayByReportDate('2018-04-13'));
|
||||
|
||||
self::assertNull($sut->getDayByDateTime(new \DateTime('2018-04-06 23:59:59')));
|
||||
self::assertNull($sut->getDayByDateTime(new \DateTime('2018-04-14 00:00:00')));
|
||||
self::assertNull($sut->getDay('2018', '4', '06'));
|
||||
self::assertNull($sut->getDay('2018', '4', '6'));
|
||||
self::assertNull($sut->getDay('2018', '4', '14'));
|
||||
self::assertNull($sut->getDay('2018', '04', '14'));
|
||||
self::assertNull($sut->getDayByReportDate('2018-04-14'));
|
||||
self::assertNull($sut->getDayByReportDate('2018-4-14'));
|
||||
}
|
||||
}
|
||||
108
tests/Model/MonthlyStatisticTest.php
Normal file
108
tests/Model/MonthlyStatisticTest.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?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\Model;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Model\MonthlyStatistic;
|
||||
use App\Model\Statistic\StatisticDate;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Model\MonthlyStatistic
|
||||
*/
|
||||
class MonthlyStatisticTest extends TestCase
|
||||
{
|
||||
public function testStatistic()
|
||||
{
|
||||
$begin = new \DateTime('2017-04-07 12:00:00');
|
||||
$end = new \DateTime('2019-11-13 18:00:00');
|
||||
$user = new User();
|
||||
$sut = new MonthlyStatistic($begin, $end, $user);
|
||||
|
||||
self::assertSame($user, $sut->getUser());
|
||||
$years = $sut->getYears();
|
||||
$months = $sut->getMonths();
|
||||
$dateTimes = $sut->getDateTimes();
|
||||
|
||||
self::assertCount(32, $months);
|
||||
self::assertCount(32, $dateTimes);
|
||||
self::assertCount(3, $years);
|
||||
|
||||
$expectedDateTimes = [
|
||||
new \DateTime('2017-04-07 00:00:00'),
|
||||
new \DateTime('2017-05-07 00:00:00'),
|
||||
new \DateTime('2017-06-07 00:00:00'),
|
||||
new \DateTime('2017-07-07 00:00:00'),
|
||||
new \DateTime('2017-08-07 00:00:00'),
|
||||
new \DateTime('2017-09-07 00:00:00'),
|
||||
new \DateTime('2017-10-07 00:00:00'),
|
||||
new \DateTime('2017-11-07 00:00:00'),
|
||||
new \DateTime('2017-12-07 00:00:00'),
|
||||
new \DateTime('2018-01-07 00:00:00'),
|
||||
new \DateTime('2018-02-07 00:00:00'),
|
||||
new \DateTime('2018-03-07 00:00:00'),
|
||||
new \DateTime('2018-04-07 00:00:00'),
|
||||
new \DateTime('2018-05-07 00:00:00'),
|
||||
new \DateTime('2018-06-07 00:00:00'),
|
||||
new \DateTime('2018-07-07 00:00:00'),
|
||||
new \DateTime('2018-08-07 00:00:00'),
|
||||
new \DateTime('2018-09-07 00:00:00'),
|
||||
new \DateTime('2018-10-07 00:00:00'),
|
||||
new \DateTime('2018-11-07 00:00:00'),
|
||||
new \DateTime('2018-12-07 00:00:00'),
|
||||
new \DateTime('2019-01-07 00:00:00'),
|
||||
new \DateTime('2019-02-07 00:00:00'),
|
||||
new \DateTime('2019-03-07 00:00:00'),
|
||||
new \DateTime('2019-04-07 00:00:00'),
|
||||
new \DateTime('2019-05-07 00:00:00'),
|
||||
new \DateTime('2019-06-07 00:00:00'),
|
||||
new \DateTime('2019-07-07 00:00:00'),
|
||||
new \DateTime('2019-08-07 00:00:00'),
|
||||
new \DateTime('2019-09-07 00:00:00'),
|
||||
new \DateTime('2019-10-07 00:00:00'),
|
||||
new \DateTime('2019-11-07 00:00:00'),
|
||||
];
|
||||
|
||||
self::assertEquals($expectedDateTimes, $dateTimes);
|
||||
|
||||
$expectedYears = [
|
||||
'2017',
|
||||
'2018',
|
||||
'2019',
|
||||
];
|
||||
|
||||
self::assertEquals($expectedYears, $years);
|
||||
|
||||
foreach ($months as $month) {
|
||||
self::assertInstanceOf(StatisticDate::class, $month);
|
||||
}
|
||||
|
||||
$year = $sut->getYear('2017');
|
||||
self::assertCount(9, $year);
|
||||
foreach ($year as $month) {
|
||||
self::assertInstanceOf(StatisticDate::class, $month);
|
||||
}
|
||||
|
||||
self::assertInstanceOf(StatisticDate::class, $sut->getMonth('2017', '4'));
|
||||
self::assertInstanceOf(StatisticDate::class, $sut->getMonth('2019', '11'));
|
||||
self::assertInstanceOf(StatisticDate::class, $sut->getMonth('2018', '4'));
|
||||
self::assertInstanceOf(StatisticDate::class, $sut->getMonth('2018', '04'));
|
||||
|
||||
self::assertNull($sut->getYear('2016'));
|
||||
self::assertNull($sut->getYear('2020'));
|
||||
self::assertNull($sut->getMonth('2018', '14'));
|
||||
self::assertNull($sut->getMonth('2017', '14'));
|
||||
self::assertNull($sut->getMonth('2017', '3'));
|
||||
self::assertNull($sut->getMonth('2017', '03'));
|
||||
self::assertNull($sut->getMonth('2019', '12'));
|
||||
self::assertNull($sut->getMonth('2020', '1'));
|
||||
self::assertNull($sut->getMonth('2020', '01'));
|
||||
}
|
||||
}
|
||||
48
tests/Model/ProjectBudgetStatisticModelTest.php
Normal file
48
tests/Model/ProjectBudgetStatisticModelTest.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?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\Model;
|
||||
|
||||
use App\Entity\EntityWithBudget;
|
||||
use App\Entity\Project;
|
||||
use App\Model\BudgetStatisticModel;
|
||||
use App\Model\ProjectBudgetStatisticModel;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Model\ProjectBudgetStatisticModel
|
||||
*/
|
||||
class ProjectBudgetStatisticModelTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @param EntityWithBudget $entity
|
||||
* @return ProjectBudgetStatisticModel
|
||||
*/
|
||||
protected function getSut(EntityWithBudget $entity): BudgetStatisticModel
|
||||
{
|
||||
\assert($entity instanceof Project);
|
||||
|
||||
return new ProjectBudgetStatisticModel($entity);
|
||||
}
|
||||
|
||||
protected function getEntity(): EntityWithBudget
|
||||
{
|
||||
return new Project();
|
||||
}
|
||||
|
||||
public function testAdditionals()
|
||||
{
|
||||
$entity = $this->getEntity();
|
||||
$sut = $this->getSut($entity);
|
||||
|
||||
self::assertInstanceOf(Project::class, $sut->getEntity());
|
||||
self::assertSame($entity, $sut->getEntity());
|
||||
self::assertSame($entity, $sut->getProject());
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,9 @@ class ProjectStatisticTest extends AbstractTimesheetCountedStatisticTest
|
||||
$this->assertJsonSerialize(new CustomerStatistic());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testAdditionalSetter()
|
||||
{
|
||||
$sut = new ProjectStatistic();
|
||||
|
||||
42
tests/Model/Statistic/AbstractTimesheetTest.php
Normal file
42
tests/Model/Statistic/AbstractTimesheetTest.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?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\Model\Statistic;
|
||||
|
||||
use App\Model\Statistic\Timesheet;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
abstract class AbstractTimesheetTest extends TestCase
|
||||
{
|
||||
protected function assertDefaultValues(Timesheet $sut)
|
||||
{
|
||||
self::assertSame(0.0, $sut->getRate());
|
||||
self::assertSame(0, $sut->getDuration());
|
||||
self::assertSame(0, $sut->getValue());
|
||||
self::assertSame(0.0, $sut->getInternalRate());
|
||||
self::assertSame(0, $sut->getTotalDuration());
|
||||
self::assertSame(0.0, $sut->getTotalRate());
|
||||
self::assertSame(0.0, $sut->getTotalInternalRate());
|
||||
}
|
||||
|
||||
protected function assertSetter(Timesheet $sut)
|
||||
{
|
||||
$sut->setTotalInternalRate(5485.84);
|
||||
$sut->setTotalRate(1234.23);
|
||||
$sut->setTotalDuration(567);
|
||||
|
||||
self::assertSame(1234.23, $sut->getRate());
|
||||
self::assertSame(567, $sut->getDuration());
|
||||
self::assertSame(567, $sut->getValue());
|
||||
self::assertSame(5485.84, $sut->getInternalRate());
|
||||
self::assertSame(567, $sut->getTotalDuration());
|
||||
self::assertSame(1234.23, $sut->getTotalRate());
|
||||
self::assertSame(5485.84, $sut->getTotalInternalRate());
|
||||
}
|
||||
}
|
||||
34
tests/Model/Statistic/BudgetStatisticTest.php
Normal file
34
tests/Model/Statistic/BudgetStatisticTest.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?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\Model\Statistic;
|
||||
|
||||
use App\Model\Statistic\BudgetStatistic;
|
||||
use App\Tests\Model\AbstractTimesheetCountedStatisticTest;
|
||||
|
||||
/**
|
||||
* @covers \App\Model\Statistic\BudgetStatistic
|
||||
*/
|
||||
class BudgetStatisticTest extends AbstractTimesheetCountedStatisticTest
|
||||
{
|
||||
public function testDefaultValues()
|
||||
{
|
||||
$this->assertDefaultValues(new BudgetStatistic());
|
||||
}
|
||||
|
||||
public function testSetter()
|
||||
{
|
||||
$this->assertSetter(new BudgetStatistic());
|
||||
}
|
||||
|
||||
public function testJsonSerialize()
|
||||
{
|
||||
$this->assertJsonSerialize(new BudgetStatistic());
|
||||
}
|
||||
}
|
||||
@@ -11,13 +11,26 @@ namespace App\Tests\Model\Statistic;
|
||||
|
||||
use App\Model\Statistic\Day;
|
||||
use DateTime;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Model\Statistic\Day
|
||||
*/
|
||||
class DayTest extends TestCase
|
||||
class DayTest extends AbstractTimesheetTest
|
||||
{
|
||||
public function testDefaultValues()
|
||||
{
|
||||
$date = new DateTime('-8 hours');
|
||||
$sut = new Day($date, 0, 0.0);
|
||||
$this->assertDefaultValues($sut);
|
||||
}
|
||||
|
||||
public function testSetter()
|
||||
{
|
||||
$date = new DateTime('-8 hours');
|
||||
$sut = new Day($date, 12340, 197.25956);
|
||||
$this->assertSetter($sut);
|
||||
}
|
||||
|
||||
public function testConstruct()
|
||||
{
|
||||
$date = new DateTime('-8 hours');
|
||||
|
||||
@@ -11,16 +11,17 @@ namespace App\Tests\Model\Statistic;
|
||||
|
||||
use App\Model\Statistic\Month;
|
||||
use InvalidArgumentException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Model\Statistic\Month
|
||||
*/
|
||||
class MonthTest extends TestCase
|
||||
class MonthTest extends AbstractTimesheetTest
|
||||
{
|
||||
public function testDefaultValues()
|
||||
{
|
||||
$sut = new Month('01');
|
||||
$this->assertDefaultValues($sut);
|
||||
|
||||
self::assertSame('01', $sut->getMonth());
|
||||
self::assertSame(0, $sut->getTotalDuration());
|
||||
self::assertSame(0.0, $sut->getTotalRate());
|
||||
@@ -88,6 +89,8 @@ class MonthTest extends TestCase
|
||||
public function testSetter()
|
||||
{
|
||||
$sut = new Month('01');
|
||||
$this->assertSetter($sut);
|
||||
|
||||
$sut->setTotalDuration(999);
|
||||
$sut->setTotalRate(0.123456789);
|
||||
$sut->setBillableDuration(123456);
|
||||
|
||||
49
tests/Model/Statistic/StatisticDateTest.php
Normal file
49
tests/Model/Statistic/StatisticDateTest.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?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\Model\Statistic;
|
||||
|
||||
use App\Model\Statistic\StatisticDate;
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
* @covers \App\Model\Statistic\StatisticDate
|
||||
*/
|
||||
class StatisticDateTest extends AbstractTimesheetTest
|
||||
{
|
||||
public function testDefaultValues()
|
||||
{
|
||||
$dateTime = new \DateTime('-8 hours');
|
||||
$sut = new StatisticDate($dateTime);
|
||||
$this->assertDefaultValues($sut);
|
||||
self::assertSame(0.0, $sut->getBillableRate());
|
||||
self::assertSame(0, $sut->getBillableDuration());
|
||||
self::assertNotSame($dateTime, $sut->getDate());
|
||||
self::assertEquals($dateTime->getTimestamp(), $sut->getDate()->getTimestamp());
|
||||
}
|
||||
|
||||
public function testSetter()
|
||||
{
|
||||
$date = new DateTime('-8 hours');
|
||||
$sut = new StatisticDate($date);
|
||||
$this->assertSetter($sut);
|
||||
}
|
||||
|
||||
public function testAdditionalMethods()
|
||||
{
|
||||
$date = new DateTime('-8 hours');
|
||||
$sut = new StatisticDate($date);
|
||||
|
||||
$sut->setBillableRate(4869.38);
|
||||
self::assertSame(4869.38, $sut->getBillableRate());
|
||||
|
||||
$sut->setBillableDuration(512376);
|
||||
self::assertSame(512376, $sut->getBillableDuration());
|
||||
}
|
||||
}
|
||||
30
tests/Model/Statistic/TimesheetTest.php
Normal file
30
tests/Model/Statistic/TimesheetTest.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?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\Model\Statistic;
|
||||
|
||||
use App\Model\Statistic\Timesheet;
|
||||
|
||||
/**
|
||||
* @covers \App\Model\Statistic\Timesheet
|
||||
*/
|
||||
class TimesheetTest extends AbstractTimesheetTest
|
||||
{
|
||||
public function testDefaultValues()
|
||||
{
|
||||
$sut = new Timesheet();
|
||||
$this->assertDefaultValues($sut);
|
||||
}
|
||||
|
||||
public function testSetter()
|
||||
{
|
||||
$sut = new Timesheet();
|
||||
$this->assertSetter($sut);
|
||||
}
|
||||
}
|
||||
@@ -11,16 +11,17 @@ namespace App\Tests\Model\Statistic;
|
||||
|
||||
use App\Model\Statistic\Month;
|
||||
use App\Model\Statistic\Year;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Model\Statistic\Year
|
||||
*/
|
||||
class YearTest extends TestCase
|
||||
class YearTest extends AbstractTimesheetTest
|
||||
{
|
||||
public function testDefaultValues()
|
||||
{
|
||||
$sut = new Year('1999');
|
||||
$this->assertDefaultValues($sut);
|
||||
|
||||
self::assertNull($sut->getMonth(1));
|
||||
self::assertEmpty($sut->getMonths());
|
||||
self::assertIsArray($sut->getMonths());
|
||||
@@ -30,6 +31,7 @@ class YearTest extends TestCase
|
||||
public function testSetter()
|
||||
{
|
||||
$sut = new Year('1999');
|
||||
$this->assertSetter($sut);
|
||||
|
||||
$sut->setMonth(new Month('01'));
|
||||
$sut->setMonth(new Month('02'));
|
||||
|
||||
@@ -10,29 +10,72 @@
|
||||
namespace App\Tests\Model;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Model\ActivityStatistic;
|
||||
use App\Model\Statistic\Month;
|
||||
use App\Model\UserStatistic;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Model\UserStatistic
|
||||
*/
|
||||
class UserStatisticTest extends TestCase
|
||||
class UserStatisticTest extends AbstractTimesheetCountedStatisticTest
|
||||
{
|
||||
public function testDefaultValues()
|
||||
private function getSut(): UserStatistic
|
||||
{
|
||||
$user = new User();
|
||||
$sut = new UserStatistic($user);
|
||||
$this->assertEquals(0, $sut->getRecordRate());
|
||||
|
||||
return new UserStatistic($user);
|
||||
}
|
||||
|
||||
public function testDefaultValues()
|
||||
{
|
||||
$this->assertDefaultValues($this->getSut());
|
||||
}
|
||||
|
||||
public function testSetter()
|
||||
{
|
||||
$sut = new ActivityStatistic();
|
||||
$sut->setRecordAmount(7654);
|
||||
$sut->setRecordDuration(826);
|
||||
$this->assertSetter($this->getSut());
|
||||
}
|
||||
|
||||
$this->assertEquals(7654, $sut->getRecordAmount());
|
||||
$this->assertEquals(826, $sut->getRecordDuration());
|
||||
public function testJsonSerialize()
|
||||
{
|
||||
$this->assertJsonSerialize($this->getSut());
|
||||
}
|
||||
|
||||
public function testAdditionalValues()
|
||||
{
|
||||
$user = new User();
|
||||
$sut = new UserStatistic($user);
|
||||
|
||||
$this->assertSetter($sut);
|
||||
|
||||
self::assertSame(22, $sut->getDuration());
|
||||
self::assertSame(1234, $sut->getDurationBillable());
|
||||
self::assertSame(323.97, $sut->getRate());
|
||||
self::assertSame(123.456, $sut->getRateBillable());
|
||||
self::assertSame(567.09, $sut->getInternalRate());
|
||||
|
||||
$month = new Month('10');
|
||||
|
||||
$sut->addValuesFromMonth($month);
|
||||
|
||||
self::assertSame(22, $sut->getDuration());
|
||||
self::assertSame(1234, $sut->getDurationBillable());
|
||||
self::assertSame(323.97, $sut->getRate());
|
||||
self::assertSame(123.456, $sut->getRateBillable());
|
||||
self::assertSame(567.09, $sut->getInternalRate());
|
||||
|
||||
$month = new Month('10');
|
||||
$month->setTotalDuration(123);
|
||||
$month->setBillableDuration(234);
|
||||
$month->setTotalRate(345.67);
|
||||
$month->setBillableRate(456.78);
|
||||
$month->setTotalInternalRate(567.89);
|
||||
|
||||
$sut->addValuesFromMonth($month);
|
||||
|
||||
self::assertSame(145, $sut->getDuration());
|
||||
self::assertSame(1468, $sut->getDurationBillable());
|
||||
self::assertSame(669.64, $sut->getRate());
|
||||
self::assertSame(580.236, $sut->getRateBillable());
|
||||
self::assertSame(1134.98, $sut->getInternalRate());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<?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\Reporting\ProjectDateRange;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\User;
|
||||
use App\Reporting\ProjectDateRange\ProjectDateRangeQuery;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Reporting\ProjectDateRange\ProjectDateRangeQuery
|
||||
*/
|
||||
class ProjectDateRangeQueryTest extends TestCase
|
||||
{
|
||||
public function testDefaults()
|
||||
{
|
||||
$user = new User();
|
||||
$date = new \DateTime();
|
||||
$sut = new ProjectDateRangeQuery($date, $user);
|
||||
|
||||
self::assertEquals($date->getTimestamp(), $sut->getMonth()->getTimestamp());
|
||||
self::assertSame($user, $sut->getUser());
|
||||
self::assertNull($sut->getCustomer());
|
||||
self::assertFalse($sut->isOnlyWithRecords());
|
||||
self::assertFalse($sut->isIncludeNoBudget());
|
||||
}
|
||||
|
||||
public function testSetterGetter()
|
||||
{
|
||||
$sut = new ProjectDateRangeQuery(new \DateTime(), new User());
|
||||
|
||||
$date = new \DateTime('+1 year');
|
||||
$customer = new Customer();
|
||||
|
||||
$sut->setMonth($date);
|
||||
$sut->setCustomer($customer);
|
||||
$sut->setIncludeNoBudget(true);
|
||||
$sut->setOnlyWithRecords(true);
|
||||
|
||||
self::assertEquals($date->getTimestamp(), $sut->getMonth()->getTimestamp());
|
||||
self::assertSame($customer, $sut->getCustomer());
|
||||
self::assertTrue($sut->isOnlyWithRecords());
|
||||
self::assertTrue($sut->isIncludeNoBudget());
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,6 @@ class ReportingServiceTest extends TestCase
|
||||
$sut = $this->getSut(true);
|
||||
$reports = $sut->getAvailableReports(new User());
|
||||
self::assertIsArray($reports);
|
||||
self::assertCount(8, $reports);
|
||||
self::assertCount(9, $reports);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ class TeamLoaderTest extends AbstractLoaderTest
|
||||
{
|
||||
public function testLoadResults()
|
||||
{
|
||||
$em = $this->getEntityManagerMock(1);
|
||||
$em = $this->getEntityManagerMock(2);
|
||||
|
||||
$sut = new TeamLoader($em);
|
||||
|
||||
|
||||
@@ -85,7 +85,8 @@ class TranslationsTest extends TestCase
|
||||
foreach ($body->children() as $transUnit) {
|
||||
$key = (string) $transUnit->source;
|
||||
if (isset($transLang[$key])) {
|
||||
if ($key !== 'stats.percentUsedLeft') { // special case, which doesn't work properly - base translation should be changed
|
||||
// some special cases, which don't work properly - base translation should be changed
|
||||
if (!\in_array($key, ['stats.percentUsedLeft', 'stats.percentUsedLeft_month'])) {
|
||||
preg_match_all('/%.+%/Uu', (string) $transUnit->target, $matches);
|
||||
asort($matches[0]);
|
||||
self::assertEquals($transLang[$key], array_values($matches[0]), sprintf('Invalid replacer "%s" in "%s"', $key, basename($file)));
|
||||
|
||||
@@ -30,21 +30,23 @@ class ExtensionsTest extends TestCase
|
||||
|
||||
public function testGetFilters()
|
||||
{
|
||||
$filters = ['docu_link', 'multiline_indent', 'color', 'font_contrast', 'default_color', 'nl2str'];
|
||||
$filters = ['report_date', 'docu_link', 'multiline_indent', 'color', 'font_contrast', 'default_color', 'nl2str'];
|
||||
$sut = $this->getSut();
|
||||
$twigFilters = $sut->getFilters();
|
||||
$this->assertCount(\count($filters), $twigFilters);
|
||||
$i = 0;
|
||||
/** @var TwigFilter $filter */
|
||||
|
||||
foreach ($twigFilters as $filter) {
|
||||
$this->assertInstanceOf(TwigFilter::class, $filter);
|
||||
$this->assertEquals($filters[$i++], $filter->getName());
|
||||
}
|
||||
|
||||
$id = array_search('nl2str', $filters);
|
||||
|
||||
// make sure that the nl2str filters does proper escaping
|
||||
self::assertEquals('nl2str', $twigFilters[5]->getName());
|
||||
self::assertEquals('html', $twigFilters[5]->getPreEscape());
|
||||
self::assertEquals(['html'], $twigFilters[5]->getSafe(new Node()));
|
||||
self::assertEquals('nl2str', $twigFilters[$id]->getName());
|
||||
self::assertEquals('html', $twigFilters[$id]->getPreEscape());
|
||||
self::assertEquals(['html'], $twigFilters[$id]->getSafe(new Node()));
|
||||
}
|
||||
|
||||
public function testGetFunctions()
|
||||
|
||||
@@ -17,8 +17,11 @@ use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\Timesheet;
|
||||
use App\Entity\User;
|
||||
use App\Model\ActivityBudgetStatisticModel;
|
||||
use App\Model\ActivityStatistic;
|
||||
use App\Model\CustomerBudgetStatisticModel;
|
||||
use App\Model\CustomerStatistic;
|
||||
use App\Model\ProjectBudgetStatisticModel;
|
||||
use App\Model\ProjectStatistic;
|
||||
use App\Project\ProjectStatisticService;
|
||||
use App\Repository\TimesheetRepository;
|
||||
@@ -38,22 +41,40 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
|
||||
*/
|
||||
class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
|
||||
{
|
||||
protected function createValidator(bool $isAllowed = false, ?ActivityStatistic $activityStatistic = null, ?ProjectStatistic $projectStatistic = null, ?CustomerStatistic $customerStatistic = null, ?array $rawData = null, ?Rate $rate = null)
|
||||
protected function createValidator(bool $isAllowed = false, ?ActivityBudgetStatisticModel $activityStatisticModel = null, ?ProjectBudgetStatisticModel $projectStatisticModel = null, ?CustomerBudgetStatisticModel $customerStatisticModel = null, ?array $rawData = null, ?Rate $rate = null)
|
||||
{
|
||||
$configuration = $this->createMock(SystemConfiguration::class);
|
||||
$configuration->method('isTimesheetAllowOverbookingBudget')->willReturn($isAllowed);
|
||||
|
||||
if ($customerStatisticModel === null) {
|
||||
$customerStatisticModel = new CustomerBudgetStatisticModel(new Customer());
|
||||
$customerStatistic = new CustomerStatistic();
|
||||
$customerStatisticModel->setStatisticTotal($customerStatistic);
|
||||
$customerStatisticModel->setStatistic($customerStatistic);
|
||||
}
|
||||
|
||||
$customerRepository = $this->createMock(CustomerStatisticService::class);
|
||||
$customerStatistic = $customerStatistic ?? new CustomerStatistic();
|
||||
$customerRepository->method('getCustomerStatistics')->willReturn($customerStatistic);
|
||||
$customerRepository->method('getBudgetStatisticModel')->willReturn($customerStatisticModel);
|
||||
|
||||
if ($projectStatisticModel === null) {
|
||||
$projectStatisticModel = new ProjectBudgetStatisticModel(new Project());
|
||||
$projectStatistic = new ProjectStatistic();
|
||||
$projectStatisticModel->setStatisticTotal($projectStatistic);
|
||||
$projectStatisticModel->setStatistic($projectStatistic);
|
||||
}
|
||||
|
||||
$projectRepository = $this->createMock(ProjectStatisticService::class);
|
||||
$projectStatistic = $projectStatistic ?? new ProjectStatistic();
|
||||
$projectRepository->method('getProjectStatistics')->willReturn($projectStatistic);
|
||||
$projectRepository->method('getBudgetStatisticModel')->willReturn($projectStatisticModel);
|
||||
|
||||
if ($activityStatisticModel === null) {
|
||||
$activityStatisticModel = new ActivityBudgetStatisticModel(new Activity());
|
||||
$activityStatistic = new ActivityStatistic();
|
||||
$activityStatisticModel->setStatisticTotal($activityStatistic);
|
||||
$activityStatisticModel->setStatistic($activityStatistic);
|
||||
}
|
||||
|
||||
$activityRepository = $this->createMock(ActivityStatisticService::class);
|
||||
$activityStatistic = $activityStatistic ?? new ActivityStatistic();
|
||||
$activityRepository->method('getActivityStatistics')->willReturn($activityStatistic);
|
||||
$activityRepository->method('getBudgetStatisticModel')->willReturn($activityStatisticModel);
|
||||
|
||||
$timesheetRepository = $this->createMock(TimesheetRepository::class);
|
||||
if (null !== $rawData) {
|
||||
@@ -168,7 +189,8 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
|
||||
public function getViolationTestData()
|
||||
{
|
||||
return [
|
||||
// activity: violations
|
||||
// activity: violations ----------------------------------------------------------------------
|
||||
// previously logged available budgets expected violation duration entry currently in database
|
||||
'a_a' => [1230, null, null, null, null, null, 3600, null, null, null, null, null, '00:20', '00:39', '01:00', 'activity', '+3600 seconds'],
|
||||
'a_b' => [null, 1001.0, null, null, null, null, null, 1000.0, null, null, null, null, '€1,001.00', '€0.00', '€1,000.00', 'activity', '+3600 seconds'],
|
||||
|
||||
@@ -177,24 +199,24 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
|
||||
'a_d' => [null, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'a_e' => [1230, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
|
||||
// previously logged available budgets expected violation duration entry currently in database
|
||||
'a_f' => [1320, null, null, null, null, null, 3600, null, null, null, null, null, '00:22', '00:38', '01:00', 'activity', '+3600 seconds', ['rate' => 1.0, 'duration' => 1000]],
|
||||
// previously logged available budgets expected violation duration entry currently in database
|
||||
'a_f1' => [1320, null, null, null, null, null, 3600, null, null, null, null, null, '00:22', '00:38', '01:00', 'activity', '+3600 seconds', ['rate' => 1.0, 'duration' => 1000]],
|
||||
'a_h1' => [7200, null, null, null, null, null, 7200, null, null, null, null, null, '02:00', '00:00', '02:00', 'activity', '+3601 seconds', ['rate' => 1.0, 'duration' => 3600]],
|
||||
'a_h' => [3601, null, null, null, null, null, 3600, null, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 1.0, 'duration' => 3601]],
|
||||
'a_g' => [null, 1002.0, null, null, null, null, null, 1000.0, null, null, null, null, '1,002.00', '0.00', '1,000.00', 'activity', '+3600 seconds', ['rate' => 1.0, 'duration' => 1010]],
|
||||
'a_h2' => [3601, null, null, null, null, null, 3600, null, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 1.0, 'duration' => 3601]],
|
||||
'a_g0' => [null, 1002.0, null, null, null, null, null, 1000.0, null, null, null, null, '1,002.00', '0.00', '1,000.00', 'activity', '+3600 seconds', ['rate' => 1.0, 'duration' => 1010]],
|
||||
'a_g1' => [null, 1002.0, null, null, null, null, null, 1000.0, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 2.0, 'duration' => 0]],
|
||||
// nothing changed => no violation
|
||||
'a_x1' => [3600, 1000.0, null, null, null, null, 3600, 1000.0, null, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 1000.0, 'duration' => 3600], new Rate(1000.0, 0.00)],
|
||||
|
||||
// project: violations
|
||||
// project: violations ----------------------------------------------------------------------
|
||||
'p_j' => [null, null, 1230, null, null, null, null, null, 3600, null, null, null, '00:20', '00:39', '01:00', 'project', '+3600 seconds'],
|
||||
'p_k' => [null, null, null, 1001.0, null, null, null, null, null, 1000.0, null, null, '€1,001.00', '€0.00', '€1,000.00', 'project', '+3600 seconds'],
|
||||
|
||||
// previously logged available budgets expected violation duration entry currently in database
|
||||
'p_f' => [null, null, 1320, null, null, null, null, null, 3600, null, null, null, '00:22', '00:38', '01:00', 'project', '+3600 seconds', ['rate' => 1.0, 'duration' => 1000]],
|
||||
// previously logged available budgets expected violation duration entry currently in database
|
||||
'p_f1' => [null, null, 1320, null, null, null, null, null, 3600, null, null, null, '00:22', '00:38', '01:00', 'project', '+3600 seconds', ['rate' => 1.0, 'duration' => 1000]],
|
||||
'p_h1' => [null, null, 7200, null, null, null, null, null, 7200, null, null, null, '02:00', '00:00', '02:00', 'project', '+3601 seconds', ['rate' => 1.0, 'duration' => 3600]],
|
||||
'p_h' => [null, null, 3601, null, null, null, null, null, 3600, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 1.0, 'duration' => 3601]],
|
||||
'p_g' => [null, null, null, 1002.0, null, null, null, null, null, 1000.0, null, null, '1,002.00', '0.00', '1,000.00', 'project', '+3600 seconds', ['rate' => 1.0, 'duration' => 1010]],
|
||||
'p_h2' => [null, null, 3601, null, null, null, null, null, 3600, null, null, null, null, null, null, null, '+3600 seconds', ['rate' => 1.0, 'duration' => 3601]],
|
||||
'p_g0' => [null, null, null, 1002.0, null, null, null, null, null, 1000.0, null, null, '1,002.00', '0.00', '1,000.00', 'project', '+3600 seconds', ['rate' => 1.0, 'duration' => 1010]],
|
||||
'p_g1' => [null, null, null, 1002.0, null, null, null, null, null, 1000.0, null, null, null, null, null, null, '+3600 seconds', ['rate' => 2.0, 'duration' => 0]],
|
||||
|
||||
// project: no violations
|
||||
@@ -208,15 +230,15 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
|
||||
'p_t' => [null, 1001.0, 1230, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
'p_u' => [1230, 1001.0, 1230, 1001.0, null, null, null, null, null, null, null, null, null, null, null, null, '+3600 seconds'],
|
||||
|
||||
// customer: violations
|
||||
// customer: violations ----------------------------------------------------------------------
|
||||
'c_v' => [null, null, null, null, 1230, null, null, null, null, null, 3600, null, '00:20', '00:39', '01:00', 'customer', '+3600 seconds'],
|
||||
'c_w' => [null, null, null, null, null, 1001.0, null, null, null, null, null, 1000.0, '€1,001.00', '€0.00', '€1,000.00', 'customer', '+3600 seconds'],
|
||||
|
||||
// previously logged available budgets expected violation duration entry currently in database
|
||||
'c_f' => [null, null, null, null, 1320, null, null, null, null, null, 3600, null, '00:22', '00:38', '01:00', 'customer', '+3600 seconds', ['rate' => 1.0, 'duration' => 1000]],
|
||||
// previously logged available budgets expected violation duration entry currently in database
|
||||
'c_f1' => [null, null, null, null, 1320, null, null, null, null, null, 3600, null, '00:22', '00:38', '01:00', 'customer', '+3600 seconds', ['rate' => 1.0, 'duration' => 1000]],
|
||||
'c_h1' => [null, null, null, null, 7200, null, null, null, null, null, 7200, null, '02:00', '00:00', '02:00', 'customer', '+3601 seconds', ['rate' => 1.0, 'duration' => 3600]],
|
||||
'c_h' => [null, null, null, null, 3601, null, null, null, null, null, 3600, null, null, null, null, null, '+3600 seconds', ['rate' => 1.0, 'duration' => 3601]],
|
||||
'c_g' => [null, null, null, null, null, 1002.0, null, null, null, null, null, 1000.0, '1,002.00', '0.00', '1,000.00', 'customer', '+3600 seconds', ['rate' => 1.0, 'duration' => 1010]],
|
||||
'c_h2' => [null, null, null, null, 3601, null, null, null, null, null, 3600, null, null, null, null, null, '+3600 seconds', ['rate' => 1.0, 'duration' => 3601]],
|
||||
'c_g0' => [null, null, null, null, null, 1002.0, null, null, null, null, null, 1000.0, '1,002.00', '0.00', '1,000.00', 'customer', '+3600 seconds', ['rate' => 1.0, 'duration' => 1010]],
|
||||
'c_g1' => [null, null, null, null, null, 1002.0, null, null, null, null, null, 1000.0, null, null, null, null, '+3600 seconds', ['rate' => 2.0, 'duration' => 0]],
|
||||
|
||||
// customer: no violations
|
||||
@@ -257,74 +279,102 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
|
||||
) {
|
||||
$activityStatistic = new ActivityStatistic();
|
||||
if ($activityDuration !== null) {
|
||||
$activityStatistic->setRecordDuration($activityDuration);
|
||||
$activityStatistic->setDuration($activityDuration);
|
||||
$activityStatistic->setDurationBillable($activityDuration);
|
||||
}
|
||||
if ($activityRate !== null) {
|
||||
$activityStatistic->setRecordRate($activityRate);
|
||||
$activityStatistic->setRate($activityRate);
|
||||
$activityStatistic->setRateBillable($activityRate);
|
||||
}
|
||||
|
||||
$projectStatistic = new ProjectStatistic();
|
||||
if ($projectDuration !== null) {
|
||||
$projectStatistic->setRecordDuration($projectDuration);
|
||||
$projectStatistic->setDuration($projectDuration);
|
||||
$projectStatistic->setDurationBillable($projectDuration);
|
||||
}
|
||||
if ($projectRate !== null) {
|
||||
$projectStatistic->setRecordRate($projectRate);
|
||||
$projectStatistic->setRate($projectRate);
|
||||
$projectStatistic->setRateBillable($projectRate);
|
||||
}
|
||||
|
||||
$customerStatistic = new CustomerStatistic();
|
||||
if ($customerDuration !== null) {
|
||||
$customerStatistic->setRecordDuration($customerDuration);
|
||||
$customerStatistic->setDuration($customerDuration);
|
||||
$customerStatistic->setDurationBillable($customerDuration);
|
||||
}
|
||||
if ($customerRate !== null) {
|
||||
$customerStatistic->setRecordRate($customerRate);
|
||||
$customerStatistic->setRate($customerRate);
|
||||
$customerStatistic->setRateBillable($customerRate);
|
||||
}
|
||||
|
||||
$begin = new DateTime();
|
||||
$end = clone $begin;
|
||||
$end->modify($duration);
|
||||
|
||||
$customer = null;
|
||||
$project = null;
|
||||
$activity = null;
|
||||
|
||||
if (!empty($rawData)) {
|
||||
if (!\array_key_exists('activity', $rawData)) {
|
||||
$rawData['activity'] = 1;
|
||||
}
|
||||
if (!\array_key_exists('billable', $rawData)) {
|
||||
$rawData['billable'] = true;
|
||||
}
|
||||
if (!\array_key_exists('project', $rawData)) {
|
||||
$rawData['project'] = 1;
|
||||
}
|
||||
if (!\array_key_exists('customer', $rawData)) {
|
||||
$rawData['customer'] = 1;
|
||||
}
|
||||
if (!\array_key_exists('rate', $rawData)) {
|
||||
$rawData['rate'] = 0.00;
|
||||
}
|
||||
if (!\array_key_exists('duration', $rawData)) {
|
||||
$rawData['duration'] = 0;
|
||||
}
|
||||
$activity = $this->createMock(Activity::class);
|
||||
$activity->method('getId')->willReturn($rawData['activity']);
|
||||
$activity->method('isMonthlyBudget')->willReturn(false);
|
||||
if ($activityTimeBudget !== null) {
|
||||
$activity->method('getTimeBudget')->willReturn($activityTimeBudget);
|
||||
$activity->method('hasTimeBudget')->willReturn(true);
|
||||
$activity->method('hasBudgets')->willReturn(true);
|
||||
}
|
||||
if ($activityBudget !== null) {
|
||||
$activity->method('getBudget')->willReturn($activityBudget);
|
||||
$activity->method('hasBudget')->willReturn(true);
|
||||
$activity->method('hasBudgets')->willReturn(true);
|
||||
}
|
||||
|
||||
$customer = $this->createMock(Customer::class);
|
||||
$customer->method('getId')->willReturn($rawData['customer']);
|
||||
$customer->method('isMonthlyBudget')->willReturn(false);
|
||||
if ($customerTimeBudget !== null) {
|
||||
$customer->method('getTimeBudget')->willReturn($customerTimeBudget);
|
||||
$customer->method('hasTimeBudget')->willReturn(true);
|
||||
$customer->method('hasBudgets')->willReturn(true);
|
||||
}
|
||||
if ($customerBudget !== null) {
|
||||
$customer->method('getBudget')->willReturn($customerBudget);
|
||||
$customer->method('hasBudget')->willReturn(true);
|
||||
$customer->method('hasBudgets')->willReturn(true);
|
||||
}
|
||||
|
||||
$project = $this->createMock(Project::class);
|
||||
$project->method('getId')->willReturn($rawData['project']);
|
||||
$project->method('getCustomer')->willReturn($customer);
|
||||
$project->method('isMonthlyBudget')->willReturn(false);
|
||||
if ($projectTimeBudget !== null) {
|
||||
$project->method('getTimeBudget')->willReturn($projectTimeBudget);
|
||||
$project->method('hasTimeBudget')->willReturn(true);
|
||||
$project->method('hasBudgets')->willReturn(true);
|
||||
}
|
||||
if ($projectBudget !== null) {
|
||||
$project->method('getBudget')->willReturn($projectBudget);
|
||||
$project->method('hasBudget')->willReturn(true);
|
||||
$project->method('hasBudgets')->willReturn(true);
|
||||
}
|
||||
|
||||
$timesheet = $this->createMock(Timesheet::class);
|
||||
@@ -335,6 +385,7 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
|
||||
$timesheet->method('getUser')->willReturn(new User());
|
||||
$timesheet->method('getProject')->willReturn($project);
|
||||
$timesheet->method('getActivity')->willReturn($activity);
|
||||
$timesheet->method('isBillable')->willReturn($rawData['billable']);
|
||||
} else {
|
||||
$activity = new Activity();
|
||||
if ($activityTimeBudget !== null) {
|
||||
@@ -369,7 +420,19 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase
|
||||
$timesheet->setActivity($activity);
|
||||
}
|
||||
|
||||
$this->validator = $this->createValidator(false, $activityStatistic, $projectStatistic, $customerStatistic, $rawData, $rate);
|
||||
$activityBudgetStatisticModel = new ActivityBudgetStatisticModel($activity);
|
||||
$activityBudgetStatisticModel->setStatistic($activityStatistic);
|
||||
$activityBudgetStatisticModel->setStatisticTotal($activityStatistic);
|
||||
|
||||
$projectBudgetStatisticModel = new ProjectBudgetStatisticModel($project);
|
||||
$projectBudgetStatisticModel->setStatistic($projectStatistic);
|
||||
$projectBudgetStatisticModel->setStatisticTotal($projectStatistic);
|
||||
|
||||
$customerBudgetStatisticModel = new CustomerBudgetStatisticModel($customer);
|
||||
$customerBudgetStatisticModel->setStatistic($customerStatistic);
|
||||
$customerBudgetStatisticModel->setStatisticTotal($customerStatistic);
|
||||
|
||||
$this->validator = $this->createValidator(false, $activityBudgetStatisticModel, $projectBudgetStatisticModel, $customerBudgetStatisticModel, $rawData, $rate);
|
||||
$this->validator->initialize($this->context);
|
||||
|
||||
$this->validator->validate($timesheet, new TimesheetBudgetUsed());
|
||||
|
||||
@@ -1,35 +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\Widget\Type;
|
||||
|
||||
use App\Repository\TimesheetRepository;
|
||||
use App\Widget\Type\AbstractWidgetType;
|
||||
use App\Widget\Type\YearChart;
|
||||
|
||||
/**
|
||||
* @covers \App\Widget\Type\YearChart
|
||||
* @covers \App\Widget\Type\SimpleStatisticChart
|
||||
* @covers \App\Widget\Type\SimpleWidget
|
||||
*/
|
||||
class YearChartTest extends AbstractSimpleStatisticsWidgetTypeTest
|
||||
{
|
||||
public function createSut(): AbstractWidgetType
|
||||
{
|
||||
$sut = new YearChart($this->createMock(TimesheetRepository::class));
|
||||
$sut->setQuery(TimesheetRepository::STATS_QUERY_ACTIVE);
|
||||
|
||||
return $sut;
|
||||
}
|
||||
|
||||
public function getDefaultOptions(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user