added project start and end date (#1303)
* added sortable js library * activity in invoice is optional * added javascript widget for paginated boxes * fix activity dropdown for globals only * added timesheet service to reduce code duplication * use repository to query for teams in dropdowns * added project validator * validate project start and end against timesheet * include begin and end in dynamic form requests for projects * added timezone and language option to import flag, improve timesheet import speed * deactivate cross-timezone filter * add virtual fields to field order list * composer update * added param to ignore dates * position loader icon fixed - fixes #1330 * permission problem when creating a new project - fixes #1340 * remove dev dependencies webserver and thanks bundle * stop information leak (begin and end date) in duration mode - fixes #1307 * unify timesheet edit dialog for user and admins * fix security issue, own rates exposed to unauthorized users in multi-update dialog
This commit is contained in:
@@ -12,7 +12,7 @@ namespace App\Tests\API;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\User;
|
||||
use App\Repository\Query\VisibilityQuery;
|
||||
use App\Repository\Query\VisibilityInterface;
|
||||
use App\Tests\Mocks\ProjectTestMetaFieldSubscriberMock;
|
||||
use Symfony\Bundle\FrameworkBundle\Client;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
@@ -98,14 +98,14 @@ class ProjectControllerTest extends APIControllerBaseTest
|
||||
// if you wonder why: SQLite does case-sensitive ordering, so "Title" > "fifth”
|
||||
yield ['/api/projects', [], [[true, 1], [false, 1], [false, 3]]];
|
||||
yield ['/api/projects', ['customer' => '1'], [[true, 1], [false, 1]]];
|
||||
yield ['/api/projects', ['customer' => '1', 'visible' => VisibilityQuery::SHOW_VISIBLE], [[true, 1], [false, 1]]];
|
||||
yield ['/api/projects', ['customer' => '1', 'visible' => VisibilityQuery::SHOW_BOTH], [[true, 1], [false, 1], [false, 1]]];
|
||||
yield ['/api/projects', ['customer' => '1', 'visible' => VisibilityQuery::SHOW_HIDDEN], [[false, 1]]];
|
||||
yield ['/api/projects', ['customer' => '1', 'visible' => VisibilityInterface::SHOW_VISIBLE], [[true, 1], [false, 1]]];
|
||||
yield ['/api/projects', ['customer' => '1', 'visible' => VisibilityInterface::SHOW_BOTH], [[true, 1], [false, 1], [false, 1]]];
|
||||
yield ['/api/projects', ['customer' => '1', 'visible' => VisibilityInterface::SHOW_HIDDEN], [[false, 1]]];
|
||||
// customer is invisible, so nothing should be returned
|
||||
yield ['/api/projects', ['customer' => '2', 'visible' => VisibilityQuery::SHOW_VISIBLE], []];
|
||||
yield ['/api/projects', ['customer' => '2', 'visible' => VisibilityQuery::SHOW_BOTH], [[false, 2], [false, 2]]];
|
||||
yield ['/api/projects', ['customer' => '2', 'visible' => VisibilityInterface::SHOW_VISIBLE], []];
|
||||
yield ['/api/projects', ['customer' => '2', 'visible' => VisibilityInterface::SHOW_BOTH], [[false, 2], [false, 2]]];
|
||||
// customer is invisible, so nothing should be returned
|
||||
yield ['/api/projects', ['customer' => '2', 'visible' => VisibilityQuery::SHOW_HIDDEN], []];
|
||||
yield ['/api/projects', ['customer' => '2', 'visible' => VisibilityInterface::SHOW_HIDDEN, 'start' => '2010-12-11T23:59:59', 'end' => '2030-12-11T23:59:59'], []];
|
||||
}
|
||||
|
||||
public function testGetEntity()
|
||||
@@ -277,7 +277,7 @@ class ProjectControllerTest extends APIControllerBaseTest
|
||||
protected function assertStructure(array $result, $full = true)
|
||||
{
|
||||
$expectedKeys = [
|
||||
'id', 'name', 'visible', 'customer', 'hourlyRate', 'fixedRate', 'color', 'metaFields', 'parentTitle'
|
||||
'id', 'name', 'visible', 'customer', 'hourlyRate', 'fixedRate', 'color', 'metaFields', 'parentTitle', 'start', 'end'
|
||||
];
|
||||
|
||||
if ($full) {
|
||||
|
||||
@@ -11,7 +11,6 @@ namespace App\Tests\DataFixtures;
|
||||
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\User;
|
||||
use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Faker\Factory;
|
||||
@@ -117,12 +116,12 @@ final class ActivityFixtures extends Fixture
|
||||
|
||||
/**
|
||||
* @param ObjectManager $manager
|
||||
* @return Project[]
|
||||
* @return array<int|string, Project>
|
||||
*/
|
||||
protected function getAllProjects(ObjectManager $manager)
|
||||
protected function getAllProjects(ObjectManager $manager): array
|
||||
{
|
||||
$all = [];
|
||||
/* @var User[] $entries */
|
||||
/** @var Project[] $entries */
|
||||
$entries = $manager->getRepository(Project::class)->findAll();
|
||||
foreach ($entries as $temp) {
|
||||
$all[$temp->getId()] = $temp;
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
namespace App\Tests\DataFixtures;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\User;
|
||||
use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Faker\Factory;
|
||||
@@ -97,20 +96,4 @@ final class CustomerFixtures extends Fixture
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ObjectManager $manager
|
||||
* @return Customer[]
|
||||
*/
|
||||
protected function getAllCustomers(ObjectManager $manager)
|
||||
{
|
||||
$all = [];
|
||||
/* @var User[] $entries */
|
||||
$entries = $manager->getRepository(Customer::class)->findAll();
|
||||
foreach ($entries as $temp) {
|
||||
$all[$temp->getId()] = $temp;
|
||||
}
|
||||
|
||||
return $all;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ namespace App\Tests\DataFixtures;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\User;
|
||||
use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Faker\Factory;
|
||||
@@ -99,12 +98,12 @@ final class ProjectFixtures extends Fixture
|
||||
|
||||
/**
|
||||
* @param ObjectManager $manager
|
||||
* @return Customer[]
|
||||
* @return array<int|string, Customer>
|
||||
*/
|
||||
protected function getAllCustomers(ObjectManager $manager)
|
||||
protected function getAllCustomers(ObjectManager $manager): array
|
||||
{
|
||||
$all = [];
|
||||
/* @var User[] $entries */
|
||||
/** @var Customer[] $entries */
|
||||
$entries = $manager->getRepository(Customer::class)->findAll();
|
||||
foreach ($entries as $temp) {
|
||||
$all[$temp->getId()] = $temp;
|
||||
|
||||
@@ -138,12 +138,12 @@ final class TeamFixtures extends Fixture
|
||||
|
||||
/**
|
||||
* @param ObjectManager $manager
|
||||
* @return Customer[]
|
||||
* @return array<int|string, Customer>
|
||||
*/
|
||||
private function getAllCustomers(ObjectManager $manager)
|
||||
{
|
||||
$all = [];
|
||||
/* @var Customer[] $entries */
|
||||
/** @var Customer[] $entries */
|
||||
$entries = $manager->getRepository(Customer::class)->findAll();
|
||||
foreach ($entries as $temp) {
|
||||
$all[$temp->getId()] = $temp;
|
||||
@@ -154,12 +154,12 @@ final class TeamFixtures extends Fixture
|
||||
|
||||
/**
|
||||
* @param ObjectManager $manager
|
||||
* @return User[]
|
||||
* @return array<int|string, User>
|
||||
*/
|
||||
private function getAllUsers(ObjectManager $manager)
|
||||
private function getAllUsers(ObjectManager $manager): array
|
||||
{
|
||||
$all = [];
|
||||
/* @var User[] $entries */
|
||||
/** @var User[] $entries */
|
||||
$entries = $manager->getRepository(User::class)->findAll();
|
||||
foreach ($entries as $temp) {
|
||||
$all[$temp->getId()] = $temp;
|
||||
|
||||
@@ -297,12 +297,12 @@ final class TimesheetFixtures extends Fixture
|
||||
|
||||
/**
|
||||
* @param ObjectManager $manager
|
||||
* @return Activity[]
|
||||
* @return array<int|string, Activity>
|
||||
*/
|
||||
protected function getAllActivities(ObjectManager $manager)
|
||||
protected function getAllActivities(ObjectManager $manager): array
|
||||
{
|
||||
$all = [];
|
||||
/* @var Activity[] $entries */
|
||||
/** @var Activity[] $entries */
|
||||
$entries = $manager->getRepository(Activity::class)->findAll();
|
||||
foreach ($entries as $temp) {
|
||||
$all[$temp->getId()] = $temp;
|
||||
@@ -313,12 +313,12 @@ final class TimesheetFixtures extends Fixture
|
||||
|
||||
/**
|
||||
* @param ObjectManager $manager
|
||||
* @return Project[]
|
||||
* @return array<int|string, Project>
|
||||
*/
|
||||
protected function getAllProjects(ObjectManager $manager)
|
||||
protected function getAllProjects(ObjectManager $manager): array
|
||||
{
|
||||
$all = [];
|
||||
/* @var Project[] $entries */
|
||||
/** @var Project[] $entries */
|
||||
$entries = $manager->getRepository(Project::class)->findAll();
|
||||
foreach ($entries as $temp) {
|
||||
$all[$temp->getId()] = $temp;
|
||||
|
||||
@@ -29,6 +29,8 @@ class ProjectTest extends TestCase
|
||||
self::assertNull($sut->getName());
|
||||
self::assertNull($sut->getOrderNumber());
|
||||
self::assertNull($sut->getOrderDate());
|
||||
self::assertNull($sut->getStart());
|
||||
self::assertNull($sut->getEnd());
|
||||
self::assertNull($sut->getComment());
|
||||
self::assertTrue($sut->getVisible());
|
||||
self::assertTrue($sut->isVisible());
|
||||
@@ -64,6 +66,16 @@ class ProjectTest extends TestCase
|
||||
self::assertInstanceOf(Project::class, $sut->setOrderDate(null));
|
||||
self::assertNull($sut->getOrderDate());
|
||||
|
||||
self::assertInstanceOf(Project::class, $sut->setStart($dateTime));
|
||||
self::assertSame($dateTime, $sut->getStart());
|
||||
self::assertInstanceOf(Project::class, $sut->setStart(null));
|
||||
self::assertNull($sut->getStart());
|
||||
|
||||
self::assertInstanceOf(Project::class, $sut->setEnd($dateTime));
|
||||
self::assertSame($dateTime, $sut->getEnd());
|
||||
self::assertInstanceOf(Project::class, $sut->setEnd(null));
|
||||
self::assertNull($sut->getEnd());
|
||||
|
||||
self::assertInstanceOf(Project::class, $sut->setComment('a comment'));
|
||||
self::assertEquals('a comment', $sut->getComment());
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
* @covers \App\Export\Base\RendererTrait
|
||||
* @covers \App\Export\Renderer\CsvRenderer
|
||||
* @covers \App\Export\Renderer\AbstractSpreadsheetRenderer
|
||||
* @covers \App\Export\Renderer\RendererTrait
|
||||
* @group integration
|
||||
*/
|
||||
class CsvRendererTest extends AbstractRendererTest
|
||||
|
||||
@@ -18,7 +18,6 @@ use Twig\Environment;
|
||||
* @covers \App\Export\Base\HtmlRenderer
|
||||
* @covers \App\Export\Base\RendererTrait
|
||||
* @covers \App\Export\Renderer\HtmlRenderer
|
||||
* @covers \App\Export\Renderer\RendererTrait
|
||||
* @group integration
|
||||
*/
|
||||
class HtmlRendererTest extends AbstractRendererTest
|
||||
|
||||
@@ -20,7 +20,6 @@ use Twig\Environment;
|
||||
* @covers \App\Export\Base\PDFRenderer
|
||||
* @covers \App\Export\Base\RendererTrait
|
||||
* @covers \App\Export\Renderer\PDFRenderer
|
||||
* @covers \App\Export\Renderer\RendererTrait
|
||||
* @group integration
|
||||
*/
|
||||
class PdfRendererTest extends AbstractRendererTest
|
||||
|
||||
@@ -18,7 +18,6 @@ use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
* @covers \App\Export\Base\RendererTrait
|
||||
* @covers \App\Export\Renderer\XlsxRenderer
|
||||
* @covers \App\Export\Renderer\AbstractSpreadsheetRenderer
|
||||
* @covers \App\Export\Renderer\RendererTrait
|
||||
* @group integration
|
||||
*/
|
||||
class XlsxRendererTest extends AbstractRendererTest
|
||||
|
||||
@@ -17,8 +17,6 @@ use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
* @covers \App\Export\Base\AbstractSpreadsheetRenderer
|
||||
* @covers \App\Export\Base\RendererTrait
|
||||
* @covers \App\Export\Timesheet\CsvRenderer
|
||||
* @covers \App\Export\Timesheet\AbstractSpreadsheetRenderer
|
||||
* @covers \App\Export\Timesheet\RendererTrait
|
||||
* @group integration
|
||||
*/
|
||||
class CsvRendererTest extends AbstractRendererTest
|
||||
|
||||
@@ -20,7 +20,6 @@ use Twig\Environment;
|
||||
* @covers \App\Export\Base\PDFRenderer
|
||||
* @covers \App\Export\Base\RendererTrait
|
||||
* @covers \App\Export\Timesheet\PDFRenderer
|
||||
* @covers \App\Export\Timesheet\RendererTrait
|
||||
* @group integration
|
||||
*/
|
||||
class PdfRendererTest extends AbstractRendererTest
|
||||
|
||||
@@ -17,8 +17,6 @@ use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
* @covers \App\Export\Base\AbstractSpreadsheetRenderer
|
||||
* @covers \App\Export\Base\RendererTrait
|
||||
* @covers \App\Export\Timesheet\XlsxRenderer
|
||||
* @covers \App\Export\Timesheet\AbstractSpreadsheetRenderer
|
||||
* @covers \App\Export\Timesheet\RendererTrait
|
||||
* @group integration
|
||||
*/
|
||||
class XlsxRendererTest extends AbstractRendererTest
|
||||
|
||||
@@ -24,6 +24,19 @@ use PHPUnit\Framework\TestCase;
|
||||
abstract class AbstractCalculatorTest extends TestCase
|
||||
{
|
||||
protected function assertEmptyModel(CalculatorInterface $sut)
|
||||
{
|
||||
$sut->setModel($this->getEmptyModel());
|
||||
|
||||
$this->assertEquals(0, $sut->getTotal());
|
||||
$this->assertEquals(0, $sut->getVat());
|
||||
$this->assertEquals('EUR', $sut->getCurrency());
|
||||
$this->assertEquals(0, $sut->getSubtotal());
|
||||
$this->assertEquals(0, $sut->getTimeWorked());
|
||||
$this->assertEquals(0, count($sut->getEntries()));
|
||||
$this->assertEquals(0, $sut->getTax());
|
||||
}
|
||||
|
||||
protected function getEmptyModel()
|
||||
{
|
||||
$customer = new Customer();
|
||||
$template = new InvoiceTemplate();
|
||||
@@ -34,15 +47,7 @@ abstract class AbstractCalculatorTest extends TestCase
|
||||
$model->setTemplate($template);
|
||||
$model->setQuery($query);
|
||||
|
||||
$sut->setModel($model);
|
||||
|
||||
$this->assertEquals(0, $sut->getTotal());
|
||||
$this->assertEquals(0, $sut->getVat());
|
||||
$this->assertEquals('EUR', $sut->getCurrency());
|
||||
$this->assertEquals(0, $sut->getSubtotal());
|
||||
$this->assertEquals(0, $sut->getTimeWorked());
|
||||
$this->assertEquals(0, count($sut->getEntries()));
|
||||
$this->assertEquals(0, $sut->getTax());
|
||||
return $model;
|
||||
}
|
||||
|
||||
protected function assertDescription(CalculatorInterface $sut, $addProject = false, $addActivity = false)
|
||||
|
||||
@@ -33,6 +33,33 @@ class ActivityInvoiceCalculatorTest extends AbstractCalculatorTest
|
||||
$this->assertEmptyModel(new ActivityInvoiceCalculator());
|
||||
}
|
||||
|
||||
public function testExceptionNoActivity()
|
||||
{
|
||||
$this->expectException('Exception');
|
||||
$this->expectExceptionMessage('Cannot work with invoice items that do not have an activity');
|
||||
$timesheet = new Timesheet();
|
||||
|
||||
$sut = new ActivityInvoiceCalculator();
|
||||
$model = $this->getEmptyModel();
|
||||
$model->addEntries([$timesheet]);
|
||||
$sut->setModel($model);
|
||||
$sut->getEntries();
|
||||
}
|
||||
|
||||
public function testExceptionNoId()
|
||||
{
|
||||
$this->expectException('Exception');
|
||||
$this->expectExceptionMessage('Cannot handle un-persisted activities');
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet->setActivity(new Activity());
|
||||
|
||||
$sut = new ActivityInvoiceCalculator();
|
||||
$model = $this->getEmptyModel();
|
||||
$model->addEntries([$timesheet]);
|
||||
$sut->setModel($model);
|
||||
$sut->getEntries();
|
||||
}
|
||||
|
||||
public function testWithMultipleEntries()
|
||||
{
|
||||
$customer = new Customer();
|
||||
|
||||
@@ -34,12 +34,7 @@ trait KernelTestTrait
|
||||
$executor->execute($loader->getFixtures(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EntityManager $em
|
||||
* @param string $username
|
||||
* @return User|null
|
||||
*/
|
||||
protected function getUserByName(EntityManager $em, string $username)
|
||||
protected function getUserByName(EntityManager $em, string $username): ?User
|
||||
{
|
||||
return $em->getRepository(User::class)->findOneBy(['username' => $username]);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace App\Tests\Repository\Query;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
use App\Repository\Query\ActivityQuery;
|
||||
use App\Repository\Query\VisibilityQuery;
|
||||
use App\Repository\Query\VisibilityInterface;
|
||||
|
||||
/**
|
||||
* @covers \App\Repository\Query\ActivityQuery
|
||||
@@ -24,7 +24,7 @@ class ActivityQueryTest extends BaseQueryTest
|
||||
$sut = new ActivityQuery();
|
||||
|
||||
$this->assertBaseQuery($sut, 'name');
|
||||
$this->assertInstanceOf(VisibilityQuery::class, $sut);
|
||||
$this->assertInstanceOf(VisibilityInterface::class, $sut);
|
||||
|
||||
$this->assertNull($sut->getCustomer());
|
||||
$this->assertNull($sut->getProject());
|
||||
|
||||
@@ -31,7 +31,7 @@ class BaseQueryTest extends TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedDeprecation BaseQuery::getResultType() is deprecated and will be removed with 1.6
|
||||
* @expectedDeprecation BaseQuery::getResultType() is deprecated and will be removed with 2.0
|
||||
* @group legacy
|
||||
*/
|
||||
public function testDeprecations()
|
||||
@@ -100,6 +100,16 @@ class BaseQueryTest extends TestCase
|
||||
|
||||
self::assertInstanceOf(BaseQuery::class, $sut->addTeam(new Team()));
|
||||
self::assertEquals(1, count($sut->getTeams()));
|
||||
|
||||
$sut->setTeams(null);
|
||||
self::assertEmpty($sut->getTeams());
|
||||
$sut->setTeams([]);
|
||||
self::assertEmpty($sut->getTeams());
|
||||
|
||||
$team = new Team();
|
||||
self::assertInstanceOf(BaseQuery::class, $sut->setTeams([$team]));
|
||||
self::assertEquals(1, count($sut->getTeams()));
|
||||
self::assertSame($team, $sut->getTeams()[0]);
|
||||
}
|
||||
|
||||
protected function assertPage(BaseQuery $sut)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace App\Tests\Repository\Query;
|
||||
|
||||
use App\Repository\Query\CustomerQuery;
|
||||
use App\Repository\Query\VisibilityQuery;
|
||||
use App\Repository\Query\VisibilityInterface;
|
||||
|
||||
/**
|
||||
* @covers \App\Repository\Query\CustomerQuery
|
||||
@@ -22,7 +22,7 @@ class CustomerQueryTest extends BaseQueryTest
|
||||
$sut = new CustomerQuery();
|
||||
|
||||
$this->assertBaseQuery($sut, 'name');
|
||||
$this->assertInstanceOf(VisibilityQuery::class, $sut);
|
||||
$this->assertInstanceOf(VisibilityInterface::class, $sut);
|
||||
|
||||
$this->assertResetByFormError(new CustomerQuery(), 'name');
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace App\Tests\Repository\Query;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Repository\Query\ProjectQuery;
|
||||
use App\Repository\Query\VisibilityQuery;
|
||||
use App\Repository\Query\VisibilityInterface;
|
||||
|
||||
/**
|
||||
* @covers \App\Repository\Query\ProjectQuery
|
||||
@@ -23,7 +23,7 @@ class ProjectQueryTest extends BaseQueryTest
|
||||
$sut = new ProjectQuery();
|
||||
|
||||
$this->assertBaseQuery($sut, 'name');
|
||||
$this->assertInstanceOf(VisibilityQuery::class, $sut);
|
||||
$this->assertInstanceOf(VisibilityInterface::class, $sut);
|
||||
|
||||
$this->assertNull($sut->getCustomer());
|
||||
|
||||
@@ -38,5 +38,21 @@ class ProjectQueryTest extends BaseQueryTest
|
||||
$this->assertEquals(99, $sut->getCustomer());
|
||||
|
||||
$this->assertResetByFormError(new ProjectQuery(), 'name');
|
||||
|
||||
self::assertNull($sut->getProjectStart());
|
||||
self::assertNull($sut->getProjectEnd());
|
||||
}
|
||||
|
||||
public function testSetter()
|
||||
{
|
||||
$sut = new ProjectQuery();
|
||||
|
||||
$start = new \DateTime();
|
||||
$sut->setProjectStart($start);
|
||||
self::assertSame($start, $sut->getProjectStart());
|
||||
|
||||
$end = new \DateTime('-1 day');
|
||||
$sut->setProjectEnd($end);
|
||||
self::assertSame($end, $sut->getProjectEnd());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace App\Tests\Repository\Query;
|
||||
|
||||
use App\Repository\Query\UserQuery;
|
||||
use App\Repository\Query\VisibilityQuery;
|
||||
use App\Repository\Query\VisibilityInterface;
|
||||
|
||||
/**
|
||||
* @covers \App\Repository\Query\UserQuery
|
||||
@@ -21,7 +21,7 @@ class UserQueryTest extends BaseQueryTest
|
||||
{
|
||||
$sut = new UserQuery();
|
||||
$this->assertBaseQuery($sut, 'username');
|
||||
$this->assertInstanceOf(VisibilityQuery::class, $sut);
|
||||
$this->assertInstanceOf(VisibilityInterface::class, $sut);
|
||||
$this->assertRole($sut);
|
||||
|
||||
$this->assertResetByFormError(new UserQuery(), 'username');
|
||||
|
||||
@@ -9,11 +9,14 @@
|
||||
|
||||
namespace App\Tests\Repository\Query;
|
||||
|
||||
use App\Repository\Query\VisibilityInterface;
|
||||
use App\Repository\Query\VisibilityQuery;
|
||||
use App\Repository\Query\VisibilityTrait;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Repository\Query\VisibilityQuery
|
||||
* @covers \App\Repository\Query\VisibilityTrait
|
||||
*/
|
||||
class VisibilityQueryTest extends TestCase
|
||||
{
|
||||
@@ -41,4 +44,34 @@ class VisibilityQueryTest extends TestCase
|
||||
$sut->setVisibility(VisibilityQuery::SHOW_VISIBLE);
|
||||
$this->assertEquals(VisibilityQuery::SHOW_VISIBLE, $sut->getVisibility());
|
||||
}
|
||||
|
||||
public function testVisibilityTrait()
|
||||
{
|
||||
$sut = new VisibilityTraitImpl();
|
||||
|
||||
$this->assertEquals(VisibilityInterface::SHOW_VISIBLE, $sut->getVisibility());
|
||||
|
||||
$sut->setVisibility('foo-bar');
|
||||
$this->assertEquals(VisibilityInterface::SHOW_VISIBLE, $sut->getVisibility());
|
||||
|
||||
$sut->setVisibility('2');
|
||||
$this->assertEquals(VisibilityInterface::SHOW_HIDDEN, $sut->getVisibility());
|
||||
|
||||
$sut->setVisibility('0'); // keep the value that was previously set
|
||||
$this->assertEquals(VisibilityInterface::SHOW_HIDDEN, $sut->getVisibility());
|
||||
|
||||
$sut->setVisibility(VisibilityInterface::SHOW_BOTH);
|
||||
$this->assertEquals(VisibilityInterface::SHOW_BOTH, $sut->getVisibility());
|
||||
|
||||
$sut->setVisibility(VisibilityInterface::SHOW_HIDDEN);
|
||||
$this->assertEquals(VisibilityInterface::SHOW_HIDDEN, $sut->getVisibility());
|
||||
|
||||
$sut->setVisibility(VisibilityInterface::SHOW_VISIBLE);
|
||||
$this->assertEquals(VisibilityInterface::SHOW_VISIBLE, $sut->getVisibility());
|
||||
}
|
||||
}
|
||||
|
||||
class VisibilityTraitImpl implements VisibilityInterface
|
||||
{
|
||||
use VisibilityTrait;
|
||||
}
|
||||
|
||||
51
tests/Validator/Constraints/ProjectValidatorTest.php
Normal file
51
tests/Validator/Constraints/ProjectValidatorTest.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Validator\Constraints;
|
||||
|
||||
use App\Entity\Project;
|
||||
use App\Validator\Constraints\Project as ProjectConstraint;
|
||||
use App\Validator\Constraints\ProjectValidator;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Validator\Constraints\ProjectValidator
|
||||
*/
|
||||
class ProjectValidatorTest extends ConstraintValidatorTestCase
|
||||
{
|
||||
protected function createValidator()
|
||||
{
|
||||
return new ProjectValidator();
|
||||
}
|
||||
|
||||
public function testConstraintIsInvalid()
|
||||
{
|
||||
$this->expectException(UnexpectedTypeException::class);
|
||||
|
||||
$this->validator->validate('foo', new NotBlank());
|
||||
}
|
||||
|
||||
public function testEndBeforeStartIsInvalid()
|
||||
{
|
||||
$begin = new \DateTime();
|
||||
$end = new \DateTime('-1 hour');
|
||||
$project = new Project();
|
||||
$project->setStart($begin);
|
||||
$project->setEnd($end);
|
||||
|
||||
$this->validator->validate($project, new ProjectConstraint());
|
||||
|
||||
$this->buildViolation('End date must not be earlier then start date.')
|
||||
->atPath('property.path.end')
|
||||
->setCode(ProjectConstraint::END_BEFORE_BEGIN_ERROR)
|
||||
->assertRaised();
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
|
||||
use Symfony\Component\Validator\Test\ConstraintViolationAssertion;
|
||||
|
||||
/**
|
||||
* @covers \App\Validator\Constraints\TimesheetValidator
|
||||
@@ -199,4 +200,68 @@ class TimesheetValidatorTest extends ConstraintValidatorTestCase
|
||||
->setCode(TimesheetConstraint::DISABLED_CUSTOMER_ERROR)
|
||||
->assertRaised();
|
||||
}
|
||||
|
||||
public function getProjectStartEndTestData()
|
||||
{
|
||||
yield [new \DateTime(), new \DateTime(), [
|
||||
['begin', TimesheetConstraint::PROJECT_NOT_STARTED, 'The project has not started at that time.'],
|
||||
['end', TimesheetConstraint::PROJECT_NOT_STARTED, 'The project has not started at that time.'],
|
||||
]];
|
||||
|
||||
yield [new \DateTime('-9 hour'), new \DateTime('-2 hour'), [
|
||||
['begin', TimesheetConstraint::PROJECT_NOT_STARTED, 'The project has not started at that time.'],
|
||||
['end', TimesheetConstraint::PROJECT_ALREADY_ENDED, 'The project is finished at that time.'],
|
||||
]];
|
||||
|
||||
yield [new \DateTime('-19 hour'), new \DateTime('-12 hour'), [
|
||||
['begin', TimesheetConstraint::PROJECT_ALREADY_ENDED, 'The project is finished at that time.'],
|
||||
['end', TimesheetConstraint::PROJECT_ALREADY_ENDED, 'The project is finished at that time.'],
|
||||
]];
|
||||
|
||||
yield [new \DateTime('-19 hour'), new \DateTime('-2 hour'), [
|
||||
['end', TimesheetConstraint::PROJECT_ALREADY_ENDED, 'The project is finished at that time.'],
|
||||
]];
|
||||
|
||||
yield [new \DateTime('-9 hour'), new \DateTime(), [
|
||||
['begin', TimesheetConstraint::PROJECT_NOT_STARTED, 'The project has not started at that time.'],
|
||||
]];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getProjectStartEndTestData
|
||||
*/
|
||||
public function testEndBeforeWithProjectStartAndEnd(\DateTime $start, \DateTime $end, array $violations)
|
||||
{
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet->setBegin(new \DateTime('-10 hour'));
|
||||
$timesheet->setEnd(new \DateTime('-1 hour'));
|
||||
|
||||
$customer = new Customer();
|
||||
$project = new Project();
|
||||
$project->setStart($start);
|
||||
$project->setEnd($end);
|
||||
$project->setCustomer($customer);
|
||||
|
||||
$timesheet->setProject($project);
|
||||
$timesheet->setActivity(new Activity());
|
||||
|
||||
$this->validator->validate($timesheet, new TimesheetConstraint(['message' => 'myMessage']));
|
||||
|
||||
/** @var ConstraintViolationAssertion $assertion */
|
||||
$assertion = null;
|
||||
foreach ($violations as $violation) {
|
||||
if (null === $assertion) {
|
||||
$assertion = $this->buildViolation($violation[2])
|
||||
->atPath('property.path.' . $violation[0])
|
||||
->setCode($violation[1])
|
||||
;
|
||||
} else {
|
||||
$assertion = $assertion->buildNextViolation($violation[2])
|
||||
->atPath('property.path.' . $violation[0])
|
||||
->setCode($violation[1])
|
||||
;
|
||||
}
|
||||
}
|
||||
$assertion->assertRaised();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ parameters:
|
||||
- '#Access to an undefined property Faker\\Generator::\$catchPhrase.#'
|
||||
- '#Access to an undefined property Faker\\Generator::\$bs.#'
|
||||
- '#Call to static method PHPUnit\\Framework\\Assert::assertSame\(\) with App\\Entity\\[a-zA-Z0-9]+ and null will always evaluate to false.#'
|
||||
- '#Method *::getUserByName\(\) should return App\\Entity\\User\|null but returns object|null.#'
|
||||
excludes_analyse:
|
||||
- %rootDir%/../../../tests/Ldap/LdapDriverTest.php
|
||||
inferPrivatePropertyTypeFromConstructor: true
|
||||
Reference in New Issue
Block a user