added team permissions (#996)
This commit is contained in:
102
tests/API/TeamControllerTest.php
Normal file
102
tests/API/TeamControllerTest.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\API;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Tests\DataFixtures\TeamFixtures;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* @group integration
|
||||
*/
|
||||
class TeamControllerTest extends APIControllerBaseTest
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$em = $client->getContainer()->get('doctrine.orm.entity_manager');
|
||||
$fixture = new TeamFixtures();
|
||||
$fixture->setAmount(1);
|
||||
$this->importFixture($em, $fixture);
|
||||
}
|
||||
|
||||
public function testIsSecure()
|
||||
{
|
||||
$this->assertUrlIsSecured('/api/teams');
|
||||
}
|
||||
|
||||
public function testGetCollection()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$this->assertAccessIsGranted($client, '/api/teams');
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertIsArray($result);
|
||||
$this->assertNotEmpty($result);
|
||||
$this->assertEquals(1, count($result));
|
||||
$this->assertStructure($result[0], false);
|
||||
}
|
||||
|
||||
public function testGetEntity()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$this->assertAccessIsGranted($client, '/api/teams/1');
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result, true);
|
||||
}
|
||||
|
||||
public function testNotFound()
|
||||
{
|
||||
$this->assertEntityNotFound(User::ROLE_USER, '/api/teams/2');
|
||||
}
|
||||
|
||||
public function testDeleteActionWithUnknownTeam()
|
||||
{
|
||||
$this->assertEntityNotFoundForDelete(User::ROLE_ADMIN, '/api/teams/255', []);
|
||||
}
|
||||
|
||||
public function testDeleteAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$this->assertAccessIsGranted($client, '/api/teams/1');
|
||||
$result = json_decode($client->getResponse()->getContent(), true);
|
||||
|
||||
$this->assertIsArray($result);
|
||||
$this->assertStructure($result);
|
||||
$this->assertNotEmpty($result['id']);
|
||||
$id = $result['id'];
|
||||
|
||||
$this->request($client, '/api/teams/' . $id, 'DELETE');
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
$this->assertEquals(Response::HTTP_NO_CONTENT, $client->getResponse()->getStatusCode());
|
||||
$this->assertEmpty($client->getResponse()->getContent());
|
||||
|
||||
$this->assertEntityNotFound(User::ROLE_USER, '/api/teams/' . $id);
|
||||
}
|
||||
|
||||
protected function assertStructure(array $result, $full = true)
|
||||
{
|
||||
$expectedKeys = [
|
||||
'id', 'name'
|
||||
];
|
||||
|
||||
if ($full) {
|
||||
$expectedKeys = array_merge($expectedKeys, []);
|
||||
}
|
||||
|
||||
$actual = array_keys($result);
|
||||
sort($actual);
|
||||
sort($expectedKeys);
|
||||
|
||||
$this->assertEquals($expectedKeys, $actual, 'Team structure does not match');
|
||||
}
|
||||
}
|
||||
@@ -26,12 +26,12 @@ class ActivityControllerTest extends ControllerBaseTest
|
||||
public function testIsSecure()
|
||||
{
|
||||
$this->assertUrlIsSecured('/admin/activity/');
|
||||
$this->assertUrlIsSecuredForRole(User::ROLE_TEAMLEAD, '/admin/activity/');
|
||||
$this->assertUrlIsSecuredForRole(User::ROLE_USER, '/admin/activity/');
|
||||
}
|
||||
|
||||
public function testIndexAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD);
|
||||
$this->assertAccessIsGranted($client, '/admin/activity/');
|
||||
$this->assertHasDataTable($client);
|
||||
}
|
||||
|
||||
@@ -9,13 +9,16 @@
|
||||
|
||||
namespace App\Tests\Controller;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\Timesheet;
|
||||
use App\Entity\User;
|
||||
use App\Tests\DataFixtures\CustomerFixtures;
|
||||
use App\Tests\DataFixtures\TeamFixtures;
|
||||
use App\Tests\DataFixtures\TimesheetFixtures;
|
||||
use App\Tests\Mocks\CustomerTestMetaFieldSubscriberMock;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Symfony\Component\DomCrawler\Field\ChoiceFormField;
|
||||
|
||||
/**
|
||||
* @group integration
|
||||
@@ -25,12 +28,12 @@ class CustomerControllerTest extends ControllerBaseTest
|
||||
public function testIsSecure()
|
||||
{
|
||||
$this->assertUrlIsSecured('/admin/customer/');
|
||||
$this->assertUrlIsSecuredForRole(User::ROLE_TEAMLEAD, '/admin/customer/');
|
||||
$this->assertUrlIsSecuredForRole(User::ROLE_USER, '/admin/customer/');
|
||||
}
|
||||
|
||||
public function testIndexAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD);
|
||||
$this->assertAccessIsGranted($client, '/admin/customer/');
|
||||
$this->assertHasDataTable($client);
|
||||
}
|
||||
@@ -111,6 +114,39 @@ class CustomerControllerTest extends ControllerBaseTest
|
||||
$this->assertEquals('Test Customer 2', $editForm->get('customer_edit_form[name]')->getValue());
|
||||
}
|
||||
|
||||
public function testTeamPermissionAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$em = $client->getContainer()->get('doctrine.orm.entity_manager');
|
||||
|
||||
/** @var Customer $customer */
|
||||
$customer = $em->getRepository(Customer::class)->find(1);
|
||||
self::assertEquals(0, $customer->getTeams()->count());
|
||||
|
||||
$fixture = new TeamFixtures();
|
||||
$fixture->setAmount(2);
|
||||
$fixture->setAddCustomer(false);
|
||||
$this->importFixture($em, $fixture);
|
||||
|
||||
$this->assertAccessIsGranted($client, '/admin/customer/1/permissions');
|
||||
$form = $client->getCrawler()->filter('form[name=customer_team_permission_form]')->form();
|
||||
/** @var ChoiceFormField $team1 */
|
||||
$team1 = $form->get('customer_team_permission_form[teams][0]');
|
||||
$team1->tick();
|
||||
/** @var ChoiceFormField $team2 */
|
||||
$team2 = $form->get('customer_team_permission_form[teams][1]');
|
||||
$team2->tick();
|
||||
|
||||
$client->submit($form);
|
||||
$this->assertIsRedirect($client, $this->createUrl('/admin/customer/'));
|
||||
$client->followRedirect();
|
||||
$this->assertHasDataTable($client);
|
||||
|
||||
/** @var Customer $customer */
|
||||
$customer = $em->getRepository(Customer::class)->find(1);
|
||||
self::assertEquals(2, $customer->getTeams()->count());
|
||||
}
|
||||
|
||||
public function testDeleteAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
|
||||
@@ -12,8 +12,10 @@ namespace App\Tests\Controller;
|
||||
use App\DataFixtures\UserFixtures;
|
||||
use App\Entity\User;
|
||||
use App\Entity\UserPreference;
|
||||
use App\Tests\DataFixtures\TeamFixtures;
|
||||
use App\Tests\DataFixtures\TimesheetFixtures;
|
||||
use Symfony\Bundle\FrameworkBundle\Client;
|
||||
use Symfony\Component\DomCrawler\Field\ChoiceFormField;
|
||||
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
|
||||
|
||||
/**
|
||||
@@ -95,7 +97,7 @@ class ProfileControllerTest extends ControllerBaseTest
|
||||
|
||||
return [
|
||||
[User::ROLE_USER, UserFixtures::USERNAME_USER, ['#settings', '#password', '#api-token']],
|
||||
[User::ROLE_SUPER_ADMIN, UserFixtures::USERNAME_SUPER_ADMIN, array_merge($userTabs, ['#roles'])],
|
||||
[User::ROLE_SUPER_ADMIN, UserFixtures::USERNAME_SUPER_ADMIN, array_merge($userTabs, ['#teams', '#roles'])],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -315,6 +317,52 @@ class ProfileControllerTest extends ControllerBaseTest
|
||||
$this->assertEquals(['ROLE_TEAMLEAD', 'ROLE_SUPER_ADMIN', 'ROLE_USER'], $user->getRoles());
|
||||
}
|
||||
|
||||
public function testTeamsActionIsSecured()
|
||||
{
|
||||
$this->assertUrlIsSecured('/profile/' . UserFixtures::USERNAME_USER . '/teams');
|
||||
$this->assertUrlIsSecuredForRole(User::ROLE_TEAMLEAD, '/profile/' . UserFixtures::USERNAME_USER . '/teams');
|
||||
}
|
||||
|
||||
public function testTeamsAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN);
|
||||
$em = $client->getContainer()->get('doctrine.orm.entity_manager');
|
||||
|
||||
/** @var User $user */
|
||||
$user = $this->getUserByRole($em, User::ROLE_USER);
|
||||
|
||||
$fixture = new TeamFixtures();
|
||||
$fixture->setAmount(3);
|
||||
$fixture->setAddCustomer(true);
|
||||
$fixture->setAddUser(false);
|
||||
$fixture->addUserToIgnore($user);
|
||||
$this->importFixture($em, $fixture);
|
||||
|
||||
$this->request($client, '/profile/' . UserFixtures::USERNAME_USER . '/teams');
|
||||
|
||||
/** @var User $user */
|
||||
$user = $this->getUserByRole($em, User::ROLE_USER);
|
||||
$this->assertEquals([], $user->getTeams()->toArray());
|
||||
|
||||
$form = $client->getCrawler()->filter('form[name=user_teams]')->form();
|
||||
/** @var ChoiceFormField $team */
|
||||
$team = $form->get('user_teams[teams][0]');
|
||||
$team->tick();
|
||||
|
||||
$client->submit($form);
|
||||
|
||||
$this->assertIsRedirect($client, $this->createUrl('/profile/' . urlencode(UserFixtures::USERNAME_USER) . '/teams'));
|
||||
$client->followRedirect();
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
|
||||
$this->assertHasFlashSuccess($client);
|
||||
|
||||
$em = $client->getContainer()->get('doctrine.orm.entity_manager');
|
||||
$user = $this->getUserByRole($em, User::ROLE_USER);
|
||||
|
||||
$this->assertEquals(1, $user->getTeams()->count());
|
||||
}
|
||||
|
||||
public function getPreferencesTestData()
|
||||
{
|
||||
return [
|
||||
|
||||
@@ -14,9 +14,11 @@ use App\Entity\Timesheet;
|
||||
use App\Entity\User;
|
||||
use App\Tests\DataFixtures\CustomerFixtures;
|
||||
use App\Tests\DataFixtures\ProjectFixtures;
|
||||
use App\Tests\DataFixtures\TeamFixtures;
|
||||
use App\Tests\DataFixtures\TimesheetFixtures;
|
||||
use App\Tests\Mocks\ProjectTestMetaFieldSubscriberMock;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Symfony\Component\DomCrawler\Field\ChoiceFormField;
|
||||
|
||||
/**
|
||||
* @group integration
|
||||
@@ -26,12 +28,12 @@ class ProjectControllerTest extends ControllerBaseTest
|
||||
public function testIsSecure()
|
||||
{
|
||||
$this->assertUrlIsSecured('/admin/project/');
|
||||
$this->assertUrlIsSecuredForRole(User::ROLE_TEAMLEAD, '/admin/project/');
|
||||
$this->assertUrlIsSecuredForRole(User::ROLE_USER, '/admin/project/');
|
||||
}
|
||||
|
||||
public function testIndexAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD);
|
||||
$this->assertAccessIsGranted($client, '/admin/project/');
|
||||
$this->assertHasDataTable($client);
|
||||
}
|
||||
@@ -135,6 +137,39 @@ class ProjectControllerTest extends ControllerBaseTest
|
||||
$this->assertEquals('Test 2', $editForm->get('project_edit_form[name]')->getValue());
|
||||
}
|
||||
|
||||
public function testTeamPermissionAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$em = $client->getContainer()->get('doctrine.orm.entity_manager');
|
||||
|
||||
/** @var Project $project */
|
||||
$project = $em->getRepository(Project::class)->find(1);
|
||||
self::assertEquals(0, $project->getTeams()->count());
|
||||
|
||||
$fixture = new TeamFixtures();
|
||||
$fixture->setAmount(2);
|
||||
$fixture->setAddCustomer(false);
|
||||
$this->importFixture($em, $fixture);
|
||||
|
||||
$this->assertAccessIsGranted($client, '/admin/project/1/permissions');
|
||||
$form = $client->getCrawler()->filter('form[name=project_team_permission_form]')->form();
|
||||
/** @var ChoiceFormField $team1 */
|
||||
$team1 = $form->get('project_team_permission_form[teams][0]');
|
||||
$team1->tick();
|
||||
/** @var ChoiceFormField $team2 */
|
||||
$team2 = $form->get('project_team_permission_form[teams][1]');
|
||||
$team2->tick();
|
||||
|
||||
$client->submit($form);
|
||||
$this->assertIsRedirect($client, $this->createUrl('/admin/project/'));
|
||||
$client->followRedirect();
|
||||
$this->assertHasDataTable($client);
|
||||
|
||||
/** @var Project $project */
|
||||
$project = $em->getRepository(Project::class)->find(1);
|
||||
self::assertEquals(2, $project->getTeams()->count());
|
||||
}
|
||||
|
||||
public function testDeleteAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
|
||||
155
tests/Controller/TeamControllerTest.php
Normal file
155
tests/Controller/TeamControllerTest.php
Normal file
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Controller;
|
||||
|
||||
use App\Entity\Team;
|
||||
use App\Entity\User;
|
||||
use App\Tests\DataFixtures\TeamFixtures;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Symfony\Bundle\FrameworkBundle\Client;
|
||||
use Symfony\Component\DomCrawler\Field\ChoiceFormField;
|
||||
|
||||
/**
|
||||
* @group integration
|
||||
*/
|
||||
class TeamControllerTest extends ControllerBaseTest
|
||||
{
|
||||
public function testIsSecure()
|
||||
{
|
||||
$this->assertUrlIsSecured('/admin/teams/');
|
||||
$this->assertUrlIsSecuredForRole(User::ROLE_TEAMLEAD, '/admin/teams/');
|
||||
}
|
||||
|
||||
public function testIndexAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$em = $client->getContainer()->get('doctrine.orm.entity_manager');
|
||||
$fixture = new TeamFixtures();
|
||||
$fixture->setAmount(5);
|
||||
$this->importFixture($em, $fixture);
|
||||
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$this->assertAccessIsGranted($client, '/admin/teams/');
|
||||
$this->assertPageActions($client, ['create' => $this->createUrl('/admin/teams/create')]);
|
||||
$this->assertHasDataTable($client);
|
||||
$this->assertDataTableRowCount($client, 'datatable_admin_teams', 5);
|
||||
}
|
||||
|
||||
public function testCreateAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$this->assertAccessIsGranted($client, '/admin/teams/create');
|
||||
$form = $client->getCrawler()->filter('form[name=team_edit_form]')->form();
|
||||
|
||||
$editForm = $client->getCrawler()->filter('form[name=team_edit_form]')->form();
|
||||
$this->assertEquals('', $editForm->get('team_edit_form[name]')->getValue());
|
||||
$this->assertEquals('5', $editForm->get('team_edit_form[teamlead]')->getValue());
|
||||
|
||||
$client->submit($form, [
|
||||
'team_edit_form' => [
|
||||
'name' => 'Test Team',
|
||||
]
|
||||
]);
|
||||
$this->assertIsRedirect($client, $this->createUrl('/admin/teams/1/edit'));
|
||||
$client->followRedirect();
|
||||
$this->assertHasFlashSuccess($client);
|
||||
$this->assertHasCustomerAndProjectPermissionBoxes($client);
|
||||
}
|
||||
|
||||
protected function assertHasCustomerAndProjectPermissionBoxes(Client $client)
|
||||
{
|
||||
$content = $client->getResponse()->getContent();
|
||||
$this->assertStringContainsString('Grant access to customers', $content);
|
||||
$this->assertStringContainsString('Grant access to projects', $content);
|
||||
$this->assertEquals(1, $client->getCrawler()->filter('form[name=team_customer_form]')->count());
|
||||
$this->assertEquals(1, $client->getCrawler()->filter('form[name=team_project_form]')->count());
|
||||
}
|
||||
|
||||
public function testEditAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
|
||||
$em = $client->getContainer()->get('doctrine.orm.entity_manager');
|
||||
$fixture = new TeamFixtures();
|
||||
$fixture->setAmount(2);
|
||||
$this->importFixture($em, $fixture);
|
||||
|
||||
$this->assertAccessIsGranted($client, '/admin/teams/1/edit');
|
||||
$form = $client->getCrawler()->filter('form[name=team_edit_form]')->form();
|
||||
$this->assertNotEmpty($form->get('team_edit_form[name]')->getValue());
|
||||
$client->submit($form, [
|
||||
'team_edit_form' => [
|
||||
'name' => 'Test Team 2'
|
||||
]
|
||||
]);
|
||||
$this->assertIsRedirect($client, $this->createUrl('/admin/teams/1/edit'));
|
||||
$client->followRedirect();
|
||||
$editForm = $client->getCrawler()->filter('form[name=team_edit_form]')->form();
|
||||
$this->assertEquals('Test Team 2', $editForm->get('team_edit_form[name]')->getValue());
|
||||
}
|
||||
|
||||
public function testEditCustomerAccessAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
|
||||
/** @var EntityManager $em */
|
||||
$em = $client->getContainer()->get('doctrine.orm.entity_manager');
|
||||
|
||||
$fixture = new TeamFixtures();
|
||||
$fixture->setAmount(2);
|
||||
$fixture->setAddCustomer(false);
|
||||
$this->importFixture($em, $fixture);
|
||||
|
||||
$team = $em->getRepository(Team::class)->find(1);
|
||||
self::assertEquals(0, count($team->getCustomers()));
|
||||
|
||||
$this->assertAccessIsGranted($client, '/admin/teams/1/edit');
|
||||
$form = $client->getCrawler()->filter('form[name=team_customer_form]')->form();
|
||||
|
||||
/** @var ChoiceFormField $customer */
|
||||
$customer = $form->get('team_customer_form[customers][0]');
|
||||
$customer->tick();
|
||||
|
||||
$client->submit($form);
|
||||
$this->assertIsRedirect($client, $this->createUrl('/admin/teams/1/edit'));
|
||||
|
||||
$team = $em->getRepository(Team::class)->find(1);
|
||||
self::assertEquals(1, count($team->getCustomers()));
|
||||
}
|
||||
|
||||
public function testEditProjectAccessAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
|
||||
/** @var EntityManager $em */
|
||||
$em = $client->getContainer()->get('doctrine.orm.entity_manager');
|
||||
|
||||
$fixture = new TeamFixtures();
|
||||
$fixture->setAmount(2);
|
||||
$fixture->setAddCustomer(false);
|
||||
$this->importFixture($em, $fixture);
|
||||
|
||||
$team = $em->getRepository(Team::class)->find(1);
|
||||
self::assertEquals(0, count($team->getProjects()));
|
||||
|
||||
$this->assertAccessIsGranted($client, '/admin/teams/1/edit');
|
||||
$form = $client->getCrawler()->filter('form[name=team_project_form]')->form();
|
||||
|
||||
/** @var ChoiceFormField $customer */
|
||||
$customer = $form->get('team_project_form[projects]');
|
||||
$customer->select([1]);
|
||||
|
||||
$client->submit($form);
|
||||
$this->assertIsRedirect($client, $this->createUrl('/admin/teams/1/edit'));
|
||||
|
||||
$team = $em->getRepository(Team::class)->find(1);
|
||||
self::assertEquals(1, count($team->getProjects()));
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,8 @@ class TimesheetTeamControllerTest extends ControllerBaseTest
|
||||
|
||||
public function testIndexActionWithQuery()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD);
|
||||
// Switching the user is not allowed for TEAMLEADs but ONLLY for admin and super-admins
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$start = new \DateTime('first day of this month');
|
||||
|
||||
$em = $client->getContainer()->get('doctrine.orm.entity_manager');
|
||||
@@ -118,7 +119,7 @@ class TimesheetTeamControllerTest extends ControllerBaseTest
|
||||
|
||||
public function testCreateAction()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD);
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$this->request($client, '/team/timesheet/create');
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
|
||||
@@ -160,7 +161,7 @@ class TimesheetTeamControllerTest extends ControllerBaseTest
|
||||
$fixture->setStartDate('2017-05-01');
|
||||
$this->importFixture($em, $fixture);
|
||||
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD);
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$this->request($client, '/team/timesheet/1/edit');
|
||||
|
||||
$response = $client->getResponse();
|
||||
|
||||
@@ -52,7 +52,7 @@ class UserControllerTest extends ControllerBaseTest
|
||||
$this->assertIsRedirect($client, $this->createUrl('/profile/' . urlencode($username) . '/edit'));
|
||||
$client->followRedirect();
|
||||
|
||||
$expectedTabs = ['#settings', '#password', '#api-token', '#roles'];
|
||||
$expectedTabs = ['#settings', '#password', '#api-token', '#teams', '#roles'];
|
||||
|
||||
$tabs = $client->getCrawler()->filter('div.nav-tabs-custom ul.nav-tabs li');
|
||||
$this->assertEquals(count($expectedTabs), $tabs->count());
|
||||
@@ -210,6 +210,6 @@ class UserControllerTest extends ControllerBaseTest
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN);
|
||||
$this->assertAccessIsGranted($client, '/admin/user/permissions');
|
||||
$this->assertHasDataTable($client);
|
||||
$this->assertDataTableRowCount($client, 'datatable_user_admin_permissions', 69);
|
||||
$this->assertDataTableRowCount($client, 'datatable_user_admin_permissions', 84);
|
||||
}
|
||||
}
|
||||
|
||||
144
tests/DataFixtures/TeamFixtures.php
Normal file
144
tests/DataFixtures/TeamFixtures.php
Normal file
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\DataFixtures;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Team;
|
||||
use App\Entity\User;
|
||||
use Doctrine\Bundle\FixturesBundle\Fixture;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Faker\Factory;
|
||||
|
||||
/**
|
||||
* Defines the sample data to load in during controller tests.
|
||||
*/
|
||||
class TeamFixtures extends Fixture
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $amount = 0;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $addCustomer = true;
|
||||
/**
|
||||
* @var User[]
|
||||
*/
|
||||
protected $skipUser = [];
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $addUser = true;
|
||||
|
||||
public function setAddCustomer(bool $useCustomer)
|
||||
{
|
||||
$this->addCustomer = $useCustomer;
|
||||
}
|
||||
|
||||
public function setAddUser(bool $useUser)
|
||||
{
|
||||
$this->addUser = $useUser;
|
||||
}
|
||||
|
||||
public function getAmount(): int
|
||||
{
|
||||
return $this->amount;
|
||||
}
|
||||
|
||||
public function setAmount(int $amount): TeamFixtures
|
||||
{
|
||||
$this->amount = $amount;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addUserToIgnore(User $user)
|
||||
{
|
||||
$this->skipUser[] = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
$faker = Factory::create();
|
||||
$user = $this->getAllUsers($manager);
|
||||
$customer = $this->getAllCustomers($manager);
|
||||
|
||||
for ($i = 0; $i < $this->amount; $i++) {
|
||||
$lead = null;
|
||||
while (null === $lead) {
|
||||
$tmp = $user[array_rand($user)];
|
||||
if (!in_array($tmp, $this->skipUser)) {
|
||||
$lead = $tmp;
|
||||
}
|
||||
}
|
||||
|
||||
$entity = new Team();
|
||||
$entity
|
||||
->setName($faker->name)
|
||||
->setTeamLead($lead)
|
||||
;
|
||||
|
||||
if ($this->addUser) {
|
||||
$userToAdd = null;
|
||||
while (null === $userToAdd) {
|
||||
$tmp = $user[array_rand($user)];
|
||||
if (!in_array($tmp, $this->skipUser)) {
|
||||
$userToAdd = $tmp;
|
||||
}
|
||||
}
|
||||
$entity->addUser($userToAdd);
|
||||
}
|
||||
|
||||
if ($this->addCustomer) {
|
||||
$entity->addCustomer($customer[array_rand($customer)]);
|
||||
}
|
||||
|
||||
$manager->persist($entity);
|
||||
}
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ObjectManager $manager
|
||||
* @return Customer[]
|
||||
*/
|
||||
protected function getAllCustomers(ObjectManager $manager)
|
||||
{
|
||||
$all = [];
|
||||
/* @var Customer[] $entries */
|
||||
$entries = $manager->getRepository(Customer::class)->findAll();
|
||||
foreach ($entries as $temp) {
|
||||
$all[$temp->getId()] = $temp;
|
||||
}
|
||||
|
||||
return $all;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ObjectManager $manager
|
||||
* @return User[]
|
||||
*/
|
||||
protected function getAllUsers(ObjectManager $manager)
|
||||
{
|
||||
$all = [];
|
||||
/* @var User[] $entries */
|
||||
$entries = $manager->getRepository(User::class)->findAll();
|
||||
foreach ($entries as $temp) {
|
||||
$all[$temp->getId()] = $temp;
|
||||
}
|
||||
|
||||
return $all;
|
||||
}
|
||||
}
|
||||
@@ -95,6 +95,7 @@ class AppExtensionTest extends TestCase
|
||||
'timezone' => null,
|
||||
'language' => 'en',
|
||||
'theme' => null,
|
||||
'currency' => 'EUR',
|
||||
]
|
||||
],
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace App\Tests\Entity;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\CustomerMeta;
|
||||
use App\Entity\Team;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
@@ -49,6 +50,8 @@ class CustomerTest extends TestCase
|
||||
$this->assertInstanceOf(Collection::class, $sut->getMetaFields());
|
||||
$this->assertEquals(0, $sut->getMetaFields()->count());
|
||||
$this->assertNull($sut->getMetaField('foo'));
|
||||
$this->assertInstanceOf(Collection::class, $sut->getTeams());
|
||||
$this->assertEquals(0, $sut->getTeams()->count());
|
||||
}
|
||||
|
||||
public function testSetterAndGetter()
|
||||
@@ -127,4 +130,23 @@ class CustomerTest extends TestCase
|
||||
self::assertEquals(3, $sut->getMetaFields()->count());
|
||||
self::assertCount(2, $sut->getVisibleMetaFields());
|
||||
}
|
||||
|
||||
public function testTeams()
|
||||
{
|
||||
$sut = new Customer();
|
||||
$team = new Team();
|
||||
self::assertEmpty($sut->getTeams());
|
||||
self::assertEmpty($team->getCustomers());
|
||||
|
||||
$sut->addTeam($team);
|
||||
self::assertCount(1, $sut->getTeams());
|
||||
self::assertCount(1, $team->getCustomers());
|
||||
self::assertSame($team, $sut->getTeams()[0]);
|
||||
self::assertSame($sut, $team->getCustomers()[0]);
|
||||
|
||||
$sut->removeTeam(new Team());
|
||||
$sut->removeTeam($team);
|
||||
self::assertCount(0, $sut->getTeams());
|
||||
self::assertCount(0, $team->getCustomers());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace App\Tests\Entity;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\ProjectMeta;
|
||||
use App\Entity\Team;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
@@ -37,6 +38,8 @@ class ProjectTest extends TestCase
|
||||
$this->assertInstanceOf(Collection::class, $sut->getMetaFields());
|
||||
$this->assertEquals(0, $sut->getMetaFields()->count());
|
||||
$this->assertNull($sut->getMetaField('foo'));
|
||||
$this->assertInstanceOf(Collection::class, $sut->getTeams());
|
||||
$this->assertEquals(0, $sut->getTeams()->count());
|
||||
}
|
||||
|
||||
public function testSetterAndGetter()
|
||||
@@ -101,4 +104,22 @@ class ProjectTest extends TestCase
|
||||
self::assertEquals(3, $sut->getMetaFields()->count());
|
||||
self::assertCount(2, $sut->getVisibleMetaFields());
|
||||
}
|
||||
|
||||
public function testTeams()
|
||||
{
|
||||
$sut = new Project();
|
||||
$team = new Team();
|
||||
self::assertEmpty($sut->getTeams());
|
||||
self::assertEmpty($team->getProjects());
|
||||
|
||||
$sut->addTeam($team);
|
||||
self::assertCount(1, $sut->getTeams());
|
||||
self::assertCount(1, $team->getProjects());
|
||||
self::assertSame($team, $sut->getTeams()[0]);
|
||||
self::assertSame($sut, $team->getProjects()[0]);
|
||||
|
||||
$sut->removeTeam($team);
|
||||
self::assertCount(0, $sut->getTeams());
|
||||
self::assertCount(0, $team->getProjects());
|
||||
}
|
||||
}
|
||||
|
||||
108
tests/Entity/TeamTest.php
Normal file
108
tests/Entity/TeamTest.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\Entity;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\Team;
|
||||
use App\Entity\User;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Entity\Team
|
||||
*/
|
||||
class TeamTest extends TestCase
|
||||
{
|
||||
public function testDefaultValues()
|
||||
{
|
||||
$sut = new Team();
|
||||
self::assertNull($sut->getId());
|
||||
self::assertNull($sut->getName());
|
||||
self::assertNull($sut->getTeamLead());
|
||||
self::assertInstanceOf(Collection::class, $sut->getUsers());
|
||||
self::assertEquals(0, $sut->getUsers()->count());
|
||||
self::assertInstanceOf(Collection::class, $sut->getCustomers());
|
||||
self::assertEquals(0, $sut->getCustomers()->count());
|
||||
self::assertInstanceOf(Collection::class, $sut->getProjects());
|
||||
self::assertEquals(0, $sut->getProjects()->count());
|
||||
}
|
||||
|
||||
public function testSetterAndGetter()
|
||||
{
|
||||
$sut = new Team();
|
||||
self::assertInstanceOf(Team::class, $sut->setName('foo-bar'));
|
||||
self::assertEquals('foo-bar', $sut->getName());
|
||||
self::assertEquals('foo-bar', (string) $sut);
|
||||
|
||||
$user = (new User())->setAlias('Foo!');
|
||||
self::assertInstanceOf(Team::class, $sut->setTeamLead($user));
|
||||
self::assertSame($user, $sut->getTeamLead());
|
||||
|
||||
self::assertFalse($sut->isTeamlead(new User()));
|
||||
self::assertTrue($sut->isTeamlead($user));
|
||||
}
|
||||
|
||||
public function testCustomer()
|
||||
{
|
||||
$customer = new Customer();
|
||||
$customer->setName('foo');
|
||||
self::assertEmpty($customer->getTeams());
|
||||
|
||||
$sut = new Team();
|
||||
$sut->addCustomer($customer);
|
||||
self::assertEquals(1, $sut->getCustomers()->count());
|
||||
$actual = $sut->getCustomers()[0];
|
||||
self::assertSame($actual, $customer);
|
||||
self::assertSame($sut, $customer->getTeams()[0]);
|
||||
$sut->removeCustomer(new Customer());
|
||||
self::assertEquals(1, $sut->getCustomers()->count());
|
||||
$sut->removeCustomer($customer);
|
||||
self::assertEquals(0, $sut->getCustomers()->count());
|
||||
}
|
||||
|
||||
public function testProject()
|
||||
{
|
||||
$project = new Project();
|
||||
$project->setName('foo');
|
||||
self::assertEmpty($project->getTeams());
|
||||
|
||||
$sut = new Team();
|
||||
$sut->addProject($project);
|
||||
self::assertEquals(1, $sut->getProjects()->count());
|
||||
$actual = $sut->getProjects()[0];
|
||||
self::assertSame($actual, $project);
|
||||
self::assertSame($sut, $project->getTeams()[0]);
|
||||
$sut->removeProject(new Project());
|
||||
self::assertEquals(1, $sut->getProjects()->count());
|
||||
$sut->removeProject($project);
|
||||
self::assertEquals(0, $sut->getProjects()->count());
|
||||
}
|
||||
|
||||
public function testUsers()
|
||||
{
|
||||
$user = new User();
|
||||
$user->setAlias('foo');
|
||||
self::assertEmpty($user->getTeams());
|
||||
|
||||
$sut = new Team();
|
||||
$sut->addUser($user);
|
||||
self::assertEquals(1, $sut->getUsers()->count());
|
||||
$actual = $sut->getUsers()[0];
|
||||
self::assertSame($actual, $user);
|
||||
self::assertSame($sut, $user->getTeams()[0]);
|
||||
self::assertFalse($sut->hasUser(new User()));
|
||||
self::assertTrue($sut->hasUser($user));
|
||||
$sut->removeUser(new User());
|
||||
self::assertEquals(1, $sut->getUsers()->count());
|
||||
$sut->removeUser($user);
|
||||
self::assertEquals(0, $sut->getUsers()->count());
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
namespace App\Tests\Entity;
|
||||
|
||||
use App\Entity\Team;
|
||||
use App\Entity\User;
|
||||
use App\Entity\UserPreference;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
@@ -97,4 +98,44 @@ class UserTest extends TestCase
|
||||
|
||||
$this->assertEquals('fr', $sut->getLocale());
|
||||
}
|
||||
|
||||
public function testTeams()
|
||||
{
|
||||
$sut = new User();
|
||||
$team = new Team();
|
||||
self::assertEmpty($sut->getTeams());
|
||||
self::assertEmpty($team->getUsers());
|
||||
|
||||
$sut->addTeam($team);
|
||||
self::assertCount(1, $sut->getTeams());
|
||||
self::assertSame($team, $sut->getTeams()[0]);
|
||||
self::assertSame($sut, $team->getUsers()[0]);
|
||||
|
||||
self::assertFalse($sut->isTeamleadOf($team));
|
||||
self::assertTrue($sut->isInTeam($team));
|
||||
|
||||
$team2 = new Team();
|
||||
self::assertFalse($sut->isInTeam($team2));
|
||||
self::assertFalse($sut->isTeamleadOf($team2));
|
||||
$team2->setTeamLead($sut);
|
||||
self::assertTrue($sut->isTeamleadOf($team2));
|
||||
self::assertTrue($sut->isInTeam($team2));
|
||||
|
||||
$sut->removeTeam(new Team());
|
||||
self::assertCount(2, $sut->getTeams());
|
||||
$sut->removeTeam($team);
|
||||
self::assertCount(1, $sut->getTeams());
|
||||
$sut->removeTeam($team2);
|
||||
self::assertCount(0, $sut->getTeams());
|
||||
}
|
||||
|
||||
public function testRoles()
|
||||
{
|
||||
$sut = new User();
|
||||
self::assertFalse($sut->isTeamlead());
|
||||
$sut->addRole(User::ROLE_ADMIN);
|
||||
self::assertFalse($sut->isTeamlead());
|
||||
$sut->addRole(User::ROLE_TEAMLEAD);
|
||||
self::assertTrue($sut->isTeamlead());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,13 +17,18 @@ abstract class AbstractMockFactory
|
||||
/**
|
||||
* @var TestCase
|
||||
*/
|
||||
protected $testCase;
|
||||
private $testCase;
|
||||
|
||||
public function __construct(TestCase $testCase)
|
||||
{
|
||||
$this->testCase = $testCase;
|
||||
}
|
||||
|
||||
protected function getTestCase(): TestCase
|
||||
{
|
||||
return $this->testCase;
|
||||
}
|
||||
|
||||
protected function getMockBuilder(string $className): MockBuilder
|
||||
{
|
||||
return new MockBuilder($this->testCase, $className);
|
||||
|
||||
46
tests/Mocks/Security/CurrentUserFactory.php
Normal file
46
tests/Mocks/Security/CurrentUserFactory.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?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\Mocks\Security;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Entity\UserPreference;
|
||||
use App\Repository\UserRepository;
|
||||
use App\Security\CurrentUser;
|
||||
use App\Tests\Mocks\AbstractMockFactory;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
|
||||
class CurrentUserFactory extends AbstractMockFactory
|
||||
{
|
||||
public function create(User $user, ?string $timezone = null): CurrentUser
|
||||
{
|
||||
return $this->getCurrentUserMock($user, $timezone);
|
||||
}
|
||||
|
||||
protected function getCurrentUserMock(User $user, ?string $timezone = null)
|
||||
{
|
||||
if (null !== $timezone) {
|
||||
$pref = new UserPreference();
|
||||
$pref->setName('timezone');
|
||||
$pref->setValue($timezone);
|
||||
$user->addPreference($pref);
|
||||
}
|
||||
|
||||
$repository = $this->getMockBuilder(UserRepository::class)->setMethods(['getUserById'])->disableOriginalConstructor()->getMock();
|
||||
$repository->expects(TestCase::atMost(1))->method('getUserById')->willReturn($user);
|
||||
$token = $this->getMockBuilder(UsernamePasswordToken::class)->setMethods(['getUser'])->disableOriginalConstructor()->getMock();
|
||||
$token->expects(TestCase::atLeast(1))->method('getUser')->willReturn($user);
|
||||
$tokenStorage = new TokenStorage();
|
||||
$tokenStorage->setToken($token);
|
||||
|
||||
return new CurrentUser($tokenStorage, $repository);
|
||||
}
|
||||
}
|
||||
@@ -10,38 +10,16 @@
|
||||
namespace App\Tests\Mocks\Security;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Entity\UserPreference;
|
||||
use App\Repository\UserRepository;
|
||||
use App\Security\CurrentUser;
|
||||
use App\Tests\Mocks\AbstractMockFactory;
|
||||
use App\Timesheet\UserDateTimeFactory;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
|
||||
class UserDateTimeFactoryFactory extends AbstractMockFactory
|
||||
{
|
||||
public function create(?string $timezone = null): UserDateTimeFactory
|
||||
{
|
||||
return new UserDateTimeFactory($this->getCurrentUserMock($timezone));
|
||||
}
|
||||
$userFactory = new CurrentUserFactory($this->getTestCase());
|
||||
$currentUser = $userFactory->create(new User(), $timezone);
|
||||
|
||||
protected function getCurrentUserMock(?string $timezone = null)
|
||||
{
|
||||
$user = new User();
|
||||
if (null !== $timezone) {
|
||||
$pref = new UserPreference();
|
||||
$pref->setName('timezone');
|
||||
$pref->setValue($timezone);
|
||||
$user->addPreference($pref);
|
||||
}
|
||||
$repository = $this->getMockBuilder(UserRepository::class)->setMethods(['getUserById'])->disableOriginalConstructor()->getMock();
|
||||
$repository->expects(TestCase::exactly(1))->method('getUserById')->willReturn($user);
|
||||
$token = $this->getMockBuilder(UsernamePasswordToken::class)->setMethods(['getUser'])->disableOriginalConstructor()->getMock();
|
||||
$token->expects(TestCase::exactly(1))->method('getUser')->willReturn($user);
|
||||
$tokenStorage = new TokenStorage();
|
||||
$tokenStorage->setToken($token);
|
||||
|
||||
return new CurrentUser($tokenStorage, $repository);
|
||||
return new UserDateTimeFactory($currentUser);
|
||||
}
|
||||
}
|
||||
|
||||
44
tests/Repository/Query/ActivityFormTypeQueryTest.php
Normal file
44
tests/Repository/Query/ActivityFormTypeQueryTest.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?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\Repository\Query;
|
||||
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\Project;
|
||||
use App\Repository\Query\ActivityFormTypeQuery;
|
||||
|
||||
/**
|
||||
* @covers \App\Repository\Query\ActivityFormTypeQuery
|
||||
*/
|
||||
class ActivityFormTypeQueryTest extends BaseQueryTest
|
||||
{
|
||||
public function testQuery()
|
||||
{
|
||||
$sut = new ActivityFormTypeQuery();
|
||||
|
||||
self::assertTrue($sut->isGlobalsOnly());
|
||||
|
||||
$project = new Project();
|
||||
self::assertNull($sut->getProject());
|
||||
self::assertInstanceOf(ActivityFormTypeQuery::class, $sut->setProject($project));
|
||||
self::assertSame($project, $sut->getProject());
|
||||
|
||||
$activity = new Activity();
|
||||
self::assertNull($sut->getActivity());
|
||||
self::assertInstanceOf(ActivityFormTypeQuery::class, $sut->setActivity($activity));
|
||||
self::assertSame($activity, $sut->getActivity());
|
||||
|
||||
self::assertFalse($sut->isGlobalsOnly());
|
||||
|
||||
$activity = new Activity();
|
||||
self::assertNull($sut->getActivityToIgnore());
|
||||
self::assertInstanceOf(ActivityFormTypeQuery::class, $sut->setActivityToIgnore($activity));
|
||||
self::assertSame($activity, $sut->getActivityToIgnore());
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
namespace App\Tests\Repository\Query;
|
||||
|
||||
use App\Entity\Team;
|
||||
use App\Repository\Query\BaseQuery;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
@@ -29,6 +30,7 @@ class BaseQueryTest extends TestCase
|
||||
$this->assertPageSize($sut);
|
||||
$this->assertOrderBy($sut, $orderBy);
|
||||
$this->assertOrder($sut);
|
||||
$this->assertTeams($sut);
|
||||
}
|
||||
|
||||
protected function assertResultType(BaseQuery $sut)
|
||||
@@ -49,6 +51,14 @@ class BaseQueryTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
protected function assertTeams(BaseQuery $sut)
|
||||
{
|
||||
self::assertEmpty($sut->getTeams());
|
||||
|
||||
self::assertInstanceOf(BaseQuery::class, $sut->addTeam(new Team()));
|
||||
self::assertEquals(1, count($sut->getTeams()));
|
||||
}
|
||||
|
||||
protected function assertPage(BaseQuery $sut)
|
||||
{
|
||||
$this->assertEquals(BaseQuery::DEFAULT_PAGE, $sut->getPage());
|
||||
|
||||
45
tests/Repository/Query/CustomerFormTypeQueryTest.php
Normal file
45
tests/Repository/Query/CustomerFormTypeQueryTest.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\Repository\Query;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Team;
|
||||
use App\Entity\User;
|
||||
use App\Repository\Query\CustomerFormTypeQuery;
|
||||
|
||||
/**
|
||||
* @covers \App\Repository\Query\CustomerFormTypeQuery
|
||||
*/
|
||||
class CustomerFormTypeQueryTest extends BaseQueryTest
|
||||
{
|
||||
public function testQuery()
|
||||
{
|
||||
$sut = new CustomerFormTypeQuery();
|
||||
|
||||
self::assertEmpty($sut->getTeams());
|
||||
self::assertInstanceOf(CustomerFormTypeQuery::class, $sut->addTeam(new Team()));
|
||||
self::assertCount(1, $sut->getTeams());
|
||||
|
||||
$customer = new Customer();
|
||||
self::assertNull($sut->getCustomer());
|
||||
self::assertInstanceOf(CustomerFormTypeQuery::class, $sut->setCustomer($customer));
|
||||
self::assertSame($customer, $sut->getCustomer());
|
||||
|
||||
$customer = new Customer();
|
||||
self::assertNull($sut->getCustomerToIgnore());
|
||||
self::assertInstanceOf(CustomerFormTypeQuery::class, $sut->setCustomerToIgnore($customer));
|
||||
self::assertSame($customer, $sut->getCustomerToIgnore());
|
||||
|
||||
$user = new User();
|
||||
self::assertNull($sut->getUser());
|
||||
self::assertInstanceOf(CustomerFormTypeQuery::class, $sut->setUser($user));
|
||||
self::assertSame($user, $sut->getUser());
|
||||
}
|
||||
}
|
||||
51
tests/Repository/Query/ProjectFormTypeQueryTest.php
Normal file
51
tests/Repository/Query/ProjectFormTypeQueryTest.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\Repository\Query;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\Team;
|
||||
use App\Entity\User;
|
||||
use App\Repository\Query\ProjectFormTypeQuery;
|
||||
|
||||
/**
|
||||
* @covers \App\Repository\Query\ProjectFormTypeQuery
|
||||
*/
|
||||
class ProjectFormTypeQueryTest extends BaseQueryTest
|
||||
{
|
||||
public function testQuery()
|
||||
{
|
||||
$sut = new ProjectFormTypeQuery();
|
||||
|
||||
self::assertEmpty($sut->getTeams());
|
||||
self::assertInstanceOf(ProjectFormTypeQuery::class, $sut->addTeam(new Team()));
|
||||
self::assertCount(1, $sut->getTeams());
|
||||
|
||||
$project = new Project();
|
||||
self::assertNull($sut->getProject());
|
||||
self::assertInstanceOf(ProjectFormTypeQuery::class, $sut->setProject($project));
|
||||
self::assertSame($project, $sut->getProject());
|
||||
|
||||
$project = new Project();
|
||||
self::assertNull($sut->getProjectToIgnore());
|
||||
self::assertInstanceOf(ProjectFormTypeQuery::class, $sut->setProjectToIgnore($project));
|
||||
self::assertSame($project, $sut->getProjectToIgnore());
|
||||
|
||||
$customer = new Customer();
|
||||
self::assertNull($sut->getCustomer());
|
||||
self::assertInstanceOf(ProjectFormTypeQuery::class, $sut->setCustomer($customer));
|
||||
self::assertSame($customer, $sut->getCustomer());
|
||||
|
||||
$user = new User();
|
||||
self::assertNull($sut->getUser());
|
||||
self::assertInstanceOf(ProjectFormTypeQuery::class, $sut->setUser($user));
|
||||
self::assertSame($user, $sut->getUser());
|
||||
}
|
||||
}
|
||||
34
tests/Repository/Query/UserFormTypeQueryTest.php
Normal file
34
tests/Repository/Query/UserFormTypeQueryTest.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\Repository\Query;
|
||||
|
||||
use App\Entity\Team;
|
||||
use App\Entity\User;
|
||||
use App\Repository\Query\UserFormTypeQuery;
|
||||
|
||||
/**
|
||||
* @covers \App\Repository\Query\UserFormTypeQuery
|
||||
*/
|
||||
class UserFormTypeQueryTest extends BaseQueryTest
|
||||
{
|
||||
public function testQuery()
|
||||
{
|
||||
$sut = new UserFormTypeQuery();
|
||||
|
||||
self::assertEmpty($sut->getTeams());
|
||||
self::assertInstanceOf(UserFormTypeQuery::class, $sut->addTeam(new Team()));
|
||||
self::assertCount(1, $sut->getTeams());
|
||||
|
||||
$user = new User();
|
||||
self::assertNull($sut->getUser());
|
||||
self::assertInstanceOf(UserFormTypeQuery::class, $sut->setUser($user));
|
||||
self::assertSame($user, $sut->getUser());
|
||||
}
|
||||
}
|
||||
@@ -9,9 +9,10 @@
|
||||
|
||||
namespace App\Tests\Repository;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Repository\TimesheetRepository;
|
||||
use App\Repository\WidgetRepository;
|
||||
use App\Security\CurrentUser;
|
||||
use App\Tests\Mocks\Security\CurrentUserFactory;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
@@ -22,7 +23,7 @@ class WidgetRepositoryTest extends TestCase
|
||||
public function testHasWidget()
|
||||
{
|
||||
$repoMock = $this->getMockBuilder(TimesheetRepository::class)->disableOriginalConstructor()->getMock();
|
||||
$userMock = $this->getMockBuilder(CurrentUser::class)->disableOriginalConstructor()->getMock();
|
||||
$userMock = (new CurrentUserFactory($this))->create(new User());
|
||||
|
||||
$sut = new WidgetRepository($repoMock, $userMock, ['test' => []]);
|
||||
|
||||
@@ -37,7 +38,7 @@ class WidgetRepositoryTest extends TestCase
|
||||
public function testGetWidgetThrowsExceptionOnNonExistingWidget()
|
||||
{
|
||||
$repoMock = $this->getMockBuilder(TimesheetRepository::class)->disableOriginalConstructor()->getMock();
|
||||
$userMock = $this->getMockBuilder(CurrentUser::class)->disableOriginalConstructor()->getMock();
|
||||
$userMock = (new CurrentUserFactory($this))->create(new User());
|
||||
|
||||
$sut = new WidgetRepository($repoMock, $userMock, ['test' => []]);
|
||||
$sut->get('foo');
|
||||
@@ -50,7 +51,7 @@ class WidgetRepositoryTest extends TestCase
|
||||
public function testGetWidgetThrowsExceptionOnInvalidType()
|
||||
{
|
||||
$repoMock = $this->getMockBuilder(TimesheetRepository::class)->disableOriginalConstructor()->getMock();
|
||||
$userMock = $this->getMockBuilder(CurrentUser::class)->disableOriginalConstructor()->getMock();
|
||||
$userMock = (new CurrentUserFactory($this))->create(new User());
|
||||
|
||||
$sut = new WidgetRepository($repoMock, $userMock, ['test' => ['type' => 'FooBar', 'user' => false]]);
|
||||
$sut->get('test');
|
||||
@@ -63,7 +64,7 @@ class WidgetRepositoryTest extends TestCase
|
||||
public function testGetWidgetTriggersExceptionOnWrongClass()
|
||||
{
|
||||
$repoMock = $this->getMockBuilder(TimesheetRepository::class)->disableOriginalConstructor()->getMock();
|
||||
$userMock = $this->getMockBuilder(CurrentUser::class)->disableOriginalConstructor()->getMock();
|
||||
$userMock = (new CurrentUserFactory($this))->create(new User());
|
||||
|
||||
$sut = new WidgetRepository($repoMock, $userMock, ['test' => ['type' => 'CompoundChart', 'user' => false]]);
|
||||
$sut->get('test');
|
||||
@@ -77,7 +78,7 @@ class WidgetRepositoryTest extends TestCase
|
||||
$repoMock = $this->getMockBuilder(TimesheetRepository::class)->disableOriginalConstructor()->getMock();
|
||||
$repoMock->method('getStatistic')->willReturn($data);
|
||||
|
||||
$userMock = $this->getMockBuilder(CurrentUser::class)->disableOriginalConstructor()->getMock();
|
||||
$userMock = (new CurrentUserFactory($this))->create(new User());
|
||||
|
||||
$widget = [
|
||||
'color' => 'sunny',
|
||||
|
||||
@@ -52,6 +52,7 @@ abstract class AbstractVoterTest extends TestCase
|
||||
$user = $this->getMockBuilder(User::class)->getMock();
|
||||
$user->method('getId')->willReturn($id);
|
||||
$user->method('getRoles')->willReturn($roles);
|
||||
$user->method('getTeams')->willReturn([]);
|
||||
|
||||
return $user;
|
||||
}
|
||||
@@ -65,8 +66,11 @@ abstract class AbstractVoterTest extends TestCase
|
||||
{
|
||||
if (!$overwrite) {
|
||||
$activities = ['view_activity', 'edit_activity', 'budget_activity', 'delete_activity', 'create_activity'];
|
||||
$activitiesTeam = ['view_activity', 'create_activity', 'edit_teamlead_activity', 'budget_teamlead_activity'];
|
||||
$projects = ['view_project', 'edit_project', 'budget_project', 'delete_project', 'create_project'];
|
||||
$projectsTeam = ['view_project', 'edit_teamlead_project', 'budget_teamlead_project', 'permissions_teamlead_project'];
|
||||
$customers = ['view_customer', 'edit_customer', 'budget_customer', 'delete_customer', 'create_customer'];
|
||||
$customersTeam = ['view_customer', 'edit_teamlead_customer', 'budget_teamlead_customer'];
|
||||
$invoice = ['view_invoice', 'create_invoice'];
|
||||
$invoiceTemplate = ['view_invoice_template', 'create_invoice_template', 'edit_invoice_template', 'delete_invoice_template'];
|
||||
$timesheet = ['view_own_timesheet', 'start_own_timesheet', 'stop_own_timesheet', 'create_own_timesheet', 'edit_own_timesheet', 'export_own_timesheet', 'delete_own_timesheet'];
|
||||
@@ -76,17 +80,18 @@ abstract class AbstractVoterTest extends TestCase
|
||||
$user = ['view_user', 'create_user', 'delete_user'];
|
||||
$rate = ['view_rate_own_timesheet', 'edit_rate_own_timesheet'];
|
||||
$rateOther = ['view_rate_other_timesheet', 'edit_rate_other_timesheet'];
|
||||
$teams = ['view_team', 'create_team', 'edit_team', 'delete_team'];
|
||||
|
||||
$roleUser = [];
|
||||
$roleUser = ['edit_team_activity', 'edit_team_project', 'edit_team_customer'];
|
||||
$roleTeamlead = ['view_rate_own_timesheet', 'view_rate_other_timesheet', 'hourly-rate_own_profile'];
|
||||
$roleAdmin = ['hourly-rate_own_profile', 'edit_exported_timesheet'];
|
||||
$roleSuperAdmin = ['hourly-rate_own_profile', 'hourly-rate_other_profile', 'delete_own_profile', 'roles_own_profile', 'system_information', 'system_configuration', 'plugins', 'edit_exported_timesheet'];
|
||||
|
||||
$permissions = [
|
||||
'ROLE_USER' => array_merge($timesheet, $profile, $roleUser),
|
||||
'ROLE_TEAMLEAD' => array_merge($invoice, $timesheet, $timesheetOthers, $profile, $roleTeamlead),
|
||||
'ROLE_ADMIN' => array_merge($activities, $projects, $customers, $invoice, $invoiceTemplate, $timesheet, $timesheetOthers, $profile, $rate, $rateOther, $roleAdmin),
|
||||
'ROLE_SUPER_ADMIN' => array_merge($activities, $projects, $customers, $invoice, $invoiceTemplate, $timesheet, $timesheetOthers, $profile, $profileOther, $user, $rate, $rateOther, $roleSuperAdmin),
|
||||
'ROLE_TEAMLEAD' => array_merge($invoice, $timesheet, $timesheetOthers, $profile, $roleTeamlead, $activitiesTeam, $projectsTeam, $customersTeam),
|
||||
'ROLE_ADMIN' => array_merge($activities, $projects, $customers, $invoice, $invoiceTemplate, $timesheet, $timesheetOthers, $profile, $rate, $rateOther, $roleAdmin, $teams),
|
||||
'ROLE_SUPER_ADMIN' => array_merge($activities, $projects, $customers, $invoice, $invoiceTemplate, $timesheet, $timesheetOthers, $profile, $profileOther, $user, $rate, $rateOther, $roleSuperAdmin, $teams),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
namespace App\Tests\Voter;
|
||||
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\Team;
|
||||
use App\Entity\User;
|
||||
use App\Voter\ActivityVoter;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
@@ -24,6 +27,11 @@ class ActivityVoterTest extends AbstractVoterTest
|
||||
* @dataProvider getTestData
|
||||
*/
|
||||
public function testVote(User $user, $subject, $attribute, $result)
|
||||
{
|
||||
$this->assertVote($user, $subject, $attribute, $result);
|
||||
}
|
||||
|
||||
protected function assertVote(User $user, $subject, $attribute, $result)
|
||||
{
|
||||
$token = new UsernamePasswordToken($user, 'foo', 'bar', $user->getRoles());
|
||||
$sut = $this->getVoter(ActivityVoter::class, $user);
|
||||
@@ -47,9 +55,19 @@ class ActivityVoterTest extends AbstractVoterTest
|
||||
yield [$user, new Activity(), 'delete', $result];
|
||||
}
|
||||
|
||||
$result = VoterInterface::ACCESS_DENIED;
|
||||
foreach ([$user0, $user1, $user2] as $user) {
|
||||
foreach ([$user2] as $user) {
|
||||
yield [$user, new Activity(), 'view', $result];
|
||||
}
|
||||
|
||||
$result = VoterInterface::ACCESS_DENIED;
|
||||
foreach ([$user0, $user1] as $user) {
|
||||
yield [$user, new Activity(), 'view', $result];
|
||||
yield [$user, new Activity(), 'edit', $result];
|
||||
yield [$user, new Activity(), 'budget', $result];
|
||||
yield [$user, new Activity(), 'delete', $result];
|
||||
}
|
||||
|
||||
foreach ([$user2] as $user) {
|
||||
yield [$user, new Activity(), 'edit', $result];
|
||||
yield [$user, new Activity(), 'budget', $result];
|
||||
yield [$user, new Activity(), 'delete', $result];
|
||||
@@ -66,4 +84,65 @@ class ActivityVoterTest extends AbstractVoterTest
|
||||
yield [$user, $user, 'delete', $result];
|
||||
}
|
||||
}
|
||||
|
||||
public function testTeamlead()
|
||||
{
|
||||
$team = new Team();
|
||||
$user = new User();
|
||||
$user->addRole(User::ROLE_TEAMLEAD);
|
||||
$team->setTeamLead($user);
|
||||
|
||||
$activity = new Activity();
|
||||
$project = new Project();
|
||||
$customer = new Customer();
|
||||
$project->setCustomer($customer);
|
||||
$activity->setProject($project);
|
||||
$customer->addTeam($team);
|
||||
|
||||
$this->assertVote($user, $activity, 'edit', VoterInterface::ACCESS_GRANTED);
|
||||
|
||||
$activity = new Activity();
|
||||
$project = new Project();
|
||||
$customer = new Customer();
|
||||
$project->setCustomer($customer);
|
||||
$activity->setProject($project);
|
||||
$project->addTeam($team);
|
||||
|
||||
$this->assertVote($user, $activity, 'edit', VoterInterface::ACCESS_GRANTED);
|
||||
|
||||
$activity = new Activity();
|
||||
|
||||
$this->assertVote($user, $activity, 'edit', VoterInterface::ACCESS_DENIED);
|
||||
}
|
||||
|
||||
public function testTeamMember()
|
||||
{
|
||||
$team = new Team();
|
||||
$user = new User();
|
||||
$user->addRole(User::ROLE_USER);
|
||||
$team->setTeamLead($user);
|
||||
|
||||
$activity = new Activity();
|
||||
$project = new Project();
|
||||
$customer = new Customer();
|
||||
$customer->addTeam($team);
|
||||
$project->setCustomer($customer);
|
||||
$activity->setProject($project);
|
||||
|
||||
$this->assertVote($user, $activity, 'edit', VoterInterface::ACCESS_GRANTED);
|
||||
|
||||
$activity = new Activity();
|
||||
$team = new Team();
|
||||
$user = new User();
|
||||
$user->addRole(User::ROLE_USER);
|
||||
$team->addUser($user);
|
||||
|
||||
$project = new Project();
|
||||
$customer = new Customer();
|
||||
$project->addTeam($team);
|
||||
$project->setCustomer($customer);
|
||||
$activity->setProject($project);
|
||||
|
||||
$this->assertVote($user, $activity, 'edit', VoterInterface::ACCESS_GRANTED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
namespace App\Tests\Voter;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Team;
|
||||
use App\Entity\User;
|
||||
use App\Voter\CustomerVoter;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
@@ -24,6 +25,11 @@ class CustomerVoterTest extends AbstractVoterTest
|
||||
* @dataProvider getTestData
|
||||
*/
|
||||
public function testVote(User $user, $subject, $attribute, $result)
|
||||
{
|
||||
$this->assertVote($user, $subject, $attribute, $result);
|
||||
}
|
||||
|
||||
protected function assertVote(User $user, $subject, $attribute, $result)
|
||||
{
|
||||
$token = new UsernamePasswordToken($user, 'foo', 'bar', $user->getRoles());
|
||||
$sut = $this->getVoter(CustomerVoter::class, $user);
|
||||
@@ -47,9 +53,19 @@ class CustomerVoterTest extends AbstractVoterTest
|
||||
yield [$user, new Customer(), 'delete', $result];
|
||||
}
|
||||
|
||||
$result = VoterInterface::ACCESS_DENIED;
|
||||
foreach ([$user0, $user1, $user2] as $user) {
|
||||
foreach ([$user2] as $user) {
|
||||
yield [$user, new Customer(), 'view', $result];
|
||||
}
|
||||
|
||||
$result = VoterInterface::ACCESS_DENIED;
|
||||
foreach ([$user0, $user1] as $user) {
|
||||
yield [$user, new Customer(), 'view', $result];
|
||||
yield [$user, new Customer(), 'edit', $result];
|
||||
yield [$user, new Customer(), 'budget', $result];
|
||||
yield [$user, new Customer(), 'delete', $result];
|
||||
}
|
||||
|
||||
foreach ([$user2] as $user) {
|
||||
yield [$user, new Customer(), 'edit', $result];
|
||||
yield [$user, new Customer(), 'budget', $result];
|
||||
yield [$user, new Customer(), 'delete', $result];
|
||||
@@ -66,4 +82,40 @@ class CustomerVoterTest extends AbstractVoterTest
|
||||
yield [$user, $user, 'delete', $result];
|
||||
}
|
||||
}
|
||||
|
||||
public function testTeamlead()
|
||||
{
|
||||
$team = new Team();
|
||||
$user = new User();
|
||||
$user->addRole(User::ROLE_TEAMLEAD);
|
||||
$team->setTeamLead($user);
|
||||
|
||||
$customer = new Customer();
|
||||
$customer->addTeam($team);
|
||||
|
||||
$this->assertVote($user, $customer, 'edit', VoterInterface::ACCESS_GRANTED);
|
||||
}
|
||||
|
||||
public function testTeamMember()
|
||||
{
|
||||
$team = new Team();
|
||||
$user = new User();
|
||||
$user->addRole(User::ROLE_USER);
|
||||
$team->setTeamLead($user);
|
||||
|
||||
$customer = new Customer();
|
||||
$customer->addTeam($team);
|
||||
|
||||
$this->assertVote($user, $customer, 'edit', VoterInterface::ACCESS_GRANTED);
|
||||
|
||||
$team = new Team();
|
||||
$user = new User();
|
||||
$user->addRole(User::ROLE_USER);
|
||||
$team->addUser($user);
|
||||
|
||||
$customer = new Customer();
|
||||
$customer->addTeam($team);
|
||||
|
||||
$this->assertVote($user, $customer, 'edit', VoterInterface::ACCESS_GRANTED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
|
||||
namespace App\Tests\Voter;
|
||||
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\Team;
|
||||
use App\Entity\User;
|
||||
use App\Voter\ProjectVoter;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
@@ -24,10 +26,19 @@ class ProjectVoterTest extends AbstractVoterTest
|
||||
* @dataProvider getTestData
|
||||
*/
|
||||
public function testVote(User $user, $subject, $attribute, $result)
|
||||
{
|
||||
$this->assertVote($user, $subject, $attribute, $result);
|
||||
}
|
||||
|
||||
protected function assertVote(User $user, $subject, $attribute, $result)
|
||||
{
|
||||
$token = new UsernamePasswordToken($user, 'foo', 'bar', $user->getRoles());
|
||||
$sut = $this->getVoter(ProjectVoter::class, $user);
|
||||
|
||||
if ($subject instanceof Project && null === $subject->getCustomer()) {
|
||||
$subject->setCustomer(new Customer());
|
||||
}
|
||||
|
||||
$this->assertEquals($result, $sut->vote($token, $subject, [$attribute]));
|
||||
}
|
||||
|
||||
@@ -47,9 +58,19 @@ class ProjectVoterTest extends AbstractVoterTest
|
||||
yield [$user, new Project(), 'delete', $result];
|
||||
}
|
||||
|
||||
$result = VoterInterface::ACCESS_DENIED;
|
||||
foreach ([$user0, $user1, $user2] as $user) {
|
||||
foreach ([$user2] as $user) {
|
||||
yield [$user, new Project(), 'view', $result];
|
||||
}
|
||||
|
||||
$result = VoterInterface::ACCESS_DENIED;
|
||||
foreach ([$user0, $user1] as $user) {
|
||||
yield [$user, new Project(), 'view', $result];
|
||||
yield [$user, new Project(), 'edit', $result];
|
||||
yield [$user, new Project(), 'budget', $result];
|
||||
yield [$user, new Project(), 'delete', $result];
|
||||
}
|
||||
|
||||
foreach ([$user2] as $user) {
|
||||
yield [$user, new Project(), 'edit', $result];
|
||||
yield [$user, new Project(), 'budget', $result];
|
||||
yield [$user, new Project(), 'delete', $result];
|
||||
@@ -67,4 +88,53 @@ class ProjectVoterTest extends AbstractVoterTest
|
||||
yield [$user, $user, 'delete', $result];
|
||||
}
|
||||
}
|
||||
|
||||
public function testTeamlead()
|
||||
{
|
||||
$team = new Team();
|
||||
$user = new User();
|
||||
$user->addRole(User::ROLE_TEAMLEAD);
|
||||
$team->setTeamLead($user);
|
||||
|
||||
$project = new Project();
|
||||
$customer = new Customer();
|
||||
$project->setCustomer($customer);
|
||||
$customer->addTeam($team);
|
||||
|
||||
$this->assertVote($user, $project, 'edit', VoterInterface::ACCESS_GRANTED);
|
||||
|
||||
$project = new Project();
|
||||
$customer = new Customer();
|
||||
$project->setCustomer($customer);
|
||||
$project->addTeam($team);
|
||||
|
||||
$this->assertVote($user, $project, 'edit', VoterInterface::ACCESS_GRANTED);
|
||||
}
|
||||
|
||||
public function testTeamMember()
|
||||
{
|
||||
$team = new Team();
|
||||
$user = new User();
|
||||
$user->addRole(User::ROLE_USER);
|
||||
$team->setTeamLead($user);
|
||||
|
||||
$project = new Project();
|
||||
$customer = new Customer();
|
||||
$customer->addTeam($team);
|
||||
$project->setCustomer($customer);
|
||||
|
||||
$this->assertVote($user, $project, 'edit', VoterInterface::ACCESS_GRANTED);
|
||||
|
||||
$team = new Team();
|
||||
$user = new User();
|
||||
$user->addRole(User::ROLE_USER);
|
||||
$team->addUser($user);
|
||||
|
||||
$project = new Project();
|
||||
$customer = new Customer();
|
||||
$project->addTeam($team);
|
||||
$project->setCustomer($customer);
|
||||
|
||||
$this->assertVote($user, $project, 'edit', VoterInterface::ACCESS_GRANTED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@ class RolePermissionVoterTest extends AbstractVoterTest
|
||||
];
|
||||
|
||||
$others = [
|
||||
'create_activity' => null,
|
||||
'create_customer' => null,
|
||||
'create_project' => null,
|
||||
];
|
||||
@@ -101,6 +100,11 @@ class RolePermissionVoterTest extends AbstractVoterTest
|
||||
yield [$user, $entity, $permission, $result];
|
||||
}
|
||||
}
|
||||
foreach ([$user0, $user1] as $user) {
|
||||
foreach (['view_activity' => null] as $permission => $entity) {
|
||||
yield [$user, $entity, $permission, $result];
|
||||
}
|
||||
}
|
||||
foreach ([$user0, $user1] as $user) {
|
||||
foreach ($invoice as $permission => $entity) {
|
||||
yield [$user, $entity, $permission, $result];
|
||||
|
||||
82
tests/Voter/TeamVoterTest.php
Normal file
82
tests/Voter/TeamVoterTest.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?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\Voter;
|
||||
|
||||
use App\Entity\Team;
|
||||
use App\Entity\User;
|
||||
use App\Voter\TeamVoter;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
|
||||
|
||||
/**
|
||||
* @covers \App\Voter\TeamVoter
|
||||
*/
|
||||
class TeamVoterTest extends AbstractVoterTest
|
||||
{
|
||||
/**
|
||||
* @dataProvider getTestData
|
||||
*/
|
||||
public function testVote(User $user, $subject, $attribute, $result)
|
||||
{
|
||||
$token = new UsernamePasswordToken($user, 'foo', 'bar', $user->getRoles());
|
||||
$sut = $this->getVoter(TeamVoter::class, $user);
|
||||
|
||||
$this->assertEquals($result, $sut->vote($token, $subject, [$attribute]));
|
||||
}
|
||||
|
||||
public function getTestData()
|
||||
{
|
||||
$user0 = $this->getUser(0, null);
|
||||
$user1 = $this->getUser(1, User::ROLE_USER);
|
||||
$user2 = $this->getUser(2, User::ROLE_TEAMLEAD);
|
||||
$user3 = $this->getUser(3, User::ROLE_ADMIN);
|
||||
$user4 = $this->getUser(4, User::ROLE_SUPER_ADMIN);
|
||||
|
||||
$team = new Team();
|
||||
|
||||
$result = VoterInterface::ACCESS_ABSTAIN;
|
||||
|
||||
$allTeamPerms = ['view_team', 'create_team', 'edit_team', 'delete_team'];
|
||||
|
||||
foreach ($allTeamPerms as $fullPerm) {
|
||||
yield [$user0, [], $fullPerm, $result];
|
||||
yield [$user0, new \stdClass(), $fullPerm, $result];
|
||||
yield [$user0, $team, $fullPerm, $result];
|
||||
yield [$user1, $team, $fullPerm, $result];
|
||||
yield [$user2, $team, $fullPerm, $result];
|
||||
yield [$user3, $team, $fullPerm, $result];
|
||||
yield [$user4, $team, $fullPerm, $result];
|
||||
}
|
||||
|
||||
$result = VoterInterface::ACCESS_DENIED;
|
||||
|
||||
yield [$user0, $team, 'view', $result];
|
||||
yield [$user0, $team, 'edit', $result];
|
||||
yield [$user0, $team, 'delete', $result];
|
||||
|
||||
yield [$user1, $team, 'view', $result];
|
||||
yield [$user1, $team, 'edit', $result];
|
||||
yield [$user1, $team, 'delete', $result];
|
||||
|
||||
yield [$user2, $team, 'view', $result];
|
||||
yield [$user2, $team, 'edit', $result];
|
||||
yield [$user2, $team, 'delete', $result];
|
||||
|
||||
$result = VoterInterface::ACCESS_GRANTED;
|
||||
|
||||
yield [$user3, $team, 'view', $result];
|
||||
yield [$user3, $team, 'edit', $result];
|
||||
yield [$user3, $team, 'delete', $result];
|
||||
|
||||
yield [$user4, $team, 'view', $result];
|
||||
yield [$user4, $team, 'edit', $result];
|
||||
yield [$user4, $team, 'delete', $result];
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ namespace App\Tests\Widget\Type;
|
||||
use App\Entity\User;
|
||||
use App\Model\Statistic\Day;
|
||||
use App\Repository\TimesheetRepository;
|
||||
use App\Security\CurrentUser;
|
||||
use App\Tests\Mocks\Security\CurrentUserFactory;
|
||||
use App\Tests\Mocks\Security\UserDateTimeFactoryFactory;
|
||||
use App\Widget\Type\AbstractWidgetType;
|
||||
use App\Widget\Type\DailyWorkingTimeChart;
|
||||
@@ -30,9 +30,9 @@ class DailyWorkingTimeChartTest extends TestCase
|
||||
public function createSut(): AbstractWidgetType
|
||||
{
|
||||
$repository = $this->getMockBuilder(TimesheetRepository::class)->disableOriginalConstructor()->getMock();
|
||||
$user = $this->getMockBuilder(CurrentUser::class)->disableOriginalConstructor()->setMethods(['getUser'])->getMock();
|
||||
$user->expects($this->once())->method('getUser')->willReturn(new User());
|
||||
$mockFactory = new UserDateTimeFactoryFactory($this);
|
||||
$userFactory = new CurrentUserFactory($this);
|
||||
$user = $userFactory->create(new User(), 'Europe/Berlin');
|
||||
|
||||
return new DailyWorkingTimeChart($repository, $user, $mockFactory->create('Europe/Berlin'));
|
||||
}
|
||||
@@ -106,8 +106,10 @@ class DailyWorkingTimeChartTest extends TestCase
|
||||
['year' => '2019', 'month' => '1', 'day' => 1, 'rate' => 13.75, 'duration' => 1234]
|
||||
];
|
||||
});
|
||||
$user = $this->getMockBuilder(CurrentUser::class)->disableOriginalConstructor()->setMethods(['getUser'])->getMock();
|
||||
$user->expects($this->once())->method('getUser')->willReturn((new User())->setUsername('tralalala'));
|
||||
|
||||
$userFactory = new CurrentUserFactory($this);
|
||||
$user = $userFactory->create(new User(), 'Europe/Berlin');
|
||||
|
||||
$mockFactory = new UserDateTimeFactoryFactory($this);
|
||||
|
||||
$sut = new DailyWorkingTimeChart($repository, $user, $mockFactory->create('Europe/Berlin'));
|
||||
|
||||
@@ -8,6 +8,7 @@ parameters:
|
||||
- '#Access to an undefined property Faker\\Generator::\$stateAbbr.#'
|
||||
- '#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.#'
|
||||
excludes_analyse:
|
||||
- %rootDir%/../../../tests/Ldap/LdapDriverTest.php
|
||||
inferPrivatePropertyTypeFromConstructor: true
|
||||
Reference in New Issue
Block a user