added avatars, show user teams in list, new team dashboard widgets (#1150)

This commit is contained in:
Kevin Papst
2019-10-03 13:44:16 +02:00
committed by GitHub
parent 718ad4b398
commit e8c25d8ac5
120 changed files with 2585 additions and 642 deletions

View File

@@ -40,14 +40,14 @@ class TeamControllerTest extends APIControllerBaseTest
$this->assertIsArray($result);
$this->assertNotEmpty($result);
$this->assertEquals(1, count($result));
$this->assertEquals(2, count($result));
$this->assertStructure($result[0], false);
}
public function testGetEntity()
{
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
$this->assertAccessIsGranted($client, '/api/teams/1');
$this->assertAccessIsGranted($client, '/api/teams/2');
$result = json_decode($client->getResponse()->getContent(), true);
$this->assertIsArray($result);
@@ -56,7 +56,7 @@ class TeamControllerTest extends APIControllerBaseTest
public function testNotFound()
{
$this->assertEntityNotFound(User::ROLE_USER, '/api/teams/2');
$this->assertEntityNotFound(User::ROLE_USER, '/api/teams/3');
}
public function testDeleteActionWithUnknownTeam()
@@ -67,7 +67,7 @@ class TeamControllerTest extends APIControllerBaseTest
public function testDeleteAction()
{
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
$this->assertAccessIsGranted($client, '/api/teams/1');
$this->assertAccessIsGranted($client, '/api/teams/2');
$result = json_decode($client->getResponse()->getContent(), true);
$this->assertIsArray($result);

View File

@@ -30,7 +30,7 @@ class UserControllerTest extends APIControllerBaseTest
$this->assertIsArray($result);
$this->assertNotEmpty($result);
$this->assertEquals(5, count($result));
$this->assertEquals(7, count($result));
foreach ($result as $user) {
$this->assertStructure($user, false);
}
@@ -58,7 +58,7 @@ class UserControllerTest extends APIControllerBaseTest
$this->assertIsArray($result);
$this->assertNotEmpty($result);
$this->assertEquals(6, count($result));
$this->assertEquals(8, count($result));
foreach ($result as $user) {
$this->assertStructure($user, false);
}

View File

@@ -16,12 +16,6 @@ use App\Entity\User;
*/
class AboutControllerTest extends ControllerBaseTest
{
public function testDebugIsSecure()
{
$this->assertUrlIsSecured('/about/debug');
$this->assertUrlIsSecuredForRole(User::ROLE_ADMIN, '/about/debug');
}
public function testIndexAction()
{
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
@@ -34,18 +28,4 @@ class AboutControllerTest extends ControllerBaseTest
$this->assertEquals(1, count($result));
$this->assertContains('MIT License', $result->text());
}
public function testDebugAction()
{
$client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN);
$this->assertAccessIsGranted($client, '/about/debug');
$content = $client->getResponse()->getContent();
$this->assertContains('<h3 class="box-title">Environment</h3>', $content);
$this->assertContains('<h3 class="box-title">PHP</h3>', $content);
$this->assertContains('<h3 class="box-title">Server</h3>', $content);
$this->assertContains('', $content);
$this->assertContains('PHP', $content);
}
}

View File

@@ -9,6 +9,7 @@
namespace App\Tests\Controller;
use App\DataFixtures\UserFixtures;
use App\Entity\User;
/**
@@ -29,6 +30,19 @@ class DashboardControllerTest extends ControllerBaseTest
$this->assertMainContentClass($client, 'dashboard');
}
public function testIndexActionForUserWithTeams()
{
$client = self::createClient([], [
'PHP_AUTH_USER' => 'test_user_1',
'PHP_AUTH_PW' => UserFixtures::DEFAULT_PASSWORD,
]);
$this->request($client, '/dashboard/');
$this->assertTrue($client->getResponse()->isSuccessful());
self::assertEquals(1, $client->getCrawler()->filter('section.content .WidgetUserTeams')->count());
// team 1 has no project assignment right now
self::assertEquals(0, $client->getCrawler()->filter('section.content .WidgetUserTeamProjects')->count());
}
public function testIndexActionForAdmin()
{
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);

View File

@@ -0,0 +1,33 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Tests\Controller;
use App\Entity\User;
/**
* @group integration
*/
class DoctorControllerTest extends ControllerBaseTest
{
public function testDoctorIsSecure()
{
$this->assertUrlIsSecured('/doctor');
$this->assertUrlIsSecuredForRole(User::ROLE_ADMIN, '/doctor');
}
public function testIndexAction()
{
$client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN);
$this->assertAccessIsGranted($client, '/doctor');
$result = $client->getCrawler()->filter('.content .box-header');
$this->assertEquals(7, count($result));
}
}

View File

@@ -35,7 +35,7 @@ class ProfileControllerTest extends ControllerBaseTest
$this->assertTrue($client->getResponse()->isSuccessful());
$this->assertHasNoEntriesWithFilter($client);
$this->assertHasProfileBox($client, UserFixtures::USERNAME_USER);
$this->assertHasProfileBox($client, 'John Doe');
$this->assertHasAboutMeBox($client, UserFixtures::USERNAME_USER);
}
@@ -68,7 +68,7 @@ class ProfileControllerTest extends ControllerBaseTest
$this->assertContains('var userProfileChart' . $year . ' = new Chart(', $content);
}
$this->assertHasProfileBox($client, UserFixtures::USERNAME_USER);
$this->assertHasProfileBox($client, 'John Doe');
$this->assertHasAboutMeBox($client, UserFixtures::USERNAME_USER);
}
@@ -76,7 +76,7 @@ class ProfileControllerTest extends ControllerBaseTest
{
$profileBox = $client->getCrawler()->filter('div.box-body.box-profile');
$this->assertEquals(1, $profileBox->count());
$profileAvatar = $profileBox->filter('img.profile-user-img');
$profileAvatar = $profileBox->filter('img.img-circle');
$this->assertEquals(1, $profileAvatar->count());
$alt = $profileAvatar->attr('alt');

View File

@@ -43,7 +43,7 @@ class TeamControllerTest extends ControllerBaseTest
'help' => 'https://www.kimai.org/documentation/teams.html'
]);
$this->assertHasDataTable($client);
$this->assertDataTableRowCount($client, 'datatable_admin_teams', 5);
$this->assertDataTableRowCount($client, 'datatable_admin_teams', 6);
}
public function testIndexActionWithSearchTermQuery()
@@ -85,7 +85,7 @@ class TeamControllerTest extends ControllerBaseTest
'name' => 'Test Team',
]
]);
$this->assertIsRedirect($client, $this->createUrl('/admin/teams/1/edit'));
$this->assertIsRedirect($client, $this->createUrl('/admin/teams/2/edit'));
$client->followRedirect();
$this->assertHasFlashSuccess($client);
$this->assertHasCustomerAndProjectPermissionBoxes($client);

View File

@@ -29,7 +29,7 @@ class UserControllerTest extends ControllerBaseTest
$client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN);
$this->assertAccessIsGranted($client, '/admin/user/');
$this->assertHasDataTable($client);
$this->assertDataTableRowCount($client, 'datatable_user_admin', 5);
$this->assertDataTableRowCount($client, 'datatable_user_admin', 7);
}
public function testIndexActionWithSearchTermQuery()
@@ -232,6 +232,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', 81);
$this->assertDataTableRowCount($client, 'datatable_user_admin_permissions', 83);
}
}

View File

@@ -28,26 +28,36 @@ class TimesheetTest extends TestCase
public function testDefaultValues()
{
$sut = new Timesheet();
$this->assertNull($sut->getId());
$this->assertNull($sut->getBegin());
$this->assertNull($sut->getEnd());
$this->assertSame(0, $sut->getDuration());
$this->assertNull($sut->getUser());
$this->assertNull($sut->getActivity());
$this->assertNull($sut->getProject());
$this->assertNull($sut->getDescription());
$this->assertSame(0.00, $sut->getRate());
$this->assertNull($sut->getFixedRate());
$this->assertNull($sut->getHourlyRate());
$this->assertEquals(new ArrayCollection(), $sut->getTags());
$this->assertEquals([], $sut->getTagsAsArray());
$this->assertInstanceOf(Timesheet::class, $sut->setFixedRate(13.47));
$this->assertEquals(13.47, $sut->getFixedRate());
$this->assertInstanceOf(Timesheet::class, $sut->setHourlyRate(99));
$this->assertEquals(99, $sut->getHourlyRate());
$this->assertInstanceOf(Collection::class, $sut->getMetaFields());
$this->assertEquals(0, $sut->getMetaFields()->count());
$this->assertNull($sut->getMetaField('foo'));
self::assertNull($sut->getId());
self::assertNull($sut->getBegin());
self::assertNull($sut->getEnd());
self::assertSame(0, $sut->getDuration());
self::assertNull($sut->getUser());
self::assertNull($sut->getActivity());
self::assertNull($sut->getProject());
self::assertNull($sut->getDescription());
self::assertSame(0.00, $sut->getRate());
self::assertNull($sut->getFixedRate());
self::assertNull($sut->getHourlyRate());
self::assertEquals(new ArrayCollection(), $sut->getTags());
self::assertEquals([], $sut->getTagsAsArray());
self::assertInstanceOf(Timesheet::class, $sut->setFixedRate(13.47));
self::assertEquals(13.47, $sut->getFixedRate());
self::assertInstanceOf(Timesheet::class, $sut->setHourlyRate(99));
self::assertEquals(99, $sut->getHourlyRate());
self::assertInstanceOf(Collection::class, $sut->getMetaFields());
self::assertEquals(0, $sut->getMetaFields()->count());
self::assertNull($sut->getMetaField('foo'));
}
public function testDurationCanBeNull()
{
$sut = new Timesheet();
self::assertEquals(0, $sut->getDuration());
$sut->setDuration(null);
self::assertNull($sut->getDuration());
$sut->setDuration(-1);
self::assertEquals(-1, $sut->getDuration());
}
protected function getEntity()
@@ -84,11 +94,11 @@ class TimesheetTest extends TestCase
$sut->addTag($tag);
$sut->addTag($tag1);
$this->assertEquals([0 => 'bar', 1 => 'foo'], $sut->getTagsAsArray());
$this->assertEquals(new ArrayCollection([$tag, $tag1]), $sut->getTags());
self::assertEquals([0 => 'bar', 1 => 'foo'], $sut->getTagsAsArray());
self::assertEquals(new ArrayCollection([$tag, $tag1]), $sut->getTags());
$sut->removeTag($tag);
$this->assertEquals([1 => 'foo'], $sut->getTagsAsArray());
self::assertEquals([1 => 'foo'], $sut->getTagsAsArray());
$sut->removeTag($tag1);
$this->assertEmpty($sut->getTags());
@@ -99,7 +109,7 @@ class TimesheetTest extends TestCase
$sut = new Timesheet();
$meta = new TimesheetMeta();
$meta->setName('foo')->setValue('bar')->setType('test');
$this->assertInstanceOf(Timesheet::class, $sut->setMetaField($meta));
self::assertInstanceOf(Timesheet::class, $sut->setMetaField($meta));
self::assertEquals(1, $sut->getMetaFields()->count());
$result = $sut->getMetaField('foo');
self::assertSame($result, $meta);
@@ -107,7 +117,7 @@ class TimesheetTest extends TestCase
$meta2 = new TimesheetMeta();
$meta2->setName('foo')->setValue('bar')->setType('test2');
$this->assertInstanceOf(Timesheet::class, $sut->setMetaField($meta2));
self::assertInstanceOf(Timesheet::class, $sut->setMetaField($meta2));
self::assertEquals(1, $sut->getMetaFields()->count());
self::assertCount(0, $sut->getVisibleMetaFields());

View File

@@ -9,6 +9,7 @@
namespace App\Tests\Model;
use App\Entity\Project;
use App\Model\ProjectStatistic;
use PHPUnit\Framework\TestCase;
@@ -19,21 +20,23 @@ class ProjectStatisticTest extends TestCase
{
public function testDefaultValues()
{
$sut = new ProjectStatistic();
$this->assertEquals(0, $sut->getActivityAmount());
$this->assertEquals(0, $sut->getRecordAmount());
$this->assertEquals(0, $sut->getRecordDuration());
$sut = new ProjectStatistic(new Project());
self::assertEquals(0, $sut->getActivityAmount());
self::assertEquals(0, $sut->getRecordAmount());
self::assertEquals(0, $sut->getRecordDuration());
}
public function testSetter()
{
$sut = new ProjectStatistic();
$project = new Project();
$sut = new ProjectStatistic($project);
$sut->setRecordAmount(7654.298);
$sut->setRecordDuration(826.10);
$sut->setActivityAmount(13);
$this->assertEquals(13, $sut->getActivityAmount());
$this->assertEquals(7654, $sut->getRecordAmount());
$this->assertEquals(826, $sut->getRecordDuration());
self::assertEquals(13, $sut->getActivityAmount());
self::assertEquals(7654, $sut->getRecordAmount());
self::assertEquals(826, $sut->getRecordDuration());
self::assertSame($project, $sut->getProject());
}
}

View File

@@ -30,6 +30,16 @@ class BaseQueryTest extends TestCase
$this->assertResetByFormError(new BaseQuery());
}
/**
* @expectedDeprecation BaseQuery::getResultType() is deprecated and will be removed with 1.6
* @group legacy
*/
public function testDeprecations()
{
$sut = new BaseQuery();
$sut->getResultType();
}
protected function assertResetByFormError(BaseQuery $sut, $orderBy = 'id', $order = 'ASC')
{
$sut->setOrder('ASK');
@@ -49,7 +59,6 @@ class BaseQueryTest extends TestCase
protected function assertBaseQuery(BaseQuery $sut, $orderBy = 'id')
{
$this->assertResultType($sut);
$this->assertPage($sut);
$this->assertPageSize($sut);
$this->assertOrderBy($sut, $orderBy);
@@ -85,24 +94,6 @@ class BaseQueryTest extends TestCase
$sut->resetByFormError($formErrors);
}
protected function assertResultType(BaseQuery $sut)
{
self::assertEquals(BaseQuery::RESULT_TYPE_PAGER, $sut->getResultType());
$sut->setResultType(BaseQuery::RESULT_TYPE_QUERYBUILDER);
self::assertEquals(BaseQuery::RESULT_TYPE_QUERYBUILDER, $sut->getResultType());
$sut->setResultType(BaseQuery::RESULT_TYPE_OBJECTS);
self::assertEquals(BaseQuery::RESULT_TYPE_OBJECTS, $sut->getResultType());
try {
$sut->setResultType('foo-bar');
} catch (\Exception $exception) {
$this->assertInstanceOf(\InvalidArgumentException::class, $exception);
self::assertEquals('Unsupported query result type', $exception->getMessage());
}
}
protected function assertTeams(BaseQuery $sut)
{
self::assertEmpty($sut->getTeams());

View File

@@ -24,7 +24,6 @@ class ExportQueryTest extends BaseQueryTest
{
$sut = new ExportQuery();
$this->assertResultType($sut);
$this->assertPage($sut);
$this->assertPageSize($sut);
$this->assertOrderBy($sut, 'begin');

View File

@@ -24,7 +24,6 @@ class InvoiceQueryTest extends BaseQueryTest
{
$sut = new InvoiceQuery();
$this->assertResultType($sut);
$this->assertPage($sut);
$this->assertPageSize($sut);
$this->assertOrderBy($sut, 'begin');

View File

@@ -25,7 +25,6 @@ class TimesheetQueryTest extends BaseQueryTest
{
$sut = new TimesheetQuery();
$this->assertResultType($sut);
$this->assertPage($sut);
$this->assertPageSize($sut);
$this->assertOrderBy($sut, 'begin');

View File

@@ -16,7 +16,6 @@ use App\Entity\Timesheet;
use App\Entity\User;
use App\Repository\ActivityRepository;
use App\Repository\ProjectRepository;
use App\Repository\Query\BaseQuery;
use App\Repository\Query\TimesheetQuery;
use App\Repository\RepositoryException;
use App\Repository\TimesheetRepository;
@@ -58,7 +57,6 @@ class TimesheetRepositoryTest extends AbstractRepositoryTest
$this->importFixture($em, $fixtures);
$query = new TimesheetQuery();
$query->setResultType(BaseQuery::RESULT_TYPE_OBJECTS);
$query->setUser($user);
$query->setState(TimesheetQuery::STATE_STOPPED);

View File

@@ -13,6 +13,7 @@ use App\Entity\User;
use App\Repository\TimesheetRepository;
use App\Repository\WidgetRepository;
use App\Tests\Mocks\Security\CurrentUserFactory;
use App\Widget\Type\CompoundChart;
use PHPUnit\Framework\TestCase;
/**
@@ -46,7 +47,7 @@ class WidgetRepositoryTest extends TestCase
/**
* @expectedException \App\Widget\WidgetException
* @expectedExceptionMessage Unknown widget type "\App\Widget\Type\FooBar"
* @expectedExceptionMessage Unknown widget type "FooBar"
*/
public function testGetWidgetThrowsExceptionOnInvalidType()
{
@@ -59,14 +60,14 @@ class WidgetRepositoryTest extends TestCase
/**
* @expectedException \App\Widget\WidgetException
* @expectedExceptionMessage Invalid widget type "\App\Widget\Type\CompoundChart" does not extend AbstractWidgetType
* @expectedExceptionMessage Widget type "App\Widget\Type\CompoundChart" is not an instance of "App\Widget\Type\AbstractWidgetType"
*/
public function testGetWidgetTriggersExceptionOnWrongClass()
{
$repoMock = $this->getMockBuilder(TimesheetRepository::class)->disableOriginalConstructor()->getMock();
$userMock = (new CurrentUserFactory($this))->create(new User());
$sut = new WidgetRepository($repoMock, $userMock, ['test' => ['type' => 'CompoundChart', 'user' => false]]);
$sut = new WidgetRepository($repoMock, $userMock, ['test' => ['type' => CompoundChart::class, 'user' => false]]);
$sut->get('test');
}

View File

@@ -0,0 +1,67 @@
<?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\Twig;
use App\Entity\User;
use App\Twig\AvatarExtension;
use App\Utils\AvatarService;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Asset\PackageInterface;
use Symfony\Component\Asset\Packages;
use Twig\TwigFunction;
/**
* @covers \App\Twig\AvatarExtension
*/
class AvatarExtensionTest extends TestCase
{
protected function getSut(int $packagesGetUrlCount): AvatarExtension
{
$default = $this->getMockBuilder(PackageInterface::class)->getMock();
$default->expects(self::exactly($packagesGetUrlCount))->method('getUrl')->willReturnCallback(function ($argument) {
return 'http://www.example.com/' . $argument;
});
$service = $this->getMockBuilder(AvatarService::class)->disableOriginalConstructor()->getMock();
$packages = new Packages();
$packages->setDefaultPackage($default);
return new AvatarExtension($service, $packages);
}
public function testGetFunctions()
{
$functions = ['avatar'];
$sut = $this->getSut(0);
$twigFunctions = $sut->getFunctions();
self::assertCount(count($functions), $twigFunctions);
$i = 0;
/** @var TwigFunction $filter */
foreach ($twigFunctions as $filter) {
self::assertInstanceOf(TwigFunction::class, $filter);
self::assertEquals($functions[$i++], $filter->getName());
}
}
public function testGetAvatarWithoutUserReturnsDefault()
{
$sut = $this->getSut(1);
self::assertEquals('http://www.example.com/blub', $sut->getAvatarUrl(null, 'blub'));
}
public function testGetAvatarWithUserProfileReturnsNullOnNullFromAvatarService()
{
$sut = $this->getSut(1);
$user = new User();
self::assertEquals('http://www.example.com/test', $sut->getAvatarUrl($user, 'test'));
}
}